Files

342 lines
21 KiB
PHP

@extends('layouts.master')
@section('styles')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="{{ asset('vendors/select2/select2.min.css') }}">
<style>
.select2-container .select2-selection--single {
height: 48px;
}
.select2-container--default
.select2-selection--single
.select2-selection__rendered {
line-height: 38px;
}
.select2-container--default
.select2-selection--single
.select2-selection__arrow {
height: 38px;
}
/* .table th {
text-align: center;
}
.table td {
text-align: right;
} */
#tabel-parkir th[data-sort] {
cursor: pointer;
white-space: nowrap;
user-select: none;
}
#tabel-parkir th[data-sort]:hover {
background-color: #f2f6ff;
}
#tabel-parkir .sort-ind {
font-size: 11px;
}
</style>
@endsection
@section('content')
<!-- partial -->
<div class="container-fluid page-body-wrapper">
<div class="main-panel">
<div class="content-wrapper">
<div class="row">
<div class="col-md-12 grid-margin stretch-card">
<div class="card">
<div class="card-header">
</div>
<div class="card-body">
<form id="filter-parkir" action="javascript:void(0)">
<div class="row align-items-end g-2">
<!-- CARI DATA -->
<div class="col-md-1">
<div class="form-group">
<label for="q">Cari Data</label>
<input type="text" class="form-control form-control-sm" id="q" placeholder="Keyword">
</div>
</div>
<div class="col-md-1">
<div class="form-group">
<label for="field">Field</label>
<select class="form-control form-control-sm js-example-basic-single" id="field">
<option value="id" selected>No. ID</option>
<option value="no_pol">No. Pol</option>
<option value="no_barcode">No. Transaksi</option>
</select>
</div>
</div>
<!-- PERIODE -->
<div class="col-md-2">
<div class="form-group">
<label for="tgl_awal">Periode Awal</label>
<input type="date" class="form-control form-control-sm" id="tgl_awal" name="tgl_awal">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label for="tgl_akhir">Periode Akhir</label>
<input type="date" class="form-control form-control-sm" id="tgl_akhir" name="tgl_akhir">
</div>
</div>
<!-- STATUS KENDARAAN : 1 masuk, 0 keluar -->
<div class="col-md-1">
<div class="form-group">
<label for="status_kendaraan">Kendaraan</label>
<select class="form-control form-control-sm js-example-basic-single" id="status_kendaraan">
<option value="" selected>Semua</option>
<option value="1">Masuk</option>
<option value="0">Keluar</option>
</select>
</div>
</div>
<!-- STATUS TRANSAKSI : 0 casual, 3 member, 32 denda -->
<div class="col-md-2">
<div class="form-group">
<label for="status_transaksi">Transaksi</label>
<select class="form-control form-control-sm js-example-basic-single" id="status_transaksi">
<option value="" selected>Semua</option>
<option value="0">Casual</option>
<option value="3">Member</option>
<option value="32">Denda</option>
</select>
</div>
</div>
<!-- AKSI -->
<div class="col-md-2 d-flex align-items-end gap-1">
<button type="submit" class="btn btn-sm btn-primary" id="btn-cari">
<i class="fa fa-search me-1"></i>Cari
</button>
<button type="button" class="btn btn-sm btn-secondary" id="btn-reset">Reset</button>
</div>
<!-- BUTTON EXPORT -->
<div class="col-md-1 text-end">
<div class="btn-list d-inline-flex gap-1">
<button type="button"
class="btn btn-sm btn-icon btn-success btn-export-excel" title="Export CSV">
<i class="fa fa-file-excel-o"></i>
</button>
<button type="button"
class="btn btn-sm btn-icon btn-danger btn-export-pdf" title="Cetak">
<i class="fa fa-file-pdf-o"></i>
</button>
</div>
</div>
</div>
</form>
<hr class="my-3">
<div class="row g-2 mb-3" id="rekap-parkir">
<div class="col-md-3"><div class="border rounded p-2 h-100"><small class="text-muted">Total (filter aktif)</small><div class="fw-bold" id="sum-total">-</div><small class="text-muted" id="sum-total-rp"></small></div></div>
<div class="col-md-3"><div class="border rounded p-2 h-100"><small class="text-muted">Keluar (status 0)</small><div class="fw-bold" id="sum-keluar">-</div><small class="text-muted" id="sum-keluar-rp"></small></div></div>
<div class="col-md-3"><div class="border rounded p-2 h-100"><small class="text-muted">Tunai</small><div class="fw-bold text-success" id="sum-tunai">-</div><small class="text-muted" id="sum-tunai-rp"></small></div></div>
<div class="col-md-3"><div class="border rounded p-2 h-100"><small class="text-muted">Cashless</small><div class="fw-bold text-info" id="sum-cashless">-</div><small class="text-muted" id="sum-cashless-rp"></small></div></div>
<div class="col-md-2"><div class="border rounded p-2 h-100"><small class="text-muted">Casual</small><div class="fw-bold" id="sum-casual">-</div><small class="text-muted" id="sum-casual-rp"></small></div></div>
<div class="col-md-2"><div class="border rounded p-2 h-100"><small class="text-muted">Member</small><div class="fw-bold" id="sum-member">-</div><small class="text-muted" id="sum-member-rp"></small></div></div>
<div class="col-md-2"><div class="border rounded p-2 h-100"><small class="text-muted">Denda</small><div class="fw-bold" id="sum-denda">-</div><small class="text-muted" id="sum-denda-rp"></small></div></div>
<div class="col-md-3"><div class="border rounded p-2 h-100"><small class="text-muted">Manual</small><div class="fw-bold" id="sum-manual">-</div><small class="text-muted" id="sum-manual-rp"></small></div></div>
<div class="col-md-3"><div class="border rounded p-2 h-100"><small class="text-muted">Masalah (-1)</small><div class="fw-bold text-warning" id="sum-masalah">-</div><small class="text-muted" id="sum-masalah-rp"></small></div></div>
</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<h5 class="card-title mb-0">Hasil Transaksi</h5>
<small class="text-muted" id="info-paging"></small>
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped" id="tabel-parkir">
<thead>
<tr>
<th width="4%">No.</th>
<th data-sort="id">ID <span class="sort-ind"></span></th>
<th data-sort="no_pol">No. Pol <span class="sort-ind"></span></th>
<th data-sort="no_barcode">Barcode <span class="sort-ind"></span></th>
<th data-sort="nama_kendaraan">Kendaraan <span class="sort-ind"></span></th>
<th data-sort="waktu_masuk">Waktu Masuk <span class="sort-ind"></span></th>
<th data-sort="waktu_keluar">Waktu Keluar <span class="sort-ind"></span></th>
<th data-sort="id_op_masuk">Op Masuk <span class="sort-ind"></span></th>
<th data-sort="id_op_keluar">Op Keluar <span class="sort-ind"></span></th>
<th data-sort="id_pintu_masuk">Pintu Masuk <span class="sort-ind"></span></th>
<th data-sort="id_pintu_keluar">Pintu Keluar <span class="sort-ind"></span></th>
<th data-sort="bayar_keluar">Bayar Keluar <span class="sort-ind"></span></th>
<th data-sort="status">Status Kendaraan <span class="sort-ind"></span></th>
<th data-sort="status_transaksi">Status Transaksi <span class="sort-ind"></span></th>
</tr>
</thead>
<tbody id="body-parkir">
<tr><td colspan="14" class="text-center">Memuat data...</td></tr>
</tbody>
</table>
</div>
<div class="d-flex justify-content-between align-items-center mt-3">
<button class="btn btn-sm btn-outline-primary" id="btn-prev" type="button">&laquo; Sebelumnya</button>
<span class="text-muted" id="label-halaman"></span>
<button class="btn btn-sm btn-outline-primary" id="btn-next" type="button">Berikutnya &raquo;</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('javascript')
<script src="{{ asset('vendors/select2/select2.min.js') }}"></script>
<script src="{{ asset('js/select2.js') }}"></script>
<script>
$(function () {
const dataUrl = '{{ route('transaksiparkir.data', [], false) }}';
let page = 1;
let sortBy = 'tanggal';
let sortDir = 'desc';
const labelKendaraan = {1: 'Masuk', 0: 'Keluar'};
const labelTransaksi = {0: 'Casual', 3: 'Member', 32: 'Denda'};
function badge(text, color) {
return '<span class="badge bg-' + color + '">' + text + '</span>';
}
function statusKendaraan(v) {
if (v == 1) return badge('Masuk', 'success');
if (v == 0) return badge('Keluar', 'secondary');
return badge(v ?? '-', 'light text-dark');
}
function statusTransaksi(v) {
const t = labelTransaksi[v] !== undefined ? labelTransaksi[v] : (v ?? '-');
const c = v == 0 ? 'primary' : (v == 3 ? 'info' : (v == 32 ? 'warning' : 'light text-dark'));
return badge(t, c);
}
function esc(v) {
return (v === null || v === undefined) ? '' : String(v)
.replace(/&/g, '&amp;').replace(/</g, '&lt;')
.replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
function params(extra) {
const p = {
q: $('#q').val().trim(),
field: $('#field').val(),
tgl_awal: $('#tgl_awal').val(),
tgl_akhir: $('#tgl_akhir').val(),
status_kendaraan: $('#status_kendaraan').val(),
status_transaksi: $('#status_transaksi').val(),
sort_by: sortBy,
sort_dir: sortDir,
page: page
};
return $.param(Object.assign(p, extra || {}));
}
function paintSort() {
$('#tabel-parkir th[data-sort] .sort-ind').text('');
const th = $('#tabel-parkir th[data-sort="' + sortBy + '"] .sort-ind');
if (th.length) th.text(sortDir === 'asc' ? '▲' : '▼');
}
$('#tabel-parkir').on('click', 'th[data-sort]', function () {
const col = $(this).data('sort');
if (sortBy === col) {
sortDir = sortDir === 'asc' ? 'desc' : 'asc';
} else {
sortBy = col;
sortDir = 'asc';
}
page = 1;
paintSort();
load();
});
function fmtRp(v) {
if (v === null || v === undefined || v === '') return '';
return 'Rp ' + Number(v).toLocaleString('id-ID');
}
function paintSummary(s) {
if (!s) return;
const segs = ['total', 'keluar', 'tunai', 'cashless', 'casual', 'member', 'denda', 'manual', 'masalah'];
segs.forEach(function (k) {
$('#sum-' + k).text((Number(s[k + '_rows']) || 0).toLocaleString('id-ID') + ' trx');
$('#sum-' + k + '-rp').text(fmtRp(s[k + '_bayar']));
});
}
function load() {
$('#body-parkir').html('<tr><td colspan="14" class="text-center text-muted py-4"><span class="spinner-border spinner-border-sm me-2"></span>Memuat data...</td></tr>');
$('#btn-cari').prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Mencari...');
$('#btn-prev, #btn-next').prop('disabled', true);
$.ajax({
url: dataUrl + '?' + params(),
type: 'GET',
success: function (r) {
paintSummary(r.summary);
if (!r.data.length) {
$('#body-parkir').html('<tr><td colspan="14" class="text-center">Data tidak ditemukan.</td></tr>');
} else {
let html = '';
const offset = (r.meta.current_page - 1) * r.meta.per_page;
r.data.forEach(function (row, i) {
const bayar = row.bayar_keluar === null || row.bayar_keluar === undefined || row.bayar_keluar === '' ? '' : Number(row.bayar_keluar).toLocaleString('id-ID');
html += '<tr>'
+ '<td class="text-center">' + (offset + i + 1) + '</td>'
+ '<td>' + esc(row.id) + '</td>'
+ '<td>' + esc(row.no_pol) + '</td>'
+ '<td>' + esc(row.no_barcode) + '</td>'
+ '<td>' + esc([row.id_kendaraan, row.nama_kendaraan].filter(Boolean).join(' - ')) + '</td>'
+ '<td>' + esc(row.waktu_masuk) + '</td>'
+ '<td>' + esc(row.waktu_keluar) + '</td>'
+ '<td>' + esc(row.id_op_masuk) + '</td>'
+ '<td>' + esc(row.id_op_keluar) + '</td>'
+ '<td>' + esc(row.id_pintu_masuk) + '</td>'
+ '<td>' + esc(row.id_pintu_keluar) + '</td>'
+ '<td class="text-end">' + bayar + '</td>'
+ '<td class="text-center">' + statusKendaraan(row.status) + '</td>'
+ '<td class="text-center">' + statusTransaksi(row.status_transaksi) + '</td>'
+ '</tr>';
});
$('#body-parkir').html(html);
}
$('#info-paging').text('Total ' + r.meta.total + ' data');
$('#label-halaman').text('Halaman ' + r.meta.current_page + ' / ' + Math.max(r.meta.last_page, 1));
$('#btn-prev').prop('disabled', r.meta.current_page <= 1);
$('#btn-next').prop('disabled', r.meta.current_page >= r.meta.last_page);
page = r.meta.current_page;
},
error: function (xhr) {
let msg = 'Gagal memuat data.';
if (xhr.status === 422 && xhr.responseJSON?.errors) {
msg = Object.values(xhr.responseJSON.errors).flat().join(' ');
}
$('#body-parkir').html('<tr><td colspan="14" class="text-center text-danger">' + esc(msg) + '</td></tr>');
Swal.fire({icon: 'error', title: 'Gagal memuat data', text: msg});
},
complete: function () {
$('#btn-cari').prop('disabled', false).html('<i class="fa fa-search me-1"></i>Cari');
}
});
}
$('#filter-parkir').on('submit', function () { page = 1; load(); });
$('#btn-reset').on('click', function () {
$('#filter-parkir')[0].reset();
$('#field, #status_kendaraan, #status_transaksi').val('').trigger('change');
$('#field').val('id').trigger('change');
page = 1; load();
});
$('#btn-prev').on('click', function () { if (page > 1) { page--; load(); } });
$('#btn-next').on('click', function () { page++; load(); });
$('.btn-export-excel').on('click', function () {
window.location = dataUrl + '?' + params({export: 'csv'});
});
$('.btn-export-pdf').on('click', function () { window.print(); });
paintSort();
load();
});
</script>
@endsection