Ubah/extend in-place data lama + search semua-field + statistik hari-minggu-bulan
This commit is contained in:
@@ -64,6 +64,7 @@
|
||||
<li class="nav-item"><a class="nav-link" href="/report/laporan-per-pintu">Teransaksi Per Pintu</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/report/laporan-semua-transaksi">Transaksi Harian</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/report/stiker/harian">Member Harian</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/report/statistik">Statistik Transaksi</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
@extends('layouts.master')
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
#tabel-statistik th[data-info] { cursor: default; }
|
||||
.stat-card { border-radius: 10px; }
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<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-body">
|
||||
<h4 class="card-title">Statistik Transaksi</h4>
|
||||
<small class="text-muted d-block mb-3">Periode berdasarkan tanggal masuk. Pecah per hari / minggu / bulan.</small>
|
||||
<form id="filter-statistik" action="javascript:void(0)">
|
||||
<div class="row align-items-end g-2">
|
||||
<div class="col-md-2">
|
||||
<label class="form-label" for="grup">Pecah Per</label>
|
||||
<select class="form-select form-select-sm" id="grup">
|
||||
<option value="hari" selected>Hari</option>
|
||||
<option value="minggu">Minggu</option>
|
||||
<option value="bulan">Bulan</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label" for="tgl-awal">Periode Awal</label>
|
||||
<input type="date" class="form-control form-control-sm" id="tgl-awal">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label" for="tgl-akhir">Periode Akhir</label>
|
||||
<input type="date" class="form-control form-control-sm" id="tgl-akhir">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label" for="status-transaksi">Status Transaksi</label>
|
||||
<select class="form-select form-select-sm" id="status-transaksi">
|
||||
<option value="" selected>Semua</option>
|
||||
<option value="0">Casual</option>
|
||||
<option value="3">Member</option>
|
||||
<option value="32">Denda</option>
|
||||
<option value="-1">Masalah</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label" for="cara">Pembayaran</label>
|
||||
<select class="form-select form-select-sm" id="cara">
|
||||
<option value="" selected>Semua</option>
|
||||
<option value="tunai">Tunai</option>
|
||||
<option value="cashless">Cashless</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2 d-flex gap-2">
|
||||
<button type="submit" class="btn btn-sm btn-primary" id="btn-proses">Proses</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr class="my-3">
|
||||
<div class="row g-2 mb-3" id="ringkasan">
|
||||
<div class="col-md-2"><div class="border rounded p-2 h-100 stat-card"><small class="text-muted">Transaksi</small><div class="fw-bold" id="sum-trx">-</div></div></div>
|
||||
<div class="col-md-2"><div class="border rounded p-2 h-100 stat-card"><small class="text-muted">Keluar</small><div class="fw-bold" id="sum-keluar">-</div></div></div>
|
||||
<div class="col-md-2"><div class="border rounded p-2 h-100 stat-card"><small class="text-muted">Pendapatan</small><div class="fw-bold text-success" id="sum-pendapatan">-</div></div></div>
|
||||
<div class="col-md-3"><div class="border rounded p-2 h-100 stat-card"><small class="text-muted">Tunai</small><div class="fw-bold" id="sum-tunai">-</div></div></div>
|
||||
<div class="col-md-3"><div class="border rounded p-2 h-100 stat-card"><small class="text-muted">Cashless</small><div class="fw-bold text-info" id="sum-cashless">-</div></div></div>
|
||||
</div>
|
||||
<div class="mb-3" style="max-height: 320px;"><canvas id="chart-statistik" height="120"></canvas></div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-striped" id="tabel-statistik">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Periode</th>
|
||||
<th class="text-end">Transaksi</th>
|
||||
<th class="text-end">Keluar</th>
|
||||
<th class="text-end">Pendapatan</th>
|
||||
<th class="text-end">Tunai</th>
|
||||
<th class="text-end">Cashless</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="body-statistik">
|
||||
<tr><td colspan="6" class="text-center text-muted">Pilih filter lalu klik Proses.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('javascript')
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
|
||||
<script src="{{ asset('vendor/sweetalert2/dist/sweetalert2.min.js') }}"></script>
|
||||
<script src="{{ asset('vendors/chart.js/Chart.min.js') }}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
const dataUrl = '{{ route('statistik.data', [], false) }}';
|
||||
let chart = null;
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const awal = new Date(Date.now() - 29 * 864e5).toISOString().split('T')[0];
|
||||
$('#tgl-akhir').val(today);
|
||||
$('#tgl-awal').val(awal);
|
||||
|
||||
function fmtRp(v) {
|
||||
return 'Rp ' + Number(v || 0).toLocaleString('id-ID');
|
||||
}
|
||||
function fmtN(v) {
|
||||
return Number(v || 0).toLocaleString('id-ID');
|
||||
}
|
||||
function labelPeriode(p, grup) {
|
||||
if (grup === 'bulan') {
|
||||
const d = new Date(p + 'T00:00:00');
|
||||
return d.toLocaleDateString('id-ID', { month: 'short', year: 'numeric' });
|
||||
}
|
||||
if (grup === 'minggu') return 'Minggu ' + p;
|
||||
const d = new Date(p + 'T00:00:00');
|
||||
return d.toLocaleDateString('id-ID', { day: '2-digit', month: 'short' });
|
||||
}
|
||||
|
||||
function drawChart(rows, grup) {
|
||||
const ctx = document.getElementById('chart-statistik');
|
||||
if (chart) chart.destroy();
|
||||
chart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: rows.map(r => labelPeriode(r.periode, grup)),
|
||||
datasets: [
|
||||
{ label: 'Tunai', data: rows.map(r => Number(r.tunai)), backgroundColor: '#198754' },
|
||||
{ label: 'Cashless', data: rows.map(r => Number(r.cashless)), backgroundColor: '#0dcaf0' },
|
||||
],
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: { y: { beginAtZero: true, ticks: { callback: v => (v / 1000) + 'rb' } } },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$('#filter-statistik').on('submit', function () {
|
||||
const btn = $('#btn-proses'); const btnHtml = btn.html();
|
||||
btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Memproses...');
|
||||
$('#body-statistik').html('<tr><td colspan="6" class="text-center text-muted py-4"><span class="spinner-border spinner-border-sm me-2"></span>Memuat statistik...</td></tr>');
|
||||
const grup = $('#grup').val();
|
||||
$.ajax({
|
||||
url: dataUrl,
|
||||
type: 'GET',
|
||||
data: {
|
||||
grup: grup,
|
||||
tgl_awal: $('#tgl-awal').val(),
|
||||
tgl_akhir: $('#tgl-akhir').val(),
|
||||
status_transaksi: $('#status-transaksi').val(),
|
||||
cara: $('#cara').val(),
|
||||
},
|
||||
success: function (r) {
|
||||
const s = r.ringkasan || {};
|
||||
$('#sum-trx').text(fmtN(s.transaksi) + ' trx');
|
||||
$('#sum-keluar').text(fmtN(s.keluar) + ' trx');
|
||||
$('#sum-pendapatan').text(fmtRp(s.pendapatan));
|
||||
$('#sum-tunai').text(fmtRp(s.tunai));
|
||||
$('#sum-cashless').text(fmtRp(s.cashless));
|
||||
if (!r.data.length) {
|
||||
$('#body-statistik').html('<tr><td colspan="6" class="text-center">Data tidak ditemukan.</td></tr>');
|
||||
if (chart) chart.destroy();
|
||||
return;
|
||||
}
|
||||
let html = '';
|
||||
r.data.forEach(function (row) {
|
||||
html += '<tr><td>' + labelPeriode(row.periode, grup) + '</td>'
|
||||
+ '<td class="text-end">' + fmtN(row.transaksi) + '</td>'
|
||||
+ '<td class="text-end">' + fmtN(row.keluar) + '</td>'
|
||||
+ '<td class="text-end">' + fmtRp(row.pendapatan) + '</td>'
|
||||
+ '<td class="text-end">' + fmtRp(row.tunai) + '</td>'
|
||||
+ '<td class="text-end">' + fmtRp(row.cashless) + '</td></tr>';
|
||||
});
|
||||
$('#body-statistik').html(html);
|
||||
drawChart(r.data, grup);
|
||||
},
|
||||
error: function (xhr) {
|
||||
let msg = 'Gagal memuat statistik.';
|
||||
if (xhr.responseJSON?.message) msg = xhr.responseJSON.message;
|
||||
else if (xhr.status === 422 && xhr.responseJSON?.errors) msg = Object.values(xhr.responseJSON.errors).flat().join(' ');
|
||||
$('#body-statistik').html('<tr><td colspan="6" class="text-center text-danger">' + msg + '</td></tr>');
|
||||
Swal.fire({icon: 'error', title: 'Gagal memuat', text: msg});
|
||||
},
|
||||
complete: function () {
|
||||
btn.prop('disabled', false).html(btnHtml);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$('#filter-statistik').submit();
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@@ -22,6 +22,7 @@
|
||||
<form class="ubah-member" id="edit-member" methode="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<input type="hidden" name="notrans" id="edit-notrans">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="edit-data" role="tabpanel">
|
||||
<div class="pt-4">
|
||||
@@ -63,7 +64,7 @@
|
||||
<div class="mb-3 row">
|
||||
<label class="col-lg-3 col-form-label form-label">Jenis</label>
|
||||
<div class="col-lg-6">
|
||||
<select class="select-data form-control" name="member" id="member">
|
||||
<select class="select-data form-control" name="member" id="edit-member-sel">
|
||||
<option selected value="">Pilih Jenis</option>
|
||||
@foreach ($memberSelect as $member)
|
||||
<option value="{{ $member->id }}">{{ $member->nama }}</option>
|
||||
@@ -74,7 +75,7 @@
|
||||
<div class="mb-3 row">
|
||||
<label class="col-lg-3 col-form-label form-label">Dept</label>
|
||||
<div class="col-lg-6">
|
||||
<select class="select-data form-control" name="depart" id="department">
|
||||
<select class="select-data form-control" name="depart" id="edit-department">
|
||||
<option selected value="">Pilih Departemen</option>
|
||||
@foreach ($departmentSelect as $department)
|
||||
<option value="{{ $department->kode }}">{{ $department->nama }}</option>
|
||||
@@ -104,12 +105,12 @@
|
||||
<div class="row form-material">
|
||||
<div class="col-xl-3 col-md-6 mb-3">
|
||||
<label class="form-label">Nomer Polisi</label>
|
||||
<input type="text" class="form-control nopol-add" onkeyup="this.value = this.value.toUpperCase();" placeholder="No. Polisi">
|
||||
<input type="text" class="form-control enopol-add" onkeyup="this.value = this.value.toUpperCase();" placeholder="No. Polisi">
|
||||
<div class="invalid-feedback">Nomer Polisi sudah ada</div>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 mb-3">
|
||||
<label class="form-label">Jenis Kendaraan :</label>
|
||||
<select class="select form-control" id="jenisVehicle">
|
||||
<select class="select form-control" id="edit-jenisVehicle">
|
||||
<option selected value="">Jenis Kendaraan</option>
|
||||
@foreach ($vehicleSelect as $kendaraan)
|
||||
<option value="{{ $kendaraan->id }}">{{ $kendaraan->nama }}</option>
|
||||
@@ -118,16 +119,16 @@
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 mb-3">
|
||||
<label class="form-label">Jenis Member :</label>
|
||||
<select class="select-data form-control member" id="jenis-member">
|
||||
<select class="select-data form-control member" id="edit-jenis-member">
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 mb-3">
|
||||
<label class="form-label">Merk : </label>
|
||||
<input type="text" class="form-control merk" onkeyup="this.value = this.value.toUpperCase();" placeholder="Honda...">
|
||||
<input type="text" class="form-control emerk" onkeyup="this.value = this.value.toUpperCase();" placeholder="Honda...">
|
||||
</div>
|
||||
<div class="col-xl-3 col-md-6 mb-3">
|
||||
<label class="form-label"></label>
|
||||
<button type="button" id="nopol-add" class="btn btn-primary btn-xs">Tambah</button>
|
||||
<button type="button" id="edit-nopol-add" class="btn btn-primary btn-xs">Tambah</button>
|
||||
</div>
|
||||
<hr>
|
||||
<table class="table-bordered table-striped">
|
||||
@@ -140,7 +141,7 @@
|
||||
<th class="col-2 text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="list-nopol">
|
||||
<tbody id="edit-list-nopol">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -152,11 +153,11 @@
|
||||
<div class="row form-material">
|
||||
<div class="col-xl-6 col-md-6 mb-3">
|
||||
<label class="form-label">Nomer Kartu</label>
|
||||
<input type="text" class="form-control kartu" placeholder="01234567...">
|
||||
<input type="text" class="form-control ekartu" placeholder="01234567...">
|
||||
</div>
|
||||
<div class="col-xl-6 col-md-6 mb-3">
|
||||
<label class="form-label">Nomer Urut</label>
|
||||
<input type="text" class="form-control nourut" placeholder="01234567...">
|
||||
<input type="text" class="form-control enourut" placeholder="01234567...">
|
||||
</div>
|
||||
<hr>
|
||||
{{-- <div class="table-responsive"> --}}
|
||||
@@ -168,7 +169,7 @@
|
||||
<th class="col-2 text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="list-card">
|
||||
<tbody id="edit-list-card">
|
||||
</tbody>
|
||||
</table>
|
||||
{{-- </div> --}}
|
||||
@@ -181,7 +182,7 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger light" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary simpan">Simpan Perubahan</button>
|
||||
<button type="button" class="btn btn-primary simpan-ubah">Simpan Perubahan</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user