MIF_E31230892/sim-pkpps/resources/views/admin/uang-saku/index.blade.php

386 lines
20 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('layouts.app')
@section('content')
<div class="page-header">
<h2><i class="fas fa-wallet"></i> Manajemen Uang Saku Santri</h2>
</div>
@if(session('success'))
<div class="alert alert-success"><i class="fas fa-check-circle"></i> {{ session('success') }}</div>
@endif
@if(session('error'))
<div class="alert alert-danger"><i class="fas fa-exclamation-circle"></i> {{ session('error') }}</div>
@endif
<style>
/* ── Row utama santri ── */
.us-row-header { transition: background .15s; }
.us-row-header:hover { background: var(--primary-light, #f0fdf7); }
/* ── Divider vertikal ── */
.vdiv {
width: 1px;
height: 48px;
background: #e2e8f0;
flex-shrink: 0;
align-self: center;
}
</style>
{{-- ── FILTER + KPI ── --}}
<div class="content-box" style="margin-bottom:16px;">
<form method="GET" action="{{ route('admin.uang-saku.index') }}" id="filterForm"
style="display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;margin-bottom:18px;">
@if(request('search')) <input type="hidden" name="search" value="{{ request('search') }}"> @endif
@if(request('sort')) <input type="hidden" name="sort" value="{{ request('sort') }}"> @endif
<div>
<label style="font-size:.78rem;color:var(--text-light);display:block;margin-bottom:3px;">Dari Tanggal</label>
<input type="date" name="dari" class="form-control" value="{{ $dari }}" style="width:155px;">
</div>
<div>
<label style="font-size:.78rem;color:var(--text-light);display:block;margin-bottom:3px;">Sampai Tanggal</label>
<input type="date" name="sampai" class="form-control" value="{{ $sampai }}" style="width:155px;">
</div>
<div style="display:flex;gap:5px;flex-wrap:wrap;align-self:flex-end;">
@php
$bulanIniDari = now()->startOfMonth()->format('Y-m-d');
$bulanIniSampai = now()->endOfMonth()->format('Y-m-d');
$isBulanIni = $dari === $bulanIniDari && $sampai === $bulanIniSampai;
$isHariIni = $dari === now()->format('Y-m-d') && $sampai === now()->format('Y-m-d');
@endphp
<button type="button" onclick="setPreset('today')"
class="btn btn-sm {{ $isHariIni ? 'btn-primary' : 'btn-secondary' }}">Hari Ini</button>
<button type="button" onclick="setPreset('month')"
class="btn btn-sm {{ $isBulanIni ? 'btn-primary' : 'btn-secondary' }}">Bulan Ini</button>
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-filter"></i> Terapkan
</button>
</div>
</form>
{{-- KPI Baris 1 --}}
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom:10px;">
<div class="card card-info" style="margin: 0;">
<h3>Total Transaksi</h3>
<p class="card-value">{{ $kpi['total_transaksi'] }} Transaksi</p>
<span class="card-sub">dari {{ $kpi['total_santri'] }} santri</span>
<i class="fas fa-exchange-alt card-icon"></i>
</div>
<div class="card card-success" style="margin: 0;">
<h3>Total Setoran (Masuk)</h3>
<p class="card-value" style="font-size:1.05rem;">Rp {{ number_format($kpi['total_pemasukan'], 0, ',', '.') }}</p>
<span class="card-sub">
{{ \Carbon\Carbon::parse($dari)->format('d M') }} &ndash; {{ \Carbon\Carbon::parse($sampai)->format('d M Y') }}
</span>
<i class="fas fa-arrow-circle-down card-icon"></i>
</div>
<div class="card card-warning" style="margin: 0;">
<h3>Total Penarikan (Keluar)</h3>
<p class="card-value" style="font-size:1.05rem;">Rp {{ number_format($kpi['total_pengeluaran'], 0, ',', '.') }}</p>
<span class="card-sub">
{{ \Carbon\Carbon::parse($dari)->format('d M') }} &ndash; {{ \Carbon\Carbon::parse($sampai)->format('d M Y') }}
</span>
<i class="fas fa-arrow-circle-up card-icon"></i>
</div>
</div>
{{-- KPI Baris 2: saldo real-time --}}
<div class="row-cards row-cards-1">
<div class="card card-primary" style="border-left:4px solid var(--primary-color);">
<div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:space-between;">
<div>
<h3 style="margin:0 0 4px;">Total Saldo Seluruh Santri</h3>
<p class="card-value" style="font-size:1.4rem;margin:0;color:var(--primary-color);">
Rp {{ number_format($kpi['total_saldo_realtime'], 0, ',', '.') }}
</p>
</div>
<span class="badge badge-info" style="font-size:.8rem;padding:5px 10px;">
<i class="fas fa-clock"></i> Akumulasi semua waktu tidak terpengaruh filter
</span>
</div>
<i class="fas fa-piggy-bank card-icon"></i>
</div>
</div>
</div>
{{-- ── DAFTAR SANTRI ── --}}
<div class="content-box">
{{-- Toolbar --}}
<div style="display:flex;justify-content:space-between;align-items:center;
margin-bottom:14px;flex-wrap:wrap;gap:10px;">
{{-- Tombol Tambah hanya untuk pamong --}}
@if($canCrud)
<a href="{{ route('admin.uang-saku.create') }}" class="btn btn-primary">
<i class="fas fa-plus"></i> Tambah Transaksi
</a>
@else
<div></div>{{-- spacer agar sort tetap rata kanan --}}
@endif
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
{{-- Sort --}}
<form method="GET" action="{{ route('admin.uang-saku.index') }}"
style="display:flex;gap:6px;align-items:center;">
<input type="hidden" name="dari" value="{{ $dari }}">
<input type="hidden" name="sampai" value="{{ $sampai }}">
@if(request('search')) <input type="hidden" name="search" value="{{ request('search') }}"> @endif
<label style="font-size:.79rem;color:var(--text-light);white-space:nowrap;">
<i class="fas fa-sort"></i> Urut:
</label>
<select name="sort" class="form-control form-control-sm"
onchange="this.form.submit()" style="width:auto;">
<option value="nama" {{ $sort==='nama' ? 'selected':'' }}>Nama</option>
<option value="saldo_asc" {{ $sort==='saldo_asc' ? 'selected':'' }}>Saldo Terendah</option>
<option value="saldo_desc" {{ $sort==='saldo_desc' ? 'selected':'' }}>Saldo Tertinggi</option>
<option value="transaksi_desc" {{ $sort==='transaksi_desc'? 'selected':'' }}>Transaksi Terbanyak</option>
<option value="terakhir" {{ $sort==='terakhir' ? 'selected':'' }}>Transaksi Terbaru</option>
</select>
</form>
{{-- Search --}}
<form method="GET" action="{{ route('admin.uang-saku.index') }}"
style="display:flex;gap:6px;">
<input type="hidden" name="dari" value="{{ $dari }}">
<input type="hidden" name="sampai" value="{{ $sampai }}">
<input type="hidden" name="sort" value="{{ $sort }}">
<input type="text" name="search" class="form-control form-control-sm"
placeholder="Cari nama / ID santri..."
value="{{ request('search') }}" style="width:210px;">
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-search"></i>
</button>
@if(request('search'))
<a href="{{ route('admin.uang-saku.index', ['dari'=>$dari,'sampai'=>$sampai,'sort'=>$sort]) }}"
class="btn btn-secondary btn-sm"><i class="fas fa-times"></i></a>
@endif
</form>
</div>
</div>
{{-- Legend warna saldo --}}
<div style="display:flex;gap:14px;margin-bottom:12px;flex-wrap:wrap;
font-size:.78rem;color:var(--text-light);">
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;
background:#6FBA9D;margin-right:4px;"></span>Saldo Rp 100.000</span>
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;
background:#f5a623;margin-right:4px;"></span>Rp 20.000 99.999</span>
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;
background:#FF8B94;margin-right:4px;"></span>&lt; Rp 20.000</span>
</div>
{{-- ── LIST SANTRI ── --}}
@if($santriList->count() > 0)
@foreach($santriList as $santri)
@php
$sc = $santri->saldo_terakhir >= 100000 ? '#6FBA9D'
: ($santri->saldo_terakhir >= 20000 ? '#f5a623' : '#FF8B94');
@endphp
<div class="content-box us-row"
style="margin-bottom:10px;padding:0;overflow:hidden;">
{{-- ── Baris utama ── --}}
<div class="us-row-header"
onclick="toggleDetail('detail-{{ $santri->id_santri }}', this)"
style="display:flex;align-items:center;cursor:pointer;
padding:12px 16px;flex-wrap:wrap;gap:10px;">
{{-- Chevron + Nama --}}
<div style="display:flex;align-items:center;gap:10px;flex:1;min-width:160px;">
<i class="fas fa-chevron-right toggle-arrow"
style="transition:transform .2s;color:var(--text-light);
font-size:.8rem;flex-shrink:0;"></i>
<div>
<div style="font-weight:700;font-size:.93rem;">
{{ $santri->nama_lengkap }}
</div>
<div style="font-size:.74rem;color:var(--text-light);">
{{ $santri->id_santri }}
</div>
</div>
</div>
{{-- Saldo saat ini (kumulatif) --}}
<div style="display:flex;flex-direction:column;align-items:center;min-width:130px;">
<div style="font-size:.62rem;color:var(--text-light);margin-bottom:2px;
font-weight:600;text-transform:uppercase;letter-spacing:.4px;">
Saldo Saat Ini
</div>
<div style="font-size:1.05rem;font-weight:800;color:{{ $sc }};
display:flex;align-items:center;gap:5px;">
<span style="width:8px;height:8px;border-radius:50%;
background:{{ $sc }};flex-shrink:0;display:inline-block;"></span>
Rp {{ number_format($santri->saldo_terakhir, 0, ',', '.') }}
</div>
<div style="font-size:.6rem;color:#ccc;margin-top:2px;">akumulasi semua waktu</div>
</div>
<div class="vdiv"></div>
{{-- Jumlah transaksi + tanggal terakhir --}}
<div style="display:flex;flex-direction:column;align-items:center;min-width:90px;">
<div style="font-size:.62rem;color:var(--text-light);margin-bottom:2px;
font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Transaksi</div>
<span class="badge badge-info" style="font-size:.74rem;">
{{ $santri->transaksi_periode }}x di periode
</span>
@if($santri->transaksi_terakhir_tgl)
<div style="font-size:.66rem;color:var(--text-light);margin-top:3px;">
terakhir {{ \Carbon\Carbon::parse($santri->transaksi_terakhir_tgl)->format('d/m/Y') }}
</div>
@endif
</div>
{{-- Aksi --}}
<div style="display:flex;gap:5px;flex-shrink:0;" onclick="event.stopPropagation()">
{{-- Tombol tambah transaksi: hanya pamong --}}
@if($canCrud)
<a href="{{ route('admin.uang-saku.create') }}?id_santri={{ $santri->id_santri }}"
class="btn btn-success btn-sm" title="Tambah Transaksi">
<i class="fas fa-plus"></i>
</a>
@endif
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}"
class="btn btn-primary btn-sm" title="Riwayat Lengkap">
<i class="fas fa-history"></i>
</a>
</div>
</div>
{{-- ── Detail transaksi (collapsed) ── --}}
<div id="detail-{{ $santri->id_santri }}"
style="display:none;border-top:1px solid var(--primary-light);padding:12px 16px;">
@if($santri->transaksi_terbaru->isNotEmpty())
<div class="table-wrapper">
<table class="data-table">
<thead>
<tr>
<th>Tanggal</th>
<th>Jenis</th>
<th>Nominal</th>
<th>Keterangan</th>
<th>Saldo Sesudah</th>
<th class="text-center">Aksi</th>
</tr>
</thead>
<tbody>
@foreach($santri->transaksi_terbaru as $tx)
<tr>
<td>{{ $tx->tanggal_transaksi->format('d/m/Y') }}</td>
<td>
@if($tx->jenis_transaksi === 'pemasukan')
<span class="badge badge-success">
<i class="fas fa-arrow-down"></i> Masuk
</span>
@else
<span class="badge badge-danger">
<i class="fas fa-arrow-up"></i> Keluar
</span>
@endif
</td>
<td class="nominal-highlight">Rp {{ number_format($tx->nominal, 0, ',', '.') }}</td>
<td><div class="content-preview">{{ $tx->keterangan ?? '-' }}</div></td>
<td style="font-weight:600;
color:{{ $tx->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94' }};">
Rp {{ number_format($tx->saldo_sesudah, 0, ',', '.') }}
</td>
<td class="text-center">
<div style="display:flex;gap:4px;justify-content:center;">
<a href="{{ route('admin.uang-saku.show', $tx->id) }}"
class="btn btn-primary btn-sm"><i class="fas fa-eye"></i></a>
{{-- Edit & Hapus: hanya pamong --}}
@if($canCrud)
<a href="{{ route('admin.uang-saku.edit', $tx->id) }}"
class="btn btn-warning btn-sm"><i class="fas fa-edit"></i></a>
<form action="{{ route('admin.uang-saku.destroy', $tx->id) }}"
method="POST" style="display:inline;"
onsubmit="return confirm('Yakin hapus transaksi ini?')">
@csrf @method('DELETE')
<button class="btn btn-danger btn-sm">
<i class="fas fa-trash"></i>
</button>
</form>
@endif
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@if($santri->transaksi_terbaru->count() >= 5)
<div style="text-align:center;margin-top:10px;">
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}"
class="btn btn-secondary btn-sm">
<i class="fas fa-arrow-right"></i> Lihat Semua Riwayat
</a>
</div>
@endif
@else
<p class="text-muted" style="margin:0;font-size:.85rem;">
<i class="fas fa-info-circle"></i>
Tidak ada transaksi pada periode ini.
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}">
Lihat semua riwayat
</a>
</p>
@endif
</div>
</div>
@endforeach
<div style="margin-top:14px;">{{ $santriList->links() }}</div>
@else
<div class="empty-state">
<i class="fas fa-wallet"></i>
<h3>Belum Ada Data</h3>
<p>Belum ada santri dengan transaksi uang saku.</p>
@if($canCrud)
<a href="{{ route('admin.uang-saku.create') }}" class="btn btn-success">
<i class="fas fa-plus"></i> Tambah Transaksi
</a>
@endif
</div>
@endif
</div>
<script>
// ═══════════════════════════════════════════════════════════════════
// TOGGLE DETAIL ROW
// ═══════════════════════════════════════════════════════════════════
function toggleDetail(id, el) {
var detail = document.getElementById(id);
var arrow = el.querySelector('.toggle-arrow');
var open = detail.style.display !== 'none';
detail.style.display = open ? 'none' : 'block';
arrow.style.transform = open ? 'rotate(0deg)' : 'rotate(90deg)';
}
// ═══════════════════════════════════════════════════════════════════
// PRESET FILTER TANGGAL
// ═══════════════════════════════════════════════════════════════════
function setPreset(type) {
var form = document.getElementById('filterForm');
var dari = form.querySelector('[name=dari]');
var sampai = form.querySelector('[name=sampai]');
var today = new Date();
var pad = function (n) { return String(n).padStart(2, '0'); };
var ymd = function (d) {
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
};
if (type === 'today') {
dari.value = sampai.value = ymd(today);
} else {
dari.value = ymd(new Date(today.getFullYear(), today.getMonth(), 1));
sampai.value = ymd(new Date(today.getFullYear(), today.getMonth() + 1, 0));
}
form.submit();
}
</script>
@endsection