upload project TA SIM Santri
This commit is contained in:
parent
1332db7373
commit
ff81f4cbf6
|
|
@ -12,6 +12,21 @@
|
||||||
|
|
||||||
class UangSakuController extends Controller
|
class UangSakuController extends Controller
|
||||||
{
|
{
|
||||||
|
// ────────────────────────────────────────────────────────────────
|
||||||
|
// PRIVATE: cek apakah user aktif adalah pamong
|
||||||
|
// ────────────────────────────────────────────────────────────────
|
||||||
|
private function isPamong(): bool
|
||||||
|
{
|
||||||
|
return auth()->user()->role === 'pamong';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function requirePamong(): void
|
||||||
|
{
|
||||||
|
if (! $this->isPamong()) {
|
||||||
|
abort(403, 'Akses ditolak. Hanya Pamong yang dapat melakukan aksi ini.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tampilkan daftar uang saku — Grouped per Santri
|
* Tampilkan daftar uang saku — Grouped per Santri
|
||||||
* Default: bulan ini
|
* Default: bulan ini
|
||||||
|
|
@ -20,12 +35,11 @@ public function index(Request $request)
|
||||||
{
|
{
|
||||||
$search = $request->get('search');
|
$search = $request->get('search');
|
||||||
|
|
||||||
// ── Default: bulan ini ──────────────────────────────────────
|
|
||||||
$dari = $request->get('dari', now()->startOfMonth()->format('Y-m-d'));
|
$dari = $request->get('dari', now()->startOfMonth()->format('Y-m-d'));
|
||||||
$sampai = $request->get('sampai', now()->endOfMonth()->format('Y-m-d'));
|
$sampai = $request->get('sampai', now()->endOfMonth()->format('Y-m-d'));
|
||||||
$sort = $request->get('sort', 'nama'); // nama | saldo_asc | saldo_desc | transaksi_desc | terakhir
|
$sort = $request->get('sort', 'nama');
|
||||||
|
|
||||||
// ── KPI ringkasan periode (dipengaruhi filter tanggal) ──────
|
// ── KPI ringkasan periode ───────────────────────────────────
|
||||||
$kpiQuery = UangSaku::whereBetween('tanggal_transaksi', [$dari, $sampai]);
|
$kpiQuery = UangSaku::whereBetween('tanggal_transaksi', [$dari, $sampai]);
|
||||||
$kpi = [
|
$kpi = [
|
||||||
'total_transaksi' => (clone $kpiQuery)->count(),
|
'total_transaksi' => (clone $kpiQuery)->count(),
|
||||||
|
|
@ -33,23 +47,22 @@ public function index(Request $request)
|
||||||
'total_pengeluaran' => (float)(clone $kpiQuery)->where('jenis_transaksi', 'pengeluaran')->sum('nominal'),
|
'total_pengeluaran' => (float)(clone $kpiQuery)->where('jenis_transaksi', 'pengeluaran')->sum('nominal'),
|
||||||
'total_santri' => (clone $kpiQuery)->distinct('id_santri')->count('id_santri'),
|
'total_santri' => (clone $kpiQuery)->distinct('id_santri')->count('id_santri'),
|
||||||
];
|
];
|
||||||
// Selisih periode: apakah dalam rentang ini uang yang masuk lebih besar dari yang keluar
|
|
||||||
$kpi['selisih'] = $kpi['total_pemasukan'] - $kpi['total_pengeluaran'];
|
$kpi['selisih'] = $kpi['total_pemasukan'] - $kpi['total_pengeluaran'];
|
||||||
|
|
||||||
// ── KPI Real-time: Total saldo aktual seluruh santri (tidak dipengaruhi filter) ──
|
// ── KPI Real-time: total saldo semua santri ─────────────────
|
||||||
// Ambil saldo_sesudah dari transaksi TERAKHIR masing-masing santri
|
$kpi['total_saldo_realtime'] = (float) DB::table('uang_saku as a')
|
||||||
$totalSaldoSemua = DB::table('uang_saku as u1')
|
->whereNotExists(function ($q) {
|
||||||
->join(DB::raw('(
|
$q->from('uang_saku as b')
|
||||||
SELECT id_santri, MAX(id) as max_id
|
->whereColumn('b.id_santri', 'a.id_santri')
|
||||||
FROM uang_saku
|
->where(function ($inner) {
|
||||||
GROUP BY id_santri
|
$inner->whereColumn('b.tanggal_transaksi', '>', 'a.tanggal_transaksi')
|
||||||
) as latest'), function ($join) {
|
->orWhere(function ($tie) {
|
||||||
$join->on('u1.id_santri', '=', 'latest.id_santri')
|
$tie->whereColumn('b.tanggal_transaksi', '=', 'a.tanggal_transaksi')
|
||||||
->on('u1.id', '=', 'latest.max_id');
|
->whereColumn('b.id', '>', 'a.id');
|
||||||
|
});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
->sum('u1.saldo_sesudah');
|
->sum('saldo_sesudah');
|
||||||
|
|
||||||
$kpi['total_saldo_realtime'] = (float) $totalSaldoSemua;
|
|
||||||
|
|
||||||
// ── Query santri ────────────────────────────────────────────
|
// ── Query santri ────────────────────────────────────────────
|
||||||
$santriQuery = Santri::aktif()
|
$santriQuery = Santri::aktif()
|
||||||
|
|
@ -64,71 +77,79 @@ public function index(Request $request)
|
||||||
}
|
}
|
||||||
|
|
||||||
$santriQuery->orderBy('nama_lengkap');
|
$santriQuery->orderBy('nama_lengkap');
|
||||||
|
|
||||||
$santriList = $santriQuery->paginate(20)->appends(request()->query());
|
$santriList = $santriQuery->paginate(20)->appends(request()->query());
|
||||||
|
|
||||||
$ids = $santriList->pluck('id_santri');
|
$ids = $santriList->pluck('id_santri');
|
||||||
|
|
||||||
// ── Saldo terakhir per santri (efisien: subquery per-id) ────
|
// ── Saldo terakhir per santri (NOT EXISTS) ──────────────────
|
||||||
// Ambil id transaksi terakhir per santri lalu join, hindari get()->unique() yang boros
|
$latestIds = DB::table('uang_saku as a')
|
||||||
$latestIds = DB::table('uang_saku')
|
->whereIn('a.id_santri', $ids)
|
||||||
->whereIn('id_santri', $ids)
|
->whereNotExists(function ($q) {
|
||||||
->select('id_santri', DB::raw('MAX(id) as max_id'))
|
$q->from('uang_saku as b')
|
||||||
->groupBy('id_santri')
|
->whereColumn('b.id_santri', 'a.id_santri')
|
||||||
->pluck('max_id', 'id_santri');
|
->where(function ($inner) {
|
||||||
|
$inner->whereColumn('b.tanggal_transaksi', '>', 'a.tanggal_transaksi')
|
||||||
|
->orWhere(function ($tie) {
|
||||||
|
$tie->whereColumn('b.tanggal_transaksi', '=', 'a.tanggal_transaksi')
|
||||||
|
->whereColumn('b.id', '>', 'a.id');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
->select('a.id_santri', 'a.id')
|
||||||
|
->pluck('a.id', 'a.id_santri');
|
||||||
|
|
||||||
$saldoMap = UangSaku::whereIn('id', $latestIds->values())
|
$saldoMap = UangSaku::whereIn('id', $latestIds->values())
|
||||||
->get()
|
->get()
|
||||||
->keyBy('id_santri');
|
->keyBy('id_santri');
|
||||||
|
|
||||||
// ── Pemasukan & pengeluaran bulan ini per santri ────────────
|
// ── Statistik per santri mengikuti PERIODE filter ───────────
|
||||||
$bulanIniStats = UangSaku::whereIn('id_santri', $ids)
|
$periodeStats = UangSaku::whereIn('id_santri', $ids)
|
||||||
->whereMonth('tanggal_transaksi', now()->month)
|
->whereBetween('tanggal_transaksi', [$dari, $sampai])
|
||||||
->whereYear('tanggal_transaksi', now()->year)
|
|
||||||
->select(
|
->select(
|
||||||
'id_santri',
|
'id_santri',
|
||||||
DB::raw('SUM(CASE WHEN jenis_transaksi="pemasukan" THEN nominal ELSE 0 END) as pemasukan_bulan'),
|
DB::raw('SUM(CASE WHEN jenis_transaksi="pemasukan" THEN nominal ELSE 0 END) as pemasukan_periode'),
|
||||||
DB::raw('SUM(CASE WHEN jenis_transaksi="pengeluaran" THEN nominal ELSE 0 END) as pengeluaran_bulan'),
|
DB::raw('SUM(CASE WHEN jenis_transaksi="pengeluaran" THEN nominal ELSE 0 END) as pengeluaran_periode'),
|
||||||
DB::raw('COUNT(*) as total_bulan')
|
DB::raw('COUNT(*) as total_periode')
|
||||||
)
|
)
|
||||||
->groupBy('id_santri')
|
->groupBy('id_santri')
|
||||||
->get()
|
->get()
|
||||||
->keyBy('id_santri');
|
->keyBy('id_santri');
|
||||||
|
|
||||||
// ── Transaksi terbaru per santri (max 5, untuk collapsed detail) ──
|
// ── Transaksi terbaru per santri (max 5) ────────────────────
|
||||||
$transaksiMap = UangSaku::whereIn('id_santri', $ids)
|
$transaksiMap = UangSaku::whereIn('id_santri', $ids)
|
||||||
->orderByDesc('tanggal_transaksi')
|
->orderByDesc('tanggal_transaksi')
|
||||||
->orderByDesc('created_at')
|
->orderByDesc('id')
|
||||||
->get()
|
->get()
|
||||||
->groupBy('id_santri')
|
->groupBy('id_santri')
|
||||||
->map(fn($g) => $g->take(5));
|
->map(fn($g) => $g->take(5));
|
||||||
|
|
||||||
// ── Attach semua data ke santri objects ─────────────────────
|
// ── Attach data ke santri objects ───────────────────────────
|
||||||
$collection = $santriList->getCollection()->map(function ($santri) use ($saldoMap, $bulanIniStats, $transaksiMap) {
|
$collection = $santriList->getCollection()->map(function ($santri) use ($saldoMap, $periodeStats, $transaksiMap) {
|
||||||
$saldoRow = $saldoMap[$santri->id_santri] ?? null;
|
$saldoRow = $saldoMap[$santri->id_santri] ?? null;
|
||||||
$bulan = $bulanIniStats[$santri->id_santri] ?? null;
|
$periode = $periodeStats[$santri->id_santri] ?? null;
|
||||||
|
|
||||||
$santri->saldo_terakhir = $saldoRow ? (float)$saldoRow->saldo_sesudah : 0;
|
$santri->saldo_terakhir = $saldoRow ? (float)$saldoRow->saldo_sesudah : 0;
|
||||||
$santri->transaksi_terakhir_tgl = $saldoRow ? $saldoRow->tanggal_transaksi : null;
|
$santri->transaksi_terakhir_tgl = $saldoRow ? $saldoRow->tanggal_transaksi : null;
|
||||||
$santri->pemasukan_bulan = $bulan ? (float)$bulan->pemasukan_bulan : 0;
|
$santri->pemasukan_periode = $periode ? (float)$periode->pemasukan_periode : 0;
|
||||||
$santri->pengeluaran_bulan = $bulan ? (float)$bulan->pengeluaran_bulan : 0;
|
$santri->pengeluaran_periode = $periode ? (float)$periode->pengeluaran_periode : 0;
|
||||||
$santri->transaksi_bulan_ini = $bulan ? (int)$bulan->total_bulan : 0;
|
$santri->transaksi_periode = $periode ? (int)$periode->total_periode : 0;
|
||||||
$santri->transaksi_terbaru = $transaksiMap[$santri->id_santri] ?? collect();
|
$santri->transaksi_terbaru = $transaksiMap[$santri->id_santri] ?? collect();
|
||||||
return $santri;
|
return $santri;
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Re-sort collection setelah attach ───────────────────────
|
|
||||||
$sorted = match($sort) {
|
$sorted = match($sort) {
|
||||||
'saldo_asc' => $collection->sortBy('saldo_terakhir'),
|
'saldo_asc' => $collection->sortBy('saldo_terakhir'),
|
||||||
'saldo_desc' => $collection->sortByDesc('saldo_terakhir'),
|
'saldo_desc' => $collection->sortByDesc('saldo_terakhir'),
|
||||||
'transaksi_desc' => $collection->sortByDesc('transaksi_bulan_ini'),
|
'transaksi_desc' => $collection->sortByDesc('transaksi_periode'),
|
||||||
'terakhir' => $collection->sortByDesc('transaksi_terakhir_tgl'),
|
'terakhir' => $collection->sortByDesc('transaksi_terakhir_tgl'),
|
||||||
default => $collection->sortBy('nama_lengkap'),
|
default => $collection->sortBy('nama_lengkap'),
|
||||||
};
|
};
|
||||||
|
|
||||||
$santriList->setCollection($sorted->values());
|
$santriList->setCollection($sorted->values());
|
||||||
|
|
||||||
return view('admin.uang-saku.index', compact('santriList', 'kpi', 'dari', 'sampai', 'sort'));
|
// Kirim flag ke view agar tampilan bisa menyesuaikan
|
||||||
|
$canCrud = $this->isPamong();
|
||||||
|
|
||||||
|
return view('admin.uang-saku.index', compact('santriList', 'kpi', 'dari', 'sampai', 'sort', 'canCrud'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -137,12 +158,11 @@ public function index(Request $request)
|
||||||
public function santriInfo($id_santri)
|
public function santriInfo($id_santri)
|
||||||
{
|
{
|
||||||
$santri = Santri::where('id_santri', $id_santri)->firstOrFail();
|
$santri = Santri::where('id_santri', $id_santri)->firstOrFail();
|
||||||
|
|
||||||
$bulanIni = now();
|
$bulanIni = now();
|
||||||
|
|
||||||
$lastTx = UangSaku::where('id_santri', $id_santri)
|
$lastTx = UangSaku::where('id_santri', $id_santri)
|
||||||
->orderByDesc('tanggal_transaksi')
|
->orderByDesc('tanggal_transaksi')
|
||||||
->orderByDesc('created_at')
|
->orderByDesc('id')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
$saldo = $lastTx ? (float)$lastTx->saldo_sesudah : 0;
|
$saldo = $lastTx ? (float)$lastTx->saldo_sesudah : 0;
|
||||||
|
|
@ -161,7 +181,7 @@ public function santriInfo($id_santri)
|
||||||
|
|
||||||
$transaksiTerakhir = UangSaku::where('id_santri', $id_santri)
|
$transaksiTerakhir = UangSaku::where('id_santri', $id_santri)
|
||||||
->orderByDesc('tanggal_transaksi')
|
->orderByDesc('tanggal_transaksi')
|
||||||
->orderByDesc('created_at')
|
->orderByDesc('id')
|
||||||
->limit(3)
|
->limit(3)
|
||||||
->get()
|
->get()
|
||||||
->map(fn($t) => [
|
->map(fn($t) => [
|
||||||
|
|
@ -183,6 +203,8 @@ public function santriInfo($id_santri)
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
|
$this->requirePamong();
|
||||||
|
|
||||||
$santriList = Santri::where('status', 'Aktif')
|
$santriList = Santri::where('status', 'Aktif')
|
||||||
->select('id_santri', 'nama_lengkap')
|
->select('id_santri', 'nama_lengkap')
|
||||||
->orderBy('nama_lengkap')
|
->orderBy('nama_lengkap')
|
||||||
|
|
@ -193,6 +215,8 @@ public function create()
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
$this->requirePamong();
|
||||||
|
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'id_santri' => 'required|exists:santris,id_santri',
|
'id_santri' => 'required|exists:santris,id_santri',
|
||||||
'jenis_transaksi' => 'required|in:pemasukan,pengeluaran',
|
'jenis_transaksi' => 'required|in:pemasukan,pengeluaran',
|
||||||
|
|
@ -205,6 +229,17 @@ public function store(Request $request)
|
||||||
try {
|
try {
|
||||||
UangSaku::create($validated);
|
UangSaku::create($validated);
|
||||||
$this->recalculateSaldoAfter($validated['id_santri'], $validated['tanggal_transaksi']);
|
$this->recalculateSaldoAfter($validated['id_santri'], $validated['tanggal_transaksi']);
|
||||||
|
|
||||||
|
if ($validated['jenis_transaksi'] === 'pengeluaran'
|
||||||
|
&& $this->hasSaldoNegatif($validated['id_santri'], $validated['tanggal_transaksi'])) {
|
||||||
|
DB::rollBack();
|
||||||
|
return back()->withInput()->with(
|
||||||
|
'error',
|
||||||
|
'Transaksi gagal: Saldo tidak mencukupi. ' .
|
||||||
|
'Jumlah pengeluaran melebihi saldo yang tersedia pada tanggal tersebut.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
Cache::forget('santri_aktif_uang_saku');
|
Cache::forget('santri_aktif_uang_saku');
|
||||||
return redirect()->route('admin.uang-saku.index')
|
return redirect()->route('admin.uang-saku.index')
|
||||||
|
|
@ -218,11 +253,14 @@ public function store(Request $request)
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$transaksi = UangSaku::with('santri')->findOrFail($id);
|
$transaksi = UangSaku::with('santri')->findOrFail($id);
|
||||||
return view('admin.uang-saku.show', compact('transaksi'));
|
$canCrud = $this->isPamong();
|
||||||
|
return view('admin.uang-saku.show', compact('transaksi', 'canCrud'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
|
$this->requirePamong();
|
||||||
|
|
||||||
$transaksi = UangSaku::with('santri')->findOrFail($id);
|
$transaksi = UangSaku::with('santri')->findOrFail($id);
|
||||||
$santriList = Santri::where('status', 'Aktif')
|
$santriList = Santri::where('status', 'Aktif')
|
||||||
->select('id_santri', 'nama_lengkap')
|
->select('id_santri', 'nama_lengkap')
|
||||||
|
|
@ -233,6 +271,8 @@ public function edit($id)
|
||||||
|
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
|
$this->requirePamong();
|
||||||
|
|
||||||
$transaksi = UangSaku::findOrFail($id);
|
$transaksi = UangSaku::findOrFail($id);
|
||||||
$validated = $request->validate([
|
$validated = $request->validate([
|
||||||
'jenis_transaksi' => 'required|in:pemasukan,pengeluaran',
|
'jenis_transaksi' => 'required|in:pemasukan,pengeluaran',
|
||||||
|
|
@ -241,20 +281,24 @@ public function update(Request $request, $id)
|
||||||
'tanggal_transaksi' => 'required|date',
|
'tanggal_transaksi' => 'required|date',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Simpan tanggal lama sebelum update, agar recalculate dimulai dari yang paling awal
|
|
||||||
$tanggalLama = $transaksi->tanggal_transaksi->format('Y-m-d');
|
$tanggalLama = $transaksi->tanggal_transaksi->format('Y-m-d');
|
||||||
|
|
||||||
DB::beginTransaction();
|
|
||||||
try {
|
|
||||||
// Gunakan saveQuietly agar model boot (updating) tidak ikut menghitung ulang saldo
|
|
||||||
// — recalculate akan dikerjakan secara menyeluruh oleh recalculateSaldoAfter()
|
|
||||||
$transaksi->fill($validated)->saveQuietly();
|
|
||||||
|
|
||||||
// Recalculate dari tanggal yang paling awal antara tanggal lama dan baru
|
|
||||||
$tanggalBaru = $validated['tanggal_transaksi'];
|
$tanggalBaru = $validated['tanggal_transaksi'];
|
||||||
$tanggalMulai = min($tanggalLama, $tanggalBaru);
|
$tanggalMulai = min($tanggalLama, $tanggalBaru);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
try {
|
||||||
|
$transaksi->fill($validated)->saveQuietly();
|
||||||
$this->recalculateSaldoAfter($transaksi->id_santri, $tanggalMulai);
|
$this->recalculateSaldoAfter($transaksi->id_santri, $tanggalMulai);
|
||||||
|
|
||||||
|
if ($this->hasSaldoNegatif($transaksi->id_santri, $tanggalMulai)) {
|
||||||
|
DB::rollBack();
|
||||||
|
return back()->withInput()->with(
|
||||||
|
'error',
|
||||||
|
'Perubahan gagal: Perubahan ini menyebabkan saldo menjadi negatif. ' .
|
||||||
|
'Pengeluaran tidak boleh melebihi saldo yang tersedia.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
Cache::forget('santri_aktif_uang_saku');
|
Cache::forget('santri_aktif_uang_saku');
|
||||||
return redirect()->route('admin.uang-saku.index')
|
return redirect()->route('admin.uang-saku.index')
|
||||||
|
|
@ -267,6 +311,8 @@ public function update(Request $request, $id)
|
||||||
|
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
|
$this->requirePamong();
|
||||||
|
|
||||||
$transaksi = UangSaku::findOrFail($id);
|
$transaksi = UangSaku::findOrFail($id);
|
||||||
$idSantri = $transaksi->id_santri;
|
$idSantri = $transaksi->id_santri;
|
||||||
$tanggal = $transaksi->tanggal_transaksi->format('Y-m-d');
|
$tanggal = $transaksi->tanggal_transaksi->format('Y-m-d');
|
||||||
|
|
@ -289,17 +335,22 @@ public function riwayat(Request $request, $id_santri)
|
||||||
{
|
{
|
||||||
$santri = Santri::where('id_santri', $id_santri)->firstOrFail();
|
$santri = Santri::where('id_santri', $id_santri)->firstOrFail();
|
||||||
|
|
||||||
$tanggalDari = $request->filled('tanggal_dari') ? $request->tanggal_dari : now()->startOfMonth()->format('Y-m-d');
|
$tanggalDari = $request->filled('tanggal_dari')
|
||||||
$tanggalSampai = $request->filled('tanggal_sampai') ? $request->tanggal_sampai : now()->endOfMonth()->format('Y-m-d');
|
? $request->tanggal_dari
|
||||||
|
: now()->startOfMonth()->format('Y-m-d');
|
||||||
|
$tanggalSampai = $request->filled('tanggal_sampai')
|
||||||
|
? $request->tanggal_sampai
|
||||||
|
: now()->endOfMonth()->format('Y-m-d');
|
||||||
|
|
||||||
$query = UangSaku::where('id_santri', $id_santri)
|
// Transaksi dalam periode (paginated)
|
||||||
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai]);
|
$transaksi = UangSaku::where('id_santri', $id_santri)
|
||||||
|
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
||||||
$transaksi = $query->orderBy('tanggal_transaksi', 'desc')
|
->orderBy('tanggal_transaksi', 'desc')
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('id', 'desc')
|
||||||
->paginate(20)
|
->paginate(20)
|
||||||
->appends($request->query());
|
->appends($request->query());
|
||||||
|
|
||||||
|
// Total pemasukan & pengeluaran periode
|
||||||
$totalPemasukan = UangSaku::where('id_santri', $id_santri)
|
$totalPemasukan = UangSaku::where('id_santri', $id_santri)
|
||||||
->where('jenis_transaksi', 'pemasukan')
|
->where('jenis_transaksi', 'pemasukan')
|
||||||
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
||||||
|
|
@ -310,50 +361,102 @@ public function riwayat(Request $request, $id_santri)
|
||||||
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
||||||
->sum('nominal');
|
->sum('nominal');
|
||||||
|
|
||||||
// Ambil saldo aktual dari transaksi TERAKHIR santri ini (real-time, bukan dari filter)
|
// Saldo aktual real-time (kumulatif semua waktu)
|
||||||
$lastTx = UangSaku::where('id_santri', $id_santri)
|
$lastTx = UangSaku::where('id_santri', $id_santri)
|
||||||
->orderByDesc('tanggal_transaksi')
|
->orderByDesc('tanggal_transaksi')
|
||||||
->orderByDesc('created_at')
|
->orderByDesc('id')
|
||||||
->first();
|
->first();
|
||||||
$saldoTerakhir = $lastTx ? (float)$lastTx->saldo_sesudah : 0;
|
$saldoTerakhir = $lastTx ? (float)$lastTx->saldo_sesudah : 0;
|
||||||
|
|
||||||
$dataGrafik = UangSaku::where('id_santri', $id_santri)
|
// Saldo awal periode = saldo_sesudah transaksi terakhir SEBELUM tanggalDari
|
||||||
|
$txSebelumPeriode = UangSaku::where('id_santri', $id_santri)
|
||||||
|
->where('tanggal_transaksi', '<', $tanggalDari)
|
||||||
|
->orderByDesc('tanggal_transaksi')
|
||||||
|
->orderByDesc('id')
|
||||||
|
->first();
|
||||||
|
$saldoAwalPeriode = $txSebelumPeriode ? (float)$txSebelumPeriode->saldo_sesudah : 0;
|
||||||
|
|
||||||
|
// Saldo akhir periode = saldo_sesudah transaksi terakhir s.d. tanggalSampai
|
||||||
|
$txAkhirPeriode = UangSaku::where('id_santri', $id_santri)
|
||||||
|
->where('tanggal_transaksi', '<=', $tanggalSampai)
|
||||||
|
->orderByDesc('tanggal_transaksi')
|
||||||
|
->orderByDesc('id')
|
||||||
|
->first();
|
||||||
|
$saldoAkhirPeriode = $txAkhirPeriode ? (float)$txAkhirPeriode->saldo_sesudah : 0;
|
||||||
|
|
||||||
|
// ── DATA GRAFIK: PERJALANAN SALDO ────────────────────────────
|
||||||
|
$saldoPerHari = UangSaku::where('id_santri', $id_santri)
|
||||||
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
->whereBetween('tanggal_transaksi', [$tanggalDari, $tanggalSampai])
|
||||||
->select(
|
->select(
|
||||||
DB::raw('DATE(tanggal_transaksi) as tanggal'),
|
DB::raw('DATE(tanggal_transaksi) as tgl'),
|
||||||
DB::raw('SUM(CASE WHEN jenis_transaksi="pemasukan" THEN nominal ELSE 0 END) as pemasukan'),
|
DB::raw('SUBSTRING_INDEX(GROUP_CONCAT(saldo_sesudah ORDER BY id DESC), ",", 1) as saldo_akhir_hari')
|
||||||
DB::raw('SUM(CASE WHEN jenis_transaksi="pengeluaran" THEN nominal ELSE 0 END) as pengeluaran')
|
|
||||||
)
|
)
|
||||||
->groupBy('tanggal')
|
->groupBy('tgl')
|
||||||
->orderBy('tanggal')
|
->orderBy('tgl')
|
||||||
->get();
|
->get()
|
||||||
|
->keyBy('tgl');
|
||||||
if ($dataGrafik->isEmpty()) {
|
|
||||||
$dataGrafik = collect([(object)['tanggal' => $tanggalDari, 'pemasukan' => 0, 'pengeluaran' => 0]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$periodeDari = Carbon::parse($tanggalDari);
|
$periodeDari = Carbon::parse($tanggalDari);
|
||||||
$periodeSampai = Carbon::parse($tanggalSampai);
|
$periodeSampai = Carbon::parse($tanggalSampai);
|
||||||
|
|
||||||
|
$dataGrafikSaldo = [];
|
||||||
|
$saldoBerjalan = $saldoAwalPeriode;
|
||||||
|
$current = $periodeDari->copy();
|
||||||
|
|
||||||
|
$dataGrafikSaldo[] = [
|
||||||
|
'tanggal' => $periodeDari->format('Y-m-d'),
|
||||||
|
'saldo' => $saldoAwalPeriode,
|
||||||
|
'is_awal' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
while ($current->lte($periodeSampai)) {
|
||||||
|
$tgl = $current->format('Y-m-d');
|
||||||
|
if (isset($saldoPerHari[$tgl])) {
|
||||||
|
$saldoBerjalan = (float)$saldoPerHari[$tgl]->saldo_akhir_hari;
|
||||||
|
}
|
||||||
|
if ($current->eq($periodeDari)) {
|
||||||
|
if (isset($saldoPerHari[$tgl])) {
|
||||||
|
$dataGrafikSaldo[0]['saldo'] = (float)$saldoPerHari[$tgl]->saldo_akhir_hari;
|
||||||
|
$dataGrafikSaldo[0]['is_awal'] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$dataGrafikSaldo[] = [
|
||||||
|
'tanggal' => $tgl,
|
||||||
|
'saldo' => $saldoBerjalan,
|
||||||
|
'is_awal' => false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$current->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
$canCrud = $this->isPamong();
|
||||||
|
|
||||||
return view('admin.uang-saku.riwayat', compact(
|
return view('admin.uang-saku.riwayat', compact(
|
||||||
'santri', 'transaksi',
|
'santri', 'transaksi',
|
||||||
'totalPemasukan', 'totalPengeluaran', 'saldoTerakhir',
|
'totalPemasukan', 'totalPengeluaran',
|
||||||
'dataGrafik', 'tanggalDari', 'tanggalSampai',
|
'saldoAwalPeriode', 'saldoAkhirPeriode', 'saldoTerakhir',
|
||||||
'periodeDari', 'periodeSampai'
|
'dataGrafikSaldo',
|
||||||
|
'tanggalDari', 'tanggalSampai',
|
||||||
|
'periodeDari', 'periodeSampai',
|
||||||
|
'canCrud'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ────────────────────────────────────────────────────────────────
|
||||||
* Hitung ulang saldo_sebelum & saldo_sesudah untuk semua transaksi
|
// PRIVATE HELPERS
|
||||||
* milik $idSantri yang tanggalnya >= $tanggal.
|
// ────────────────────────────────────────────────────────────────
|
||||||
*
|
|
||||||
* Dipanggil setelah store / update / destroy agar urutan saldo
|
private function hasSaldoNegatif(string $idSantri, string $tanggal): bool
|
||||||
* tetap konsisten meski transaksi disisipkan di tengah.
|
{
|
||||||
*/
|
return UangSaku::where('id_santri', $idSantri)
|
||||||
|
->where('tanggal_transaksi', '>=', $tanggal)
|
||||||
|
->where('saldo_sesudah', '<', 0)
|
||||||
|
->exists();
|
||||||
|
}
|
||||||
|
|
||||||
private function recalculateSaldoAfter($idSantri, $tanggal)
|
private function recalculateSaldoAfter($idSantri, $tanggal)
|
||||||
{
|
{
|
||||||
// Pastikan format tanggal string (bukan Carbon object)
|
$tanggal = $tanggal instanceof Carbon
|
||||||
$tanggal = $tanggal instanceof \Carbon\Carbon
|
|
||||||
? $tanggal->format('Y-m-d')
|
? $tanggal->format('Y-m-d')
|
||||||
: $tanggal;
|
: $tanggal;
|
||||||
|
|
||||||
|
|
@ -366,7 +469,6 @@ private function recalculateSaldoAfter($idSantri, $tanggal)
|
||||||
|
|
||||||
foreach ($transaksiSetelah as $index => $trans) {
|
foreach ($transaksiSetelah as $index => $trans) {
|
||||||
if ($index === 0) {
|
if ($index === 0) {
|
||||||
// Cari saldo_sesudah transaksi tepat sebelum batch ini
|
|
||||||
$prev = UangSaku::where('id_santri', $idSantri)
|
$prev = UangSaku::where('id_santri', $idSantri)
|
||||||
->where('tanggal_transaksi', '<', $tanggal)
|
->where('tanggal_transaksi', '<', $tanggal)
|
||||||
->orderByDesc('tanggal_transaksi')
|
->orderByDesc('tanggal_transaksi')
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,240 @@
|
||||||
{{-- Select2 CSS --}}
|
{{-- Select2 CSS --}}
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
OVERRIDE SELECT2 agar sesuai tema
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.select2-container--default .select2-selection--single {
|
||||||
|
height: 44px;
|
||||||
|
border: 1.5px solid #d1d9e0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: border-color .2s, box-shadow .2s;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single:hover {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
}
|
||||||
|
.select2-container--default.select2-container--focus .select2-selection--single,
|
||||||
|
.select2-container--default.select2-container--open .select2-selection--single {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
box-shadow: 0 0 0 3px rgba(111,186,157,.18);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #333;
|
||||||
|
padding: 0;
|
||||||
|
font-size: .93rem;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||||
|
height: 42px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: var(--primary-color, #6FBA9D);
|
||||||
|
}
|
||||||
|
.select2-dropdown {
|
||||||
|
border: 1.5px solid var(--primary-color, #6FBA9D);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0,0,0,.12);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.select2-search--dropdown .select2-search__field {
|
||||||
|
border: 1.5px solid #d1d9e0;
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 7px 10px;
|
||||||
|
font-size: .88rem;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.select2-search--dropdown .select2-search__field:focus {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
}
|
||||||
|
.select2-results__option {
|
||||||
|
padding: 9px 14px;
|
||||||
|
font-size: .88rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
LABEL FIELD
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.field-label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: .8rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: .5px;
|
||||||
|
color: var(--text-light, #888);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.field-label .fi { margin-right: 5px; color: var(--primary-color, #6FBA9D); }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
CARD PILIH JENIS TRANSAKSI
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.jenis-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
.jenis-card {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 2.5px solid #e0e7ef;
|
||||||
|
padding: 18px 16px 16px;
|
||||||
|
transition: border-color .2s, box-shadow .2s, transform .15s, background .2s;
|
||||||
|
background: #fff;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
.jenis-card:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,.09); }
|
||||||
|
.jenis-card input[type="radio"] { position:absolute; opacity:0; width:0; height:0; }
|
||||||
|
.jenis-card .ji-wrap {
|
||||||
|
width: 46px; height: 46px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
transition: background .2s;
|
||||||
|
}
|
||||||
|
.jenis-card .ji-title { font-weight: 700; font-size: .93rem; margin-bottom: 4px; transition: color .2s; }
|
||||||
|
.jenis-card .ji-desc { font-size: .75rem; color: #b0b8c4; line-height: 1.4; }
|
||||||
|
.jenis-card .ji-check {
|
||||||
|
position: absolute; top: 12px; right: 12px;
|
||||||
|
width: 22px; height: 22px; border-radius: 50%;
|
||||||
|
border: 2px solid #d1d9e0;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-size: .68rem; color: transparent;
|
||||||
|
transition: all .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pemasukan aktif */
|
||||||
|
.jenis-card.pemasukan.active {
|
||||||
|
border-color: #6FBA9D;
|
||||||
|
background: linear-gradient(135deg, #f0fdf7 0%, #e6f9f2 100%);
|
||||||
|
box-shadow: 0 4px 18px rgba(111,186,157,.22);
|
||||||
|
}
|
||||||
|
.jenis-card.pemasukan .ji-wrap { background: #edf9f4; color: #6FBA9D; }
|
||||||
|
.jenis-card.pemasukan.active .ji-wrap { background: rgba(111,186,157,.2); color: #38a169; }
|
||||||
|
.jenis-card.pemasukan.active .ji-title { color: #38a169; }
|
||||||
|
.jenis-card.pemasukan.active .ji-check { background: #6FBA9D; border-color: #6FBA9D; color: #fff; }
|
||||||
|
|
||||||
|
/* Pengeluaran aktif */
|
||||||
|
.jenis-card.pengeluaran.active {
|
||||||
|
border-color: #FF8B94;
|
||||||
|
background: linear-gradient(135deg, #fff5f6 0%, #ffe9eb 100%);
|
||||||
|
box-shadow: 0 4px 18px rgba(255,139,148,.22);
|
||||||
|
}
|
||||||
|
.jenis-card.pengeluaran .ji-wrap { background: #fff0f1; color: #FF8B94; }
|
||||||
|
.jenis-card.pengeluaran.active .ji-wrap { background: rgba(255,139,148,.2); color: #e53e3e; }
|
||||||
|
.jenis-card.pengeluaran.active .ji-title { color: #e53e3e; }
|
||||||
|
.jenis-card.pengeluaran.active .ji-check { background: #FF8B94; border-color: #FF8B94; color: #fff; }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
BOX PERINGATAN SALDO
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
#warning-saldo {
|
||||||
|
display: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1.5px solid #FC8181;
|
||||||
|
background: linear-gradient(135deg, #fff5f5 0%, #ffecec 100%);
|
||||||
|
padding: 13px 16px;
|
||||||
|
margin-top: 10px;
|
||||||
|
animation: warnIn .22s ease;
|
||||||
|
}
|
||||||
|
@keyframes warnIn {
|
||||||
|
from { opacity: 0; transform: translateY(-6px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
#warning-saldo .wt { font-weight: 700; color: #c53030; font-size: .87rem; margin-bottom: 5px; }
|
||||||
|
#warning-saldo .wb { font-size: .8rem; color: #742a2a; line-height: 1.55; }
|
||||||
|
#warning-saldo .ws-grid {
|
||||||
|
display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 10px;
|
||||||
|
}
|
||||||
|
#warning-saldo .ws-cell {
|
||||||
|
background: rgba(255,255,255,.75); border-radius: 8px;
|
||||||
|
padding: 8px 10px; text-align: center;
|
||||||
|
}
|
||||||
|
#warning-saldo .ws-cell small { display:block; font-size:.68rem; color:#aaa; margin-bottom:3px; }
|
||||||
|
#warning-saldo .ws-cell strong { font-size:.86rem; font-weight:700; }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
INPUT NOMINAL
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.nominal-wrap { position: relative; display: flex; align-items: center; }
|
||||||
|
.nominal-prefix {
|
||||||
|
position: absolute; left: 14px;
|
||||||
|
font-weight: 700; color: #aaa;
|
||||||
|
pointer-events: none; font-size: .93rem; z-index: 1;
|
||||||
|
}
|
||||||
|
.nominal-wrap input {
|
||||||
|
padding-left: 44px !important;
|
||||||
|
font-size: 1rem; font-weight: 600; letter-spacing: .3px;
|
||||||
|
height: 44px; border-radius: 10px;
|
||||||
|
border: 1.5px solid #d1d9e0;
|
||||||
|
transition: border-color .2s, box-shadow .2s;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.nominal-wrap input:focus {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
box-shadow: 0 0 0 3px rgba(111,186,157,.18);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.nominal-wrap.danger input {
|
||||||
|
border-color: #FC8181 !important;
|
||||||
|
box-shadow: 0 0 0 3px rgba(255,139,148,.18) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* form-control radius konsisten */
|
||||||
|
.form-control { border-radius: 10px !important; border: 1.5px solid #d1d9e0; transition: border-color .2s, box-shadow .2s; }
|
||||||
|
.form-control:focus {
|
||||||
|
border-color: var(--primary-color, #6FBA9D) !important;
|
||||||
|
box-shadow: 0 0 0 3px rgba(111,186,157,.18) !important;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
textarea.form-control { height: auto; }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
INFO CARD SANTRI
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
#santri-info {
|
||||||
|
border-radius: 12px; overflow: hidden;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1.5px solid var(--primary-color, #6FBA9D);
|
||||||
|
box-shadow: 0 4px 14px rgba(111,186,157,.13);
|
||||||
|
animation: fadeUp .22s ease;
|
||||||
|
}
|
||||||
|
@keyframes fadeUp {
|
||||||
|
from { opacity:0; transform:translateY(6px); }
|
||||||
|
to { opacity:1; transform:translateY(0); }
|
||||||
|
}
|
||||||
|
.si-header {
|
||||||
|
background: linear-gradient(90deg, #6FBA9D 0%, #38a169 100%);
|
||||||
|
padding: 10px 16px;
|
||||||
|
display: flex; align-items: center; gap: 8px;
|
||||||
|
color: #fff; font-weight: 700;
|
||||||
|
font-size: .8rem; text-transform: uppercase; letter-spacing: .45px;
|
||||||
|
}
|
||||||
|
.si-body { padding: 14px 16px; background: #f9fdfb; }
|
||||||
|
.si-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 12px; }
|
||||||
|
.si-stat {
|
||||||
|
background: #fff; border-radius: 9px;
|
||||||
|
padding: 10px 12px; text-align: center;
|
||||||
|
border: 1px solid #e8f5ef;
|
||||||
|
}
|
||||||
|
.si-stat small { display:block; font-size:.68rem; color:#aaa; text-transform:uppercase; letter-spacing:.3px; margin-bottom:4px; }
|
||||||
|
.si-val { font-size: .93rem; font-weight: 800; }
|
||||||
|
|
||||||
|
.form-group { margin-bottom: 20px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><i class="fas fa-plus-circle"></i> Tambah Transaksi Uang Saku</h2>
|
<h2><i class="fas fa-plus-circle"></i> Tambah Transaksi Uang Saku</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -12,17 +246,21 @@
|
||||||
<form action="{{ route('admin.uang-saku.store') }}" method="POST" id="transaksiForm">
|
<form action="{{ route('admin.uang-saku.store') }}" method="POST" id="transaksiForm">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
|
{{-- ══════════════════════════════════════
|
||||||
|
1. PILIH SANTRI
|
||||||
|
══════════════════════════════════════ --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id_santri">
|
<label class="field-label" for="id_santri">
|
||||||
<i class="fas fa-user form-icon"></i>
|
<i class="fas fa-user fi"></i> Pilih Santri
|
||||||
Pilih Santri <span style="color: red;">*</span>
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<select name="id_santri" id="id_santri" class="form-control @error('id_santri') is-invalid @enderror" required>
|
<select name="id_santri" id="id_santri"
|
||||||
<option value="">-- Pilih Santri --</option>
|
class="form-control @error('id_santri') is-invalid @enderror" required>
|
||||||
|
<option value="">Cari ID atau nama santri...</option>
|
||||||
@foreach($santriList as $santri)
|
@foreach($santriList as $santri)
|
||||||
<option value="{{ $santri->id_santri }}"
|
<option value="{{ $santri->id_santri }}"
|
||||||
{{ (old('id_santri', request('id_santri')) == $santri->id_santri) ? 'selected' : '' }}>
|
{{ (old('id_santri', request('id_santri')) == $santri->id_santri) ? 'selected' : '' }}>
|
||||||
{{ $santri->id_santri }} - {{ $santri->nama_lengkap }}
|
{{ $santri->id_santri }} — {{ $santri->nama_lengkap }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -31,63 +269,142 @@
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Info Card Santri (AJAX) --}}
|
{{-- Info Card Santri --}}
|
||||||
<div id="santri-info" style="display:none; margin-bottom: 14px;">
|
<div id="santri-info" style="display:none;">
|
||||||
<div class="content-box" style="padding:16px; background:var(--primary-light);">
|
<div class="si-header">
|
||||||
<div style="display:grid; grid-template-columns:repeat(3, 1fr); gap:12px; margin-bottom:12px;">
|
<i class="fas fa-id-card"></i>
|
||||||
<div>
|
<span id="info-nama">—</span>
|
||||||
<small class="text-muted">Saldo Terakhir</small>
|
|
||||||
<div id="info-saldo" style="font-weight:700; font-size:1.1rem;"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="si-body">
|
||||||
<small class="text-muted">Pemasukan Bln Ini</small>
|
<div class="si-stats">
|
||||||
<div id="info-masuk" style="font-weight:600; color:#6FBA9D;"></div>
|
<div class="si-stat">
|
||||||
|
<small>Saldo Saat Ini</small>
|
||||||
|
<div class="si-val" id="info-saldo">—</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="si-stat">
|
||||||
<small class="text-muted">Pengeluaran Bln Ini</small>
|
<small>Masuk Bln Ini</small>
|
||||||
<div id="info-keluar" style="font-weight:600; color:#FF8B94;"></div>
|
<div class="si-val" id="info-masuk" style="color:#6FBA9D;">—</div>
|
||||||
|
</div>
|
||||||
|
<div class="si-stat">
|
||||||
|
<small>Keluar Bln Ini</small>
|
||||||
|
<div class="si-val" id="info-keluar" style="color:#FF8B94;">—</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="info-riwayat"></div>
|
<div id="info-riwayat"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ══════════════════════════════════════
|
||||||
|
2. JENIS TRANSAKSI — Card pilihan
|
||||||
|
══════════════════════════════════════ --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="jenis_transaksi">
|
<label class="field-label">
|
||||||
<i class="fas fa-exchange-alt form-icon"></i>
|
<i class="fas fa-exchange-alt fi"></i> Jenis Transaksi
|
||||||
Jenis Transaksi <span style="color: red;">*</span>
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<select name="jenis_transaksi" id="jenis_transaksi" class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
|
|
||||||
<option value="">-- Pilih Jenis --</option>
|
{{-- Hidden select → dikirim ke server & divalidasi Laravel --}}
|
||||||
<option value="pemasukan" {{ old('jenis_transaksi') == 'pemasukan' ? 'selected' : '' }}>
|
<select name="jenis_transaksi" id="jenis_transaksi" style="display:none;"
|
||||||
Pemasukan (Terima Uang Saku)
|
class="@error('jenis_transaksi') is-invalid @enderror" required>
|
||||||
</option>
|
<option value=""></option>
|
||||||
<option value="pengeluaran" {{ old('jenis_transaksi') == 'pengeluaran' ? 'selected' : '' }}>
|
<option value="pemasukan" {{ old('jenis_transaksi') == 'pemasukan' ? 'selected' : '' }}>pemasukan</option>
|
||||||
Pengeluaran (Gunakan Uang Saku)
|
<option value="pengeluaran" {{ old('jenis_transaksi') == 'pengeluaran' ? 'selected' : '' }}>pengeluaran</option>
|
||||||
</option>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<div class="jenis-cards">
|
||||||
|
<div class="jenis-card pemasukan {{ old('jenis_transaksi') == 'pemasukan' ? 'active' : '' }}"
|
||||||
|
id="card-pemasukan" onclick="pilihJenis('pemasukan')" role="button" tabindex="0"
|
||||||
|
onkeydown="if(event.key==='Enter'||event.key===' ')pilihJenis('pemasukan')">
|
||||||
|
<input type="radio" name="_jenis_ui" value="pemasukan"
|
||||||
|
{{ old('jenis_transaksi') == 'pemasukan' ? 'checked' : '' }}>
|
||||||
|
<div class="ji-wrap"><i class="fas fa-arrow-circle-down"></i></div>
|
||||||
|
<div class="ji-title">Pemasukan</div>
|
||||||
|
<div class="ji-desc">Santri menerima uang saku dari wali / pesantren</div>
|
||||||
|
<div class="ji-check"><i class="fas fa-check"></i></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="jenis-card pengeluaran {{ old('jenis_transaksi') == 'pengeluaran' ? 'active' : '' }}"
|
||||||
|
id="card-pengeluaran" onclick="pilihJenis('pengeluaran')" role="button" tabindex="0"
|
||||||
|
onkeydown="if(event.key==='Enter'||event.key===' ')pilihJenis('pengeluaran')">
|
||||||
|
<input type="radio" name="_jenis_ui" value="pengeluaran"
|
||||||
|
{{ old('jenis_transaksi') == 'pengeluaran' ? 'checked' : '' }}>
|
||||||
|
<div class="ji-wrap"><i class="fas fa-arrow-circle-up"></i></div>
|
||||||
|
<div class="ji-title">Pengeluaran</div>
|
||||||
|
<div class="ji-desc">Santri menggunakan uang saku untuk keperluan</div>
|
||||||
|
<div class="ji-check"><i class="fas fa-check"></i></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@error('jenis_transaksi')
|
@error('jenis_transaksi')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div style="color:#e53e3e;font-size:.82rem;margin-top:6px;">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> {{ $message }}
|
||||||
|
</div>
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ══════════════════════════════════════
|
||||||
|
3. NOMINAL
|
||||||
|
══════════════════════════════════════ --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="nominal">
|
<label class="field-label" for="nominal_display">
|
||||||
<i class="fas fa-money-bill-wave form-icon"></i>
|
<i class="fas fa-money-bill-wave fi"></i> Nominal (Rp)
|
||||||
Nominal (Rp) <span style="color: red;">*</span>
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input type="number" name="nominal" id="nominal" class="form-control @error('nominal') is-invalid @enderror"
|
|
||||||
value="{{ old('nominal') }}" placeholder="Contoh: 50000" min="1" step="1" required>
|
<div class="nominal-wrap" id="nominalWrap">
|
||||||
|
<span class="nominal-prefix">Rp</span>
|
||||||
|
<input type="text"
|
||||||
|
id="nominal_display"
|
||||||
|
class="@error('nominal') is-invalid @enderror"
|
||||||
|
placeholder="0"
|
||||||
|
autocomplete="off"
|
||||||
|
inputmode="numeric"
|
||||||
|
value="{{ old('nominal') ? number_format((int)old('nominal'), 0, ',', '.') : '' }}">
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="nominal" id="nominal" value="{{ old('nominal') }}">
|
||||||
|
|
||||||
@error('nominal')
|
@error('nominal')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div style="color:#e53e3e;font-size:.82rem;margin-top:5px;">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> {{ $message }}
|
||||||
|
</div>
|
||||||
@enderror
|
@enderror
|
||||||
<small class="form-text">Masukkan nominal tanpa titik atau koma</small>
|
|
||||||
|
|
||||||
|
{{-- ── KOTAK PERINGATAN SALDO TIDAK CUKUP ── --}}
|
||||||
|
<div id="warning-saldo">
|
||||||
|
<div class="wt">
|
||||||
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
|
Peringatan: Saldo Tidak Mencukupi!
|
||||||
|
</div>
|
||||||
|
<div class="wb">
|
||||||
|
Nominal pengeluaran yang dimasukkan melebihi saldo santri saat ini.
|
||||||
|
Sistem akan menolak transaksi ini. Silakan kurangi nominal atau pastikan
|
||||||
|
data saldo sudah benar.
|
||||||
|
</div>
|
||||||
|
<div class="ws-grid">
|
||||||
|
<div class="ws-cell">
|
||||||
|
<small>Saldo Tersedia</small>
|
||||||
|
<strong id="warn-saldo" style="color:#38a169;">—</strong>
|
||||||
|
</div>
|
||||||
|
<div class="ws-cell">
|
||||||
|
<small>Nominal Diinput</small>
|
||||||
|
<strong id="warn-nominal" style="color:#c53030;">—</strong>
|
||||||
|
</div>
|
||||||
|
<div class="ws-cell">
|
||||||
|
<small>Kekurangan</small>
|
||||||
|
<strong id="warn-kurang" style="color:#c53030;">—</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ══════════════════════════════════════
|
||||||
|
4. TANGGAL
|
||||||
|
══════════════════════════════════════ --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tanggal_transaksi">
|
<label class="field-label" for="tanggal_transaksi">
|
||||||
<i class="fas fa-calendar form-icon"></i>
|
<i class="fas fa-calendar fi"></i> Tanggal Transaksi
|
||||||
Tanggal Transaksi <span style="color: red;">*</span>
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input type="date" name="tanggal_transaksi" id="tanggal_transaksi"
|
<input type="date" name="tanggal_transaksi" id="tanggal_transaksi"
|
||||||
class="form-control @error('tanggal_transaksi') is-invalid @enderror"
|
class="form-control @error('tanggal_transaksi') is-invalid @enderror"
|
||||||
|
|
@ -97,21 +414,25 @@ class="form-control @error('tanggal_transaksi') is-invalid @enderror"
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- ══════════════════════════════════════
|
||||||
|
5. KETERANGAN
|
||||||
|
══════════════════════════════════════ --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="keterangan">
|
<label class="field-label" for="keterangan">
|
||||||
<i class="fas fa-sticky-note form-icon"></i>
|
<i class="fas fa-sticky-note fi"></i> Keterangan
|
||||||
Keterangan
|
<span style="font-weight:400;text-transform:none;letter-spacing:0;color:#bbb;">(opsional)</span>
|
||||||
</label>
|
</label>
|
||||||
<textarea name="keterangan" id="keterangan" class="form-control @error('keterangan') is-invalid @enderror"
|
<textarea name="keterangan" id="keterangan"
|
||||||
rows="4" placeholder="Tuliskan Nama Petugas disini">{{ old('keterangan') }}</textarea>
|
class="form-control @error('keterangan') is-invalid @enderror"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Contoh: Uang saku januari">{{ old('keterangan') }}</textarea>
|
||||||
@error('keterangan')
|
@error('keterangan')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
<small class="form-text">Opsional - Jelaskan detail transaksi</small>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button type="submit" class="btn btn-success hover-lift">
|
<button type="submit" class="btn btn-success hover-lift" id="btnSubmit">
|
||||||
<i class="fas fa-save"></i> Simpan Transaksi
|
<i class="fas fa-save"></i> Simpan Transaksi
|
||||||
</button>
|
</button>
|
||||||
<a href="{{ route('admin.uang-saku.index') }}" class="btn btn-secondary">
|
<a href="{{ route('admin.uang-saku.index') }}" class="btn btn-secondary">
|
||||||
|
|
@ -124,54 +445,174 @@ class="form-control @error('tanggal_transaksi') is-invalid @enderror"
|
||||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
// ═══════════════════════════════════════════
|
||||||
// Inisialisasi Select2
|
// STATE GLOBAL
|
||||||
$('#id_santri').select2({
|
// ═══════════════════════════════════════════
|
||||||
placeholder: '-- Pilih Santri --',
|
var saldoSantri = 0; // saldo raw santri terpilih
|
||||||
allowClear: true,
|
var jenisAktif = ''; // 'pemasukan' | 'pengeluaran' | ''
|
||||||
width: '100%'
|
var nominalBersih = 0; // nominal tanpa titik
|
||||||
});
|
|
||||||
$('#jenis_transaksi').select2({
|
// ═══════════════════════════════════════════
|
||||||
placeholder: '-- Pilih Jenis --',
|
// FORMAT HELPER
|
||||||
allowClear: true,
|
// ═══════════════════════════════════════════
|
||||||
width: '100%'
|
function formatRibuan(val) {
|
||||||
|
var b = String(val).replace(/\D/g, '');
|
||||||
|
return b ? b.replace(/\B(?=(\d{3})+(?!\d))/g, '.') : '';
|
||||||
|
}
|
||||||
|
function stripRibuan(val) { return String(val).replace(/\./g, ''); }
|
||||||
|
function rpStr(angka) { return 'Rp\u00a0' + formatRibuan(angka); }
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// PILIH JENIS (kartu)
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
function pilihJenis(jenis) {
|
||||||
|
jenisAktif = jenis;
|
||||||
|
document.getElementById('jenis_transaksi').value = jenis;
|
||||||
|
document.getElementById('card-pemasukan').classList.toggle('active', jenis === 'pemasukan');
|
||||||
|
document.getElementById('card-pengeluaran').classList.toggle('active', jenis === 'pengeluaran');
|
||||||
|
cekPeringatan();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// CEK PERINGATAN SALDO
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
function cekPeringatan() {
|
||||||
|
var box = document.getElementById('warning-saldo');
|
||||||
|
var wrap = document.getElementById('nominalWrap');
|
||||||
|
var btn = document.getElementById('btnSubmit');
|
||||||
|
|
||||||
|
var kurang = nominalBersih - saldoSantri;
|
||||||
|
var tampil = jenisAktif === 'pengeluaran' && nominalBersih > 0 && kurang > 0;
|
||||||
|
|
||||||
|
if (tampil) {
|
||||||
|
document.getElementById('warn-saldo').textContent = rpStr(saldoSantri);
|
||||||
|
document.getElementById('warn-nominal').textContent = rpStr(nominalBersih);
|
||||||
|
document.getElementById('warn-kurang').textContent = rpStr(kurang);
|
||||||
|
box.style.display = 'block';
|
||||||
|
wrap.classList.add('danger');
|
||||||
|
btn.style.opacity = '.6';
|
||||||
|
btn.title = 'Saldo tidak mencukupi — transaksi akan ditolak!';
|
||||||
|
} else {
|
||||||
|
box.style.display = 'none';
|
||||||
|
wrap.classList.remove('danger');
|
||||||
|
btn.style.opacity = '1';
|
||||||
|
btn.title = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// INPUT NOMINAL — auto titik ribuan
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
var dispEl = document.getElementById('nominal_display');
|
||||||
|
var hiddenEl = document.getElementById('nominal');
|
||||||
|
|
||||||
|
dispEl.addEventListener('input', function () {
|
||||||
|
var bersih = stripRibuan(this.value);
|
||||||
|
var diformat = formatRibuan(bersih);
|
||||||
|
|
||||||
|
// Jaga posisi kursor agar tidak melompat
|
||||||
|
var pos = this.selectionStart;
|
||||||
|
var dotBef = (this.value.substring(0, pos).match(/\./g) || []).length;
|
||||||
|
this.value = diformat;
|
||||||
|
var dotAft = (diformat.substring(0, pos).match(/\./g) || []).length;
|
||||||
|
try { this.setSelectionRange(pos + dotAft - dotBef, pos + dotAft - dotBef); } catch(e) {}
|
||||||
|
|
||||||
|
nominalBersih = parseInt(bersih) || 0;
|
||||||
|
hiddenEl.value = nominalBersih || '';
|
||||||
|
cekPeringatan();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// SUBMIT — konfirmasi ekstra jika saldo kurang
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
document.getElementById('transaksiForm').addEventListener('submit', function (e) {
|
||||||
|
hiddenEl.value = stripRibuan(dispEl.value) || '';
|
||||||
|
|
||||||
|
if (jenisAktif === 'pengeluaran' && nominalBersih > saldoSantri) {
|
||||||
|
var lanjut = confirm(
|
||||||
|
'\u26a0\ufe0f PERINGATAN: Saldo Tidak Mencukupi!\n\n' +
|
||||||
|
'Saldo santri : ' + rpStr(saldoSantri) + '\n' +
|
||||||
|
'Nominal input : ' + rpStr(nominalBersih) + '\n' +
|
||||||
|
'Kekurangan : ' + rpStr(nominalBersih - saldoSantri) + '\n\n' +
|
||||||
|
'Transaksi ini akan DITOLAK oleh sistem.\n' +
|
||||||
|
'Yakin tetap ingin melanjutkan?'
|
||||||
|
);
|
||||||
|
if (!lanjut) { e.preventDefault(); return false; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// SELECT2 + AJAX INFO SANTRI
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
$('#id_santri').select2({
|
||||||
|
placeholder: 'Cari ID atau nama santri...',
|
||||||
|
allowClear: true,
|
||||||
|
width: '100%',
|
||||||
|
language: {
|
||||||
|
noResults: function () { return 'Santri tidak ditemukan'; },
|
||||||
|
searching: function () { return 'Mencari...'; }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Info santri via AJAX – pakai jQuery .on('change') agar kompatibel dengan Select2
|
|
||||||
$('#id_santri').on('change', function () {
|
$('#id_santri').on('change', function () {
|
||||||
var infoBox = document.getElementById('santri-info');
|
var infoBox = document.getElementById('santri-info');
|
||||||
var val = this.value;
|
var val = this.value;
|
||||||
|
|
||||||
|
saldoSantri = 0;
|
||||||
|
cekPeringatan();
|
||||||
|
|
||||||
if (!val) { infoBox.style.display = 'none'; return; }
|
if (!val) { infoBox.style.display = 'none'; return; }
|
||||||
|
|
||||||
fetch('{{ url("admin/uang-saku/santri-info") }}/' + val)
|
fetch('{{ url("admin/uang-saku/santri-info") }}/' + val)
|
||||||
.then(function (r) { return r.json(); })
|
.then(function (r) { return r.json(); })
|
||||||
.then(function (d) {
|
.then(function (d) {
|
||||||
var saldoColor = d.saldo_raw >= 0 ? '#6FBA9D' : '#FF8B94';
|
saldoSantri = d.saldo_raw;
|
||||||
document.getElementById('info-saldo').innerHTML = '<span style="color:' + saldoColor + '">Rp ' + d.saldo_terakhir + '</span>';
|
|
||||||
document.getElementById('info-masuk').textContent = 'Rp ' + d.total_pemasukan_bulan_ini;
|
document.getElementById('info-nama').textContent = d.nama;
|
||||||
document.getElementById('info-keluar').textContent = 'Rp ' + d.total_pengeluaran_bulan_ini;
|
|
||||||
|
var sc = d.saldo_raw >= 100000 ? '#38a169'
|
||||||
|
: d.saldo_raw >= 20000 ? '#f5a623' : '#e53e3e';
|
||||||
|
document.getElementById('info-saldo').innerHTML =
|
||||||
|
'<span style="color:' + sc + '">Rp\u00a0' + d.saldo_terakhir + '</span>';
|
||||||
|
document.getElementById('info-masuk').textContent = 'Rp\u00a0' + d.total_pemasukan_bulan_ini;
|
||||||
|
document.getElementById('info-keluar').textContent = 'Rp\u00a0' + d.total_pengeluaran_bulan_ini;
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
if (d.transaksi_terakhir.length > 0) {
|
if (d.transaksi_terakhir.length > 0) {
|
||||||
html = '<small class="text-muted">3 Transaksi Terakhir:</small><table class="data-table" style="margin-top:6px;font-size:.85rem;"><thead><tr><th>Tanggal</th><th>Jenis</th><th>Nominal</th><th>Ket</th></tr></thead><tbody>';
|
html = '<div style="font-size:.7rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:7px;">3 Transaksi Terakhir</div>';
|
||||||
|
html += '<table class="data-table" style="font-size:.81rem;"><thead><tr>';
|
||||||
|
html += '<th>Tanggal</th><th>Jenis</th><th>Nominal</th><th>Keterangan</th>';
|
||||||
|
html += '</tr></thead><tbody>';
|
||||||
d.transaksi_terakhir.forEach(function (t) {
|
d.transaksi_terakhir.forEach(function (t) {
|
||||||
var badge = t.jenis === 'pemasukan'
|
var badge = t.jenis === 'pemasukan'
|
||||||
? '<span class="badge badge-success">Masuk</span>'
|
? '<span class="badge badge-success">Masuk</span>'
|
||||||
: '<span class="badge badge-danger">Keluar</span>';
|
: '<span class="badge badge-danger">Keluar</span>';
|
||||||
html += '<tr><td>' + t.tanggal + '</td><td>' + badge + '</td><td>Rp ' + t.nominal + '</td><td>' + t.keterangan + '</td></tr>';
|
html += '<tr><td>' + t.tanggal + '</td><td>' + badge +
|
||||||
|
'</td><td>Rp\u00a0' + t.nominal + '</td><td>' + t.keterangan + '</td></tr>';
|
||||||
});
|
});
|
||||||
html += '</tbody></table>';
|
html += '</tbody></table>';
|
||||||
|
} else {
|
||||||
|
html = '<p style="font-size:.8rem;color:#aaa;margin:0;">Belum ada riwayat transaksi.</p>';
|
||||||
}
|
}
|
||||||
document.getElementById('info-riwayat').innerHTML = html;
|
document.getElementById('info-riwayat').innerHTML = html;
|
||||||
infoBox.style.display = 'block';
|
infoBox.style.display = 'block';
|
||||||
|
|
||||||
|
cekPeringatan();
|
||||||
})
|
})
|
||||||
.catch(function() { infoBox.style.display = 'none'; });
|
.catch(function () {
|
||||||
|
document.getElementById('santri-info').style.display = 'none';
|
||||||
|
saldoSantri = 0;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trigger on page load if santri pre-selected
|
// Trigger jika sudah ada pilihan (dari ?id_santri=xxx atau old())
|
||||||
if ($('#id_santri').val()) {
|
if ($('#id_santri').val()) $('#id_santri').trigger('change');
|
||||||
$('#id_santri').trigger('change');
|
|
||||||
}
|
// Restore jenis dari old() setelah validasi server gagal
|
||||||
|
var oldJenis = '{{ old("jenis_transaksi", "") }}';
|
||||||
|
if (oldJenis) pilihJenis(oldJenis);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -1,6 +1,28 @@
|
||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
<style>
|
||||||
|
/* Styling input nominal dengan prefix Rp */
|
||||||
|
.nominal-wrap {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.nominal-wrap .nominal-prefix {
|
||||||
|
position: absolute;
|
||||||
|
left: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-light);
|
||||||
|
pointer-events: none;
|
||||||
|
font-size: .95rem;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.nominal-wrap input {
|
||||||
|
padding-left: 38px !important;
|
||||||
|
letter-spacing: .3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><i class="fas fa-edit"></i> Edit Transaksi Uang Saku</h2>
|
<h2><i class="fas fa-edit"></i> Edit Transaksi Uang Saku</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -10,12 +32,15 @@
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
|
|
||||||
|
{{-- Santri (readonly) --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id_santri">
|
<label for="id_santri">
|
||||||
<i class="fas fa-user form-icon"></i>
|
<i class="fas fa-user form-icon"></i>
|
||||||
Santri
|
Santri
|
||||||
</label>
|
</label>
|
||||||
<input type="text" class="form-control" value="{{ $transaksi->santri->id_santri }} - {{ $transaksi->santri->nama_lengkap }}" readonly disabled>
|
<input type="text" class="form-control"
|
||||||
|
value="{{ $transaksi->santri->id_santri }} - {{ $transaksi->santri->nama_lengkap }}"
|
||||||
|
readonly disabled>
|
||||||
<small class="form-text">Santri tidak dapat diubah</small>
|
<small class="form-text">Santri tidak dapat diubah</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -40,17 +65,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Jenis Transaksi --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="jenis_transaksi">
|
<label for="jenis_transaksi">
|
||||||
<i class="fas fa-exchange-alt form-icon"></i>
|
<i class="fas fa-exchange-alt form-icon"></i>
|
||||||
Jenis Transaksi <span style="color: red;">*</span>
|
Jenis Transaksi <span style="color: red;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<select name="jenis_transaksi" id="jenis_transaksi" class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
|
<select name="jenis_transaksi" id="jenis_transaksi"
|
||||||
|
class="form-control @error('jenis_transaksi') is-invalid @enderror" required>
|
||||||
<option value="">-- Pilih Jenis --</option>
|
<option value="">-- Pilih Jenis --</option>
|
||||||
<option value="pemasukan" {{ old('jenis_transaksi', $transaksi->jenis_transaksi) == 'pemasukan' ? 'selected' : '' }}>
|
<option value="pemasukan"
|
||||||
|
{{ old('jenis_transaksi', $transaksi->jenis_transaksi) == 'pemasukan' ? 'selected' : '' }}>
|
||||||
Pemasukan (Terima Uang Saku)
|
Pemasukan (Terima Uang Saku)
|
||||||
</option>
|
</option>
|
||||||
<option value="pengeluaran" {{ old('jenis_transaksi', $transaksi->jenis_transaksi) == 'pengeluaran' ? 'selected' : '' }}>
|
<option value="pengeluaran"
|
||||||
|
{{ old('jenis_transaksi', $transaksi->jenis_transaksi) == 'pengeluaran' ? 'selected' : '' }}>
|
||||||
Pengeluaran (Gunakan Uang Saku)
|
Pengeluaran (Gunakan Uang Saku)
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -59,18 +88,43 @@
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{--
|
||||||
|
NOMINAL — Auto-format dengan titik sebagai pemisah ribuan.
|
||||||
|
Cara kerja:
|
||||||
|
• #nominal_display → input text yang ditampilkan ke user (format: 10.000)
|
||||||
|
• #nominal → hidden input yang dikirim ke server (raw: 10000)
|
||||||
|
--}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="nominal">
|
<label for="nominal_display">
|
||||||
<i class="fas fa-money-bill-wave form-icon"></i>
|
<i class="fas fa-money-bill-wave form-icon"></i>
|
||||||
Nominal (Rp) <span style="color: red;">*</span>
|
Nominal (Rp) <span style="color: red;">*</span>
|
||||||
</label>
|
</label>
|
||||||
<input type="number" name="nominal" id="nominal" class="form-control @error('nominal') is-invalid @enderror"
|
|
||||||
value="{{ old('nominal', $transaksi->nominal) }}" placeholder="Contoh: 50000" min="1" step="1" required>
|
<div class="nominal-wrap">
|
||||||
@error('nominal')
|
<span class="nominal-prefix">Rp</span>
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
@php
|
||||||
@enderror
|
$nominalLama = old('nominal', $transaksi->nominal);
|
||||||
|
$nominalDisplay = $nominalLama ? number_format((int)$nominalLama, 0, ',', '.') : '';
|
||||||
|
@endphp
|
||||||
|
<input type="text"
|
||||||
|
id="nominal_display"
|
||||||
|
class="form-control @error('nominal') is-invalid @enderror"
|
||||||
|
placeholder="0"
|
||||||
|
autocomplete="off"
|
||||||
|
inputmode="numeric"
|
||||||
|
value="{{ $nominalDisplay }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Input tersembunyi yang benar-benar dikirim --}}
|
||||||
|
<input type="hidden" name="nominal" id="nominal" value="{{ $nominalLama }}">
|
||||||
|
|
||||||
|
@error('nominal')
|
||||||
|
<div class="invalid-feedback" style="display:block;">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
<small class="form-text">Ketik angka, titik akan muncul otomatis. Contoh: <strong>50.000</strong></small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Tanggal Transaksi --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tanggal_transaksi">
|
<label for="tanggal_transaksi">
|
||||||
<i class="fas fa-calendar form-icon"></i>
|
<i class="fas fa-calendar form-icon"></i>
|
||||||
|
|
@ -84,13 +138,16 @@ class="form-control @error('tanggal_transaksi') is-invalid @enderror"
|
||||||
@enderror
|
@enderror
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- Keterangan --}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="keterangan">
|
<label for="keterangan">
|
||||||
<i class="fas fa-sticky-note form-icon"></i>
|
<i class="fas fa-sticky-note form-icon"></i>
|
||||||
Keterangan
|
Keterangan
|
||||||
</label>
|
</label>
|
||||||
<textarea name="keterangan" id="keterangan" class="form-control @error('keterangan') is-invalid @enderror"
|
<textarea name="keterangan" id="keterangan"
|
||||||
rows="4" placeholder="Contoh: Uang saku bulan Januari 2025">{{ old('keterangan', $transaksi->keterangan) }}</textarea>
|
class="form-control @error('keterangan') is-invalid @enderror"
|
||||||
|
rows="4"
|
||||||
|
placeholder="Contoh: Uang saku bulan Januari 2025">{{ old('keterangan', $transaksi->keterangan) }}</textarea>
|
||||||
@error('keterangan')
|
@error('keterangan')
|
||||||
<div class="invalid-feedback">{{ $message }}</div>
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
@enderror
|
@enderror
|
||||||
|
|
@ -108,24 +165,65 @@ class="form-control @error('tanggal_transaksi') is-invalid @enderror"
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// ── Helpers format angka ────────────────────────────────────────────
|
||||||
|
function formatRibuan(nilai) {
|
||||||
|
var bersih = String(nilai).replace(/\D/g, '');
|
||||||
|
if (!bersih) return '';
|
||||||
|
return bersih.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripRibuan(nilai) {
|
||||||
|
return String(nilai).replace(/\./g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Inisialisasi input nominal ──────────────────────────────────────
|
||||||
|
var displayInput = document.getElementById('nominal_display');
|
||||||
|
var hiddenInput = document.getElementById('nominal');
|
||||||
|
|
||||||
|
displayInput.addEventListener('input', function () {
|
||||||
|
var bersih = stripRibuan(this.value);
|
||||||
|
var diformat = formatRibuan(bersih);
|
||||||
|
|
||||||
|
var selStart = this.selectionStart;
|
||||||
|
var selEnd = this.selectionEnd;
|
||||||
|
var dotSebelum = (this.value.substring(0, selStart).match(/\./g) || []).length;
|
||||||
|
this.value = diformat;
|
||||||
|
var dotSesudah = (diformat.substring(0, selStart).match(/\./g) || []).length;
|
||||||
|
var offset = dotSesudah - dotSebelum;
|
||||||
|
|
||||||
|
try { this.setSelectionRange(selStart + offset, selEnd + offset); } catch (e) {}
|
||||||
|
|
||||||
|
hiddenInput.value = bersih;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Saat form submit: pastikan hidden input sudah terisi dari display
|
||||||
|
document.getElementById('transaksiForm').addEventListener('submit', function () {
|
||||||
|
hiddenInput.value = stripRibuan(displayInput.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Info santri via AJAX saat halaman load ──────────────────────────
|
||||||
(function () {
|
(function () {
|
||||||
var idSantri = '{{ $transaksi->santri->id_santri }}';
|
var idSantri = '{{ $transaksi->santri->id_santri }}';
|
||||||
fetch('{{ url("admin/uang-saku/santri-info") }}/' + idSantri)
|
fetch('{{ url("admin/uang-saku/santri-info") }}/' + idSantri)
|
||||||
.then(function (r) { return r.json(); })
|
.then(function (r) { return r.json(); })
|
||||||
.then(function (d) {
|
.then(function (d) {
|
||||||
var saldoColor = d.saldo_raw >= 0 ? '#6FBA9D' : '#FF8B94';
|
var saldoColor = d.saldo_raw >= 0 ? '#6FBA9D' : '#FF8B94';
|
||||||
document.getElementById('info-saldo').innerHTML = '<span style="color:' + saldoColor + '">Rp ' + d.saldo_terakhir + '</span>';
|
document.getElementById('info-saldo').innerHTML =
|
||||||
|
'<span style="color:' + saldoColor + '">Rp ' + d.saldo_terakhir + '</span>';
|
||||||
document.getElementById('info-masuk').textContent = 'Rp ' + d.total_pemasukan_bulan_ini;
|
document.getElementById('info-masuk').textContent = 'Rp ' + d.total_pemasukan_bulan_ini;
|
||||||
document.getElementById('info-keluar').textContent = 'Rp ' + d.total_pengeluaran_bulan_ini;
|
document.getElementById('info-keluar').textContent = 'Rp ' + d.total_pengeluaran_bulan_ini;
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
if (d.transaksi_terakhir.length > 0) {
|
if (d.transaksi_terakhir.length > 0) {
|
||||||
html = '<small class="text-muted">3 Transaksi Terakhir:</small><table class="data-table" style="margin-top:6px;font-size:.85rem;"><thead><tr><th>Tanggal</th><th>Jenis</th><th>Nominal</th><th>Ket</th></tr></thead><tbody>';
|
html = '<small class="text-muted">3 Transaksi Terakhir:</small>';
|
||||||
|
html += '<table class="data-table" style="margin-top:6px;font-size:.85rem;">';
|
||||||
|
html += '<thead><tr><th>Tanggal</th><th>Jenis</th><th>Nominal</th><th>Ket</th></tr></thead><tbody>';
|
||||||
d.transaksi_terakhir.forEach(function (t) {
|
d.transaksi_terakhir.forEach(function (t) {
|
||||||
var badge = t.jenis === 'pemasukan'
|
var badge = t.jenis === 'pemasukan'
|
||||||
? '<span class="badge badge-success">Masuk</span>'
|
? '<span class="badge badge-success">Masuk</span>'
|
||||||
: '<span class="badge badge-danger">Keluar</span>';
|
: '<span class="badge badge-danger">Keluar</span>';
|
||||||
html += '<tr><td>' + t.tanggal + '</td><td>' + badge + '</td><td>Rp ' + t.nominal + '</td><td>' + t.keterangan + '</td></tr>';
|
html += '<tr><td>' + t.tanggal + '</td><td>' + badge +
|
||||||
|
'</td><td>Rp ' + t.nominal + '</td><td>' + t.keterangan + '</td></tr>';
|
||||||
});
|
});
|
||||||
html += '</tbody></table>';
|
html += '</tbody></table>';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,22 @@
|
||||||
<div class="alert alert-danger"><i class="fas fa-exclamation-circle"></i> {{ session('error') }}</div>
|
<div class="alert alert-danger"><i class="fas fa-exclamation-circle"></i> {{ session('error') }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- ── FILTER + KPI ── --}}
|
<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;">
|
<div class="content-box" style="margin-bottom:16px;">
|
||||||
<form method="GET" action="{{ route('admin.uang-saku.index') }}" id="filterForm"
|
<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;">
|
style="display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;margin-bottom:18px;">
|
||||||
|
|
@ -28,7 +43,6 @@
|
||||||
<input type="date" name="sampai" class="form-control" value="{{ $sampai }}" style="width:155px;">
|
<input type="date" name="sampai" class="form-control" value="{{ $sampai }}" style="width:155px;">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Preset cepat --}}
|
|
||||||
<div style="display:flex;gap:5px;flex-wrap:wrap;align-self:flex-end;">
|
<div style="display:flex;gap:5px;flex-wrap:wrap;align-self:flex-end;">
|
||||||
@php
|
@php
|
||||||
$bulanIniDari = now()->startOfMonth()->format('Y-m-d');
|
$bulanIniDari = now()->startOfMonth()->format('Y-m-d');
|
||||||
|
|
@ -37,136 +51,107 @@
|
||||||
$isHariIni = $dari === now()->format('Y-m-d') && $sampai === now()->format('Y-m-d');
|
$isHariIni = $dari === now()->format('Y-m-d') && $sampai === now()->format('Y-m-d');
|
||||||
@endphp
|
@endphp
|
||||||
<button type="button" onclick="setPreset('today')"
|
<button type="button" onclick="setPreset('today')"
|
||||||
class="btn btn-sm {{ $isHariIni ? 'btn-primary' : 'btn-secondary' }}">
|
class="btn btn-sm {{ $isHariIni ? 'btn-primary' : 'btn-secondary' }}">Hari Ini</button>
|
||||||
Hari Ini
|
|
||||||
</button>
|
|
||||||
<button type="button" onclick="setPreset('month')"
|
<button type="button" onclick="setPreset('month')"
|
||||||
class="btn btn-sm {{ $isBulanIni ? 'btn-primary' : 'btn-secondary' }}">
|
class="btn btn-sm {{ $isBulanIni ? 'btn-primary' : 'btn-secondary' }}">Bulan Ini</button>
|
||||||
Bulan Ini
|
|
||||||
</button>
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm">
|
<button type="submit" class="btn btn-primary btn-sm">
|
||||||
<i class="fas fa-filter"></i> Terapkan
|
<i class="fas fa-filter"></i> Terapkan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{--
|
{{-- KPI Baris 1 --}}
|
||||||
┌─────────────────────────────────────────────────────────────────────â”
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom:10px;">
|
||||||
│ KPI Cards │
|
<div class="card card-info" style="margin: 0;">
|
||||||
│ │
|
|
||||||
│ Baris 1 (dipengaruhi filter tanggal): │
|
|
||||||
│ • Total Transaksi — jumlah baris transaksi di periode ini │
|
|
||||||
│ • Total Pemasukan — uang masuk ke santri di periode ini │
|
|
||||||
│ • Total Pengeluaran — uang keluar dari santri di periode ini │
|
|
||||||
│ • Selisih (Net) — pemasukan minus pengeluaran di periode ini │
|
|
||||||
│ positif = lebih banyak uang masuk (surplus) │
|
|
||||||
│ negatif = lebih banyak uang keluar (defisit)│
|
|
||||||
│ │
|
|
||||||
│ Baris 2 (REAL-TIME, tidak terpengaruh filter): │
|
|
||||||
│ • Total Saldo Seluruh Santri — total uang yang sedang dipegang │
|
|
||||||
│ oleh seluruh santri aktif saat ini │
|
|
||||||
└─────────────────────────────────────────────────────────────────────┘
|
|
||||||
--}}
|
|
||||||
|
|
||||||
{{-- KPI Baris 1: berdasarkan filter periode --}}
|
|
||||||
<div class="row-cards row-cards-4" style="margin-bottom:10px;">
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Total Transaksi</h3>
|
<h3>Total Transaksi</h3>
|
||||||
<p class="card-value">{{ $kpi['total_transaksi'] }}</p>
|
<p class="card-value">{{ $kpi['total_transaksi'] }} Transaksi</p>
|
||||||
<span class="card-sub">dari {{ $kpi['total_santri'] }} santri</span>
|
<span class="card-sub">dari {{ $kpi['total_santri'] }} santri</span>
|
||||||
<i class="fas fa-exchange-alt card-icon"></i>
|
<i class="fas fa-exchange-alt card-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="card card-success">
|
<div class="card card-success" style="margin: 0;">
|
||||||
<h3>Total Pemasukan</h3>
|
<h3>Total Setoran (Masuk)</h3>
|
||||||
<p class="card-value" style="font-size:1.05rem;">Rp {{ number_format($kpi['total_pemasukan'], 0, ',', '.') }}</p>
|
<p class="card-value" style="font-size:1.05rem;">Rp {{ number_format($kpi['total_pemasukan'], 0, ',', '.') }}</p>
|
||||||
<span class="card-sub">
|
<span class="card-sub">
|
||||||
{{ \Carbon\Carbon::parse($dari)->format('d M') }} – {{ \Carbon\Carbon::parse($sampai)->format('d M Y') }}
|
{{ \Carbon\Carbon::parse($dari)->format('d M') }} – {{ \Carbon\Carbon::parse($sampai)->format('d M Y') }}
|
||||||
</span>
|
</span>
|
||||||
<i class="fas fa-arrow-circle-down card-icon"></i>
|
<i class="fas fa-arrow-circle-down card-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="card card-warning">
|
<div class="card card-warning" style="margin: 0;">
|
||||||
<h3>Total Pengeluaran</h3>
|
<h3>Total Penarikan (Keluar)</h3>
|
||||||
<p class="card-value" style="font-size:1.05rem;">Rp {{ number_format($kpi['total_pengeluaran'], 0, ',', '.') }}</p>
|
<p class="card-value" style="font-size:1.05rem;">Rp {{ number_format($kpi['total_pengeluaran'], 0, ',', '.') }}</p>
|
||||||
<span class="card-sub">
|
<span class="card-sub">
|
||||||
{{ \Carbon\Carbon::parse($dari)->format('d M') }} – {{ \Carbon\Carbon::parse($sampai)->format('d M Y') }}
|
{{ \Carbon\Carbon::parse($dari)->format('d M') }} – {{ \Carbon\Carbon::parse($sampai)->format('d M Y') }}
|
||||||
</span>
|
</span>
|
||||||
<i class="fas fa-arrow-circle-up card-icon"></i>
|
<i class="fas fa-arrow-circle-up card-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="card {{ $kpi['selisih'] >= 0 ? 'card-success' : 'card-danger' }}">
|
|
||||||
<h3>
|
|
||||||
Selisih Periode
|
|
||||||
<span title="Selisih = Total Pemasukan dikurangi Total Pengeluaran pada periode yang dipilih. Surplus berarti lebih banyak uang masuk; Defisit berarti lebih banyak uang keluar."
|
|
||||||
style="cursor:help;font-size:.75rem;color:var(--text-light);">
|
|
||||||
<i class="fas fa-question-circle"></i>
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
<p class="card-value" style="font-size:1.05rem;">
|
|
||||||
{{ $kpi['selisih'] >= 0 ? '+' : '-' }} Rp {{ number_format(abs($kpi['selisih']), 0, ',', '.') }}
|
|
||||||
</p>
|
|
||||||
<span class="card-sub">{{ $kpi['selisih'] >= 0 ? '✓ Surplus periode ini' : '✗ Defisit periode ini' }}</span>
|
|
||||||
<i class="fas fa-balance-scale card-icon"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- KPI Baris 2: real-time, tidak berubah meski filter diganti --}}
|
{{-- KPI Baris 2: saldo real-time --}}
|
||||||
<div class="row-cards row-cards-1">
|
<div class="row-cards row-cards-1">
|
||||||
<div class="card card-primary" style="border-left: 4px solid var(--primary-color); position:relative;">
|
<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 style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:space-between;">
|
||||||
<div>
|
<div>
|
||||||
<h3 style="margin:0 0 4px;">
|
<h3 style="margin:0 0 4px;">Total Saldo Seluruh Santri</h3>
|
||||||
Total Saldo Seluruh Santri
|
|
||||||
</h3>
|
|
||||||
<p class="card-value" style="font-size:1.4rem;margin:0;color:var(--primary-color);">
|
<p class="card-value" style="font-size:1.4rem;margin:0;color:var(--primary-color);">
|
||||||
Rp {{ number_format($kpi['total_saldo_realtime'], 0, ',', '.') }}
|
Rp {{ number_format($kpi['total_saldo_realtime'], 0, ',', '.') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align:right;">
|
|
||||||
<span class="badge badge-info" style="font-size:.8rem;padding:5px 10px;">
|
<span class="badge badge-info" style="font-size:.8rem;padding:5px 10px;">
|
||||||
<i class="fas fa-clock"></i> Real-time — tidak terpengaruh filter tanggal
|
<i class="fas fa-clock"></i> Akumulasi semua waktu — tidak terpengaruh filter
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<i class="fas fa-piggy-bank card-icon"></i>
|
<i class="fas fa-piggy-bank card-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- ── DAFTAR SANTRI ── --}}
|
{{-- ── DAFTAR SANTRI ── --}}
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
|
|
||||||
{{-- Toolbar: Tambah + Search + Sort --}}
|
{{-- Toolbar --}}
|
||||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:14px; flex-wrap:wrap; gap:10px;">
|
<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">
|
<a href="{{ route('admin.uang-saku.create') }}" class="btn btn-primary">
|
||||||
<i class="fas fa-plus"></i> Tambah Transaksi
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
</a>
|
</a>
|
||||||
|
@else
|
||||||
|
<div></div>{{-- spacer agar sort tetap rata kanan --}}
|
||||||
|
@endif
|
||||||
|
|
||||||
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
|
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
|
||||||
{{-- Sort --}}
|
{{-- Sort --}}
|
||||||
<form method="GET" action="{{ route('admin.uang-saku.index') }}" id="sortForm" style="display:flex;gap:6px;align-items:center;">
|
<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="dari" value="{{ $dari }}">
|
||||||
<input type="hidden" name="sampai" value="{{ $sampai }}">
|
<input type="hidden" name="sampai" value="{{ $sampai }}">
|
||||||
@if(request('search')) <input type="hidden" name="search" value="{{ request('search') }}"> @endif
|
@if(request('search')) <input type="hidden" name="search" value="{{ request('search') }}"> @endif
|
||||||
<label style="font-size:.79rem;color:var(--text-light);white-space:nowrap;">
|
<label style="font-size:.79rem;color:var(--text-light);white-space:nowrap;">
|
||||||
<i class="fas fa-sort"></i> Urut:
|
<i class="fas fa-sort"></i> Urut:
|
||||||
</label>
|
</label>
|
||||||
<select name="sort" class="form-control form-control-sm" onchange="this.form.submit()" style="width:auto;">
|
<select name="sort" class="form-control form-control-sm"
|
||||||
<option value="nama" {{ $sort==='nama' ? 'selected' : '' }}>Nama A–Z</option>
|
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_asc" {{ $sort==='saldo_asc' ? 'selected':'' }}>Saldo Terendah</option>
|
||||||
<option value="saldo_desc" {{ $sort==='saldo_desc' ? 'selected':'' }}>Saldo Tertinggi</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="transaksi_desc" {{ $sort==='transaksi_desc'? 'selected':'' }}>Transaksi Terbanyak</option>
|
||||||
<option value="terakhir" {{ $sort==='terakhir' ? 'selected':'' }}>Transaksi Terbaru</option>
|
<option value="terakhir" {{ $sort==='terakhir' ? 'selected':'' }}>Transaksi Terbaru</option>
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{{-- Search --}}
|
{{-- Search --}}
|
||||||
<form method="GET" action="{{ route('admin.uang-saku.index') }}" style="display:flex;gap:6px;">
|
<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="dari" value="{{ $dari }}">
|
||||||
<input type="hidden" name="sampai" value="{{ $sampai }}">
|
<input type="hidden" name="sampai" value="{{ $sampai }}">
|
||||||
<input type="hidden" name="sort" value="{{ $sort }}">
|
<input type="hidden" name="sort" value="{{ $sort }}">
|
||||||
<input type="text" name="search" class="form-control form-control-sm"
|
<input type="text" name="search" class="form-control form-control-sm"
|
||||||
placeholder="Cari nama / ID santri..."
|
placeholder="Cari nama / ID santri..."
|
||||||
value="{{ request('search') }}" style="width:210px;">
|
value="{{ request('search') }}" style="width:210px;">
|
||||||
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-search"></i></button>
|
<button type="submit" class="btn btn-primary btn-sm">
|
||||||
|
<i class="fas fa-search"></i>
|
||||||
|
</button>
|
||||||
@if(request('search'))
|
@if(request('search'))
|
||||||
<a href="{{ route('admin.uang-saku.index', ['dari'=>$dari,'sampai'=>$sampai,'sort'=>$sort]) }}"
|
<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>
|
class="btn btn-secondary btn-sm"><i class="fas fa-times"></i></a>
|
||||||
|
|
@ -175,75 +160,76 @@ class="btn btn-secondary btn-sm"><i class="fas fa-times"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Legend saldo --}}
|
{{-- Legend warna saldo --}}
|
||||||
<div style="display:flex;gap:14px;margin-bottom:12px;flex-wrap:wrap;font-size:.78rem;color:var(--text-light);">
|
<div style="display:flex;gap:14px;margin-bottom:12px;flex-wrap:wrap;
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#6FBA9D;margin-right:4px;"></span>Saldo ≥ Rp 100rb</span>
|
font-size:.78rem;color:var(--text-light);">
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#f5a623;margin-right:4px;"></span>Saldo Rp 20rb – 99rb</span>
|
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;
|
||||||
<span><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:#FF8B94;margin-right:4px;"></span>Saldo < Rp 20rb</span>
|
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>< Rp 20.000</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- List santri --}}
|
{{-- ── LIST SANTRI ── --}}
|
||||||
@if($santriList->count() > 0)
|
@if($santriList->count() > 0)
|
||||||
|
|
||||||
@foreach($santriList as $santri)
|
@foreach($santriList as $santri)
|
||||||
@php
|
@php
|
||||||
$saldoColor = $santri->saldo_terakhir >= 100000 ? '#6FBA9D'
|
$sc = $santri->saldo_terakhir >= 100000 ? '#6FBA9D'
|
||||||
: ($santri->saldo_terakhir >= 20000 ? '#f5a623' : '#FF8B94');
|
: ($santri->saldo_terakhir >= 20000 ? '#f5a623' : '#FF8B94');
|
||||||
$saldoDot = $saldoColor;
|
|
||||||
@endphp
|
@endphp
|
||||||
<div class="content-box us-row" style="margin-bottom:10px;padding:0;overflow:hidden;">
|
|
||||||
|
|
||||||
{{-- Baris utama — klik untuk expand --}}
|
<div class="content-box us-row"
|
||||||
|
style="margin-bottom:10px;padding:0;overflow:hidden;">
|
||||||
|
|
||||||
|
{{-- ── Baris utama ── --}}
|
||||||
<div class="us-row-header"
|
<div class="us-row-header"
|
||||||
onclick="toggleDetail('detail-{{ $santri->id_santri }}', this)"
|
onclick="toggleDetail('detail-{{ $santri->id_santri }}', this)"
|
||||||
style="display:flex;align-items:center;gap:0;cursor:pointer;padding:13px 16px;flex-wrap:wrap;gap:10px;">
|
style="display:flex;align-items:center;cursor:pointer;
|
||||||
|
padding:12px 16px;flex-wrap:wrap;gap:10px;">
|
||||||
|
|
||||||
{{-- Chevron + Nama --}}
|
{{-- Chevron + Nama --}}
|
||||||
<div style="display:flex;align-items:center;gap:10px;flex:1;min-width:160px;">
|
<div style="display:flex;align-items:center;gap:10px;flex:1;min-width:160px;">
|
||||||
<i class="fas fa-chevron-right toggle-arrow"
|
<i class="fas fa-chevron-right toggle-arrow"
|
||||||
style="transition:transform .2s;color:var(--text-light);font-size:.8rem;flex-shrink:0;"></i>
|
style="transition:transform .2s;color:var(--text-light);
|
||||||
|
font-size:.8rem;flex-shrink:0;"></i>
|
||||||
<div>
|
<div>
|
||||||
<div style="font-weight:700;font-size:.93rem;">{{ $santri->nama_lengkap }}</div>
|
<div style="font-weight:700;font-size:.93rem;">
|
||||||
<div style="font-size:.76rem;color:var(--text-light);">{{ $santri->id_santri }}</div>
|
{{ $santri->nama_lengkap }}
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.74rem;color:var(--text-light);">
|
||||||
|
{{ $santri->id_santri }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Saldo sekarang (prominent) --}}
|
{{-- Saldo saat ini (kumulatif) --}}
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:120px;">
|
<div style="display:flex;flex-direction:column;align-items:center;min-width:130px;">
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Saldo</div>
|
<div style="font-size:.62rem;color:var(--text-light);margin-bottom:2px;
|
||||||
<div style="font-size:1.05rem;font-weight:800;color:{{ $saldoColor }};display:flex;align-items:center;gap:5px;">
|
font-weight:600;text-transform:uppercase;letter-spacing:.4px;">
|
||||||
<span style="width:8px;height:8px;border-radius:50%;background:{{ $saldoDot }};flex-shrink:0;display:inline-block;"></span>
|
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, ',', '.') }}
|
Rp {{ number_format($santri->saldo_terakhir, 0, ',', '.') }}
|
||||||
</div>
|
</div>
|
||||||
|
<div style="font-size:.6rem;color:#ccc;margin-top:2px;">akumulasi semua waktu</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Divider --}}
|
<div class="vdiv"></div>
|
||||||
<div style="width:1px;height:36px;background:var(--primary-light);flex-shrink:0;"></div>
|
|
||||||
|
|
||||||
{{-- Pemasukan bulan ini --}}
|
{{-- Jumlah transaksi + tanggal terakhir --}}
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:100px;">
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Masuk Bln Ini</div>
|
|
||||||
<div style="font-size:.85rem;font-weight:700;color:#6FBA9D;">
|
|
||||||
+ Rp {{ number_format($santri->pemasukan_bulan, 0, ',', '.') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Pengeluaran bulan ini --}}
|
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:100px;">
|
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Keluar Bln Ini</div>
|
|
||||||
<div style="font-size:.85rem;font-weight:700;color:#FF8B94;">
|
|
||||||
- Rp {{ number_format($santri->pengeluaran_bulan, 0, ',', '.') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Divider --}}
|
|
||||||
<div style="width:1px;height:36px;background:var(--primary-light);flex-shrink:0;"></div>
|
|
||||||
|
|
||||||
{{-- Transaksi + tanggal terakhir --}}
|
|
||||||
<div style="display:flex;flex-direction:column;align-items:center;min-width:90px;">
|
<div style="display:flex;flex-direction:column;align-items:center;min-width:90px;">
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-bottom:2px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;">Transaksi</div>
|
<div style="font-size:.62rem;color:var(--text-light);margin-bottom:2px;
|
||||||
<span class="badge badge-info" style="font-size:.74rem;">{{ $santri->transaksi_bulan_ini }}x bln ini</span>
|
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)
|
@if($santri->transaksi_terakhir_tgl)
|
||||||
<div style="font-size:.7rem;color:var(--text-light);margin-top:3px;">
|
<div style="font-size:.66rem;color:var(--text-light);margin-top:3px;">
|
||||||
terakhir {{ \Carbon\Carbon::parse($santri->transaksi_terakhir_tgl)->format('d/m/Y') }}
|
terakhir {{ \Carbon\Carbon::parse($santri->transaksi_terakhir_tgl)->format('d/m/Y') }}
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
@ -251,10 +237,13 @@ class="btn btn-secondary btn-sm"><i class="fas fa-times"></i></a>
|
||||||
|
|
||||||
{{-- Aksi --}}
|
{{-- Aksi --}}
|
||||||
<div style="display:flex;gap:5px;flex-shrink:0;" onclick="event.stopPropagation()">
|
<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 }}"
|
<a href="{{ route('admin.uang-saku.create') }}?id_santri={{ $santri->id_santri }}"
|
||||||
class="btn btn-success btn-sm" title="Tambah Transaksi">
|
class="btn btn-success btn-sm" title="Tambah Transaksi">
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}"
|
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}"
|
||||||
class="btn btn-primary btn-sm" title="Riwayat Lengkap">
|
class="btn btn-primary btn-sm" title="Riwayat Lengkap">
|
||||||
<i class="fas fa-history"></i>
|
<i class="fas fa-history"></i>
|
||||||
|
|
@ -262,7 +251,7 @@ class="btn btn-primary btn-sm" title="Riwayat Lengkap">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Detail transaksi (collapsed) --}}
|
{{-- ── Detail transaksi (collapsed) ── --}}
|
||||||
<div id="detail-{{ $santri->id_santri }}"
|
<div id="detail-{{ $santri->id_santri }}"
|
||||||
style="display:none;border-top:1px solid var(--primary-light);padding:12px 16px;">
|
style="display:none;border-top:1px solid var(--primary-light);padding:12px 16px;">
|
||||||
@if($santri->transaksi_terbaru->isNotEmpty())
|
@if($santri->transaksi_terbaru->isNotEmpty())
|
||||||
|
|
@ -274,7 +263,7 @@ class="btn btn-primary btn-sm" title="Riwayat Lengkap">
|
||||||
<th>Jenis</th>
|
<th>Jenis</th>
|
||||||
<th>Nominal</th>
|
<th>Nominal</th>
|
||||||
<th>Keterangan</th>
|
<th>Keterangan</th>
|
||||||
<th>Saldo</th>
|
<th>Saldo Sesudah</th>
|
||||||
<th class="text-center">Aksi</th>
|
<th class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
@ -284,25 +273,38 @@ class="btn btn-primary btn-sm" title="Riwayat Lengkap">
|
||||||
<td>{{ $tx->tanggal_transaksi->format('d/m/Y') }}</td>
|
<td>{{ $tx->tanggal_transaksi->format('d/m/Y') }}</td>
|
||||||
<td>
|
<td>
|
||||||
@if($tx->jenis_transaksi === 'pemasukan')
|
@if($tx->jenis_transaksi === 'pemasukan')
|
||||||
<span class="badge badge-success"><i class="fas fa-arrow-down"></i> Masuk</span>
|
<span class="badge badge-success">
|
||||||
|
<i class="fas fa-arrow-down"></i> Masuk
|
||||||
|
</span>
|
||||||
@else
|
@else
|
||||||
<span class="badge badge-danger"><i class="fas fa-arrow-up"></i> Keluar</span>
|
<span class="badge badge-danger">
|
||||||
|
<i class="fas fa-arrow-up"></i> Keluar
|
||||||
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="nominal-highlight">{{ $tx->nominal_format }}</td>
|
<td class="nominal-highlight">Rp {{ number_format($tx->nominal, 0, ',', '.') }}</td>
|
||||||
<td><div class="content-preview">{{ $tx->keterangan ?? '-' }}</div></td>
|
<td><div class="content-preview">{{ $tx->keterangan ?? '-' }}</div></td>
|
||||||
<td style="font-weight:600;color:{{ $tx->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94' }};">
|
<td style="font-weight:600;
|
||||||
|
color:{{ $tx->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94' }};">
|
||||||
Rp {{ number_format($tx->saldo_sesudah, 0, ',', '.') }}
|
Rp {{ number_format($tx->saldo_sesudah, 0, ',', '.') }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div style="display:flex;gap:4px;justify-content: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>
|
<a href="{{ route('admin.uang-saku.show', $tx->id) }}"
|
||||||
<a href="{{ route('admin.uang-saku.edit', $tx->id) }}" class="btn btn-warning btn-sm"><i class="fas fa-edit"></i></a>
|
class="btn btn-primary btn-sm"><i class="fas fa-eye"></i></a>
|
||||||
<form action="{{ route('admin.uang-saku.destroy', $tx->id) }}" method="POST"
|
{{-- Edit & Hapus: hanya pamong --}}
|
||||||
style="display:inline;" onsubmit="return confirm('Yakin hapus transaksi ini?')">
|
@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')
|
@csrf @method('DELETE')
|
||||||
<button class="btn btn-danger btn-sm"><i class="fas fa-trash"></i></button>
|
<button class="btn btn-danger btn-sm">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -319,26 +321,38 @@ class="btn btn-secondary btn-sm">
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
<p class="text-muted" style="margin:0;">Belum ada transaksi.</p>
|
<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
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
<div style="margin-top:14px;">{{ $santriList->links() }}</div>
|
<div style="margin-top:14px;">{{ $santriList->links() }}</div>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<i class="fas fa-wallet"></i>
|
<i class="fas fa-wallet"></i>
|
||||||
<h3>Belum Ada Data</h3>
|
<h3>Belum Ada Data</h3>
|
||||||
<p>Belum ada santri dengan transaksi uang saku.</p>
|
<p>Belum ada santri dengan transaksi uang saku.</p>
|
||||||
|
@if($canCrud)
|
||||||
<a href="{{ route('admin.uang-saku.create') }}" class="btn btn-success">
|
<a href="{{ route('admin.uang-saku.create') }}" class="btn btn-success">
|
||||||
<i class="fas fa-plus"></i> Tambah Transaksi
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
// TOGGLE DETAIL ROW
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
function toggleDetail(id, el) {
|
function toggleDetail(id, el) {
|
||||||
var detail = document.getElementById(id);
|
var detail = document.getElementById(id);
|
||||||
var arrow = el.querySelector('.toggle-arrow');
|
var arrow = el.querySelector('.toggle-arrow');
|
||||||
|
|
@ -347,24 +361,26 @@ function toggleDetail(id, el) {
|
||||||
arrow.style.transform = open ? 'rotate(0deg)' : 'rotate(90deg)';
|
arrow.style.transform = open ? 'rotate(0deg)' : 'rotate(90deg)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
// PRESET FILTER TANGGAL
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
function setPreset(type) {
|
function setPreset(type) {
|
||||||
var form = document.getElementById('filterForm');
|
var form = document.getElementById('filterForm');
|
||||||
var dari = form.querySelector('[name=dari]');
|
var dari = form.querySelector('[name=dari]');
|
||||||
var sampai = form.querySelector('[name=sampai]');
|
var sampai = form.querySelector('[name=sampai]');
|
||||||
var today = new Date();
|
var today = new Date();
|
||||||
var pad = n => String(n).padStart(2, '0');
|
var pad = function (n) { return String(n).padStart(2, '0'); };
|
||||||
var ymd = d => d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
|
var ymd = function (d) {
|
||||||
|
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
|
||||||
|
};
|
||||||
if (type === 'today') {
|
if (type === 'today') {
|
||||||
dari.value = ymd(today);
|
dari.value = sampai.value = ymd(today);
|
||||||
sampai.value = ymd(today);
|
} else {
|
||||||
} else if (type === 'month') {
|
dari.value = ymd(new Date(today.getFullYear(), today.getMonth(), 1));
|
||||||
var first = new Date(today.getFullYear(), today.getMonth(), 1);
|
sampai.value = ymd(new Date(today.getFullYear(), today.getMonth() + 1, 0));
|
||||||
var last = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
|
||||||
dari.value = ymd(first);
|
|
||||||
sampai.value = ymd(last);
|
|
||||||
}
|
}
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -2,46 +2,34 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><i class="fas fa-history"></i> Riwayat Uang Saku - {{ $santri->nama_lengkap }}</h2>
|
<h2><i class="fas fa-history"></i> Riwayat Uang Saku — {{ $santri->nama_lengkap }}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Filter Periode --}}
|
{{-- Filter Periode --}}
|
||||||
<div class="content-box" style="margin-bottom:14px;">
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
<form method="GET" action="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}" id="filterPeriode">
|
<form method="GET" action="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}" id="filterPeriode">
|
||||||
<div style="display: flex; align-items: end; gap: 11px; flex-wrap: wrap;">
|
<div style="display:flex;align-items:flex-end;gap:11px;flex-wrap:wrap;">
|
||||||
<div class="form-group" style="margin-bottom:0;flex:1;min-width:200px;">
|
<div class="form-group" style="margin-bottom:0;flex:1;min-width:200px;">
|
||||||
<label for="tanggal_dari" style="display:block;margin-bottom:5px;font-weight:600;">
|
<label for="tanggal_dari" style="display:block;margin-bottom:5px;font-weight:600;">
|
||||||
<i class="fas fa-calendar-alt"></i> Dari Tanggal
|
<i class="fas fa-calendar-alt"></i> Dari Tanggal
|
||||||
</label>
|
</label>
|
||||||
<input type="date"
|
<input type="date" name="tanggal_dari" id="tanggal_dari"
|
||||||
name="tanggal_dari"
|
class="form-control" value="{{ $tanggalDari }}" max="{{ date('Y-m-d') }}">
|
||||||
id="tanggal_dari"
|
|
||||||
class="form-control"
|
|
||||||
value="{{ $tanggalDari }}"
|
|
||||||
max="{{ date('Y-m-d') }}">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" style="margin-bottom:0;flex:1;min-width:200px;">
|
<div class="form-group" style="margin-bottom:0;flex:1;min-width:200px;">
|
||||||
<label for="tanggal_sampai" style="display:block;margin-bottom:5px;font-weight:600;">
|
<label for="tanggal_sampai" style="display:block;margin-bottom:5px;font-weight:600;">
|
||||||
<i class="fas fa-calendar-check"></i> Sampai Tanggal
|
<i class="fas fa-calendar-check"></i> Sampai Tanggal
|
||||||
</label>
|
</label>
|
||||||
<input type="date"
|
<input type="date" name="tanggal_sampai" id="tanggal_sampai"
|
||||||
name="tanggal_sampai"
|
class="form-control" value="{{ $tanggalSampai }}" max="{{ date('Y-m-d') }}">
|
||||||
id="tanggal_sampai"
|
|
||||||
class="form-control"
|
|
||||||
value="{{ $tanggalSampai }}"
|
|
||||||
max="{{ date('Y-m-d') }}">
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display:flex;gap:10px;">
|
<div style="display:flex;gap:10px;">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
<i class="fas fa-filter"></i> Terapkan
|
<i class="fas fa-filter"></i> Terapkan
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-success" onclick="setBulanIni()">
|
<button type="button" class="btn btn-success" onclick="setBulanIni()">
|
||||||
<i class="fas fa-calendar-day"></i> Bulan Ini
|
<i class="fas fa-calendar-day"></i> Bulan Ini
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}" class="btn btn-secondary">
|
<a href="{{ route('admin.uang-saku.riwayat', $santri->id_santri) }}" class="btn btn-secondary">
|
||||||
<i class="fas fa-redo"></i> Reset
|
<i class="fas fa-redo"></i> Reset
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -50,108 +38,219 @@ class="form-control"
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Info Periode --}}
|
{{-- ═══════════════════════════════════════════════════
|
||||||
<div class="info-box" style="margin-bottom: 14px;">
|
PERSAMAAN SALDO PERIODE
|
||||||
<p style="margin: 0;">
|
════════════════════════════════════════════════════ --}}
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
<strong>Periode:</strong>
|
<div style="margin-bottom:10px;">
|
||||||
{{ $periodeDari->format('d F Y') }} - {{ $periodeSampai->format('d F Y') }}
|
<div style="font-size:.78rem;font-weight:600;color:var(--text-light);
|
||||||
({{ $periodeDari->diffInDays($periodeSampai) + 1 }} hari)
|
text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;">
|
||||||
</p>
|
<i class="fas fa-calculator" style="color:var(--primary-color);"></i>
|
||||||
|
Ringkasan Periode:
|
||||||
|
<strong style="color:var(--text-color);">
|
||||||
|
{{ $periodeDari->format('d M Y') }} – {{ $periodeSampai->format('d M Y') }}
|
||||||
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Summary Cards -->
|
{{-- Persamaan saldo --}}
|
||||||
<div class="row-cards">
|
<div style="display:grid;
|
||||||
<div class="card card-success hover-lift">
|
grid-template-columns: 1fr 32px 1fr 32px 1fr 32px 1fr;
|
||||||
<h3>Total Pemasukan</h3>
|
gap:0;align-items:stretch;
|
||||||
<div class="card-value">Rp {{ number_format($totalPemasukan, 0, ',', '.') }}</div>
|
border-radius:12px;overflow:hidden;
|
||||||
<p style="margin: 10px 0 0 0; font-size: 0.85rem; color: var(--text-light);">
|
border:1.5px solid #e2e8f0;background:#fff;
|
||||||
Periode yang dipilih
|
margin-bottom:10px;">
|
||||||
</p>
|
|
||||||
<i class="fas fa-arrow-down card-icon"></i>
|
{{-- Saldo Awal --}}
|
||||||
|
<div style="padding:14px 16px;border-right:1px solid #e2e8f0;">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Saldo Awal Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;color:#4a5568;">
|
||||||
|
Rp {{ number_format($saldoAwalPeriode, 0, ',', '.') }}
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">
|
||||||
|
per {{ $periodeDari->format('d M Y') }}
|
||||||
|
@if($saldoAwalPeriode == 0)
|
||||||
|
<span style="color:#f5a623;">(belum ada saldo sebelumnya)</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card card-danger hover-lift">
|
{{-- + --}}
|
||||||
<h3>Total Pengeluaran</h3>
|
<div style="display:flex;align-items:center;justify-content:center;
|
||||||
<div class="card-value">Rp {{ number_format($totalPengeluaran, 0, ',', '.') }}</div>
|
font-size:1.3rem;font-weight:300;color:#6FBA9D;
|
||||||
<p style="margin: 10px 0 0 0; font-size: 0.85rem; color: var(--text-light);">
|
border-right:1px solid #e2e8f0;">+</div>
|
||||||
Periode yang dipilih
|
|
||||||
</p>
|
{{-- Pemasukan --}}
|
||||||
<i class="fas fa-arrow-up card-icon"></i>
|
<div style="padding:14px 16px;border-right:1px solid #e2e8f0;">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Pemasukan Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;color:#6FBA9D;">
|
||||||
|
Rp {{ number_format($totalPemasukan, 0, ',', '.') }}
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">uang masuk di periode ini</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card card-info hover-lift">
|
{{-- − --}}
|
||||||
<h3>Selisih</h3>
|
<div style="display:flex;align-items:center;justify-content:center;
|
||||||
<div class="card-value" style="color: {{ ($totalPemasukan - $totalPengeluaran) >= 0 ? '#6FBA9D' : '#FF8B94' }}">
|
font-size:1.3rem;font-weight:300;color:#FF8B94;
|
||||||
Rp {{ number_format($totalPemasukan - $totalPengeluaran, 0, ',', '.') }}
|
border-right:1px solid #e2e8f0;">−</div>
|
||||||
|
|
||||||
|
{{-- Pengeluaran --}}
|
||||||
|
<div style="padding:14px 16px;border-right:1px solid #e2e8f0;">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Pengeluaran Periode
|
||||||
</div>
|
</div>
|
||||||
<p style="margin: 10px 0 0 0; font-size: 0.85rem; color: var(--text-light);">
|
<div style="font-size:1rem;font-weight:800;color:#FF8B94;">
|
||||||
Pemasukan - Pengeluaran
|
Rp {{ number_format($totalPengeluaran, 0, ',', '.') }}
|
||||||
</p>
|
</div>
|
||||||
<i class="fas fa-chart-line card-icon"></i>
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">uang keluar di periode ini</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card card-primary hover-lift">
|
{{-- = --}}
|
||||||
<h3>Saldo Saat Ini</h3>
|
<div style="display:flex;align-items:center;justify-content:center;
|
||||||
<div class="card-value" style="color: {{ $saldoTerakhir >= 0 ? '#6FBA9D' : '#FF8B94' }}">
|
font-size:1.3rem;font-weight:300;color:#718096;
|
||||||
|
border-right:1px solid #e2e8f0;">=</div>
|
||||||
|
|
||||||
|
{{-- Saldo Akhir --}}
|
||||||
|
<div style="padding:14px 16px;background:linear-gradient(135deg,#f0fdf7 0%,#e6f9f2 100%);">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Saldo Akhir Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;
|
||||||
|
color:{{ $saldoAkhirPeriode >= 0 ? '#38a169' : '#e53e3e' }};">
|
||||||
|
Rp {{ number_format($saldoAkhirPeriode, 0, ',', '.') }}
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">
|
||||||
|
per {{ $periodeSampai->format('d M Y') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Notif jika saldo akhir periode ≠ saldo saat ini --}}
|
||||||
|
@if(round($saldoAkhirPeriode) !== round($saldoTerakhir))
|
||||||
|
<div style="background:#fffbeb;border:1px solid #fbd38d;border-radius:9px;
|
||||||
|
padding:10px 14px;font-size:.8rem;color:#744210;margin-bottom:10px;
|
||||||
|
display:flex;align-items:flex-start;gap:8px;">
|
||||||
|
<i class="fas fa-exclamation-triangle" style="color:#f5a623;margin-top:2px;flex-shrink:0;"></i>
|
||||||
|
<div>
|
||||||
|
<strong>Catatan:</strong>
|
||||||
|
Saldo akhir periode (Rp {{ number_format($saldoAkhirPeriode, 0, ',', '.') }})
|
||||||
|
berbeda dengan <strong>Saldo Saat Ini (Rp {{ number_format($saldoTerakhir, 0, ',', '.') }})</strong>
|
||||||
|
karena ada transaksi di luar rentang
|
||||||
|
{{ $periodeDari->format('d M') }}–{{ $periodeSampai->format('d M Y') }}.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Saldo saat ini (real-time) --}}
|
||||||
|
<div style="background:linear-gradient(135deg,#ebf8ff 0%,#bee3f8 40%,#ebf8ff 100%);
|
||||||
|
border:1.5px solid #90cdf4;border-radius:12px;
|
||||||
|
padding:14px 18px;display:flex;justify-content:space-between;
|
||||||
|
align-items:center;flex-wrap:wrap;gap:10px;">
|
||||||
|
<div>
|
||||||
|
<div style="font-size:.66rem;color:#2b6cb0;text-transform:uppercase;
|
||||||
|
letter-spacing:.5px;margin-bottom:4px;font-weight:600;">
|
||||||
|
<i class="fas fa-wallet"></i> Saldo Saat Ini (Akumulasi Semua Waktu)
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1.4rem;font-weight:900;
|
||||||
|
color:{{ $saldoTerakhir >= 0 ? '#2b6cb0' : '#e53e3e' }};">
|
||||||
Rp {{ number_format($saldoTerakhir, 0, ',', '.') }}
|
Rp {{ number_format($saldoTerakhir, 0, ',', '.') }}
|
||||||
</div>
|
</div>
|
||||||
<p style="margin: 10px 0 0 0; font-size: 0.85rem; color: var(--text-light);">
|
</div>
|
||||||
Total keseluruhan
|
<div style="font-size:.78rem;color:#2c5282;text-align:right;max-width:300px;line-height:1.5;">
|
||||||
</p>
|
<i class="fas fa-info-circle"></i>
|
||||||
<i class="fas fa-wallet card-icon"></i>
|
Total uang santri saat ini, dihitung dari <strong>seluruh transaksi sejak awal</strong>,
|
||||||
|
bukan hanya periode yang ditampilkan.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Grafik -->
|
{{-- ═══════════════════════════════════════════════════
|
||||||
|
GRAFIK PERJALANAN SALDO
|
||||||
|
════════════════════════════════════════════════════ --}}
|
||||||
<div class="content-box" style="margin-bottom:22px;">
|
<div class="content-box" style="margin-bottom:22px;">
|
||||||
<h3 style="margin-bottom: 14px; color: var(--primary-color);">
|
<div style="display:flex;justify-content:space-between;align-items:flex-start;
|
||||||
<i class="fas fa-chart-line"></i> Grafik Arus Uang Saku
|
flex-wrap:wrap;gap:8px;margin-bottom:16px;">
|
||||||
|
<div>
|
||||||
|
<h3 style="margin:0 0 4px;color:var(--primary-color);">
|
||||||
|
<i class="fas fa-chart-area"></i> Perjalanan Saldo
|
||||||
</h3>
|
</h3>
|
||||||
<canvas id="chartUangSaku" style="max-height: 400px;"></canvas>
|
<div style="font-size:.78rem;color:var(--text-light);">
|
||||||
|
{{ $periodeDari->format('d M Y') }} – {{ $periodeSampai->format('d M Y') }}
|
||||||
|
• Grafik menunjukkan nilai saldo aktual setiap hari
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{-- Mini legend --}}
|
||||||
|
<div style="display:flex;gap:14px;align-items:center;font-size:.78rem;color:var(--text-light);">
|
||||||
|
<span>
|
||||||
|
<span style="display:inline-block;width:24px;height:3px;background:#6FBA9D;
|
||||||
|
vertical-align:middle;border-radius:2px;margin-right:5px;"></span>
|
||||||
|
Saldo naik (pemasukan)
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<span style="display:inline-block;width:24px;height:3px;background:#FF8B94;
|
||||||
|
vertical-align:middle;border-radius:2px;margin-right:5px;"></span>
|
||||||
|
Saldo turun (pengeluaran)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<canvas id="chartSaldo" style="max-height:380px;"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
{{-- Action Buttons --}}
|
||||||
<div class="content-box" style="margin-bottom:14px;">
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:11px;">
|
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:11px;">
|
||||||
<div style="display:flex;gap:10px;flex-wrap:wrap;">
|
<div style="display:flex;gap:10px;flex-wrap:wrap;">
|
||||||
<a href="{{ route('admin.uang-saku.index') }}" class="btn btn-secondary">
|
<a href="{{ route('admin.uang-saku.index') }}" class="btn btn-secondary">
|
||||||
<i class="fas fa-arrow-left"></i> Kembali ke Daftar
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ route('admin.santri.show', $santri->id) }}" class="btn btn-primary">
|
<a href="{{ route('admin.santri.show', $santri->id) }}" class="btn btn-primary">
|
||||||
<i class="fas fa-user"></i> Profil Santri
|
<i class="fas fa-user"></i> Profil Santri
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
{{-- Tambah Transaksi: hanya pamong --}}
|
||||||
<a href="{{ route('admin.uang-saku.create') }}?id_santri={{ $santri->id_santri }}" class="btn btn-success">
|
@if($canCrud)
|
||||||
|
<a href="{{ route('admin.uang-saku.create') }}?id_santri={{ $santri->id_santri }}"
|
||||||
|
class="btn btn-success">
|
||||||
<i class="fas fa-plus"></i> Tambah Transaksi
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
</a>
|
</a>
|
||||||
</div>
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tabel Riwayat -->
|
{{-- Tabel Riwayat --}}
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
<h3 style="margin-bottom: 15px; color: var(--text-color);">
|
<h3 style="margin-bottom:12px;color:var(--text-color);">
|
||||||
<i class="fas fa-list"></i> Daftar Transaksi
|
<i class="fas fa-list"></i> Daftar Transaksi
|
||||||
@if($transaksi->total() > 0)
|
@if($transaksi->total() > 0)
|
||||||
<span style="color: var(--text-light);">({{ $transaksi->total() }} transaksi)</span>
|
<span style="color:var(--text-light);font-weight:400;">
|
||||||
|
({{ $transaksi->total() }} transaksi)
|
||||||
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
@if($transaksi->count() > 0)
|
@if($transaksi->count() > 0)
|
||||||
|
<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;
|
||||||
|
padding:9px 14px;margin-bottom:12px;font-size:.78rem;color:var(--text-light);">
|
||||||
|
<i class="fas fa-info-circle" style="color:var(--primary-color);"></i>
|
||||||
|
<strong>Saldo Sebelum</strong> & <strong>Saldo Sesudah</strong>
|
||||||
|
menunjukkan saldo kumulatif santri sebelum dan setelah tiap transaksi.
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 5%;">No</th>
|
<th style="width:4%;">No</th>
|
||||||
<th style="width: 12%;">ID Transaksi</th>
|
<th style="width:11%;">ID</th>
|
||||||
<th style="width: 12%;">Tanggal</th>
|
<th style="width:10%;">Tanggal</th>
|
||||||
<th style="width: 12%;">Jenis</th>
|
<th style="width:10%;">Jenis</th>
|
||||||
<th style="width: 15%;">Nominal</th>
|
<th style="width:13%;">Nominal</th>
|
||||||
<th style="width:13%;">Saldo Sebelum</th>
|
<th style="width:13%;">Saldo Sebelum</th>
|
||||||
<th style="width:13%;">Saldo Sesudah</th>
|
<th style="width:13%;">Saldo Sesudah</th>
|
||||||
<th style="width: 12%;">Keterangan</th>
|
<th style="width:20%;">Keterangan</th>
|
||||||
<th style="width:6%;" class="text-center">Aksi</th>
|
<th style="width:6%;" class="text-center">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
@ -164,42 +263,37 @@ class="form-control"
|
||||||
<td>
|
<td>
|
||||||
@if($item->jenis_transaksi === 'pemasukan')
|
@if($item->jenis_transaksi === 'pemasukan')
|
||||||
<span class="badge badge-success">
|
<span class="badge badge-success">
|
||||||
<i class="fas fa-arrow-down"></i> Pemasukan
|
<i class="fas fa-arrow-down"></i> Masuk
|
||||||
</span>
|
</span>
|
||||||
@else
|
@else
|
||||||
<span class="badge badge-danger">
|
<span class="badge badge-danger">
|
||||||
<i class="fas fa-arrow-up"></i> Pengeluaran
|
<i class="fas fa-arrow-up"></i> Keluar
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td class="nominal-highlight">
|
<td class="nominal-highlight">{{ $item->nominal_format }}</td>
|
||||||
{{ $item->nominal_format }}
|
<td style="color:#718096;">
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Rp {{ number_format($item->saldo_sebelum, 0, ',', '.') }}
|
Rp {{ number_format($item->saldo_sebelum, 0, ',', '.') }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<strong style="color: {{ $item->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94' }}">
|
<strong style="color:{{ $item->saldo_sesudah >= 0 ? '#38a169' : '#e53e3e' }};">
|
||||||
{{ $item->saldo_sesudah_format }}
|
{{ $item->saldo_sesudah_format }}
|
||||||
</strong>
|
</strong>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td><div class="content-preview">{{ $item->keterangan ?? '-' }}</div></td>
|
||||||
<div class="content-preview">
|
|
||||||
{{ $item->keterangan ?? '-' }}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<div style="display: flex; gap: 5px; justify-content: center;">
|
<div style="display:flex;gap:4px;justify-content:center;">
|
||||||
<a href="{{ route('admin.uang-saku.show', $item->id) }}"
|
<a href="{{ route('admin.uang-saku.show', $item->id) }}"
|
||||||
class="btn btn-primary btn-sm"
|
class="btn btn-primary btn-sm" title="Detail">
|
||||||
title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
<i class="fas fa-eye"></i>
|
||||||
</a>
|
</a>
|
||||||
|
{{-- Edit: hanya pamong --}}
|
||||||
|
@if($canCrud)
|
||||||
<a href="{{ route('admin.uang-saku.edit', $item->id) }}"
|
<a href="{{ route('admin.uang-saku.edit', $item->id) }}"
|
||||||
class="btn btn-warning btn-sm"
|
class="btn btn-warning btn-sm" title="Edit">
|
||||||
title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -207,176 +301,201 @@ class="btn btn-warning btn-sm"
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="margin-top:14px;">{{ $transaksi->links() }}</div>
|
||||||
|
|
||||||
<div style="margin-top: 14px;">
|
|
||||||
{{ $transaksi->links() }}
|
|
||||||
</div>
|
|
||||||
@else
|
@else
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<i class="fas fa-calendar-times"></i>
|
<i class="fas fa-calendar-times"></i>
|
||||||
<h3>Tidak Ada Transaksi</h3>
|
<h3>Tidak Ada Transaksi</h3>
|
||||||
<p>Tidak ada transaksi pada periode {{ $periodeDari->format('d F Y') }} - {{ $periodeSampai->format('d F Y') }}</p>
|
<p>
|
||||||
<a href="{{ route('admin.uang-saku.create') }}?id_santri={{ $santri->id_santri }}" class="btn btn-success">
|
Tidak ada transaksi pada periode
|
||||||
|
{{ $periodeDari->format('d F Y') }} – {{ $periodeSampai->format('d F Y') }}.
|
||||||
|
</p>
|
||||||
|
@if(round($saldoTerakhir) > 0)
|
||||||
|
<p style="font-size:.85rem;color:var(--text-light);">
|
||||||
|
Santri memiliki saldo
|
||||||
|
<strong>Rp {{ number_format($saldoTerakhir, 0, ',', '.') }}</strong>
|
||||||
|
dari transaksi di periode lain.
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
|
@if($canCrud)
|
||||||
|
<a href="{{ route('admin.uang-saku.create') }}?id_santri={{ $santri->id_santri }}"
|
||||||
|
class="btn btn-success">
|
||||||
<i class="fas fa-plus"></i> Tambah Transaksi
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Chart.js Library -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Data untuk grafik dari Laravel
|
// ═══════════════════════════════════════════════════════════════
|
||||||
const dataGrafik = @json($dataGrafik);
|
// DATA dari Laravel
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const rawData = @json($dataGrafikSaldo);
|
||||||
|
|
||||||
// Format data untuk Chart.js (per hari)
|
// ═══════════════════════════════════════════════════════════════
|
||||||
const labels = dataGrafik.map(item => {
|
// Bangun dataset perjalanan saldo
|
||||||
const date = new Date(item.tanggal);
|
// ═══════════════════════════════════════════════════════════════
|
||||||
return date.toLocaleDateString('id-ID', { day: 'numeric', month: 'short' });
|
const labels = [];
|
||||||
|
const saldoArr = [];
|
||||||
|
|
||||||
|
rawData.forEach((d, i) => {
|
||||||
|
const dt = new Date(d.tanggal + 'T00:00:00');
|
||||||
|
const opt = { day: 'numeric', month: 'short' };
|
||||||
|
labels.push(
|
||||||
|
d.is_awal
|
||||||
|
? dt.toLocaleDateString('id-ID', opt) + ' (Awal)'
|
||||||
|
: dt.toLocaleDateString('id-ID', opt)
|
||||||
|
);
|
||||||
|
saldoArr.push(d.saldo);
|
||||||
});
|
});
|
||||||
|
|
||||||
const pemasukan = dataGrafik.map(item => parseFloat(item.pemasukan));
|
function segmentColor(ctx, naik, turun, flat) {
|
||||||
const pengeluaran = dataGrafik.map(item => parseFloat(item.pengeluaran));
|
const i = ctx.p1DataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
if (cur > prv) return naik;
|
||||||
|
if (cur < prv) return turun;
|
||||||
|
return flat;
|
||||||
|
}
|
||||||
|
|
||||||
// Konfigurasi Chart
|
function buildGradient(ctx) {
|
||||||
const ctx = document.getElementById('chartUangSaku').getContext('2d');
|
const chart = ctx.chart;
|
||||||
const chartUangSaku = new Chart(ctx, {
|
const { chartArea } = chart;
|
||||||
|
if (!chartArea) return 'rgba(111,186,157,0.15)';
|
||||||
|
const gradient = chart.ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
|
||||||
|
gradient.addColorStop(0, 'rgba(111,186,157,0.25)');
|
||||||
|
gradient.addColorStop(0.6, 'rgba(111,186,157,0.06)');
|
||||||
|
gradient.addColorStop(1, 'rgba(111,186,157,0.0)');
|
||||||
|
return gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = document.getElementById('chartSaldo').getContext('2d');
|
||||||
|
|
||||||
|
new Chart(ctx, {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: {
|
data: {
|
||||||
labels: labels,
|
labels,
|
||||||
datasets: [
|
datasets: [{
|
||||||
{
|
label: 'Saldo',
|
||||||
label: 'Pemasukan',
|
data: saldoArr,
|
||||||
data: pemasukan,
|
|
||||||
borderColor: '#6FBA9D',
|
|
||||||
backgroundColor: 'rgba(111, 186, 157, 0.1)',
|
|
||||||
borderWidth: 3,
|
borderWidth: 3,
|
||||||
|
tension: 0.35,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.4,
|
backgroundColor: buildGradient,
|
||||||
pointRadius: 5,
|
pointRadius: function(ctx) {
|
||||||
pointHoverRadius: 7,
|
const i = ctx.dataIndex;
|
||||||
pointBackgroundColor: '#6FBA9D',
|
const cur = saldoArr[i];
|
||||||
pointBorderColor: '#fff',
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
pointBorderWidth: 2
|
return cur !== prv || i === 0 || i === saldoArr.length - 1 ? 6 : 3;
|
||||||
|
},
|
||||||
|
pointHoverRadius: 8,
|
||||||
|
pointBackgroundColor: function(ctx) {
|
||||||
|
const i = ctx.dataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
if (i === 0) return '#718096';
|
||||||
|
if (cur > prv) return '#6FBA9D';
|
||||||
|
if (cur < prv) return '#FF8B94';
|
||||||
|
return '#d1d9e0';
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'Pengeluaran',
|
|
||||||
data: pengeluaran,
|
|
||||||
borderColor: '#FF8B94',
|
|
||||||
backgroundColor: 'rgba(255, 139, 148, 0.1)',
|
|
||||||
borderWidth: 3,
|
|
||||||
fill: true,
|
|
||||||
tension: 0.4,
|
|
||||||
pointRadius: 5,
|
|
||||||
pointHoverRadius: 7,
|
|
||||||
pointBackgroundColor: '#FF8B94',
|
|
||||||
pointBorderColor: '#fff',
|
pointBorderColor: '#fff',
|
||||||
pointBorderWidth: 2
|
pointBorderWidth: 2,
|
||||||
}
|
segment: {
|
||||||
]
|
borderColor: ctx => segmentColor(ctx, '#6FBA9D', '#FF8B94', '#d1d9e0'),
|
||||||
|
},
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: true,
|
maintainAspectRatio: true,
|
||||||
interaction: {
|
interaction: { intersect: false, mode: 'index' },
|
||||||
intersect: false,
|
|
||||||
mode: 'index'
|
|
||||||
},
|
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: { display: false },
|
||||||
display: true,
|
|
||||||
position: 'top',
|
|
||||||
labels: {
|
|
||||||
padding: 15,
|
|
||||||
font: {
|
|
||||||
size: 13,
|
|
||||||
family: "'Inter', sans-serif"
|
|
||||||
},
|
|
||||||
usePointStyle: true,
|
|
||||||
pointStyle: 'circle'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
tooltip: {
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
backgroundColor: 'rgba(30,41,59,0.92)',
|
||||||
padding: 12,
|
padding: 13,
|
||||||
titleFont: {
|
cornerRadius: 10,
|
||||||
size: 14,
|
titleFont: { size: 13, weight: 'bold' },
|
||||||
weight: 'bold'
|
bodyFont: { size: 13 },
|
||||||
},
|
|
||||||
bodyFont: {
|
|
||||||
size: 13
|
|
||||||
},
|
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label: function(context) {
|
title: items => items[0].label,
|
||||||
let label = context.dataset.label || '';
|
label: item => {
|
||||||
if (label) {
|
const i = item.dataIndex;
|
||||||
label += ': ';
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
const diff = cur - prv;
|
||||||
|
const fmt = v => 'Rp\u00a0' + new Intl.NumberFormat('id-ID').format(v);
|
||||||
|
|
||||||
|
let lines = [' Saldo: ' + fmt(cur)];
|
||||||
|
if (i > 0 && diff !== 0) {
|
||||||
|
const sign = diff > 0 ? '▲ +' : '▼ ';
|
||||||
|
lines.push(' ' + sign + fmt(Math.abs(diff))
|
||||||
|
+ (diff > 0 ? ' (pemasukan)' : ' (pengeluaran)'));
|
||||||
|
} else if (i > 0) {
|
||||||
|
lines.push(' — tidak ada transaksi');
|
||||||
}
|
}
|
||||||
label += 'Rp ' + new Intl.NumberFormat('id-ID').format(context.parsed.y);
|
return lines;
|
||||||
return label;
|
},
|
||||||
|
labelColor: item => {
|
||||||
|
const i = item.dataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
const c = i === 0 ? '#718096'
|
||||||
|
: cur > prv ? '#6FBA9D'
|
||||||
|
: cur < prv ? '#FF8B94' : '#d1d9e0';
|
||||||
|
return { borderColor: c, backgroundColor: c, borderRadius: 3 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
y: {
|
y: {
|
||||||
beginAtZero: true,
|
min: function() {
|
||||||
|
const minVal = Math.min(...saldoArr);
|
||||||
|
return Math.max(0, Math.floor(minVal * 0.8 / 10000) * 10000);
|
||||||
|
}(),
|
||||||
ticks: {
|
ticks: {
|
||||||
callback: function(value) {
|
callback: v => 'Rp\u00a0' + new Intl.NumberFormat('id-ID', {
|
||||||
return 'Rp ' + new Intl.NumberFormat('id-ID', {
|
notation: 'compact', compactDisplay: 'short'
|
||||||
notation: 'compact',
|
}).format(v),
|
||||||
compactDisplay: 'short'
|
font: { size: 12 },
|
||||||
}).format(value);
|
maxTicksLimit: 8,
|
||||||
},
|
},
|
||||||
font: {
|
grid: { color: 'rgba(0,0,0,.05)', drawBorder: false }
|
||||||
size: 12
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
color: 'rgba(111, 186, 157, 0.1)',
|
|
||||||
drawBorder: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
x: {
|
x: {
|
||||||
grid: {
|
grid: { display: false, drawBorder: false },
|
||||||
display: false,
|
|
||||||
drawBorder: false
|
|
||||||
},
|
|
||||||
ticks: {
|
ticks: {
|
||||||
font: {
|
font: { size: 11 },
|
||||||
size: 11
|
|
||||||
},
|
|
||||||
maxRotation: 45,
|
maxRotation: 45,
|
||||||
minRotation: 45
|
minRotation: 45,
|
||||||
|
maxTicksLimit: rawData.length > 20 ? 12 : rawData.length,
|
||||||
|
autoSkip: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
animation: {
|
animation: { duration: 1200, easing: 'easeInOutQuart' }
|
||||||
duration: 1500,
|
|
||||||
easing: 'easeInOutQuart'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function untuk set bulan ini
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Helpers
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
function setBulanIni() {
|
function setBulanIni() {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
|
const first = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||||
const lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
const last = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
||||||
|
document.getElementById('tanggal_dari').value = first.toISOString().split('T')[0];
|
||||||
document.getElementById('tanggal_dari').value = firstDay.toISOString().split('T')[0];
|
document.getElementById('tanggal_sampai').value = last.toISOString().split('T')[0];
|
||||||
document.getElementById('tanggal_sampai').value = lastDay.toISOString().split('T')[0];
|
|
||||||
|
|
||||||
document.getElementById('filterPeriode').submit();
|
document.getElementById('filterPeriode').submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validasi tanggal
|
|
||||||
document.getElementById('tanggal_sampai').addEventListener('change', function () {
|
document.getElementById('tanggal_sampai').addEventListener('change', function () {
|
||||||
const dari = document.getElementById('tanggal_dari').value;
|
const dari = document.getElementById('tanggal_dari').value;
|
||||||
const sampai = this.value;
|
if (dari && this.value && this.value < dari) {
|
||||||
|
|
||||||
if (dari && sampai && sampai < dari) {
|
|
||||||
alert('Tanggal sampai tidak boleh lebih kecil dari tanggal dari!');
|
alert('Tanggal sampai tidak boleh lebih kecil dari tanggal dari!');
|
||||||
this.value = dari;
|
this.value = dari;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,12 @@
|
||||||
<a href="{{ route('admin.uang-saku.riwayat', $transaksi->id_santri) }}" class="btn btn-primary">
|
<a href="{{ route('admin.uang-saku.riwayat', $transaksi->id_santri) }}" class="btn btn-primary">
|
||||||
<i class="fas fa-history"></i> Lihat Riwayat
|
<i class="fas fa-history"></i> Lihat Riwayat
|
||||||
</a>
|
</a>
|
||||||
|
{{-- Edit: hanya pamong --}}
|
||||||
|
@if($canCrud)
|
||||||
<a href="{{ route('admin.uang-saku.edit', $transaksi->id) }}" class="btn btn-warning">
|
<a href="{{ route('admin.uang-saku.edit', $transaksi->id) }}" class="btn btn-warning">
|
||||||
<i class="fas fa-edit"></i> Edit
|
<i class="fas fa-edit"></i> Edit
|
||||||
</a>
|
</a>
|
||||||
|
@endif
|
||||||
<a href="{{ route('admin.uang-saku.index') }}" class="btn btn-secondary">
|
<a href="{{ route('admin.uang-saku.index') }}" class="btn btn-secondary">
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -114,6 +117,8 @@
|
||||||
<a href="{{ route('admin.uang-saku.riwayat', $transaksi->id_santri) }}" class="btn btn-primary">
|
<a href="{{ route('admin.uang-saku.riwayat', $transaksi->id_santri) }}" class="btn btn-primary">
|
||||||
<i class="fas fa-history"></i> Lihat Riwayat
|
<i class="fas fa-history"></i> Lihat Riwayat
|
||||||
</a>
|
</a>
|
||||||
|
{{-- Edit & Hapus: hanya pamong --}}
|
||||||
|
@if($canCrud)
|
||||||
<a href="{{ route('admin.uang-saku.edit', $transaksi->id) }}" class="btn btn-warning">
|
<a href="{{ route('admin.uang-saku.edit', $transaksi->id) }}" class="btn btn-warning">
|
||||||
<i class="fas fa-edit"></i> Edit Transaksi
|
<i class="fas fa-edit"></i> Edit Transaksi
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -127,6 +132,7 @@
|
||||||
<i class="fas fa-trash"></i> Hapus
|
<i class="fas fa-trash"></i> Hapus
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -441,10 +441,18 @@
|
||||||
Route::post('/', [UangSakuController::class, 'store'])->name('store');
|
Route::post('/', [UangSakuController::class, 'store'])->name('store');
|
||||||
Route::get('/santri-info/{id_santri}',[UangSakuController::class, 'santriInfo'])->name('santri-info');
|
Route::get('/santri-info/{id_santri}',[UangSakuController::class, 'santriInfo'])->name('santri-info');
|
||||||
Route::get('/riwayat/{id_santri}', [UangSakuController::class, 'riwayat'])->name('riwayat');
|
Route::get('/riwayat/{id_santri}', [UangSakuController::class, 'riwayat'])->name('riwayat');
|
||||||
Route::get('/{uangSaku}', [UangSakuController::class, 'show'])->name('show');
|
Route::get('/{uangSaku}', [UangSakuController::class, 'show'])
|
||||||
Route::get('/{uangSaku}/edit', [UangSakuController::class, 'edit'])->name('edit');
|
->whereNumber('uangSaku')
|
||||||
Route::put('/{uangSaku}', [UangSakuController::class, 'update'])->name('update');
|
->name('show');
|
||||||
Route::delete('/{uangSaku}', [UangSakuController::class, 'destroy'])->name('destroy');
|
Route::get('/{uangSaku}/edit', [UangSakuController::class, 'edit'])
|
||||||
|
->whereNumber('uangSaku')
|
||||||
|
->name('edit');
|
||||||
|
Route::put('/{uangSaku}', [UangSakuController::class, 'update'])
|
||||||
|
->whereNumber('uangSaku')
|
||||||
|
->name('update');
|
||||||
|
Route::delete('/{uangSaku}', [UangSakuController::class, 'destroy'])
|
||||||
|
->whereNumber('uangSaku')
|
||||||
|
->name('destroy');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
a:4:{s:6:"_token";s:40:"Rogr1HsMSukvmYR2m3b7pPraVOehwZvcU2GYYNaA";s:9:"_previous";a:1:{s:3:"url";s:44:"http://127.0.0.1:8000/admin/laporan-kegiatan";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
a:3:{s:6:"_token";s:40:"z2Q3wuWmkF9oCYl0WHpsIaXywzR0FjwyltHaEHA1";s:9:"_previous";a:1:{s:3:"url";s:34:"http://127.0.0.1:8000/santri/login";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
a:4:{s:6:"_token";s:40:"TiMKyzlAzRLRL9vdvNjuuT4zMOD7QGCBKyJKG7lC";s:3:"url";a:1:{s:8:"intended";s:58:"http://localhost/admin/laporan-kegiatan?periode=minggu_ini";}s:9:"_previous";a:1:{s:3:"url";s:58:"http://localhost/admin/laporan-kegiatan?periode=minggu_ini";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
a:3:{s:6:"_token";s:40:"38E76quLNOyMUAX08jBlb63KKtrUj910NO6H7reC";s:6:"_flash";a:2:{s:3:"new";a:0:{}s:3:"old";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:33:"http://127.0.0.1:8000/admin/login";}}
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
a:4:{s:6:"_token";s:40:"6coVi3IEjegOzvk6b3puL9vN7Cj70VOUTHaB1oEN";s:9:"_previous";a:1:{s:3:"url";s:36:"http://127.0.0.1:8000/admin/kegiatan";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:5;}
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
a:4:{s:6:"_token";s:40:"JkoSzSFooBHlizoZQ1QgxXKBUyzQsoduDjvLAUrc";s:9:"_previous";a:1:{s:3:"url";s:38:"http://127.0.0.1:8000/admin/kepulangan";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
a:4:{s:6:"_token";s:40:"J6ggUD8C2cAW8afPm7ZlmET0SBcvC47D9khAiGHB";s:9:"_previous";a:1:{s:3:"url";s:37:"http://127.0.0.1:8000/admin/uang-saku";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:1;}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<?php $__env->startSection('title', __('Not Found')); ?>
|
|
||||||
<?php $__env->startSection('code', '404'); ?>
|
|
||||||
<?php $__env->startSection('message', __('Not Found')); ?>
|
|
||||||
|
|
||||||
<?php echo $__env->make('errors::minimal', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\vendor\laravel\framework\src\Illuminate\Foundation\Exceptions/views/404.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,417 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
/* =====================================================
|
|
||||||
DETAIL SANTRI — Riwayat Kehadiran
|
|
||||||
===================================================== */
|
|
||||||
|
|
||||||
.ds-header { display:flex; justify-content:space-between; align-items:flex-start; gap:12px;
|
|
||||||
margin-bottom:18px; flex-wrap:wrap; }
|
|
||||||
.ds-header h2 { margin:0; font-size:1.3rem; color:var(--primary-dark); display:flex; align-items:center; gap:9px; }
|
|
||||||
|
|
||||||
/* Info santri */
|
|
||||||
.ds-info-box { background:#fff; border-radius:12px; padding:16px 20px; margin-bottom:14px;
|
|
||||||
box-shadow:0 2px 10px rgba(0,0,0,0.06); display:flex; justify-content:space-between;
|
|
||||||
align-items:center; flex-wrap:wrap; gap:12px; }
|
|
||||||
.ds-info-box h3 { margin:0 0 5px; color:var(--primary-color); font-size:1.1rem; }
|
|
||||||
.ds-info-meta { font-size:0.83rem; color:#64748b; display:flex; flex-wrap:wrap; gap:10px; }
|
|
||||||
.ds-info-meta span { display:inline-flex; align-items:center; gap:4px; }
|
|
||||||
|
|
||||||
/* KPI cards */
|
|
||||||
.ds-kpi-grid { display:grid; grid-template-columns:repeat(5,1fr); gap:10px; margin-bottom:14px; }
|
|
||||||
@media(max-width:900px) { .ds-kpi-grid { grid-template-columns:repeat(3,1fr); } }
|
|
||||||
@media(max-width:540px) { .ds-kpi-grid { grid-template-columns:repeat(2,1fr); } }
|
|
||||||
|
|
||||||
.ds-kpi { background:#fff; border-radius:10px; padding:12px 14px;
|
|
||||||
box-shadow:0 2px 8px rgba(0,0,0,0.06); display:flex; align-items:center; gap:10px; }
|
|
||||||
.ds-kpi .ico { width:36px; height:36px; border-radius:9px; display:flex; align-items:center;
|
|
||||||
justify-content:center; font-size:1.1rem; flex-shrink:0; }
|
|
||||||
.ds-kpi.hadir .ico { background:#d1fae5; color:#065f46; }
|
|
||||||
.ds-kpi.terlambat .ico { background:#fff3e0; color:#e65100; }
|
|
||||||
.ds-kpi.izin .ico { background:#fef3c7; color:#92400e; }
|
|
||||||
.ds-kpi.sakit .ico { background:#dbeafe; color:#1e40af; }
|
|
||||||
.ds-kpi.alpa .ico { background:#fee2e2; color:#991b1b; }
|
|
||||||
.ds-kpi .cnt { font-size:1.4rem; font-weight:800; color:var(--primary-dark); line-height:1; }
|
|
||||||
.ds-kpi .lbl { font-size:0.74rem; color:#94a3b8; margin-top:2px; }
|
|
||||||
|
|
||||||
/* Terlambat note */
|
|
||||||
.ds-terlambat-note { font-size:0.76rem; color:#6b7280; background:#fff7ed; border:1px solid #fed7aa;
|
|
||||||
border-radius:8px; padding:6px 12px; margin-bottom:14px;
|
|
||||||
display:flex; align-items:center; gap:6px; }
|
|
||||||
.ds-terlambat-note i { color:#ea580c; }
|
|
||||||
|
|
||||||
/* Tren chart box */
|
|
||||||
.ds-chart-box { background:#fff; border-radius:12px; padding:16px 18px; margin-bottom:14px;
|
|
||||||
box-shadow:0 2px 10px rgba(0,0,0,0.06); }
|
|
||||||
.ds-chart-box h4 { margin:0 0 14px; color:var(--primary-color); font-size:0.95rem;
|
|
||||||
display:flex; align-items:center; gap:7px; }
|
|
||||||
|
|
||||||
/* Riwayat lengkap dengan tabs */
|
|
||||||
.ds-riwayat-box { background:#fff; border-radius:12px; overflow:hidden; margin-bottom:14px;
|
|
||||||
box-shadow:0 2px 10px rgba(0,0,0,0.06); }
|
|
||||||
.ds-riwayat-head { padding:14px 18px 0; border-bottom:2px solid #f1f5f9; }
|
|
||||||
.ds-riwayat-head h4 { margin:0 0 12px; color:var(--primary-dark); font-size:0.95rem;
|
|
||||||
display:flex; align-items:center; gap:7px; }
|
|
||||||
|
|
||||||
/* Tabs */
|
|
||||||
.ds-tabs { display:flex; gap:0; overflow-x:auto; -webkit-overflow-scrolling:touch; }
|
|
||||||
.ds-tabs::-webkit-scrollbar { height:0; }
|
|
||||||
.ds-tab { padding:9px 16px; font-size:0.82rem; font-weight:600; border:none; background:transparent;
|
|
||||||
cursor:pointer; white-space:nowrap; color:#64748b; border-bottom:3px solid transparent;
|
|
||||||
transition:all 0.15s; text-decoration:none; display:inline-flex; align-items:center; gap:6px; }
|
|
||||||
.ds-tab:hover { color:var(--primary-color); background:#f0fdf4; }
|
|
||||||
.ds-tab.active { color:var(--primary-color); border-bottom-color:var(--primary-color); background:#f0fdf4; }
|
|
||||||
.ds-tab .tab-cnt { background:#e8f7f2; color:var(--primary-color); padding:1px 7px; border-radius:10px;
|
|
||||||
font-size:0.72rem; font-weight:700; }
|
|
||||||
.ds-tab.active .tab-cnt { background:var(--primary-color); color:#fff; }
|
|
||||||
.ds-tab .tab-hadir { background:#d1fae5; color:#065f46; padding:1px 7px; border-radius:10px;
|
|
||||||
font-size:0.7rem; font-weight:700; }
|
|
||||||
|
|
||||||
/* Per-page toolbar */
|
|
||||||
.ds-toolbar { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap;
|
|
||||||
gap:8px; padding:10px 18px; background:#fafafa; border-bottom:1px solid #f1f5f9; }
|
|
||||||
.ds-toolbar-left { font-size:0.8rem; color:#64748b; }
|
|
||||||
.ds-toolbar-right { display:flex; align-items:center; gap:8px; font-size:0.8rem; color:#64748b; }
|
|
||||||
.ds-perpage-group { display:flex; gap:4px; }
|
|
||||||
.ds-pp-btn { padding:4px 10px; border:1.5px solid #e2e8f0; border-radius:6px; background:#fff;
|
|
||||||
font-size:0.78rem; font-weight:600; color:#64748b; cursor:pointer;
|
|
||||||
text-decoration:none; transition:all 0.15s; }
|
|
||||||
.ds-pp-btn:hover { border-color:var(--primary-color); color:var(--primary-color); }
|
|
||||||
.ds-pp-btn.active { background:var(--primary-color); color:#fff; border-color:var(--primary-color); }
|
|
||||||
|
|
||||||
/* Table */
|
|
||||||
.ds-table-wrap { overflow-x:auto; }
|
|
||||||
.ds-table { width:100%; border-collapse:collapse; min-width:540px; }
|
|
||||||
.ds-table thead th { padding:9px 14px; text-align:left; font-size:0.78rem; font-weight:600;
|
|
||||||
color:#64748b; background:#f8fafc; border-bottom:1px solid #e2e8f0; }
|
|
||||||
.ds-table tbody td { padding:9px 14px; font-size:0.83rem; border-bottom:1px solid #f8fafc; vertical-align:middle; }
|
|
||||||
.ds-table tbody tr:last-child td { border-bottom:none; }
|
|
||||||
.ds-table tbody tr:hover { background:#f8fafc; }
|
|
||||||
|
|
||||||
/* Status badges (inline fallback jika status_badge tidak ada) */
|
|
||||||
.s-hadir { background:#d1fae5; color:#065f46; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
|
||||||
.s-terlambat { background:#fff3e0; color:#e65100; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
|
||||||
.s-izin { background:#fef3c7; color:#92400e; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
|
||||||
.s-sakit { background:#dbeafe; color:#1e40af; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
|
||||||
.s-alpa { background:#fee2e2; color:#991b1b; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
|
||||||
.s-pulang { background:#f3e8ff; color:#6b21a8; padding:3px 9px; border-radius:9px; font-size:0.74rem; font-weight:700; }
|
|
||||||
|
|
||||||
/* Button back */
|
|
||||||
.btn-ds-back { padding:8px 16px; background:#6b7280; color:#fff; border-radius:8px; font-size:0.82rem;
|
|
||||||
font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:6px;
|
|
||||||
transition:background 0.18s; }
|
|
||||||
.btn-ds-back:hover { background:#4b5563; color:#fff; }
|
|
||||||
|
|
||||||
/* Empty */
|
|
||||||
.ds-empty { text-align:center; padding:30px; color:#94a3b8; }
|
|
||||||
.ds-empty i { font-size:2.5rem; display:block; margin-bottom:10px; opacity:0.35; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$totalHadirEfektif = $stats['_hadir_efektif'] ?? 0;
|
|
||||||
$totalHadir = $stats['Hadir'] ?? 0;
|
|
||||||
$totalTerlambat = $stats['Terlambat'] ?? 0;
|
|
||||||
$totalIzin = $stats['Izin'] ?? 0;
|
|
||||||
$totalSakit = $stats['Sakit'] ?? 0;
|
|
||||||
$totalAlpa = $stats['Alpa'] ?? 0;
|
|
||||||
|
|
||||||
$persenHadir = ($totalHadirEfektif + $totalIzin + $totalSakit + $totalAlpa) > 0
|
|
||||||
? round($totalHadirEfektif / ($totalHadirEfektif + $totalIzin + $totalSakit + $totalAlpa) * 100, 1)
|
|
||||||
: 0;
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ds-header">
|
|
||||||
<h2><i class="fas fa-user-clock" style="color:var(--primary-color);"></i>
|
|
||||||
Riwayat Kehadiran: <?php echo e($santri->nama_lengkap); ?>
|
|
||||||
|
|
||||||
</h2>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn-ds-back">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ds-info-box">
|
|
||||||
<div>
|
|
||||||
<h3><?php echo e($santri->nama_lengkap); ?></h3>
|
|
||||||
<div class="ds-info-meta">
|
|
||||||
<span><i class="fas fa-id-card"></i> <strong><?php echo e($santri->id_santri); ?></strong></span>
|
|
||||||
<span><i class="fas fa-school"></i> <?php echo e($santri->kelas); ?></span>
|
|
||||||
<span><i class="fas fa-circle" style="font-size:0.5rem; color:#22c55e;"></i>
|
|
||||||
<span class="badge badge-success" style="font-size:0.76rem;"><?php echo e($santri->status); ?></span>
|
|
||||||
</span>
|
|
||||||
<?php if($persenHadir > 0): ?>
|
|
||||||
<span style="font-weight:700; color:<?php echo e($persenHadir >= 85 ? '#059669' : ($persenHadir >= 70 ? '#d97706' : '#dc2626')); ?>;">
|
|
||||||
<i class="fas fa-chart-pie"></i> Kehadiran <?php echo e($persenHadir); ?>%
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($totalTerlambat > 0): ?>
|
|
||||||
<div class="ds-terlambat-note">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
<strong><?php echo e($totalTerlambat); ?>x Terlambat</strong> dihitung sebagai <strong>Hadir</strong> (bukan Alpa).
|
|
||||||
Total hadir efektif: <strong><?php echo e($totalHadirEfektif); ?></strong> kali
|
|
||||||
(<?php echo e($totalHadir); ?> hadir tepat waktu + <?php echo e($totalTerlambat); ?> terlambat).
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ds-kpi-grid">
|
|
||||||
<div class="ds-kpi hadir">
|
|
||||||
<div class="ico"><i class="fas fa-check-circle"></i></div>
|
|
||||||
<div>
|
|
||||||
<div class="cnt"><?php echo e($totalHadirEfektif); ?></div>
|
|
||||||
<div class="lbl">Hadir Efektif</div>
|
|
||||||
<?php if($totalTerlambat > 0): ?>
|
|
||||||
<div style="font-size:0.68rem; color:#94a3b8;"><?php echo e($totalHadir); ?>+<?php echo e($totalTerlambat); ?>tl</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ds-kpi terlambat">
|
|
||||||
<div class="ico"><i class="fas fa-clock"></i></div>
|
|
||||||
<div><div class="cnt"><?php echo e($totalTerlambat); ?></div><div class="lbl">Terlambat</div></div>
|
|
||||||
</div>
|
|
||||||
<div class="ds-kpi izin">
|
|
||||||
<div class="ico"><i class="fas fa-envelope"></i></div>
|
|
||||||
<div><div class="cnt"><?php echo e($totalIzin); ?></div><div class="lbl">Izin</div></div>
|
|
||||||
</div>
|
|
||||||
<div class="ds-kpi sakit">
|
|
||||||
<div class="ico"><i class="fas fa-heartbeat"></i></div>
|
|
||||||
<div><div class="cnt"><?php echo e($totalSakit); ?></div><div class="lbl">Sakit</div></div>
|
|
||||||
</div>
|
|
||||||
<div class="ds-kpi alpa">
|
|
||||||
<div class="ico"><i class="fas fa-times-circle"></i></div>
|
|
||||||
<div><div class="cnt"><?php echo e($totalAlpa); ?></div><div class="lbl">Alpa</div></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($riwayat30Hari->count() > 0): ?>
|
|
||||||
<div class="ds-chart-box">
|
|
||||||
<h4><i class="fas fa-chart-line"></i> Tren Kehadiran 30 Hari Terakhir
|
|
||||||
<span style="font-size:0.76rem; font-weight:400; color:#94a3b8; margin-left:4px;">
|
|
||||||
(Hadir + Terlambat)
|
|
||||||
</span>
|
|
||||||
</h4>
|
|
||||||
<canvas id="chartTren" style="max-height:220px;"></canvas>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ds-riwayat-box">
|
|
||||||
<div class="ds-riwayat-head">
|
|
||||||
<h4><i class="fas fa-list-alt" style="color:var(--primary-color);"></i> Riwayat Lengkap per Kategori</h4>
|
|
||||||
|
|
||||||
<?php if($kategoriList->count() > 0): ?>
|
|
||||||
|
|
||||||
<div class="ds-tabs" role="tablist">
|
|
||||||
<?php $__currentLoopData = $kategoriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$tabParams = array_merge(request()->query(), [
|
|
||||||
'tab_kat' => $kat->kategori_id,
|
|
||||||
'per_page' => $perPage,
|
|
||||||
'page' => 1,
|
|
||||||
]);
|
|
||||||
$isActive = ($activeKategori == $kat->kategori_id);
|
|
||||||
$pctKat = $kat->total > 0 ? round($kat->hadir_efektif / $kat->total * 100) : 0;
|
|
||||||
?>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($tabParams)); ?>"
|
|
||||||
class="ds-tab <?php echo e($isActive ? 'active' : ''); ?>"
|
|
||||||
role="tab">
|
|
||||||
<i class="fas fa-tag" style="font-size:0.72rem;"></i>
|
|
||||||
<?php echo e($kat->nama_kategori); ?>
|
|
||||||
|
|
||||||
<span class="tab-cnt"><?php echo e($kat->total); ?></span>
|
|
||||||
<?php if($kat->hadir_efektif > 0): ?>
|
|
||||||
<span class="tab-hadir" title="Hadir efektif"><?php echo e($pctKat); ?>%</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</a>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($riwayats->count() > 0): ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ds-toolbar">
|
|
||||||
<div class="ds-toolbar-left">
|
|
||||||
<?php if(!$showAll): ?>
|
|
||||||
Menampilkan
|
|
||||||
<strong><?php echo e($riwayats->firstItem()); ?>–<?php echo e($riwayats->lastItem()); ?></strong>
|
|
||||||
dari <strong><?php echo e($riwayats->total()); ?></strong> riwayat
|
|
||||||
<?php else: ?>
|
|
||||||
Menampilkan <strong>semua <?php echo e($riwayats->total()); ?></strong> riwayat
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php $activeKat = $kategoriList->firstWhere('kategori_id', $activeKategori); ?>
|
|
||||||
<?php if($activeKat): ?>
|
|
||||||
— <span style="color:var(--primary-color); font-weight:600;"><?php echo e($activeKat->nama_kategori); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="ds-toolbar-right">
|
|
||||||
Tampilkan:
|
|
||||||
<div class="ds-perpage-group">
|
|
||||||
<?php $__currentLoopData = [15, 50, 100]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $pp): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php $ppParams = array_merge(request()->query(), ['per_page' => $pp, 'page' => 1]); ?>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($ppParams)); ?>"
|
|
||||||
class="ds-pp-btn <?php echo e((!$showAll && $perPage == $pp) ? 'active' : ''); ?>">
|
|
||||||
<?php echo e($pp); ?>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<?php $allParams = array_merge(request()->query(), ['per_page' => 'all', 'page' => 1]); ?>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($allParams)); ?>"
|
|
||||||
class="ds-pp-btn <?php echo e($showAll ? 'active' : ''); ?>"
|
|
||||||
title="Tampilkan semua data sekaligus (bisa lambat jika data banyak)">
|
|
||||||
Semua
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="ds-table-wrap">
|
|
||||||
<table class="ds-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:50px;">No</th>
|
|
||||||
<th style="width:110px;">Tanggal</th>
|
|
||||||
<th>Nama Kegiatan</th>
|
|
||||||
<th style="width:115px; text-align:center;">Status</th>
|
|
||||||
<th style="width:90px; text-align:center;">Waktu</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $riwayats; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $idx => $riwayat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td style="color:#94a3b8; font-size:0.78rem;"><?php echo e($riwayats->firstItem() + $idx); ?></td>
|
|
||||||
<td style="font-size:0.81rem; color:#64748b;">
|
|
||||||
<?php echo e($riwayat->tanggal->format('d/m/Y')); ?>
|
|
||||||
|
|
||||||
<div style="font-size:0.71rem; color:#94a3b8;">
|
|
||||||
<?php echo e($riwayat->tanggal->locale('id')->isoFormat('ddd')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<strong style="font-size:0.85rem;"><?php echo e($riwayat->kegiatan->nama_kegiatan); ?></strong>
|
|
||||||
<div style="font-size:0.74rem; color:#94a3b8; margin-top:1px;">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
<?php echo e(date('H:i', strtotime($riwayat->kegiatan->waktu_mulai))); ?>–<?php echo e(date('H:i', strtotime($riwayat->kegiatan->waktu_selesai))); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center;">
|
|
||||||
<?php if(method_exists($riwayat, 'getStatusBadgeAttribute') || isset($riwayat->status_badge)): ?>
|
|
||||||
<?php echo $riwayat->status_badge; ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<?php $st = $riwayat->status; ?>
|
|
||||||
<span class="s-<?php echo e(strtolower($st)); ?>"><?php echo e($st); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center; font-size:0.81rem; color:#64748b;">
|
|
||||||
<?php echo e($riwayat->waktu_absen ? date('H:i', strtotime($riwayat->waktu_absen)) : '–'); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(!$showAll && $riwayats->lastPage() > 1): ?>
|
|
||||||
<div style="padding:12px 16px;">
|
|
||||||
<?php echo e($riwayats->links()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php elseif($showAll): ?>
|
|
||||||
<div style="padding:10px 16px; font-size:0.78rem; color:#94a3b8; background:#fafafa; border-top:1px solid #f1f5f9;">
|
|
||||||
<i class="fas fa-info-circle"></i> Semua <strong><?php echo e($riwayats->total()); ?></strong> data ditampilkan.
|
|
||||||
|
|
||||||
<?php $backPaged = array_merge(request()->query(), ['per_page' => 15, 'page' => 1]); ?>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $santri->id_santri)); ?>?<?php echo e(http_build_query($backPaged)); ?>"
|
|
||||||
style="color:var(--primary-color);">Kembali ke paginasi</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php elseif($kategoriList->count() > 0): ?>
|
|
||||||
<div class="ds-empty">
|
|
||||||
<i class="fas fa-inbox"></i>
|
|
||||||
<p>Belum ada riwayat untuk kategori ini.</p>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="ds-empty">
|
|
||||||
<i class="fas fa-inbox"></i>
|
|
||||||
<p>Santri ini belum memiliki riwayat kehadiran apapun.</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($riwayat30Hari->count() > 0): ?>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
||||||
<script>
|
|
||||||
(function() {
|
|
||||||
var ctx = document.getElementById('chartTren');
|
|
||||||
if (!ctx) return;
|
|
||||||
|
|
||||||
var labels = <?php echo json_encode($riwayat30Hari->pluck('tanggal')->map(fn($d) => date('d/m', strtotime($d)))); ?>;
|
|
||||||
var hadir = <?php echo json_encode($riwayat30Hari->pluck('hadir')); ?>;
|
|
||||||
var total = <?php echo json_encode($riwayat30Hari->pluck('total')); ?>;
|
|
||||||
|
|
||||||
new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: labels,
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: 'Hadir (termasuk terlambat)',
|
|
||||||
data: hadir,
|
|
||||||
borderColor: '#6FBA9D',
|
|
||||||
backgroundColor: 'rgba(111,186,157,0.12)',
|
|
||||||
tension: 0.4,
|
|
||||||
fill: true,
|
|
||||||
pointRadius: 4,
|
|
||||||
pointBackgroundColor: '#6FBA9D',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Total Kegiatan',
|
|
||||||
data: total,
|
|
||||||
borderColor: '#cbd5e1',
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
borderDash: [5, 5],
|
|
||||||
tension: 0.4,
|
|
||||||
fill: false,
|
|
||||||
pointRadius: 0,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: true,
|
|
||||||
interaction: { mode: 'index', intersect: false },
|
|
||||||
plugins: {
|
|
||||||
legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 11 } } }
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: { beginAtZero: true, ticks: { stepSize: 1 }, grid: { color: '#f1f5f9' } },
|
|
||||||
x: { grid: { display: false }, ticks: { font: { size: 10 } } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/riwayat/detail-santri.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,704 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<?php
|
||||||
|
// -- Day-tab calculations --
|
||||||
|
$isoDay = $selectedDate->dayOfWeekIso;
|
||||||
|
$monOfWeek = $selectedDate->copy()->subDays($isoDay - 1);
|
||||||
|
$hariMapTab = [
|
||||||
|
'Senin' => 'Senin','Selasa' => 'Selasa','Rabu' => 'Rabu',
|
||||||
|
'Kamis' => 'Kamis','Jumat' => 'Jumat','Sabtu' => 'Sabtu','Minggu' => 'Ahad'
|
||||||
|
];
|
||||||
|
$activeTab = $hariMapTab[$selectedDate->locale('id')->isoFormat('dddd')] ?? 'Senin';
|
||||||
|
$todayHari = $hariMapTab[now()->locale('id')->isoFormat('dddd')] ?? 'Senin';
|
||||||
|
|
||||||
|
$tabHari = [
|
||||||
|
['nama' => 'Senin', 'offset' => 0],
|
||||||
|
['nama' => 'Selasa', 'offset' => 1],
|
||||||
|
['nama' => 'Rabu', 'offset' => 2],
|
||||||
|
['nama' => 'Kamis', 'offset' => 3],
|
||||||
|
['nama' => 'Jumat', 'offset' => 4],
|
||||||
|
['nama' => 'Sabtu', 'offset' => 5],
|
||||||
|
['nama' => 'Minggu', 'offset' => 6],
|
||||||
|
];
|
||||||
|
|
||||||
|
$kelompokGroups = $kelasList->groupBy('kelompok.nama_kelompok');
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="page-header" style="display:flex; align-items:center; justify-content:space-between;">
|
||||||
|
<h2><i class="fas fa-tachometer-alt"></i> Dashboard Absensi</h2>
|
||||||
|
|
||||||
|
<div style="display:flex; gap:8px;">
|
||||||
|
<a href="<?php echo e(route('admin.mesin.mapping-santri.index')); ?>"
|
||||||
|
class="btn btn-sm btn-secondary">
|
||||||
|
<i class="fas fa-link"></i> Mapping Fingerprint
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo e(route('admin.mesin.import.index')); ?>"
|
||||||
|
class="btn btn-sm btn-success"
|
||||||
|
style="background:#0F7B6C; border-color:#0F7B6C;">
|
||||||
|
<i class="fas fa-file-import"></i> Import
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="color: var(--text-light); margin-top: 5px; margin-bottom: 14px;">
|
||||||
|
<?php echo e($selectedDate->locale('id')->isoFormat('dddd, D MMMM Y')); ?>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php if(session('success')): ?>
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="kpi-grid-kegiatan">
|
||||||
|
<div class="kpi-kegiatan bg-primary">
|
||||||
|
<i class="fas fa-calendar-day kpi-icon"></i>
|
||||||
|
<div class="kpi-value"><?php echo e($totalKegiatanHariIni); ?></div>
|
||||||
|
<div class="kpi-label">Total Kegiatan</div>
|
||||||
|
<div class="kpi-sub">
|
||||||
|
<i class="fas fa-<?php echo e($comparisonTotal >= 0 ? 'arrow-up' : 'arrow-down'); ?>"></i>
|
||||||
|
<?php echo e(abs($comparisonTotal)); ?> vs minggu lalu
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kpi-kegiatan bg-success">
|
||||||
|
<i class="fas fa-check-circle kpi-icon"></i>
|
||||||
|
<div class="kpi-value"><?php echo e($kegiatanSelesai); ?></div>
|
||||||
|
<div class="kpi-label">Kegiatan Selesai</div>
|
||||||
|
<div class="kpi-sub">dari <?php echo e($totalKegiatanHariIni); ?> kegiatan</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kpi-kegiatan bg-warning">
|
||||||
|
<i class="fas fa-chart-line kpi-icon"></i>
|
||||||
|
<div class="kpi-value"><?php echo e($avgKehadiran); ?>%</div>
|
||||||
|
<div class="kpi-label">Rata-rata Kehadiran</div>
|
||||||
|
<div class="kpi-sub">
|
||||||
|
<i class="fas fa-<?php echo e($comparisonAvg >= 0 ? 'arrow-up' : 'arrow-down'); ?>"></i>
|
||||||
|
<?php echo e(abs($comparisonAvg)); ?>% vs minggu lalu
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kpi-kegiatan bg-info">
|
||||||
|
<i class="fas fa-clock kpi-icon"></i>
|
||||||
|
<div class="kpi-value"><?php echo e($kegiatanBerlangsung); ?></div>
|
||||||
|
<div class="kpi-label">Sedang Berlangsung</div>
|
||||||
|
<?php if($kegiatanBerlangsung > 0): ?>
|
||||||
|
<div class="kpi-sub"><i class="fas fa-circle" style="color: #90ee90;"></i> Live Now</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="kpi-sub">Tidak ada kegiatan</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<div class="day-tabs">
|
||||||
|
<?php $__currentLoopData = $tabHari; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tab): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$tabDate = $monOfWeek->copy()->addDays($tab['offset']);
|
||||||
|
$tabDateStr = $tabDate->format('Y-m-d');
|
||||||
|
$isActive = ($activeTab === $tab['nama']);
|
||||||
|
$isToday = ($todayHari === $tab['nama'] && now()->format('W') === $selectedDate->format('W'));
|
||||||
|
$params = array_merge(
|
||||||
|
request()->only(['kelas', 'kategori_id']),
|
||||||
|
['tanggal' => $tabDateStr]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<a href="<?php echo e(route('admin.kegiatan.index', $params)); ?>"
|
||||||
|
class="day-tab <?php echo e($isActive ? 'active' : ''); ?> <?php echo e($isToday ? 'today-tab' : ''); ?>">
|
||||||
|
<span class="day-name"><?php echo e($tab['nama']); ?></span>
|
||||||
|
<span class="day-date"><?php echo e($tabDate->format('d/m')); ?></span>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<form method="GET" action="<?php echo e(route('admin.kegiatan.index')); ?>" id="filterForm" class="filter-form-inline" style="margin-top: 10px;">
|
||||||
|
<input type="hidden" name="kelas" id="kelasInput" value="<?php echo e($selectedKelasId); ?>">
|
||||||
|
|
||||||
|
<div class="filter-form-inline" style="gap: 8px;">
|
||||||
|
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
||||||
|
<i class="fas fa-calendar"></i> Tanggal:
|
||||||
|
</label>
|
||||||
|
<input type="date" name="tanggal" class="form-control"
|
||||||
|
value="<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
||||||
|
onchange="this.form.submit()" style="max-width: 170px;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-form-inline" style="gap: 8px;">
|
||||||
|
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
||||||
|
<i class="fas fa-tags"></i> Kategori:
|
||||||
|
</label>
|
||||||
|
<select name="kategori_id" class="form-control" onchange="this.form.submit()" style="max-width: 180px;">
|
||||||
|
<option value="">Semua Kategori</option>
|
||||||
|
<?php $__currentLoopData = $kategoris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kat): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<option value="<?php echo e($kat->kategori_id); ?>" <?php echo e(request('kategori_id') == $kat->kategori_id ? 'selected' : ''); ?>>
|
||||||
|
<?php echo e($kat->nama_kategori); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-form-inline" style="gap: 8px;">
|
||||||
|
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
||||||
|
<i class="fas fa-school"></i> Kelas:
|
||||||
|
</label>
|
||||||
|
<select name="kelas" class="form-control" onchange="this.form.submit()" style="max-width: 200px;">
|
||||||
|
<option value="">Semua Kelas</option>
|
||||||
|
<option value="umum" <?php echo e($selectedKelasId === 'umum' ? 'selected' : ''); ?>>Kegiatan Umum</option>
|
||||||
|
<?php $__currentLoopData = $kelompokGroups; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompokNama => $kelasGroup): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<optgroup label="<?php echo e($kelompokNama); ?>">
|
||||||
|
<?php $__currentLoopData = $kelasGroup; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<option value="<?php echo e($kelas->id); ?>" <?php echo e($selectedKelasId == $kelas->id ? 'selected' : ''); ?>>
|
||||||
|
<?php echo e($kelas->nama_kelas); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</optgroup>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-sm btn-primary" onclick="setToday()">
|
||||||
|
<i class="fas fa-calendar-day"></i> Hari Ini
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" onclick="prevDay()">
|
||||||
|
<i class="fas fa-chevron-left"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" onclick="nextDay()">
|
||||||
|
<i class="fas fa-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php if(count($insights) > 0): ?>
|
||||||
|
<div class="content-box" style="margin-top: 14px;">
|
||||||
|
<h4 style="margin: 0 0 12px; color: var(--primary-color);">
|
||||||
|
<i class="fas fa-lightbulb"></i> Insight Hari Ini
|
||||||
|
</h4>
|
||||||
|
<?php $__currentLoopData = $insights; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $insight): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<div class="insight-item <?php echo e($insight['type']); ?>">
|
||||||
|
<div class="insight-content">
|
||||||
|
<div class="insight-message">
|
||||||
|
<i class="fas fa-<?php echo e($insight['icon']); ?>"></i> <?php echo e($insight['message']); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="insight-detail"><?php echo e($insight['detail']); ?></div>
|
||||||
|
</div>
|
||||||
|
<?php if($insight['action_url']): ?>
|
||||||
|
<a href="<?php echo e($insight['action_url']); ?>" class="btn btn-sm btn-<?php echo e($insight['type']); ?>">
|
||||||
|
<?php echo e($insight['action_text']); ?>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="layout-kegiatan" style="margin-top: 14px;">
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<?php if($kegiatanHariIni->count() > 0): ?>
|
||||||
|
<div class="kegiatan-list">
|
||||||
|
<?php $__currentLoopData = $kegiatanHariIni; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$persen = $kegiatan->persen_kehadiran;
|
||||||
|
$totalSantri = $kegiatan->total_santri_kegiatan;
|
||||||
|
$totalHadir = $kegiatan->total_hadir; // hadir + terlambat
|
||||||
|
$totalInput = $kegiatan->total_absensi; // sudah diinput (semua status)
|
||||||
|
$belumAbsen = $kegiatan->belum_absen; // belum diinput sama sekali
|
||||||
|
$terlambat = $kegiatan->total_terlambat;
|
||||||
|
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
||||||
|
|
||||||
|
// Warna progress bar
|
||||||
|
$pClass = $persen >= 85 ? 'p-success' : ($persen >= 70 ? 'p-warning' : ($persen >= 50 ? 'p-orange' : 'p-danger'));
|
||||||
|
|
||||||
|
// Hitung per kelas: sudah input berapa
|
||||||
|
$infoPerKelas = $kegiatan->info_per_kelas ?? collect();
|
||||||
|
?>
|
||||||
|
<div class="kegiatan-card">
|
||||||
|
<div class="kegiatan-card-header">
|
||||||
|
<div class="kegiatan-info">
|
||||||
|
<h3 class="kegiatan-title">
|
||||||
|
<i class="fas fa-calendar" style="color: var(--primary-color);"></i>
|
||||||
|
<?php echo e($kegiatan->nama_kegiatan); ?>
|
||||||
|
|
||||||
|
</h3>
|
||||||
|
<div class="kegiatan-meta">
|
||||||
|
<span>
|
||||||
|
<i class="fas fa-clock"></i>
|
||||||
|
<?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?> –
|
||||||
|
<?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<span class="badge badge-info">
|
||||||
|
<i class="fas fa-tag"></i>
|
||||||
|
<?php echo e($kegiatan->kategori->nama_kategori); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<?php if($kegiatan->materi): ?>
|
||||||
|
<span>
|
||||||
|
<i class="fas fa-book"></i>
|
||||||
|
<?php echo e(Str::limit($kegiatan->materi, 40)); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<span>
|
||||||
|
<i class="fas fa-layer-group"></i>
|
||||||
|
<?php if($isUmum): ?>
|
||||||
|
<span class="badge badge-secondary">Kegiatan Umum</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php echo e($kegiatan->kelasKegiatan->pluck('nama_kelas')->implode(', ')); ?>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="status-badge status-<?php echo e($kegiatan->status_kegiatan); ?>">
|
||||||
|
<?php if($kegiatan->status_kegiatan == 'belum'): ?>
|
||||||
|
<i class="fas fa-hourglass-start"></i> Belum Dimulai
|
||||||
|
<?php elseif($kegiatan->status_kegiatan == 'berlangsung'): ?>
|
||||||
|
<i class="fas fa-play-circle"></i> Berlangsung
|
||||||
|
<?php else: ?>
|
||||||
|
<i class="fas fa-check-circle"></i> Selesai
|
||||||
|
<?php endif; ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="kegiatan-progress">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="kegiatan-progress-header" style="margin-bottom: 4px;">
|
||||||
|
<span style="font-weight: 500;">
|
||||||
|
<i class="fas fa-users"></i> Kehadiran
|
||||||
|
|
||||||
|
<?php if($terlambat > 0): ?>
|
||||||
|
<span style="font-size: 0.78rem; color: #FF9800; font-weight: 400; margin-left: 4px;">
|
||||||
|
(termasuk <?php echo e($terlambat); ?> terlambat)
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</span>
|
||||||
|
<span style="font-weight: 700; font-size: 1rem; color: <?php echo e($persen >= 85 ? '#059669' : ($persen >= 70 ? '#d97706' : '#dc2626')); ?>;">
|
||||||
|
<?php echo e($totalHadir); ?>/<?php echo e($totalSantri); ?> santri
|
||||||
|
<span style="font-size: 0.85rem;">(<?php echo e($persen); ?>%)</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 12px; margin-bottom: 6px; font-size: 0.78rem; flex-wrap: wrap;">
|
||||||
|
<span style="color: #059669;">
|
||||||
|
<i class="fas fa-check"></i>
|
||||||
|
Sudah diinput: <strong><?php echo e($totalInput); ?></strong> santri
|
||||||
|
</span>
|
||||||
|
<?php if($belumAbsen > 0): ?>
|
||||||
|
<span style="color: #dc2626;">
|
||||||
|
<i class="fas fa-hourglass-half"></i>
|
||||||
|
Belum absen: <strong><?php echo e($belumAbsen); ?></strong> santri
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color: #059669;">
|
||||||
|
<i class="fas fa-check-double"></i>
|
||||||
|
Semua sudah diinput
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$hadirMurni = $kegiatan->total_hadir_murni ?? ($totalHadir - $terlambat);
|
||||||
|
$alpa = $kegiatan->total_alpa ?? 0;
|
||||||
|
$izin = $kegiatan->total_izin ?? 0;
|
||||||
|
$sakit = $kegiatan->total_sakit ?? 0;
|
||||||
|
|
||||||
|
$pctHadir = $totalSantri > 0 ? round($hadirMurni / $totalSantri * 100) : 0;
|
||||||
|
$pctTlmbat = $totalSantri > 0 ? round($terlambat / $totalSantri * 100) : 0;
|
||||||
|
$pctIzin = $totalSantri > 0 ? round($izin / $totalSantri * 100) : 0;
|
||||||
|
$pctSakit = $totalSantri > 0 ? round($sakit / $totalSantri * 100) : 0;
|
||||||
|
$pctAlpa = $totalSantri > 0 ? round($alpa / $totalSantri * 100) : 0;
|
||||||
|
$pctBelum = $totalSantri > 0 ? round($belumAbsen / $totalSantri * 100) : 0;
|
||||||
|
?>
|
||||||
|
<div style="height: 22px; background: #f3f4f6; border-radius: 11px; overflow: hidden; display: flex; margin-bottom: 6px;">
|
||||||
|
<?php if($pctHadir > 0): ?>
|
||||||
|
<div style="width:<?php echo e($pctHadir); ?>%; background:#22c55e; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Hadir: <?php echo e($hadirMurni); ?>"><?php echo e($hadirMurni > 0 && $pctHadir > 5 ? $hadirMurni : ''); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($pctTlmbat > 0): ?>
|
||||||
|
<div style="width:<?php echo e($pctTlmbat); ?>%; background:#FF9800; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Terlambat : <?php echo e($terlambat); ?>"><?php echo e($terlambat > 0 && $pctTlmbat > 5 ? $terlambat : ''); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($pctIzin > 0): ?>
|
||||||
|
<div style="width:<?php echo e($pctIzin); ?>%; background:#f59e0b; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Izin: <?php echo e($izin); ?>"><?php echo e($izin > 0 && $pctIzin > 5 ? $izin : ''); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($pctSakit > 0): ?>
|
||||||
|
<div style="width:<?php echo e($pctSakit); ?>%; background:#3b82f6; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Sakit: <?php echo e($sakit); ?>"><?php echo e($sakit > 0 && $pctSakit > 5 ? $sakit : ''); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($pctAlpa > 0): ?>
|
||||||
|
<div style="width:<?php echo e($pctAlpa); ?>%; background:#ef4444; display:flex; align-items:center; justify-content:center; color:white; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Alpa: <?php echo e($alpa); ?>"><?php echo e($alpa > 0 && $pctAlpa > 5 ? $alpa : ''); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($pctBelum > 0): ?>
|
||||||
|
<div style="width:<?php echo e($pctBelum); ?>%; background:#d1d5db; display:flex; align-items:center; justify-content:center; color:#6b7280; font-size:0.7rem; font-weight:700;"
|
||||||
|
title="Belum absen: <?php echo e($belumAbsen); ?>"><?php echo e($belumAbsen > 0 && $pctBelum > 5 ? $belumAbsen : ''); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:flex; gap:10px; flex-wrap:wrap; font-size:0.72rem; color:#6b7280; margin-bottom: 6px;">
|
||||||
|
<?php if($hadirMurni > 0): ?>
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#22c55e;margin-right:2px;"></span>Hadir</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($terlambat > 0): ?>
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#FF9800;margin-right:2px;"></span>Terlambat</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($izin > 0): ?>
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#f59e0b;margin-right:2px;"></span>Izin</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($sakit > 0): ?>
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#3b82f6;margin-right:2px;"></span>Sakit</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($alpa > 0): ?>
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#ef4444;margin-right:2px;"></span>Alpa</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($belumAbsen > 0): ?>
|
||||||
|
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:#d1d5db;margin-right:2px;"></span>Belum absen</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if(!$isUmum && $infoPerKelas->count() > 1): ?>
|
||||||
|
<div style="margin-top: 8px; padding: 8px 10px; background: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;">
|
||||||
|
<div style="font-size: 0.75rem; font-weight: 600; color: #475569; margin-bottom: 5px;">
|
||||||
|
<i class="fas fa-school"></i> Status per Kelas:
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; flex-wrap: wrap; gap: 6px;">
|
||||||
|
<?php $__currentLoopData = $infoPerKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $infoKls): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
// Hitung santri kelas ini yg sudah diinput dari data absensis
|
||||||
|
$sudahKelas = $kegiatan->absensis->filter(function($ab) use ($infoKls) {
|
||||||
|
return ($ab->santri->kelas_name ?? '') === $infoKls['nama'];
|
||||||
|
})->count();
|
||||||
|
$totalKls = $infoKls['total_santri'];
|
||||||
|
$belumKls = max(0, $totalKls - $sudahKelas);
|
||||||
|
$sudahSemua = $belumKls === 0 && $totalKls > 0;
|
||||||
|
?>
|
||||||
|
<div style="display: flex; align-items: center; gap: 4px; padding: 3px 8px;
|
||||||
|
background: <?php echo e($sudahSemua ? '#dcfce7' : ($sudahKelas > 0 ? '#fef9c3' : '#f1f5f9')); ?>;
|
||||||
|
border: 1px solid <?php echo e($sudahSemua ? '#86efac' : ($sudahKelas > 0 ? '#fde68a' : '#e2e8f0')); ?>;
|
||||||
|
border-radius: 6px; font-size: 0.72rem;">
|
||||||
|
<i class="fas fa-<?php echo e($sudahSemua ? 'check-circle' : ($sudahKelas > 0 ? 'minus-circle' : 'circle')); ?>"
|
||||||
|
style="color: <?php echo e($sudahSemua ? '#16a34a' : ($sudahKelas > 0 ? '#ca8a04' : '#94a3b8')); ?>;"></i>
|
||||||
|
<span style="font-weight: 600;"><?php echo e($infoKls['nama']); ?></span>
|
||||||
|
<span style="color: #64748b;">
|
||||||
|
<?php echo e($sudahKelas); ?>/<?php echo e($totalKls); ?>
|
||||||
|
|
||||||
|
<?php if(!$sudahSemua && $belumKls > 0): ?>
|
||||||
|
<span style="color: #dc2626;">(<?php echo e($belumKls); ?> belum)</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="kegiatan-actions">
|
||||||
|
<a href="<?php echo e(route('admin.absensi-kegiatan.input', $kegiatan->kegiatan_id)); ?>?tanggal=<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
||||||
|
class="btn btn-sm btn-primary">
|
||||||
|
<i class="fas fa-clipboard-check"></i> Input Absensi
|
||||||
|
</a>
|
||||||
|
<button type="button" class="btn btn-sm btn-info"
|
||||||
|
data-id="<?php echo e($kegiatan->kegiatan_id); ?>"
|
||||||
|
data-tanggal="<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
||||||
|
onclick="showDetailModal(this.getAttribute('data-id'), this.getAttribute('data-tanggal'))">
|
||||||
|
<i class="fas fa-eye"></i> Lihat Detail
|
||||||
|
</button>
|
||||||
|
<a href="<?php echo e(route('admin.absensi-kegiatan.rekap', $kegiatan->kegiatan_id)); ?>?tanggal=<?php echo e($selectedDate->format('Y-m-d')); ?>"
|
||||||
|
class="btn btn-sm btn-secondary">
|
||||||
|
<i class="fas fa-chart-bar"></i> Rekap
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="empty-state">
|
||||||
|
<i class="fas fa-calendar-times"></i>
|
||||||
|
<h3>Tidak Ada Kegiatan Dijadwalkan</h3>
|
||||||
|
<p>Tidak ada kegiatan untuk
|
||||||
|
<?php echo e($selectedKelasId ? 'kelas ini' : 'hari ini'); ?>
|
||||||
|
|
||||||
|
pada <?php echo e($selectedDate->locale('id')->isoFormat('dddd, D MMMM Y')); ?>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
<a href="<?php echo e(route('admin.kegiatan.create')); ?>" class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Buat Kegiatan Baru
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="heatmap-calendar">
|
||||||
|
<div class="heatmap-header">
|
||||||
|
<i class="fas fa-calendar-alt"></i>
|
||||||
|
<span>Kalender Kehadiran</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-form-inline" style="margin-bottom: 12px;">
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" style="padding: 4px 8px;"
|
||||||
|
onclick="changeHeatmapMonth(-1)">
|
||||||
|
<i class="fas fa-chevron-left"></i>
|
||||||
|
</button>
|
||||||
|
<select id="heatmapMonth" onchange="updateHeatmap()" class="form-control" style="flex: 1;">
|
||||||
|
<?php for($m = 1; $m <= 12; $m++): ?>
|
||||||
|
<option value="<?php echo e($m); ?>" <?php echo e($m == now()->month ? 'selected' : ''); ?>>
|
||||||
|
<?php echo e(\Carbon\Carbon::create(null, $m, 1)->locale('id')->isoFormat('MMMM')); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
<select id="heatmapYear" onchange="updateHeatmap()" class="form-control" style="width: 80px;">
|
||||||
|
<?php for($y = now()->year - 2; $y <= now()->year + 1; $y++): ?>
|
||||||
|
<option value="<?php echo e($y); ?>" <?php echo e($y == now()->year ? 'selected' : ''); ?>><?php echo e($y); ?></option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" style="padding: 4px 8px;"
|
||||||
|
onclick="changeHeatmapMonth(1)">
|
||||||
|
<i class="fas fa-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center; font-weight: 600; color: var(--primary-color); margin-bottom: 10px;"
|
||||||
|
id="heatmapMonthName">
|
||||||
|
<?php echo e(now()->locale('id')->isoFormat('MMMM Y')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="heatmap-days">
|
||||||
|
<div class="heatmap-day-label">Sen</div>
|
||||||
|
<div class="heatmap-day-label">Sel</div>
|
||||||
|
<div class="heatmap-day-label">Rab</div>
|
||||||
|
<div class="heatmap-day-label">Kam</div>
|
||||||
|
<div class="heatmap-day-label">Jum</div>
|
||||||
|
<div class="heatmap-day-label">Sab</div>
|
||||||
|
<div class="heatmap-day-label">Ahd</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="heatmap-grid" id="heatmapGrid">
|
||||||
|
<?php $__currentLoopData = $heatmapData; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $day): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<div class="heatmap-cell heatmap-level-<?php echo e($day['level']); ?> <?php echo e($day['is_today'] ? 'today' : ''); ?>"
|
||||||
|
data-date="<?php echo e($day['date']); ?>"
|
||||||
|
data-percentage="<?php echo e($day['percentage']); ?>"
|
||||||
|
title="<?php echo e(\Carbon\Carbon::parse($day['date'])->locale('id')->isoFormat('dddd, D MMM Y')); ?>: <?php echo e($day['percentage']); ?>%">
|
||||||
|
<?php echo e(\Carbon\Carbon::parse($day['date'])->format('j')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="heatmap-legend">
|
||||||
|
<div class="heatmap-legend-title">Legend:</div>
|
||||||
|
<div class="heatmap-legend-items">
|
||||||
|
<div class="heatmap-legend-item">
|
||||||
|
<div class="heatmap-legend-box heatmap-level-4"></div>
|
||||||
|
<span>>90%</span>
|
||||||
|
</div>
|
||||||
|
<div class="heatmap-legend-item">
|
||||||
|
<div class="heatmap-legend-box heatmap-level-3"></div>
|
||||||
|
<span>80-90%</span>
|
||||||
|
</div>
|
||||||
|
<div class="heatmap-legend-item">
|
||||||
|
<div class="heatmap-legend-box heatmap-level-2"></div>
|
||||||
|
<span>70-80%</span>
|
||||||
|
</div>
|
||||||
|
<div class="heatmap-legend-item">
|
||||||
|
<div class="heatmap-legend-box heatmap-level-1"></div>
|
||||||
|
<span><70%</span>
|
||||||
|
</div>
|
||||||
|
<div class="heatmap-legend-item">
|
||||||
|
<div class="heatmap-legend-box heatmap-level-0"></div>
|
||||||
|
<span>No data</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="detailModal" class="modal-kegiatan">
|
||||||
|
<div class="modal-kegiatan-panel">
|
||||||
|
<div class="modal-kegiatan-head">
|
||||||
|
<h3><i class="fas fa-info-circle"></i> Detail Absensi Kegiatan</h3>
|
||||||
|
<button class="modal-kegiatan-close" onclick="closeModal()">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-kegiatan-body" id="modalBody">
|
||||||
|
<div style="text-align: center; padding: 22px;">
|
||||||
|
<i class="fas fa-spinner fa-spin" style="font-size: 2rem; color: var(--primary-color);"></i>
|
||||||
|
<p style="margin-top: 10px;">Memuat data...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function setToday() {
|
||||||
|
var now = new Date();
|
||||||
|
var y = now.getFullYear();
|
||||||
|
var m = ('0' + (now.getMonth() + 1)).slice(-2);
|
||||||
|
var d = ('0' + now.getDate()).slice(-2);
|
||||||
|
document.querySelector('input[name="tanggal"]').value = y + '-' + m + '-' + d;
|
||||||
|
document.getElementById('filterForm').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function prevDay() {
|
||||||
|
var currentDate = new Date('<?php echo e($selectedDate->format("Y-m-d")); ?>');
|
||||||
|
currentDate.setDate(currentDate.getDate() - 1);
|
||||||
|
document.querySelector('input[name="tanggal"]').value = currentDate.toISOString().split('T')[0];
|
||||||
|
document.getElementById('filterForm').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDay() {
|
||||||
|
var currentDate = new Date('<?php echo e($selectedDate->format("Y-m-d")); ?>');
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
|
document.querySelector('input[name="tanggal"]').value = currentDate.toISOString().split('T')[0];
|
||||||
|
document.getElementById('filterForm').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function goToDate(date) {
|
||||||
|
document.querySelector('input[name="tanggal"]').value = date;
|
||||||
|
document.getElementById('filterForm').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDetailModal(kegiatanId, tanggal) {
|
||||||
|
var modal = document.getElementById('detailModal');
|
||||||
|
var modalBody = document.getElementById('modalBody');
|
||||||
|
modal.classList.add('active');
|
||||||
|
|
||||||
|
var baseUrl = '<?php echo e(route("admin.kegiatan.detail-modal", ":id")); ?>';
|
||||||
|
var url = baseUrl.replace(':id', kegiatanId) + '?tanggal=' + tanggal;
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(function(r) { return r.text(); })
|
||||||
|
.then(function(html) { modalBody.innerHTML = html; })
|
||||||
|
.catch(function() {
|
||||||
|
modalBody.innerHTML =
|
||||||
|
'<div style="text-align:center;padding:22px;">' +
|
||||||
|
'<i class="fas fa-exclamation-circle" style="font-size:2.2rem;color:var(--danger-color);"></i>' +
|
||||||
|
'<h4 style="margin:20px 0 10px;color:var(--danger-color);">Gagal Memuat Data</h4>' +
|
||||||
|
'<p style="color:var(--text-light);">Terjadi kesalahan saat memuat detail absensi.</p>' +
|
||||||
|
'<button class="btn btn-primary" onclick="closeModal()">Tutup</button>' +
|
||||||
|
'</div>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
document.getElementById('detailModal').classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onclick = function(event) {
|
||||||
|
var modal = document.getElementById('detailModal');
|
||||||
|
if (event.target === modal) { closeModal(); }
|
||||||
|
};
|
||||||
|
document.addEventListener('keydown', function(event) {
|
||||||
|
if (event.key === 'Escape') { closeModal(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('heatmapGrid').addEventListener('click', function(e) {
|
||||||
|
var cell = e.target.closest('.heatmap-cell');
|
||||||
|
if (cell && cell.dataset.date) { goToDate(cell.dataset.date); }
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeHeatmapMonth(delta) {
|
||||||
|
var monthSelect = document.getElementById('heatmapMonth');
|
||||||
|
var yearSelect = document.getElementById('heatmapYear');
|
||||||
|
var month = parseInt(monthSelect.value) + delta;
|
||||||
|
var year = parseInt(yearSelect.value);
|
||||||
|
if (month > 12) { month = 1; year++; }
|
||||||
|
else if (month < 1) { month = 12; year--; }
|
||||||
|
monthSelect.value = month;
|
||||||
|
yearSelect.value = year;
|
||||||
|
updateHeatmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateHeatmap() {
|
||||||
|
var month = document.getElementById('heatmapMonth').value;
|
||||||
|
var year = document.getElementById('heatmapYear').value;
|
||||||
|
var kelasId = document.getElementById('kelasInput').value;
|
||||||
|
|
||||||
|
var monthNames = ['Januari','Februari','Maret','April','Mei','Juni',
|
||||||
|
'Juli','Agustus','September','Oktober','November','Desember'];
|
||||||
|
document.getElementById('heatmapMonthName').textContent = monthNames[month - 1] + ' ' + year;
|
||||||
|
|
||||||
|
var url = '<?php echo e(route("admin.kegiatan.index")); ?>' +
|
||||||
|
'?heatmap=1&month=' + month + '&year=' + year + '&kelas=' + kelasId;
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(function(r) { return r.json(); })
|
||||||
|
.then(function(data) {
|
||||||
|
var grid = document.getElementById('heatmapGrid');
|
||||||
|
grid.innerHTML = '';
|
||||||
|
|
||||||
|
var firstDay = new Date(year, month - 1, 1).getDay();
|
||||||
|
var startDay = firstDay === 0 ? 6 : firstDay - 1;
|
||||||
|
for (var i = 0; i < startDay; i++) {
|
||||||
|
var empty = document.createElement('div');
|
||||||
|
empty.className = 'heatmap-cell';
|
||||||
|
empty.style.visibility = 'hidden';
|
||||||
|
grid.appendChild(empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.heatmapData.forEach(function(day) {
|
||||||
|
var cell = document.createElement('div');
|
||||||
|
var date = new Date(day.date);
|
||||||
|
var today = new Date();
|
||||||
|
var isToday = date.toDateString() === today.toDateString();
|
||||||
|
cell.className = 'heatmap-cell heatmap-level-' + day.level + (isToday ? ' today' : '');
|
||||||
|
cell.setAttribute('data-date', day.date);
|
||||||
|
cell.setAttribute('data-percentage', day.percentage);
|
||||||
|
cell.setAttribute('title', day.title);
|
||||||
|
cell.onclick = function() { goToDate(day.date); };
|
||||||
|
cell.textContent = date.getDate();
|
||||||
|
grid.appendChild(cell);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) { console.error('Error loading heatmap:', err); });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/data/dashboard.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$totalSantri = $kegiatan->total_absensi;
|
|
||||||
$hdr = $kegiatan->hadir ?? 0;
|
|
||||||
$tlb = $kegiatan->terlambat ?? 0;
|
|
||||||
$izn = $kegiatan->izin ?? 0;
|
|
||||||
$skt = $kegiatan->sakit ?? 0;
|
|
||||||
$alp = $kegiatan->alpa ?? 0;
|
|
||||||
$plg = $kegiatan->pulang ?? 0;
|
|
||||||
$tot = $kegiatan->total_absensi ?? 0;
|
|
||||||
|
|
||||||
$pct = fn($n) => $tot > 0 ? round($n / $tot * 100) : 0;
|
|
||||||
|
|
||||||
$isUmum = $kegiatan->kelasKegiatan->isEmpty();
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="rw-card">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-card-head">
|
|
||||||
<div style="flex: 1; min-width: 0;">
|
|
||||||
<div class="rw-card-title">
|
|
||||||
<i class="fas fa-clipboard-list"></i>
|
|
||||||
<?php echo e($kegiatan->nama_kegiatan); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="rw-card-meta">
|
|
||||||
<span><i class="fas fa-clock"></i>
|
|
||||||
<?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?>–<?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span class="rw-kat-tag"><i class="fas fa-tag"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
<?php if($isUmum): ?>
|
|
||||||
<span class="rw-umum-tag"><i class="fas fa-globe"></i> Umum</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php $__currentLoopData = $kegiatan->kelasKegiatan->take(3); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kls): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<span class="rw-kelas-tag"><?php echo e($kls->nama_kelas); ?></span>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($kegiatan->kelasKegiatan->count() > 3): ?>
|
|
||||||
<span class="rw-umum-tag">+<?php echo e($kegiatan->kelasKegiatan->count() - 3); ?> kelas</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(isset($passParams) && $passParams['mode'] === 'hari_ini'): ?>
|
|
||||||
<div style="font-size: 0.75rem; color: var(--primary-color); font-weight: 700;
|
|
||||||
background: #f0fdf4; padding: 4px 10px; border-radius: 20px; border: 1px solid #bbf7d0;
|
|
||||||
white-space: nowrap; flex-shrink: 0;">
|
|
||||||
<i class="fas fa-calendar-day"></i> <?php echo e($kegiatan->hari); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-card-body">
|
|
||||||
<?php if($tot > 0): ?>
|
|
||||||
|
|
||||||
<div class="rw-stats-row">
|
|
||||||
<?php if($hdr > 0): ?> <span class="rw-chip hadir"><i class="fas fa-check"></i> <?php echo e($hdr); ?> Hadir</span> <?php endif; ?>
|
|
||||||
<?php if($tlb > 0): ?> <span class="rw-chip terlambat"><i class="fas fa-clock"></i> <?php echo e($tlb); ?> Terlambat</span> <?php endif; ?>
|
|
||||||
<?php if($izn > 0): ?> <span class="rw-chip izin"><i class="fas fa-envelope"></i> <?php echo e($izn); ?> Izin</span> <?php endif; ?>
|
|
||||||
<?php if($skt > 0): ?> <span class="rw-chip sakit"><i class="fas fa-heartbeat"></i> <?php echo e($skt); ?> Sakit</span> <?php endif; ?>
|
|
||||||
<?php if($alp > 0): ?> <span class="rw-chip alpa"><i class="fas fa-times"></i> <?php echo e($alp); ?> Alpa</span> <?php endif; ?>
|
|
||||||
<?php if($plg > 0): ?> <span class="rw-chip pulang"><i class="fas fa-home"></i> <?php echo e($plg); ?> Pulang</span> <?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-progress-wrap">
|
|
||||||
<?php if($hdr > 0): ?> <div class="rw-prog-hadir" style="width:<?php echo e($pct($hdr)); ?>%;" title="Hadir <?php echo e($hdr); ?>"></div> <?php endif; ?>
|
|
||||||
<?php if($tlb > 0): ?> <div class="rw-prog-terlambat" style="width:<?php echo e($pct($tlb)); ?>%;" title="Terlambat <?php echo e($tlb); ?>"></div> <?php endif; ?>
|
|
||||||
<?php if($izn > 0): ?> <div class="rw-prog-izin" style="width:<?php echo e($pct($izn)); ?>%;" title="Izin <?php echo e($izn); ?>"></div> <?php endif; ?>
|
|
||||||
<?php if($skt > 0): ?> <div class="rw-prog-sakit" style="width:<?php echo e($pct($skt)); ?>%;" title="Sakit <?php echo e($skt); ?>"></div> <?php endif; ?>
|
|
||||||
<?php if($alp > 0): ?> <div class="rw-prog-alpa" style="width:<?php echo e($pct($alp)); ?>%;" title="Alpa <?php echo e($alp); ?>"></div> <?php endif; ?>
|
|
||||||
<?php if($plg > 0): ?> <div class="rw-prog-pulang" style="width:<?php echo e($pct($plg)); ?>%;" title="Pulang <?php echo e($plg); ?>"></div> <?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 0.74rem; color: #94a3b8;">
|
|
||||||
Total tercatat: <strong style="color:#374151;"><?php echo e($tot); ?></strong> santri
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="rw-chip none"><i class="fas fa-inbox"></i> Belum ada data absensi</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-card-foot">
|
|
||||||
<div class="rw-total-txt">
|
|
||||||
<?php if($tot > 0): ?>
|
|
||||||
<i class="fas fa-users" style="color:var(--primary-color);"></i>
|
|
||||||
<strong><?php echo e($hdr + $tlb); ?></strong> hadir dari <strong><?php echo e($tot); ?></strong> tercatat
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color:#cbd5e1;"><i class="fas fa-info-circle"></i> Belum ada absensi diinput</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$detailParams = array_merge($passParams ?? [], ['kategori_id' => request('kategori_id')]);
|
|
||||||
?>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kegiatan->id)); ?>?<?php echo e(http_build_query($detailParams)); ?>"
|
|
||||||
class="btn-rw-detail">
|
|
||||||
<i class="fas fa-users"></i> Lihat Santri
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/riwayat/_card.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,395 @@
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-wallet"></i> Manajemen Uang Saku Santri</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if(session('success')): ?>
|
||||||
|
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if(session('error')): ?>
|
||||||
|
<div class="alert alert-danger"><i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?></div>
|
||||||
|
<?php 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>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom:16px;">
|
||||||
|
<form method="GET" action="<?php echo e(route('admin.uang-saku.index')); ?>" id="filterForm"
|
||||||
|
style="display:flex;flex-wrap:wrap;gap:10px;align-items:flex-end;margin-bottom:18px;">
|
||||||
|
<?php if(request('search')): ?> <input type="hidden" name="search" value="<?php echo e(request('search')); ?>"> <?php endif; ?>
|
||||||
|
<?php if(request('sort')): ?> <input type="hidden" name="sort" value="<?php echo e(request('sort')); ?>"> <?php 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="<?php echo e($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="<?php echo e($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');
|
||||||
|
?>
|
||||||
|
<button type="button" onclick="setPreset('today')"
|
||||||
|
class="btn btn-sm <?php echo e($isHariIni ? 'btn-primary' : 'btn-secondary'); ?>">Hari Ini</button>
|
||||||
|
<button type="button" onclick="setPreset('month')"
|
||||||
|
class="btn btn-sm <?php echo e($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>
|
||||||
|
|
||||||
|
|
||||||
|
<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"><?php echo e($kpi['total_transaksi']); ?> Transaksi</p>
|
||||||
|
<span class="card-sub">dari <?php echo e($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 <?php echo e(number_format($kpi['total_pemasukan'], 0, ',', '.')); ?></p>
|
||||||
|
<span class="card-sub">
|
||||||
|
<?php echo e(\Carbon\Carbon::parse($dari)->format('d M')); ?> – <?php echo e(\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 <?php echo e(number_format($kpi['total_pengeluaran'], 0, ',', '.')); ?></p>
|
||||||
|
<span class="card-sub">
|
||||||
|
<?php echo e(\Carbon\Carbon::parse($dari)->format('d M')); ?> – <?php echo e(\Carbon\Carbon::parse($sampai)->format('d M Y')); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<i class="fas fa-arrow-circle-up card-icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<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 <?php echo e(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>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:flex;justify-content:space-between;align-items:center;
|
||||||
|
margin-bottom:14px;flex-wrap:wrap;gap:10px;">
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.create')); ?>" class="btn btn-primary">
|
||||||
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
|
</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<div></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
|
||||||
|
|
||||||
|
<form method="GET" action="<?php echo e(route('admin.uang-saku.index')); ?>"
|
||||||
|
style="display:flex;gap:6px;align-items:center;">
|
||||||
|
<input type="hidden" name="dari" value="<?php echo e($dari); ?>">
|
||||||
|
<input type="hidden" name="sampai" value="<?php echo e($sampai); ?>">
|
||||||
|
<?php if(request('search')): ?> <input type="hidden" name="search" value="<?php echo e(request('search')); ?>"> <?php 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" <?php echo e($sort==='nama' ? 'selected':''); ?>>Nama</option>
|
||||||
|
<option value="saldo_asc" <?php echo e($sort==='saldo_asc' ? 'selected':''); ?>>Saldo Terendah</option>
|
||||||
|
<option value="saldo_desc" <?php echo e($sort==='saldo_desc' ? 'selected':''); ?>>Saldo Tertinggi</option>
|
||||||
|
<option value="transaksi_desc" <?php echo e($sort==='transaksi_desc'? 'selected':''); ?>>Transaksi Terbanyak</option>
|
||||||
|
<option value="terakhir" <?php echo e($sort==='terakhir' ? 'selected':''); ?>>Transaksi Terbaru</option>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form method="GET" action="<?php echo e(route('admin.uang-saku.index')); ?>"
|
||||||
|
style="display:flex;gap:6px;">
|
||||||
|
<input type="hidden" name="dari" value="<?php echo e($dari); ?>">
|
||||||
|
<input type="hidden" name="sampai" value="<?php echo e($sampai); ?>">
|
||||||
|
<input type="hidden" name="sort" value="<?php echo e($sort); ?>">
|
||||||
|
<input type="text" name="search" class="form-control form-control-sm"
|
||||||
|
placeholder="Cari nama / ID santri..."
|
||||||
|
value="<?php echo e(request('search')); ?>" style="width:210px;">
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm">
|
||||||
|
<i class="fas fa-search"></i>
|
||||||
|
</button>
|
||||||
|
<?php if(request('search')): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.index', ['dari'=>$dari,'sampai'=>$sampai,'sort'=>$sort])); ?>"
|
||||||
|
class="btn btn-secondary btn-sm"><i class="fas fa-times"></i></a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<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>< Rp 20.000</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if($santriList->count() > 0): ?>
|
||||||
|
|
||||||
|
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$sc = $santri->saldo_terakhir >= 100000 ? '#6FBA9D'
|
||||||
|
: ($santri->saldo_terakhir >= 20000 ? '#f5a623' : '#FF8B94');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="content-box us-row"
|
||||||
|
style="margin-bottom:10px;padding:0;overflow:hidden;">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="us-row-header"
|
||||||
|
onclick="toggleDetail('detail-<?php echo e($santri->id_santri); ?>', this)"
|
||||||
|
style="display:flex;align-items:center;cursor:pointer;
|
||||||
|
padding:12px 16px;flex-wrap:wrap;gap:10px;">
|
||||||
|
|
||||||
|
|
||||||
|
<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;">
|
||||||
|
<?php echo e($santri->nama_lengkap); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.74rem;color:var(--text-light);">
|
||||||
|
<?php echo e($santri->id_santri); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<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:<?php echo e($sc); ?>;
|
||||||
|
display:flex;align-items:center;gap:5px;">
|
||||||
|
<span style="width:8px;height:8px;border-radius:50%;
|
||||||
|
background:<?php echo e($sc); ?>;flex-shrink:0;display:inline-block;"></span>
|
||||||
|
Rp <?php echo e(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>
|
||||||
|
|
||||||
|
|
||||||
|
<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;">
|
||||||
|
<?php echo e($santri->transaksi_periode); ?>x di periode
|
||||||
|
</span>
|
||||||
|
<?php if($santri->transaksi_terakhir_tgl): ?>
|
||||||
|
<div style="font-size:.66rem;color:var(--text-light);margin-top:3px;">
|
||||||
|
terakhir <?php echo e(\Carbon\Carbon::parse($santri->transaksi_terakhir_tgl)->format('d/m/Y')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:flex;gap:5px;flex-shrink:0;" onclick="event.stopPropagation()">
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.create')); ?>?id_santri=<?php echo e($santri->id_santri); ?>"
|
||||||
|
class="btn btn-success btn-sm" title="Tambah Transaksi">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<a href="<?php echo e(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>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="detail-<?php echo e($santri->id_santri); ?>"
|
||||||
|
style="display:none;border-top:1px solid var(--primary-light);padding:12px 16px;">
|
||||||
|
<?php 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>
|
||||||
|
<?php $__currentLoopData = $santri->transaksi_terbaru; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tx): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo e($tx->tanggal_transaksi->format('d/m/Y')); ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if($tx->jenis_transaksi === 'pemasukan'): ?>
|
||||||
|
<span class="badge badge-success">
|
||||||
|
<i class="fas fa-arrow-down"></i> Masuk
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge badge-danger">
|
||||||
|
<i class="fas fa-arrow-up"></i> Keluar
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="nominal-highlight">Rp <?php echo e(number_format($tx->nominal, 0, ',', '.')); ?></td>
|
||||||
|
<td><div class="content-preview"><?php echo e($tx->keterangan ?? '-'); ?></div></td>
|
||||||
|
<td style="font-weight:600;
|
||||||
|
color:<?php echo e($tx->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94'); ?>;">
|
||||||
|
Rp <?php echo e(number_format($tx->saldo_sesudah, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div style="display:flex;gap:4px;justify-content:center;">
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.show', $tx->id)); ?>"
|
||||||
|
class="btn btn-primary btn-sm"><i class="fas fa-eye"></i></a>
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.edit', $tx->id)); ?>"
|
||||||
|
class="btn btn-warning btn-sm"><i class="fas fa-edit"></i></a>
|
||||||
|
<form action="<?php echo e(route('admin.uang-saku.destroy', $tx->id)); ?>"
|
||||||
|
method="POST" style="display:inline;"
|
||||||
|
onsubmit="return confirm('Yakin hapus transaksi ini?')">
|
||||||
|
<?php echo csrf_field(); ?> <?php echo method_field('DELETE'); ?>
|
||||||
|
<button class="btn btn-danger btn-sm">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<?php if($santri->transaksi_terbaru->count() >= 5): ?>
|
||||||
|
<div style="text-align:center;margin-top:10px;">
|
||||||
|
<a href="<?php echo e(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>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php 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="<?php echo e(route('admin.uang-saku.riwayat', $santri->id_santri)); ?>">
|
||||||
|
Lihat semua riwayat
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
|
||||||
|
<div style="margin-top:14px;"><?php echo e($santriList->links()); ?></div>
|
||||||
|
|
||||||
|
<?php 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>
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.create')); ?>" class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php 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>
|
||||||
|
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/uang-saku/index.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,777 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
/* ── Filter Periode ── */
|
|
||||||
.period-bar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
|
|
||||||
.period-btn {
|
|
||||||
padding:6px 14px; border-radius:20px; border:1px solid #e2e8f0;
|
|
||||||
background:#fff; cursor:pointer; font-size:0.85rem; transition:all .2s;
|
|
||||||
}
|
|
||||||
.period-btn:hover, .period-btn.active {
|
|
||||||
background:var(--primary-color); color:#fff; border-color:var(--primary-color);
|
|
||||||
}
|
|
||||||
.custom-range { display:none; align-items:center; gap:8px; }
|
|
||||||
.custom-range.show { display:flex; }
|
|
||||||
.custom-range input[type=date] {
|
|
||||||
padding:5px 10px; border:1px solid #e2e8f0; border-radius:6px; font-size:0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── KPI Strip ── */
|
|
||||||
.kpi-strip {
|
|
||||||
display:grid;
|
|
||||||
grid-template-columns: repeat(5, 1fr);
|
|
||||||
gap:12px;
|
|
||||||
margin-bottom:18px;
|
|
||||||
}
|
|
||||||
.kpi-card {
|
|
||||||
background:#fff; border-radius:10px; padding:14px 16px;
|
|
||||||
box-shadow:0 2px 8px rgba(0,0,0,.06);
|
|
||||||
border-top:3px solid transparent;
|
|
||||||
}
|
|
||||||
.kpi-card.kpi-hadir { border-color:#10B981; }
|
|
||||||
.kpi-card.kpi-alpa { border-color:#EF4444; }
|
|
||||||
.kpi-card.kpi-avg { border-color:#3B82F6; }
|
|
||||||
.kpi-card.kpi-warning{ border-color:#F59E0B; }
|
|
||||||
.kpi-card.kpi-info { border-color:#6366F1; }
|
|
||||||
.kpi-label { font-size:0.78rem; color:#6B7280; margin-bottom:4px; }
|
|
||||||
.kpi-value { font-size:1.45rem; font-weight:700; color:var(--primary-dark); line-height:1.1; }
|
|
||||||
.kpi-context { font-size:0.75rem; color:#9CA3AF; margin-top:4px; }
|
|
||||||
.kpi-trend { font-size:0.78rem; margin-top:5px; display:flex; align-items:center; gap:4px; }
|
|
||||||
.kpi-trend.up { color:#10B981; }
|
|
||||||
.kpi-trend.down { color:#EF4444; }
|
|
||||||
.kpi-trend.neutral { color:#6B7280; }
|
|
||||||
|
|
||||||
/* ── Dua kolom ── */
|
|
||||||
.two-col { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:16px; }
|
|
||||||
.three-col { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:16px; }
|
|
||||||
@media(max-width:900px){
|
|
||||||
.kpi-strip { grid-template-columns:repeat(2,1fr); }
|
|
||||||
.two-col { grid-template-columns:1fr; }
|
|
||||||
.three-col { grid-template-columns:1fr; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Cards ── */
|
|
||||||
.panel {
|
|
||||||
background:#fff; border-radius:10px; padding:16px;
|
|
||||||
box-shadow:0 2px 8px rgba(0,0,0,.06);
|
|
||||||
}
|
|
||||||
.panel-title {
|
|
||||||
font-size:.93rem; font-weight:600; margin:0 0 12px;
|
|
||||||
display:flex; align-items:center; gap:8px;
|
|
||||||
}
|
|
||||||
.panel-title a { font-size:.78rem; margin-left:auto; color:var(--primary-color); font-weight:400; }
|
|
||||||
|
|
||||||
/* ── List item kegiatan ── */
|
|
||||||
.kg-item {
|
|
||||||
display:flex; align-items:center; gap:10px;
|
|
||||||
padding:8px 0; border-bottom:1px solid #f1f5f9; font-size:.84rem;
|
|
||||||
}
|
|
||||||
.kg-item:last-child { border-bottom:none; }
|
|
||||||
.kg-name { flex:1; font-weight:500; }
|
|
||||||
.kg-context { font-size:.76rem; color:#6B7280; }
|
|
||||||
.kg-persen {
|
|
||||||
font-weight:700; font-size:.9rem; min-width:52px; text-align:right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Anomali ── */
|
|
||||||
.alert-row {
|
|
||||||
display:flex; align-items:flex-start; gap:10px;
|
|
||||||
padding:10px 12px; border-radius:8px; margin-bottom:6px;
|
|
||||||
font-size:.85rem; border-left:4px solid transparent;
|
|
||||||
}
|
|
||||||
.alert-row:last-child { margin-bottom:0; }
|
|
||||||
.alert-row.a-danger { background:#FEF2F2; border-color:#EF4444; color:#991B1B; }
|
|
||||||
.alert-row.a-warning { background:#FFFBEB; border-color:#F59E0B; color:#92400E; }
|
|
||||||
.alert-row.a-info { background:#EFF6FF; border-color:#3B82F6; color:#1E40AF; }
|
|
||||||
.alert-row.a-success { background:#ECFDF5; border-color:#10B981; color:#065F46; }
|
|
||||||
.alert-text { flex:1; }
|
|
||||||
.alert-title { font-weight:600; font-size:.86rem; }
|
|
||||||
.alert-desc { font-size:.8rem; opacity:.85; margin-top:2px; }
|
|
||||||
|
|
||||||
/* ── Kelas chart legend ── */
|
|
||||||
.kelas-legend { display:flex; gap:16px; flex-wrap:wrap; margin-top:10px; font-size:.78rem; }
|
|
||||||
.kelas-legend-item { display:flex; align-items:center; gap:5px; color:#6B7280; }
|
|
||||||
.kelas-legend-dot { width:10px; height:10px; border-radius:50%; flex-shrink:0; }
|
|
||||||
|
|
||||||
/* ── Santri perlu perhatian ── */
|
|
||||||
.spp-item {
|
|
||||||
display:flex; align-items:center; gap:10px;
|
|
||||||
padding:7px 0; border-bottom:1px solid #f1f5f9; font-size:.84rem;
|
|
||||||
}
|
|
||||||
.spp-item:last-child { border-bottom:none; }
|
|
||||||
.spp-rank { width:22px; text-align:center; color:#9CA3AF; font-size:.78rem; }
|
|
||||||
.spp-name { flex:1; font-weight:500; }
|
|
||||||
.spp-pct { font-weight:700; color:#EF4444; }
|
|
||||||
.spp-ctx { font-size:.75rem; color:#9CA3AF; }
|
|
||||||
|
|
||||||
/* ── Trend chart ── */
|
|
||||||
.chart-wrap { background:#fff; border-radius:10px; padding:16px; box-shadow:0 2px 8px rgba(0,0,0,.06); margin-bottom:16px; }
|
|
||||||
.chart-wrap h4 { margin:0 0 10px; font-size:.93rem; color:var(--primary-dark); }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-chart-line"></i> Laporan Kegiatan</h2>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom:16px;">
|
|
||||||
<form method="GET" id="periodForm" action="<?php echo e(route('admin.laporan-kegiatan.index')); ?>">
|
|
||||||
<div class="period-bar">
|
|
||||||
<span style="font-size:.85rem;color:var(--text-light);">
|
|
||||||
<i class="fas fa-calendar-alt"></i> Periode:
|
|
||||||
</span>
|
|
||||||
<?php $__currentLoopData = ['hari_ini'=>'Hari Ini','minggu_ini'=>'Minggu Ini','bulan_ini'=>'Bulan Ini','semester_ini'=>'Semester','custom'=>'Custom']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $key=>$label): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<button type="button"
|
|
||||||
class="period-btn <?php echo e($periode===$key?'active':''); ?>"
|
|
||||||
onclick="setPeriode('<?php echo e($key); ?>')"><?php echo e($label); ?></button>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="custom-range <?php echo e($periode==='custom'?'show':''); ?>" id="customRange">
|
|
||||||
<input type="date" name="tanggal_dari"
|
|
||||||
value="<?php echo e(request('tanggal_dari', $startDate->format('Y-m-d'))); ?>">
|
|
||||||
<span>–</span>
|
|
||||||
<input type="date" name="tanggal_sampai"
|
|
||||||
value="<?php echo e(request('tanggal_sampai', $endDate->format('Y-m-d'))); ?>">
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="periode" id="periodeInput" value="<?php echo e($periode); ?>">
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm">
|
|
||||||
<i class="fas fa-sync-alt"></i> Terapkan
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<p style="margin:8px 0 0;font-size:.82rem;color:var(--text-light);">
|
|
||||||
<i class="fas fa-info-circle"></i> Data: <strong><?php echo e($periodeLabel); ?></strong>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-strip">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-card kpi-avg">
|
|
||||||
<div class="kpi-label">Rata-rata Kehadiran</div>
|
|
||||||
<div class="kpi-value"><?php echo e($kpi['avg_kehadiran']); ?>%</div>
|
|
||||||
<div class="kpi-context">
|
|
||||||
<?php echo e(number_format($kpi['total_hadir'])); ?> hadir dari
|
|
||||||
<?php echo e(number_format($kpi['total_absensi'])); ?> tercatat
|
|
||||||
</div>
|
|
||||||
<?php $diffAvg = $kpiComparison['avg_kehadiran']; ?>
|
|
||||||
<div class="kpi-trend <?php echo e($diffAvg > 0 ? 'up' : ($diffAvg < 0 ? 'down' : 'neutral')); ?>">
|
|
||||||
<i class="fas fa-arrow-<?php echo e($diffAvg >= 0 ? 'up' : 'down'); ?>"></i>
|
|
||||||
<?php echo e(abs($diffAvg)); ?>% vs periode sebelumnya
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-card kpi-hadir">
|
|
||||||
<div class="kpi-label">Hadir Efektif</div>
|
|
||||||
<div class="kpi-value"><?php echo e(number_format($kpi['total_hadir'])); ?></div>
|
|
||||||
<div class="kpi-context">
|
|
||||||
termasuk <?php echo e($kpi['total_terlambat']); ?> terlambat
|
|
||||||
— dari <?php echo e(number_format($kpi['total_absensi'])); ?> sesi tercatat
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-card kpi-alpa">
|
|
||||||
<div class="kpi-label">Total Alpa</div>
|
|
||||||
<div class="kpi-value"><?php echo e(number_format($kpi['total_alpa'])); ?></div>
|
|
||||||
<div class="kpi-context">
|
|
||||||
<?php $alpaRate = $kpi['total_absensi'] > 0 ? round($kpi['total_alpa']/$kpi['total_absensi']*100,1) : 0; ?>
|
|
||||||
<?php echo e($alpaRate); ?>% dari <?php echo e(number_format($kpi['total_absensi'])); ?> tercatat
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-card kpi-warning">
|
|
||||||
<div class="kpi-label">Santri Perlu Perhatian</div>
|
|
||||||
<div class="kpi-value"><?php echo e($kpi['santri_perlu_perhatian']); ?></div>
|
|
||||||
<div class="kpi-context">
|
|
||||||
dari <?php echo e($kpi['total_santri_aktif']); ?> santri aktif
|
|
||||||
(kehadiran <70%)
|
|
||||||
</div>
|
|
||||||
<?php $diffSpp = $kpiComparison['santri_perlu_perhatian']; ?>
|
|
||||||
<div class="kpi-trend <?php echo e($diffSpp <= 0 ? 'up' : 'down'); ?>">
|
|
||||||
<i class="fas fa-arrow-<?php echo e($diffSpp <= 0 ? 'down' : 'up'); ?>"></i>
|
|
||||||
<?php echo e(abs($diffSpp)); ?> vs periode sebelumnya
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="kpi-card kpi-info">
|
|
||||||
<div class="kpi-label">Kehadiran Terbaik</div>
|
|
||||||
<div class="kpi-value" style="font-size:1rem;">
|
|
||||||
<?php echo e($kpi['kegiatan_terbaik']['nama']); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="kpi-context">
|
|
||||||
<?php echo e($kpi['kegiatan_terbaik']['persen']); ?>%
|
|
||||||
(<?php echo e($kpi['kegiatan_terbaik']['hadir']); ?> hadir dari <?php echo e($kpi['kegiatan_terbaik']['total']); ?> tercatat)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$buckets = $distribusiSantri['buckets'];
|
|
||||||
$totalDengan = $distribusiSantri['total'];
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="chart-wrap" style="margin-bottom:16px;">
|
|
||||||
<div style="display:flex;align-items:flex-start;gap:24px;flex-wrap:wrap;">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="position:relative;width:200px;height:200px;flex-shrink:0;">
|
|
||||||
<canvas id="distribusiChart"></canvas>
|
|
||||||
|
|
||||||
<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;pointer-events:none;">
|
|
||||||
<div style="font-size:1.6rem;font-weight:700;color:var(--primary-dark);line-height:1;">
|
|
||||||
<?php echo e($totalDengan); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div style="font-size:.72rem;color:#6B7280;margin-top:2px;">santri<br>tercatat</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="flex:1;min-width:220px;">
|
|
||||||
<h4 style="margin:0 0 6px;font-size:.93rem;color:var(--primary-dark);">
|
|
||||||
<i class="fas fa-users"></i> Kondisi Kehadiran Santri
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $buckets; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $b): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;">
|
|
||||||
<div style="width:12px;height:12px;border-radius:50%;background:<?php echo e($b['color']); ?>;flex-shrink:0;"></div>
|
|
||||||
<div style="flex:1;min-width:0;">
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:3px;">
|
|
||||||
<span style="font-size:.83rem;font-weight:600;color:var(--primary-dark);">
|
|
||||||
<?php echo e($b['label']); ?>
|
|
||||||
|
|
||||||
<?php if($b['label']==='Sangat Baik'): ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(≥95%)</span>
|
|
||||||
<?php elseif($b['label']==='Baik'): ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(85–94%)</span>
|
|
||||||
<?php elseif($b['label']==='Cukup'): ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(70–84%)</span>
|
|
||||||
<?php else: ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(<70%)</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
<span style="font-size:.83rem;font-weight:700;color:<?php echo e($b['color']); ?>;">
|
|
||||||
<?php echo e($b['count']); ?> santri
|
|
||||||
<span style="font-weight:400;color:#9CA3AF;">(<?php echo e($b['persen']); ?>%)</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div style="background:#f1f5f9;border-radius:4px;height:6px;overflow:hidden;">
|
|
||||||
<div style="width:<?php echo e($b['persen']); ?>%;height:100%;background:<?php echo e($b['color']); ?>;border-radius:4px;"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<?php $tanpaData = $kpi['total_santri_aktif'] - $totalDengan; ?>
|
|
||||||
<?php if($tanpaData > 0): ?>
|
|
||||||
<p style="margin:6px 0 0;font-size:.76rem;color:#9CA3AF;">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
<?php echo e($tanpaData); ?> santri aktif belum punya data absensi di periode ini.
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="panel" style="margin-bottom:16px;">
|
|
||||||
<div class="panel-title" style="color:#EF4444;">
|
|
||||||
<i class="fas fa-bell"></i> Anomali & Perlu Tindak Lanjut
|
|
||||||
</div>
|
|
||||||
<?php if(!empty($patterns) && count($patterns) > 0): ?>
|
|
||||||
<?php $__currentLoopData = $patterns; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div class="alert-row a-<?php echo e($p['type']); ?>">
|
|
||||||
<?php if($p['type']==='danger'): ?>
|
|
||||||
<i class="fas fa-exclamation-circle" style="margin-top:2px;"></i>
|
|
||||||
<?php elseif($p['type']==='warning'): ?>
|
|
||||||
<i class="fas fa-exclamation-triangle" style="margin-top:2px;"></i>
|
|
||||||
<?php else: ?>
|
|
||||||
<i class="fas fa-info-circle" style="margin-top:2px;"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
<div class="alert-text">
|
|
||||||
<div class="alert-title"><?php echo e($p['title']); ?></div>
|
|
||||||
<div class="alert-desc"><?php echo e($p['description']); ?></div>
|
|
||||||
</div>
|
|
||||||
<?php if(!empty($p['action_url'])): ?>
|
|
||||||
<a href="<?php echo e($p['action_url']); ?>"
|
|
||||||
class="btn btn-sm btn-<?php echo e($p['type']==='danger'?'danger':($p['type']==='warning'?'warning':'info')); ?>"
|
|
||||||
style="white-space:nowrap;">
|
|
||||||
<?php echo e($p['action_text'] ?? 'Lihat'); ?>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="alert-row a-success">
|
|
||||||
<i class="fas fa-check-circle"></i>
|
|
||||||
<div class="alert-text">
|
|
||||||
<div class="alert-title">Tidak ada anomali</div>
|
|
||||||
<div class="alert-desc">Pola kehadiran dalam kondisi normal.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$trendLabels = $trendData['labels'] ?? [];
|
|
||||||
$trendDs = $trendData['datasets'] ?? [];
|
|
||||||
$avgLine = [];
|
|
||||||
foreach ($trendLabels as $i => $_) {
|
|
||||||
$sum=0; $cnt=0;
|
|
||||||
foreach ($trendDs as $ds) {
|
|
||||||
if (isset($ds['data'][$i]) && $ds['data'][$i] !== null) { $sum+=$ds['data'][$i]; $cnt++; }
|
|
||||||
}
|
|
||||||
$avgLine[] = $cnt > 0 ? round($sum/$cnt,1) : null;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="chart-wrap">
|
|
||||||
<h4><i class="fas fa-chart-line"></i> Trend Kehadiran Rata-rata</h4>
|
|
||||||
<p style="margin:0 0 10px;font-size:.8rem;color:#6B7280;">
|
|
||||||
Angka = % hadir efektif (Terlambat dihitung Hadir). Hover untuk detail.
|
|
||||||
</p>
|
|
||||||
<div style="position:relative;height:200px;">
|
|
||||||
<canvas id="trendChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="three-col">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="panel">
|
|
||||||
<div class="panel-title" style="color:#10B981;">
|
|
||||||
<i class="fas fa-trophy"></i> Kehadiran Terbaik
|
|
||||||
</div>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $topKegiatan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<div class="kg-item">
|
|
||||||
|
|
||||||
<span style="color:#9CA3AF;font-size:.75rem;width:16px;flex-shrink:0;text-align:center;">
|
|
||||||
<?php echo e($i + 1); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="flex:1;min-width:0;">
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:6px;margin-bottom:2px;">
|
|
||||||
<div class="kg-name"
|
|
||||||
style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.84rem;font-weight:600;">
|
|
||||||
<?php echo e($kg['nama_kegiatan']); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<span style="font-weight:700;color:#10B981;font-size:.88rem;flex-shrink:0;">
|
|
||||||
<?php echo e($kg['persen']); ?>%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background:#f1f5f9;border-radius:4px;height:6px;overflow:hidden;margin-bottom:4px;">
|
|
||||||
<div style="width:<?php echo e($kg['persen']); ?>%;height:100%;background:#10B981;border-radius:4px;transition:width .5s;"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;">
|
|
||||||
<span class="kg-context">
|
|
||||||
<?php echo e($kg['nama_kategori'] ?? '-'); ?> · <?php echo e($kg['hari'] ?? '-'); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span style="font-size:.74rem;color:#10B981;">
|
|
||||||
<?php echo e($kg['hadir']); ?>/<?php echo e($kg['total']); ?> sesi
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<p style="color:var(--text-light);font-size:.85rem;text-align:center;padding:16px 0;">
|
|
||||||
Belum ada data absensi di periode ini.
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="panel">
|
|
||||||
<div class="panel-title" style="color:#EF4444;">
|
|
||||||
<i class="fas fa-arrow-trend-down"></i> Kehadiran Terendah
|
|
||||||
</div>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $bottomKegiatan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<?php
|
|
||||||
$warna = $kg['persen'] < 70 ? '#EF4444' : '#F59E0B';
|
|
||||||
$bgBar = $kg['persen'] < 70 ? '#FEF2F2' : '#FFFBEB';
|
|
||||||
$kgId = $kg['id'];
|
|
||||||
?>
|
|
||||||
<div class="kg-item">
|
|
||||||
<span style="color:#9CA3AF;font-size:.75rem;width:16px;flex-shrink:0;text-align:center;">
|
|
||||||
<?php echo e($i + 1); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div style="flex:1;min-width:0;">
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:6px;margin-bottom:2px;">
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kgId)); ?>"
|
|
||||||
style="text-decoration:none;color:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.84rem;font-weight:600;flex:1;min-width:0;">
|
|
||||||
<?php echo e($kg['nama_kegiatan']); ?>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
<span style="font-weight:700;color:<?php echo e($warna); ?>;font-size:.88rem;flex-shrink:0;">
|
|
||||||
<?php echo e($kg['persen']); ?>%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background:<?php echo e($bgBar); ?>;border-radius:4px;height:6px;overflow:hidden;margin-bottom:4px;">
|
|
||||||
<div style="width:<?php echo e($kg['persen']); ?>%;height:100%;background:<?php echo e($warna); ?>;border-radius:4px;transition:width .5s;"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;">
|
|
||||||
<span class="kg-context">
|
|
||||||
<?php echo e($kg['nama_kategori'] ?? '-'); ?> · <?php echo e($kg['hari'] ?? '-'); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<span style="font-size:.74rem;color:<?php echo e($warna); ?>;">
|
|
||||||
<?php echo e($kg['hadir']); ?>/<?php echo e($kg['total']); ?> sesi
|
|
||||||
<?php if(($kg['alpa'] ?? 0) > 0): ?>
|
|
||||||
· <strong><?php echo e($kg['alpa']); ?>× alpa</strong>
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<p style="color:var(--text-light);font-size:.85rem;text-align:center;padding:16px 0;">
|
|
||||||
Belum ada data absensi di periode ini.
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="panel">
|
|
||||||
<div class="panel-title" style="color:#F59E0B;">
|
|
||||||
<i class="fas fa-user-clock"></i> Santri Perlu Perhatian
|
|
||||||
<a href="<?php echo e(route('admin.laporan-kegiatan.santri-perlu-perhatian', request()->query())); ?>">
|
|
||||||
Lihat Semua →
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<p style="font-size:.78rem;color:#6B7280;margin:0 0 10px;">
|
|
||||||
<?php echo e($kpi['santri_perlu_perhatian']); ?> dari <?php echo e($kpi['total_santri_aktif']); ?> santri aktif
|
|
||||||
dengan kehadiran <70%
|
|
||||||
</p>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $santriPerluPerhatianList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<div class="spp-item">
|
|
||||||
<span class="spp-rank"><?php echo e($i + 1); ?></span>
|
|
||||||
|
|
||||||
<div style="flex:1;min-width:0;">
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:6px;margin-bottom:2px;">
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $s->id_santri)); ?>"
|
|
||||||
class="spp-name"
|
|
||||||
style="text-decoration:none;color:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;">
|
|
||||||
<?php echo e($s->nama_lengkap); ?>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
<span class="spp-pct" style="flex-shrink:0;"><?php echo e($s->persen); ?>%</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background:#FEF2F2;border-radius:4px;height:6px;overflow:hidden;margin-bottom:3px;">
|
|
||||||
<div style="width:<?php echo e($s->persen); ?>%;height:100%;background:#EF4444;border-radius:4px;transition:width .5s;"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="spp-ctx">
|
|
||||||
<?php echo e($s->hadir); ?>/<?php echo e($s->total); ?> sesi · <?php echo e($s->alpa); ?>× alpa
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<div style="padding:12px;background:#ECFDF5;border-radius:8px;color:#065F46;
|
|
||||||
font-size:.85rem;display:flex;align-items:center;gap:8px;margin-top:4px;">
|
|
||||||
<i class="fas fa-check-circle"></i> Semua santri kehadiran ≥70%. Alhamdulillah!
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
/* Flatten semua kelas dari semua kelompok untuk chart */
|
|
||||||
$chartKelasLabels = [];
|
|
||||||
$chartKelasData = [];
|
|
||||||
$chartKelasColors = [];
|
|
||||||
$chartKelasContext = []; // untuk tooltip: "hadir / total"
|
|
||||||
$chartKelasGroups = []; // label kelompok per kelas
|
|
||||||
|
|
||||||
foreach ($kelasRingkasan as $kelompok) {
|
|
||||||
foreach ($kelompok['kelas'] as $k) {
|
|
||||||
$chartKelasLabels[] = $k['nama_kelas'];
|
|
||||||
$chartKelasData[] = $k['persen'];
|
|
||||||
$chartKelasColors[] = $k['persen'] >= 85 ? '#10B981' : ($k['persen'] >= 70 ? '#F59E0B' : '#EF4444');
|
|
||||||
$chartKelasContext[] = $k['hadir'] . ' hadir dari ' . $k['total'] . ' tercatat';
|
|
||||||
$chartKelasGroups[] = $kelompok['nama_kelompok'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$chartHeight = max(180, count($chartKelasLabels) * 34 + 40);
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="chart-wrap" style="margin-bottom:16px;">
|
|
||||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;flex-wrap:wrap;gap:8px;">
|
|
||||||
<h4 style="margin:0;">
|
|
||||||
<i class="fas fa-school"></i> Kehadiran Per Kelas
|
|
||||||
</h4>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>"
|
|
||||||
style="font-size:.78rem;color:var(--primary-color);">
|
|
||||||
Detail di Riwayat Kegiatan →
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<p style="margin:0 0 12px;font-size:.78rem;color:#6B7280;">
|
|
||||||
% hadir efektif — Terlambat dihitung Hadir. Hover bar untuk melihat angka lengkap.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php if(count($chartKelasLabels) > 0): ?>
|
|
||||||
<div style="position:relative;height:<?php echo e($chartHeight); ?>px;">
|
|
||||||
<canvas id="kelasChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<div class="kelas-legend">
|
|
||||||
<div class="kelas-legend-item">
|
|
||||||
<div class="kelas-legend-dot" style="background:#10B981;"></div> ≥85% Baik
|
|
||||||
</div>
|
|
||||||
<div class="kelas-legend-item">
|
|
||||||
<div class="kelas-legend-dot" style="background:#F59E0B;"></div> 70–84% Cukup
|
|
||||||
</div>
|
|
||||||
<div class="kelas-legend-item">
|
|
||||||
<div class="kelas-legend-dot" style="background:#EF4444;"></div> <70% Perlu Perhatian
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<p style="color:var(--text-light);font-size:.85rem;text-align:center;padding:20px 0;">
|
|
||||||
Belum ada data kelas untuk periode ini.
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
|
||||||
<script>
|
|
||||||
function setPeriode(p) {
|
|
||||||
document.getElementById('periodeInput').value = p;
|
|
||||||
document.querySelectorAll('.period-btn').forEach(b => b.classList.remove('active'));
|
|
||||||
event.target.classList.add('active');
|
|
||||||
const cr = document.getElementById('customRange');
|
|
||||||
if (p === 'custom') { cr.classList.add('show'); }
|
|
||||||
else { cr.classList.remove('show'); document.getElementById('periodForm').submit(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Distribusi Santri Donut Chart ──
|
|
||||||
const distribusiBuckets = <?php echo json_encode($buckets, 15, 512) ?>;
|
|
||||||
new Chart(document.getElementById('distribusiChart'), {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels: distribusiBuckets.map(b => b.label),
|
|
||||||
datasets: [{
|
|
||||||
data: distribusiBuckets.map(b => b.count),
|
|
||||||
backgroundColor: distribusiBuckets.map(b => b.color),
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: '#fff',
|
|
||||||
hoverOffset: 8,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
cutout: '68%',
|
|
||||||
plugins: {
|
|
||||||
legend: { display: false },
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
label: (ctx) => {
|
|
||||||
const b = distribusiBuckets[ctx.dataIndex];
|
|
||||||
return [
|
|
||||||
` ${b.count} santri (${b.persen}%)`,
|
|
||||||
` dari <?php echo e($totalDengan); ?> santri tercatat`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
backgroundColor: 'rgba(17,24,39,.9)',
|
|
||||||
titleFont: { size: 13, weight: '600' },
|
|
||||||
bodyFont: { size: 12 },
|
|
||||||
padding: 10,
|
|
||||||
cornerRadius: 8,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const labels = <?php echo json_encode($trendLabels, 15, 512) ?>;
|
|
||||||
const avgLine = <?php echo json_encode($avgLine, 15, 512) ?>;
|
|
||||||
|
|
||||||
new Chart(document.getElementById('trendChart'), {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels,
|
|
||||||
datasets: [{
|
|
||||||
label: 'Rata-rata Kehadiran',
|
|
||||||
data: avgLine,
|
|
||||||
borderColor: '#10B981',
|
|
||||||
backgroundColor: 'rgba(16,185,129,.1)',
|
|
||||||
tension: 0.4, fill: true,
|
|
||||||
pointRadius: 4, pointHoverRadius: 6,
|
|
||||||
spanGaps: true,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
legend: { display: false },
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
label: ctx => {
|
|
||||||
const v = ctx.parsed.y;
|
|
||||||
return v !== null ? `${v}% kehadiran rata-rata` : 'Tidak ada data';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
min: 0, max: 100,
|
|
||||||
ticks: { callback: v => v + '%' },
|
|
||||||
grid: { color: '#f1f5f9' }
|
|
||||||
},
|
|
||||||
x: { grid: { display: false } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// ── Horizontal Bar Chart: Kehadiran Per Kelas ──
|
|
||||||
<?php if(count($chartKelasLabels) > 0): ?>
|
|
||||||
const kelasLabels = <?php echo json_encode($chartKelasLabels, 15, 512) ?>;
|
|
||||||
const kelasData = <?php echo json_encode($chartKelasData, 15, 512) ?>;
|
|
||||||
const kelasColors = <?php echo json_encode($chartKelasColors, 15, 512) ?>;
|
|
||||||
const kelasContext = <?php echo json_encode($chartKelasContext, 15, 512) ?>;
|
|
||||||
const kelasGroups = <?php echo json_encode($chartKelasGroups, 15, 512) ?>;
|
|
||||||
|
|
||||||
new Chart(document.getElementById('kelasChart'), {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: kelasLabels,
|
|
||||||
datasets: [{
|
|
||||||
label: '% Kehadiran',
|
|
||||||
data: kelasData,
|
|
||||||
backgroundColor: kelasColors,
|
|
||||||
borderRadius: 5,
|
|
||||||
borderSkipped: false,
|
|
||||||
barThickness: 20,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
indexAxis: 'y', // horizontal
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
legend: { display: false },
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: (items) => {
|
|
||||||
const i = items[0].dataIndex;
|
|
||||||
return `${kelasLabels[i]} — ${kelasGroups[i]}`;
|
|
||||||
},
|
|
||||||
label: (ctx) => {
|
|
||||||
const i = ctx.dataIndex;
|
|
||||||
return [
|
|
||||||
`Kehadiran: ${ctx.parsed.x}%`,
|
|
||||||
kelasContext[i],
|
|
||||||
];
|
|
||||||
},
|
|
||||||
labelColor: (ctx) => ({
|
|
||||||
borderColor: kelasColors[ctx.dataIndex],
|
|
||||||
backgroundColor: kelasColors[ctx.dataIndex],
|
|
||||||
borderRadius: 3,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
backgroundColor: 'rgba(17,24,39,.9)',
|
|
||||||
titleFont: { size: 13, weight: '600' },
|
|
||||||
bodyFont: { size: 12 },
|
|
||||||
padding: 10,
|
|
||||||
cornerRadius: 8,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
x: {
|
|
||||||
min: 0, max: 100,
|
|
||||||
ticks: { callback: v => v + '%', font: { size: 11 } },
|
|
||||||
grid: { color: '#f1f5f9' },
|
|
||||||
// Garis referensi 70% dan 85%
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
ticks: { font: { size: 11 } },
|
|
||||||
grid: { display: false },
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Plugin untuk garis referensi 70% dan 85%
|
|
||||||
plugins: {
|
|
||||||
legend: { display: false },
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
title: (items) => {
|
|
||||||
const i = items[0].dataIndex;
|
|
||||||
return `${kelasLabels[i]} — ${kelasGroups[i]}`;
|
|
||||||
},
|
|
||||||
label: (ctx) => {
|
|
||||||
const i = ctx.dataIndex;
|
|
||||||
return [
|
|
||||||
`Kehadiran: ${ctx.parsed.x}%`,
|
|
||||||
kelasContext[i],
|
|
||||||
];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
backgroundColor: 'rgba(17,24,39,.9)',
|
|
||||||
titleFont: { size: 13, weight: '600' },
|
|
||||||
bodyFont: { size: 12 },
|
|
||||||
padding: 10,
|
|
||||||
cornerRadius: 8,
|
|
||||||
},
|
|
||||||
annotation: undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [{
|
|
||||||
// Plugin custom: garis vertikal referensi 70% dan 85%
|
|
||||||
id: 'refLines',
|
|
||||||
afterDraw(chart) {
|
|
||||||
const { ctx, chartArea: { top, bottom }, scales: { x } } = chart;
|
|
||||||
[{ v: 70, color: '#F59E0B', label: '70%' }, { v: 85, color: '#10B981', label: '85%' }].forEach(ref => {
|
|
||||||
const xPx = x.getPixelForValue(ref.v);
|
|
||||||
ctx.save();
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.setLineDash([4, 4]);
|
|
||||||
ctx.moveTo(xPx, top);
|
|
||||||
ctx.lineTo(xPx, bottom);
|
|
||||||
ctx.strokeStyle = ref.color;
|
|
||||||
ctx.lineWidth = 1.5;
|
|
||||||
ctx.globalAlpha = 0.6;
|
|
||||||
ctx.stroke();
|
|
||||||
ctx.globalAlpha = 1;
|
|
||||||
ctx.fillStyle = ref.color;
|
|
||||||
ctx.font = '10px sans-serif';
|
|
||||||
ctx.fillText(ref.label, xPx + 3, top + 10);
|
|
||||||
ctx.restore();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
<?php endif; ?>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
@media print {
|
|
||||||
.period-bar, .btn, button { display:none !important; }
|
|
||||||
.panel, .chart-wrap { box-shadow:none !important; border:1px solid #e2e8f0; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/laporan/index.blade.php ENDPATH**/ ?>
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,164 +0,0 @@
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="id">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Bukti Pembayaran SPP - <?php echo e($pembayaranSpp->id_pembayaran); ?></title>
|
|
||||||
<style>
|
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
||||||
body { font-family: Arial, sans-serif; padding: 30px; font-size: 13px; }
|
|
||||||
|
|
||||||
.bukti-container { max-width: 600px; margin: 0 auto; border: 3px solid #6FBA9D; border-radius: 10px; padding: 25px; }
|
|
||||||
|
|
||||||
/* ── KOP SURAT ─────────────────────────────────── */
|
|
||||||
.kop { display: flex; align-items: center; gap: 16px; padding-bottom: 12px; border-bottom: 3px double #6FBA9D; margin-bottom: 8px; }
|
|
||||||
.kop img { width: 72px; height: 72px; object-fit: contain; flex-shrink: 0; }
|
|
||||||
.kop-text { flex: 1; text-align: center; }
|
|
||||||
.kop-text .nama-lembaga { font-size: 17px; font-weight: bold; color: #1a1a1a; letter-spacing: .4px; text-transform: uppercase; }
|
|
||||||
.kop-text .nama-singkat { font-size: 13px; color: #555; margin: 2px 0; }
|
|
||||||
.kop-text .alamat { font-size: 10.5px; color: #555; line-height: 16px; margin-top: 4px; }
|
|
||||||
|
|
||||||
/* ── JUDUL DOKUMEN ─────────────────────────────── */
|
|
||||||
.header { text-align: center; margin: 14px 0 20px; }
|
|
||||||
.header h2 { font-size: 15px; color: #6FBA9D; letter-spacing: 2px; text-transform: uppercase; }
|
|
||||||
.header p { font-size: 12px; color: #666; margin-top: 4px; }
|
|
||||||
|
|
||||||
.bukti-info { background: #f9f9f9; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
|
|
||||||
.bukti-info table { width: 100%; }
|
|
||||||
.bukti-info tr { line-height: 28px; }
|
|
||||||
.bukti-info td:first-child { font-weight: bold; width: 160px; color: #555; }
|
|
||||||
.bukti-info td:nth-child(2) { width: 20px; }
|
|
||||||
.bukti-info td:last-child { color: #333; }
|
|
||||||
|
|
||||||
.nominal-box { background: linear-gradient(135deg, #6FBA9D 0%, #8FCAAE 100%); color: white; padding: 20px; border-radius: 8px; text-align: center; margin: 25px 0; }
|
|
||||||
.nominal-box h3 { font-size: 14px; margin-bottom: 10px; opacity: .9; }
|
|
||||||
.nominal-box .amount { font-size: 32px; font-weight: bold; letter-spacing: 1px; }
|
|
||||||
|
|
||||||
.status-box { text-align: center; padding: 15px; border-radius: 8px; margin-bottom: 20px; }
|
|
||||||
.status-lunas { background: #d4edda; color: #155724; border: 2px solid #c3e6cb; }
|
|
||||||
.status-belum { background: #fff3cd; color: #856404; border: 2px solid #ffeaa7; }
|
|
||||||
|
|
||||||
.footer { text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px dashed #ddd; }
|
|
||||||
.footer p { font-size: 11px; color: #888; line-height: 18px; }
|
|
||||||
|
|
||||||
.ttd-section { margin-top: 40px; display: flex; justify-content: flex-end; }
|
|
||||||
.ttd-box { text-align: center; width: 45%; }
|
|
||||||
.ttd-box p { margin-bottom: 60px; font-size: 12px; }
|
|
||||||
.ttd-box strong { font-size: 13px; border-top: 1px solid #333; padding-top: 5px; display: inline-block; }
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body { padding: 0; }
|
|
||||||
.no-print { display: none; }
|
|
||||||
@page { margin: 1.5cm; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- Tombol Print -->
|
|
||||||
<div class="no-print" style="text-align:center; margin-bottom:20px;">
|
|
||||||
<button onclick="window.print()" style="padding:12px 30px; background:#6FBA9D; color:white; border:none; border-radius:5px; cursor:pointer; font-size:14px;">
|
|
||||||
Cetak Bukti
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bukti-container">
|
|
||||||
|
|
||||||
<!-- ══ KOP SURAT ══ -->
|
|
||||||
<div class="kop">
|
|
||||||
<img src="<?php echo e(asset('images/logo.png')); ?>" alt="Logo PKPPS Riyadlul Jannah">
|
|
||||||
<div class="kop-text">
|
|
||||||
<div class="nama-lembaga">PKPPS Riyadlul Jannah Mojokerto</div>
|
|
||||||
<div class="alamat">
|
|
||||||
Jl. Raya Brangkal No. 42 RT. 02 RW. 01, Desa Brangkal<br>
|
|
||||||
Kec. Sooko, Kab. Mojokerto, Prov. Jawa Timur
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ══ JUDUL DOKUMEN ══ -->
|
|
||||||
<div class="header">
|
|
||||||
<h2>Bukti Pembayaran SPP</h2>
|
|
||||||
<p>No. Bukti: <strong><?php echo e($pembayaranSpp->id_pembayaran); ?></strong></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Status -->
|
|
||||||
<?php if($pembayaranSpp->status === 'Lunas'): ?>
|
|
||||||
<div class="status-box status-lunas">
|
|
||||||
<strong style="font-size:16px;">✓ LUNAS</strong>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="status-box status-belum">
|
|
||||||
<strong style="font-size:16px;">⚠ BELUM LUNAS</strong>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- Info Santri & Pembayaran -->
|
|
||||||
<div class="bukti-info">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>ID Santri</td>
|
|
||||||
<td>:</td>
|
|
||||||
<td><?php echo e($pembayaranSpp->santri->id_santri); ?></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Nama Santri</td>
|
|
||||||
<td>:</td>
|
|
||||||
<td><strong><?php echo e($pembayaranSpp->santri->nama_lengkap); ?></strong></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Periode Pembayaran</td>
|
|
||||||
<td>:</td>
|
|
||||||
<td><strong><?php echo e($pembayaranSpp->periode_lengkap); ?></strong></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tanggal Bayar</td>
|
|
||||||
<td>:</td>
|
|
||||||
<td>
|
|
||||||
<?php if($pembayaranSpp->tanggal_bayar): ?>
|
|
||||||
<?php echo e($pembayaranSpp->tanggal_bayar->format('d F Y')); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color:#999;">Belum dibayar</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php if($pembayaranSpp->keterangan): ?>
|
|
||||||
<tr>
|
|
||||||
<td>Keterangan</td>
|
|
||||||
<td>:</td>
|
|
||||||
<td><?php echo e($pembayaranSpp->keterangan); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Nominal -->
|
|
||||||
<div class="nominal-box">
|
|
||||||
<h3>JUMLAH PEMBAYARAN</h3>
|
|
||||||
<div class="amount"><?php echo e($pembayaranSpp->nominal_format); ?></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tanda Tangan -->
|
|
||||||
<div class="ttd-section">
|
|
||||||
<div class="ttd-box">
|
|
||||||
<p>Petugas</p>
|
|
||||||
<strong>( )</strong>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<div class="footer">
|
|
||||||
<p>
|
|
||||||
<strong>PERHATIAN:</strong><br>
|
|
||||||
Bukti pembayaran ini sah dan merupakan tanda terima yang diakui secara resmi.<br>
|
|
||||||
Simpan bukti ini sebagai arsip pembayaran SPP.<br>
|
|
||||||
Dicetak pada: <?php echo e(date('d F Y, H:i')); ?> WIB
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/cetak-bukti.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,303 @@
|
||||||
|
<?php $__env->startSection('title', 'Generate SPP Massal'); ?>
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-cogs"></i> Generate SPP Massal</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
<strong>Informasi:</strong> Fitur ini akan membuat data pembayaran SPP untuk <strong>semua santri aktif</strong> dalam periode yang ditentukan.
|
||||||
|
Data yang sudah ada akan dilewati (tidak duplikat).
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="<?php echo e(route('admin.pembayaran-spp.generate')); ?>" method="POST" onsubmit="return confirmGenerate()">
|
||||||
|
<?php echo csrf_field(); ?>
|
||||||
|
|
||||||
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||||
|
<!-- Bulan -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-calendar form-icon"></i> Bulan <span style="color: red;">*</span></label>
|
||||||
|
<select name="bulan" class="form-control <?php $__errorArgs = ['bulan'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>" required>
|
||||||
|
<option value="">-- Pilih Bulan --</option>
|
||||||
|
<?php for($i = 1; $i <= 12; $i++): ?>
|
||||||
|
<option value="<?php echo e($i); ?>" <?php echo e(old('bulan', date('n')) == $i ? 'selected' : ''); ?>>
|
||||||
|
<?php echo e(DateTime::createFromFormat('!m', $i)->format('F')); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
<?php $__errorArgs = ['bulan'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tahun -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-calendar-alt form-icon"></i> Tahun <span style="color: red;">*</span></label>
|
||||||
|
<input type="number"
|
||||||
|
name="tahun"
|
||||||
|
class="form-control <?php $__errorArgs = ['tahun'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>"
|
||||||
|
value="<?php echo e(old('tahun', date('Y'))); ?>"
|
||||||
|
min="2020"
|
||||||
|
max="2100"
|
||||||
|
required>
|
||||||
|
<?php $__errorArgs = ['tahun'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
|
||||||
|
<!-- Nominal -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-money-bill-wave form-icon"></i> Nominal per Santri (Rp) <span style="color: red;">*</span></label>
|
||||||
|
<input type="number"
|
||||||
|
name="nominal"
|
||||||
|
id="input-nominal"
|
||||||
|
class="form-control <?php $__errorArgs = ['nominal'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>"
|
||||||
|
value="<?php echo e(old('nominal')); ?>"
|
||||||
|
placeholder="Contoh: 250000"
|
||||||
|
min="0"
|
||||||
|
step="1000"
|
||||||
|
required>
|
||||||
|
<?php $__errorArgs = ['nominal'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
<small class="form-text" id="nominal-helper">
|
||||||
|
<span id="nominal-display" style="color: var(--primary-color); font-weight: 600;">Masukkan nominal pembayaran</span>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Batas Bayar -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label><i class="fas fa-clock form-icon"></i> Batas Bayar <span style="color: red;">*</span></label>
|
||||||
|
<input type="date"
|
||||||
|
name="batas_bayar"
|
||||||
|
class="form-control <?php $__errorArgs = ['batas_bayar'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>"
|
||||||
|
value="<?php echo e(old('batas_bayar', date('Y-m-10'))); ?>"
|
||||||
|
required>
|
||||||
|
<?php $__errorArgs = ['batas_bayar'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Preview Info Santri -->
|
||||||
|
<div class="info-box" style="background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); border-color: var(--success-color);">
|
||||||
|
<p style="margin: 0; line-height: 1.8;">
|
||||||
|
<i class="fas fa-users"></i>
|
||||||
|
Data SPP akan dibuat untuk <strong><?php echo e(\App\Models\Santri::where('status', 'Aktif')->count()); ?> santri</strong> dengan status Aktif.<br>
|
||||||
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
|
Pastikan data sudah benar sebelum melanjutkan. Proses ini tidak dapat dibatalkan.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Periode Yang Sudah Di-Generate -->
|
||||||
|
<?php
|
||||||
|
$periodeGenerated = \App\Models\PembayaranSpp::selectRaw('DISTINCT bulan, tahun')
|
||||||
|
->orderBy('tahun', 'desc')
|
||||||
|
->orderBy('bulan', 'desc')
|
||||||
|
->get();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if($periodeGenerated->count() > 0): ?>
|
||||||
|
<div class="info-box" style="background: linear-gradient(135deg, #FFF8E1 0%, #FFF3CD 100%); border-color: var(--warning-color);">
|
||||||
|
<p style="margin: 0 0 10px 0; font-weight: 600; color: var(--text-color);">
|
||||||
|
<i class="fas fa-info-circle"></i> Periode Yang Sudah Di-Generate:
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; flex-wrap: wrap; gap: 8px;">
|
||||||
|
<?php $__currentLoopData = $periodeGenerated; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $periode): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$bulanNama = DateTime::createFromFormat('!m', $periode->bulan)->format('F');
|
||||||
|
?>
|
||||||
|
<span style="background: white; padding: 6px 12px; border-radius: 5px; font-size: 0.9rem; border: 1px solid #ddd;">
|
||||||
|
<?php echo e($bulanNama); ?> <?php echo e($periode->tahun); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</div>
|
||||||
|
<p style="margin: 10px 0 0 0; font-size: 0.85rem; color: var(--text-light);">
|
||||||
|
<i class="fas fa-lightbulb"></i> Jika Anda generate periode yang sudah ada, data akan di-skip (tidak duplikat).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Buttons -->
|
||||||
|
<div style="display: flex; gap: 10px; margin-top: 25px;">
|
||||||
|
<button type="submit" class="btn btn-success hover-shadow" id="btn-generate">
|
||||||
|
<i class="fas fa-cogs"></i> Generate SPP
|
||||||
|
</button>
|
||||||
|
<a href="<?php echo e(route('admin.pembayaran-spp.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading Overlay -->
|
||||||
|
<div id="loading-overlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 9999; justify-content: center; align-items: center;">
|
||||||
|
<div style="background: white; padding: 22px; border-radius: 15px; text-align: center; max-width: 400px;">
|
||||||
|
<div style="border: 4px solid var(--primary-light); border-top: 4px solid var(--primary-color); border-radius: 50%; width: 60px; height: 60px; animation: spin 1s linear infinite; margin: 0 auto 20px;"></div>
|
||||||
|
<h3 style="color: var(--primary-color); margin-bottom: 10px;">Generating SPP...</h3>
|
||||||
|
<p style="color: var(--text-light); margin: 0;">Mohon tunggu, proses sedang berjalan.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php $__env->startPush('styles'); ?>
|
||||||
|
<style>
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<?php $__env->stopPush(); ?>
|
||||||
|
|
||||||
|
<?php $__env->startPush('scripts'); ?>
|
||||||
|
<script>
|
||||||
|
// Daftar periode yang sudah di-generate
|
||||||
|
const periodeGenerated = <?php echo json_encode($periodeGenerated->map(function($p) {
|
||||||
|
return ['bulan' => $p->bulan, 'tahun' => $p->tahun];
|
||||||
|
}), 512) ?>;
|
||||||
|
|
||||||
|
// Format nominal display saat user mengetik
|
||||||
|
document.getElementById('input-nominal').addEventListener('input', function() {
|
||||||
|
const value = parseInt(this.value) || 0;
|
||||||
|
const displayElement = document.getElementById('nominal-display');
|
||||||
|
|
||||||
|
if (value > 0) {
|
||||||
|
const formatted = new Intl.NumberFormat('id-ID', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'IDR',
|
||||||
|
minimumFractionDigits: 0,
|
||||||
|
maximumFractionDigits: 0
|
||||||
|
}).format(value);
|
||||||
|
displayElement.textContent = formatted;
|
||||||
|
displayElement.style.color = 'var(--primary-color)';
|
||||||
|
} else {
|
||||||
|
displayElement.textContent = 'Masukkan nominal pembayaran';
|
||||||
|
displayElement.style.color = 'var(--text-light)';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check apakah periode sudah pernah di-generate
|
||||||
|
function checkPeriode(bulan, tahun) {
|
||||||
|
return periodeGenerated.some(p => p.bulan == bulan && p.tahun == tahun);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm before generate
|
||||||
|
function confirmGenerate() {
|
||||||
|
const bulan = document.querySelector('select[name="bulan"]');
|
||||||
|
const tahun = document.querySelector('input[name="tahun"]');
|
||||||
|
const nominal = document.querySelector('input[name="nominal"]');
|
||||||
|
const batasBayar = document.querySelector('input[name="batas_bayar"]');
|
||||||
|
|
||||||
|
// Validasi nominal harus diisi
|
||||||
|
if (!nominal.value || parseInt(nominal.value) <= 0) {
|
||||||
|
alert('Nominal pembayaran harus diisi!');
|
||||||
|
nominal.focus();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bulanValue = parseInt(bulan.value);
|
||||||
|
const tahunValue = parseInt(tahun.value);
|
||||||
|
const bulanText = bulan.options[bulan.selectedIndex].text;
|
||||||
|
const nominalFormatted = new Intl.NumberFormat('id-ID', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'IDR',
|
||||||
|
minimumFractionDigits: 0
|
||||||
|
}).format(nominal.value);
|
||||||
|
|
||||||
|
const jumlahSantri = <?php echo e(\App\Models\Santri::where('status', 'Aktif')->count()); ?>;
|
||||||
|
const totalNominal = new Intl.NumberFormat('id-ID', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'IDR',
|
||||||
|
minimumFractionDigits: 0
|
||||||
|
}).format(nominal.value * jumlahSantri);
|
||||||
|
|
||||||
|
// Cek apakah periode sudah pernah di-generate
|
||||||
|
const sudahDiGenerate = checkPeriode(bulanValue, tahunValue);
|
||||||
|
let warningText = '';
|
||||||
|
|
||||||
|
if (sudahDiGenerate) {
|
||||||
|
warningText = `\nâš ï¸ PERINGATAN: Periode ${bulanText} ${tahunValue} sudah pernah di-generate!\nData yang sudah ada akan di-skip (tidak akan duplikat).\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = `Anda akan generate SPP untuk semua santri aktif dengan detail:\n\n` +
|
||||||
|
`Periode: ${bulanText} ${tahunValue}\n` +
|
||||||
|
`Nominal per Santri: ${nominalFormatted}\n` +
|
||||||
|
`Batas Bayar: ${new Date(batasBayar.value).toLocaleDateString('id-ID')}\n` +
|
||||||
|
`Jumlah Santri: ${jumlahSantri} santri\n` +
|
||||||
|
`Total Nominal: ${totalNominal}\n` +
|
||||||
|
warningText +
|
||||||
|
`\nLanjutkan?`;
|
||||||
|
|
||||||
|
if (confirm(message)) {
|
||||||
|
// Show loading overlay
|
||||||
|
document.getElementById('loading-overlay').style.display = 'flex';
|
||||||
|
document.getElementById('btn-generate').disabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<?php $__env->stopPush(); ?>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/generate.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,168 +0,0 @@
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="id">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Laporan Pembayaran SPP</title>
|
|
||||||
<style>
|
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
||||||
body { font-family: Arial, sans-serif; padding: 20px; font-size: 12px; }
|
|
||||||
|
|
||||||
.header { text-align: center; margin-bottom: 30px; border-bottom: 3px solid #333; padding-bottom: 15px; }
|
|
||||||
.header h1 { font-size: 20px; margin-bottom: 5px; }
|
|
||||||
.header h2 { font-size: 16px; color: #666; margin-bottom: 10px; }
|
|
||||||
.header p { font-size: 11px; color: #888; }
|
|
||||||
|
|
||||||
.info-box { background: #f5f5f5; padding: 15px; margin-bottom: 20px; border-radius: 5px; }
|
|
||||||
.info-box table { width: 100%; }
|
|
||||||
.info-box td { padding: 5px; }
|
|
||||||
.info-box td:first-child { font-weight: bold; width: 150px; }
|
|
||||||
|
|
||||||
.stats { display: flex; justify-content: space-around; margin-bottom: 20px; }
|
|
||||||
.stat-card { text-align: center; flex: 1; padding: 15px; background: #f9f9f9; border-radius: 5px; margin: 0 5px; }
|
|
||||||
.stat-card h3 { font-size: 11px; color: #666; margin-bottom: 8px; }
|
|
||||||
.stat-card .value { font-size: 18px; font-weight: bold; color: #333; }
|
|
||||||
|
|
||||||
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
|
||||||
th, td { padding: 10px; text-align: left; border: 1px solid #ddd; }
|
|
||||||
th { background: #6FBA9D; color: white; font-weight: bold; }
|
|
||||||
tr:nth-child(even) { background: #f9f9f9; }
|
|
||||||
|
|
||||||
.text-center { text-align: center; }
|
|
||||||
.text-right { text-align: right; }
|
|
||||||
.badge { padding: 4px 8px; border-radius: 3px; font-size: 10px; font-weight: bold; }
|
|
||||||
.badge-success { background: #d4edda; color: #155724; }
|
|
||||||
.badge-warning { background: #fff3cd; color: #856404; }
|
|
||||||
.badge-danger { background: #f8d7da; color: #721c24; }
|
|
||||||
|
|
||||||
.footer { margin-top: 30px; text-align: center; font-size: 10px; color: #888; border-top: 1px solid #ddd; padding-top: 10px; }
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body { padding: 0; }
|
|
||||||
.no-print { display: none; }
|
|
||||||
@page { margin: 1cm; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- Tombol Print -->
|
|
||||||
<div class="no-print" style="margin-bottom: 20px; text-align: right;">
|
|
||||||
<button onclick="window.print()" style="padding: 10px 20px; background: #6FBA9D; color: white; border: none; border-radius: 5px; cursor: pointer;">
|
|
||||||
<i class="fas fa-print"></i> Cetak Laporan
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Header -->
|
|
||||||
<div class="header">
|
|
||||||
<h1>PKPPS RIYADLUL JANNAH</h1>
|
|
||||||
<h2>LAPORAN PEMBAYARAN SPP</h2>
|
|
||||||
<p>Tanggal Cetak: <?php echo e(date('d F Y')); ?> WIB</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Info Filter -->
|
|
||||||
<?php if(request()->has('bulan') || request()->has('tahun') || request()->has('status')): ?>
|
|
||||||
<div class="info-box">
|
|
||||||
<table>
|
|
||||||
<?php if(request()->filled('bulan')): ?>
|
|
||||||
<tr>
|
|
||||||
<td>Bulan</td>
|
|
||||||
<td>: <?php echo e(DateTime::createFromFormat('!m', request('bulan'))->format('F')); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(request()->filled('tahun')): ?>
|
|
||||||
<tr>
|
|
||||||
<td>Tahun</td>
|
|
||||||
<td>: <?php echo e(request('tahun')); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(request()->filled('status')): ?>
|
|
||||||
<tr>
|
|
||||||
<td>Status</td>
|
|
||||||
<td>: <?php echo e(request('status')); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<!-- Statistik -->
|
|
||||||
<div class="stats">
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>Total Terbayar</h3>
|
|
||||||
<div class="value" style="color: #28a745;">Rp <?php echo e(number_format($totalLunas, 0, ',', '.')); ?></div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>Total Tunggakan</h3>
|
|
||||||
<div class="value" style="color: #dc3545;">Rp <?php echo e(number_format($totalTunggakan, 0, ',', '.')); ?></div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>Pembayaran Telat</h3>
|
|
||||||
<div class="value" style="color: #ffc107;"><?php echo e($jumlahTelat); ?></div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>Total Data</h3>
|
|
||||||
<div class="value" style="color: #17a2b8;"><?php echo e($pembayaranSpp->count()); ?></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Tabel Data -->
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th width="5%">No</th>
|
|
||||||
<th width="10%">ID</th>
|
|
||||||
<th width="20%">Santri</th>
|
|
||||||
<th width="15%">Periode</th>
|
|
||||||
<th width="15%">Nominal</th>
|
|
||||||
<th width="12%">Batas Bayar</th>
|
|
||||||
<th width="12%">Tgl Bayar</th>
|
|
||||||
<th width="11%">Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $pembayaranSpp; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $spp): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<tr>
|
|
||||||
<td class="text-center"><?php echo e($index + 1); ?></td>
|
|
||||||
<td><?php echo e($spp->id_pembayaran); ?></td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($spp->santri->nama_lengkap); ?></strong><br>
|
|
||||||
<small style="color: #666;"><?php echo e($spp->santri->id_santri); ?></small>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($spp->periode_lengkap); ?></td>
|
|
||||||
<td class="text-right"><strong><?php echo e($spp->nominal_format); ?></strong></td>
|
|
||||||
<td class="text-center"><?php echo e($spp->batas_bayar->format('d/m/Y')); ?></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<?php if($spp->tanggal_bayar): ?>
|
|
||||||
<?php echo e($spp->tanggal_bayar->format('d/m/Y')); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color: #999;">-</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<?php if($spp->status === 'Lunas'): ?>
|
|
||||||
<span class="badge badge-success">Lunas</span>
|
|
||||||
<?php elseif($spp->isTelat()): ?>
|
|
||||||
<span class="badge badge-danger">Telat</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span class="badge badge-warning">Belum Lunas</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="8" class="text-center" style="padding: 30px; color: #999;">
|
|
||||||
Tidak ada data pembayaran SPP
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Auto print saat load (opsional)
|
|
||||||
// window.onload = function() { window.print(); }
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/cetak-laporan.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
.text-center { text-align:center; }
|
|
||||||
.progress-inline { display:flex; align-items:center; gap:8px; }
|
|
||||||
.progress-bar-mini { flex:1; background:#e9ecef; border-radius:8px; height:8px; overflow:hidden; max-width:120px; }
|
|
||||||
.progress-bar-mini .fill { height:100%; border-radius:8px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-user-clock"></i> Santri Perlu Perhatian</h2>
|
|
||||||
<a href="<?php echo e(route('admin.laporan-kegiatan.index', request()->only('periode','tanggal_dari','tanggal_sampai'))); ?>"
|
|
||||||
class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom:14px;">
|
|
||||||
<p style="margin:0;font-size:.88rem;color:var(--text-light);">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
Menampilkan <strong><?php echo e($santris->total()); ?> santri</strong>
|
|
||||||
dari <strong><?php echo e($totalSantriAktif); ?> santri aktif</strong>
|
|
||||||
yang kehadiran efektifnya <70%
|
|
||||||
dalam periode <strong><?php echo e($periodeLabel); ?></strong>.
|
|
||||||
<br>
|
|
||||||
<span style="font-size:.8rem;opacity:.8;">
|
|
||||||
<i class="fas fa-clock"></i> Terlambat dihitung sebagai Hadir efektif.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="margin-bottom:14px;">
|
|
||||||
<form method="GET" style="display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;">
|
|
||||||
<input type="hidden" name="periode" value="<?php echo e(request('periode','bulan_ini')); ?>">
|
|
||||||
<input type="hidden" name="tanggal_dari" value="<?php echo e(request('tanggal_dari')); ?>">
|
|
||||||
<input type="hidden" name="tanggal_sampai" value="<?php echo e(request('tanggal_sampai')); ?>">
|
|
||||||
<div class="form-group" style="margin:0;">
|
|
||||||
<label style="font-size:.82rem;">Filter Kelas</label>
|
|
||||||
<select name="id_kelas" class="form-control" style="min-width:180px;">
|
|
||||||
<option value="">-- Semua Kelas --</option>
|
|
||||||
<?php $__currentLoopData = $kelasList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($k->id); ?>" <?php echo e(request('id_kelas')==$k->id?'selected':''); ?>>
|
|
||||||
<?php echo e($k->kelompok->nama_kelompok ?? ''); ?> – <?php echo e($k->nama_kelas); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-filter"></i> Filter</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
<?php if($santris->count() > 0): ?>
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table" style="font-size:.84rem;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>No</th>
|
|
||||||
<th>Nama</th>
|
|
||||||
<th class="text-center">Total Sesi</th>
|
|
||||||
<th class="text-center">
|
|
||||||
Hadir Efektif
|
|
||||||
<span style="display:block;font-weight:400;font-size:.73rem;color:#9CA3AF;">(Hadir+Terlambat)</span>
|
|
||||||
</th>
|
|
||||||
<th class="text-center">Terlambat</th>
|
|
||||||
<th class="text-center">Alpa</th>
|
|
||||||
<th class="text-center">Izin</th>
|
|
||||||
<th class="text-center">Sakit</th>
|
|
||||||
<th class="text-center" style="min-width:180px;">
|
|
||||||
% Kehadiran
|
|
||||||
<span style="display:block;font-weight:400;font-size:.73rem;color:#9CA3AF;">(hadir / total sesi)</span>
|
|
||||||
</th>
|
|
||||||
<th>Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo e($santris->firstItem() + $i); ?></td>
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($s->nama_lengkap); ?></strong>
|
|
||||||
<div style="font-size:.75rem;color:#9CA3AF;"><code><?php echo e($s->id_santri); ?></code></div>
|
|
||||||
</td>
|
|
||||||
<td class="text-center"><?php echo e($s->total); ?></td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge badge-success"><?php echo e($s->hadir); ?></span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<?php if(($s->terlambat ?? 0) > 0): ?>
|
|
||||||
<span class="badge badge-warning"><?php echo e($s->terlambat); ?></span>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color:#9CA3AF;">0</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge badge-danger"><?php echo e($s->alpa); ?></span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge badge-warning"><?php echo e($s->izin); ?></span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<span class="badge badge-info"><?php echo e($s->sakit); ?></span>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div class="progress-inline" style="justify-content:center;">
|
|
||||||
<div class="progress-bar-mini">
|
|
||||||
<div class="fill" style="width:<?php echo e($s->persen); ?>%;background:#EF4444;"></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<strong style="color:#EF4444;"><?php echo e($s->persen); ?>%</strong>
|
|
||||||
|
|
||||||
<div style="font-size:.72rem;color:#9CA3AF;">
|
|
||||||
<?php echo e($s->hadir); ?> dari <?php echo e($s->total); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $s->id_santri)); ?>"
|
|
||||||
class="btn btn-sm btn-info" title="Lihat Riwayat Lengkap">
|
|
||||||
<i class="fas fa-history"></i> Riwayat
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div style="margin-top:16px;"><?php echo e($santris->links()); ?></div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-state">
|
|
||||||
<i class="fas fa-check-circle" style="color:#10B981;font-size:2rem;"></i>
|
|
||||||
<h3>Alhamdulillah!</h3>
|
|
||||||
<p>Tidak ada santri dengan kehadiran di bawah 70%.</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/laporan/santri-perlu-perhatian.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="id">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo $__env->yieldContent('title', 'Login'); ?> | SIM Santri</title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="<?php echo e(asset('css/app.css')); ?>">
|
|
||||||
<style>
|
|
||||||
/* Gaya dasar untuk halaman auth/login */
|
|
||||||
body.auth-page {
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
.auth-container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
background: white;
|
|
||||||
padding: 22px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
.auth-header {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
.auth-header h2 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
}
|
|
||||||
.auth-header p {
|
|
||||||
color: #777;
|
|
||||||
margin-top: 5px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
.btn-full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="auth-page">
|
|
||||||
<div class="auth-container">
|
|
||||||
<?php echo $__env->yieldContent('auth-content'); ?>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/auth/auth_layout.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,592 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Data Kepulangan Santri'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-home"></i> Data Kepulangan Santri</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$pendingPengajuan = \App\Models\PengajuanKepulangan::where('status', 'Menunggu')->count();
|
|
||||||
?>
|
|
||||||
|
|
||||||
<?php if($pendingPengajuan > 0): ?>
|
|
||||||
<div class="alert alert-warning" style="display: flex; align-items: center; gap: 11px; margin-bottom: 14px; background: linear-gradient(135deg, #ffc107 0%, #ff9800 100%); border: none; color: #000;">
|
|
||||||
<i class="fas fa-bell" style="font-size: 2rem;"></i>
|
|
||||||
<div style="flex: 1;">
|
|
||||||
<strong style="font-size: 1.1rem;">Ada <?php echo e($pendingPengajuan); ?> pengajuan kepulangan dari mobile yang menunggu review!</strong>
|
|
||||||
<p style="margin: 5px 0 0 0; opacity: 0.8;">Klik tombol di bawah untuk melihat dan meninjau pengajuan.</p>
|
|
||||||
</div>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.pengajuan')); ?>" class="btn btn-dark" style="white-space: nowrap;">
|
|
||||||
<i class="fas fa-mobile-alt"></i> Lihat Pengajuan
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background: linear-gradient(135deg, #6FBA9D 0%, #89cdb3 100%); color: white; padding: 14px; border-radius: 12px; margin-bottom: 14px;">
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; align-items: center;">
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0 0 5px 0; opacity: 0.9;"> Periode Kuota</h4>
|
|
||||||
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
|
|
||||||
<?php echo e($settings->periode_mulai->format('d M Y')); ?> - <?php echo e($settings->periode_akhir->format('d M Y')); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0 0 5px 0; opacity: 0.9;"> Kuota Maksimal</h4>
|
|
||||||
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;"><?php echo e($settings->kuota_maksimal); ?> Hari / Tahun</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 style="margin: 0 0 5px 0; opacity: 0.9;"> Terakhir Reset</h4>
|
|
||||||
<p style="margin: 0; font-size: 1.1rem; font-weight: 600;">
|
|
||||||
<?php echo e($settings->terakhir_reset ? $settings->terakhir_reset->format('d M Y') : 'Belum Pernah'); ?>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right;">
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.settings')); ?>" class="btn btn-light" style="background: white; color: #667eea; font-weight: 600;">
|
|
||||||
<i class="fas fa-cog"></i> Kelola Pengaturan
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row-cards">
|
|
||||||
<div class="card card-info">
|
|
||||||
<h3>Total Data</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['total_data']); ?></div>
|
|
||||||
<i class="fas fa-clipboard-list card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-warning">
|
|
||||||
<h3>Menunggu Approval</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['menunggu_approval']); ?></div>
|
|
||||||
<i class="fas fa-clock card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-success">
|
|
||||||
<h3>Sedang Izin</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['sedang_izin']); ?></div>
|
|
||||||
<i class="fas fa-home card-icon"></i>
|
|
||||||
</div>
|
|
||||||
<div class="card card-danger">
|
|
||||||
<h3>Over Limit (><?php echo e($settings->kuota_maksimal); ?> Hari)</h3>
|
|
||||||
<div class="card-value"><?php echo e($stats['over_limit_santri']); ?></div>
|
|
||||||
<i class="fas fa-exclamation-triangle card-icon"></i>
|
|
||||||
<?php if($stats['over_limit_santri'] > 0): ?>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.over-limit')); ?>" style="font-size: 0.85rem; color: #dc3545; text-decoration: underline; margin-top: 5px; display: block;">
|
|
||||||
Lihat Detail
|
|
||||||
</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="alert alert-success">
|
|
||||||
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if(session('error')): ?>
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<i class="fas fa-exclamation-circle"></i> <?php echo e(session('error')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.create')); ?>" class="btn btn-primary">
|
|
||||||
<i class="fas fa-plus"></i> Tambah Izin Kepulangan
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.pengajuan')); ?>" class="btn btn-warning">
|
|
||||||
<i class="fas fa-mobile-alt"></i> Pengajuan izin
|
|
||||||
<?php if($pendingPengajuan > 0): ?>
|
|
||||||
<span class="badge" style="background: #dc3545; color: white; margin-left: 5px; padding: 3px 8px; border-radius: 10px; font-size: 0.75rem;">
|
|
||||||
<?php echo e($pendingPengajuan); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.kepulangan.index')); ?>" id="filterForm" style="margin-bottom: 14px;">
|
|
||||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px; align-items: end;">
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<input type="text" name="search" class="form-control" placeholder="Cari nama, ID, atau alasan..." value="<?php echo e(request('search')); ?>" id="searchInput">
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="status" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Status</option>
|
|
||||||
<option value="Menunggu" <?php echo e(request('status') == 'Menunggu' ? 'selected' : ''); ?>>Menunggu</option>
|
|
||||||
<option value="Disetujui" <?php echo e(request('status') == 'Disetujui' ? 'selected' : ''); ?>>Disetujui</option>
|
|
||||||
<option value="Ditolak" <?php echo e(request('status') == 'Ditolak' ? 'selected' : ''); ?>>Ditolak</option>
|
|
||||||
<option value="Selesai" <?php echo e(request('status') == 'Selesai' ? 'selected' : ''); ?>>Selesai</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="tahun" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Tahun</option>
|
|
||||||
<?php $__currentLoopData = $tahunList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tahun): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($tahun); ?>" <?php echo e(request('tahun') == $tahun ? 'selected' : ''); ?>><?php echo e($tahun); ?></option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin-bottom: 0;">
|
|
||||||
<select name="bulan" class="form-control" onchange="document.getElementById('filterForm').submit();">
|
|
||||||
<option value="">Semua Bulan</option>
|
|
||||||
<?php for($i = 1; $i <= 12; $i++): ?>
|
|
||||||
<option value="<?php echo e($i); ?>" <?php echo e(request('bulan') == $i ? 'selected' : ''); ?>>
|
|
||||||
<?php echo e(\Carbon\Carbon::create()->month($i)->format('F')); ?>
|
|
||||||
|
|
||||||
</option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px;">
|
|
||||||
<button type="submit" class="btn btn-primary"><i class="fas fa-search"></i> Filter</button>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.index')); ?>" class="btn btn-secondary"><i class="fas fa-redo"></i> Reset</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="overflow-x: auto;">
|
|
||||||
<div class="table-wrapper">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Santri</th>
|
|
||||||
<th>Tanggal Pulang</th>
|
|
||||||
<th>Tanggal Kembali</th>
|
|
||||||
<th>Durasi</th>
|
|
||||||
<th>Total Kuota Terpakai</th>
|
|
||||||
<th>Alasan</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th class="text-center">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__empty_1 = true; $__currentLoopData = $kepulangan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
||||||
<?php
|
|
||||||
$isOverLimit = isset($santriOverLimit[$item->id_santri]);
|
|
||||||
$totalHariTerpakai = $isOverLimit ? $santriOverLimit[$item->id_santri] : 0;
|
|
||||||
?>
|
|
||||||
<tr style="<?php echo e($isOverLimit ? 'background-color: rgba(220, 53, 69, 0.1); border-left: 4px solid #dc3545;' : ''); ?>">
|
|
||||||
<td>
|
|
||||||
<strong><?php echo e($item->id_kepulangan); ?></strong>
|
|
||||||
<?php if($isOverLimit): ?>
|
|
||||||
<span style="display: inline-block; background: #dc3545; color: white; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; margin-left: 5px; animation: pulse 2s infinite;" title="Over Limit: <?php echo e($totalHariTerpakai); ?> hari">
|
|
||||||
<i class="fas fa-exclamation-triangle"></i>
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>
|
|
||||||
<strong><?php echo e($item->santri->nama_lengkap ?? 'N/A'); ?></strong><br>
|
|
||||||
<small style="color: #7F8C8D;"><?php echo e($item->santri->id_santri ?? ''); ?> | <?php echo e($item->santri->kelas ?? ''); ?></small>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td><?php echo e($item->tanggal_pulang_formatted); ?></td>
|
|
||||||
<td><?php echo e($item->tanggal_kembali_formatted); ?></td>
|
|
||||||
<td>
|
|
||||||
<span style="display: inline-block; background: <?php echo e($item->durasi_izin > 7 ? '#ffc107' : '#6c757d'); ?>; color: <?php echo e($item->durasi_izin > 7 ? '#000' : '#fff'); ?>; padding: 4px 8px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
|
|
||||||
<?php echo e($item->durasi_izin); ?> hari
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php
|
|
||||||
$kuotaSantri = \App\Models\Kepulangan::getSisaKuotaSantri($item->id_santri);
|
|
||||||
$badgeColor = $kuotaSantri['badge_color'];
|
|
||||||
$badgeColors = ['success' => '#28a745', 'warning' => '#ffc107', 'danger' => '#dc3545'];
|
|
||||||
$bgColor = $badgeColors[$badgeColor] ?? '#6c757d';
|
|
||||||
$textColor = $badgeColor == 'warning' ? '#000' : '#fff';
|
|
||||||
?>
|
|
||||||
<div style="text-align: center;">
|
|
||||||
<span style="display: inline-block; background: <?php echo e($bgColor); ?>; color: <?php echo e($textColor); ?>; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;">
|
|
||||||
<?php echo e($kuotaSantri['total_terpakai']); ?> / <?php echo e($kuotaSantri['kuota_maksimal']); ?> hari
|
|
||||||
</span>
|
|
||||||
<div style="margin-top: 5px; font-size: 0.75rem; color: #7F8C8D;">
|
|
||||||
<?php if($kuotaSantri['status'] === 'melebihi'): ?>
|
|
||||||
<strong style="color: #dc3545;">OVER LIMIT</strong>
|
|
||||||
<?php else: ?>
|
|
||||||
Sisa: <?php echo e($kuotaSantri['sisa_kuota']); ?> hari (<?php echo e($kuotaSantri['persentase']); ?>%)
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block;" title="<?php echo e($item->alasan); ?>">
|
|
||||||
<?php echo e($item->alasan); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span style="display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.85rem; font-weight: 600;
|
|
||||||
<?php if($item->status == 'Menunggu'): ?> background: #ffc107; color: #000;
|
|
||||||
<?php elseif($item->status == 'Disetujui'): ?> background: #28a745; color: white;
|
|
||||||
<?php elseif($item->status == 'Ditolak'): ?> background: #dc3545; color: white;
|
|
||||||
<?php else: ?> background: #6c757d; color: white;
|
|
||||||
<?php endif; ?>">
|
|
||||||
<?php echo e($item->status); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<?php if($item->is_aktif): ?>
|
|
||||||
<br><small style="color: #28a745; font-weight: 600;">Sedang Izin</small>
|
|
||||||
<?php elseif($item->is_terlambat): ?>
|
|
||||||
<br><small style="color: #dc3545; font-weight: 600;">Terlambat</small>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.show', $item->id_kepulangan)); ?>" class="btn btn-sm btn-primary" title="Detail">
|
|
||||||
<i class="fas fa-eye"></i>
|
|
||||||
</a>
|
|
||||||
<?php if($item->status == 'Menunggu'): ?>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.edit', $item->id_kepulangan)); ?>" class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="fas fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-sm btn-success" onclick="approveKepulangan('<?php echo e($item->id_kepulangan); ?>')" title="Setujui">
|
|
||||||
<i class="fas fa-check"></i>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-danger" onclick="rejectKepulangan('<?php echo e($item->id_kepulangan); ?>')" title="Tolak">
|
|
||||||
<i class="fas fa-times"></i>
|
|
||||||
</button>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if($item->status == 'Disetujui'): ?>
|
|
||||||
<a href="<?php echo e(route('admin.kepulangan.print', $item->id_kepulangan)); ?>" class="btn btn-sm btn-secondary" target="_blank" title="Cetak Surat">
|
|
||||||
<i class="fas fa-print"></i>
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-sm btn-success"
|
|
||||||
onclick="completeKepulangan('<?php echo e($item->id_kepulangan); ?>', '<?php echo e($item->santri->nama_lengkap); ?>', '<?php echo e($item->tanggal_pulang->format('Y-m-d')); ?>', '<?php echo e($item->tanggal_kembali->format('Y-m-d')); ?>', <?php echo e($item->durasi_izin); ?>)"
|
|
||||||
title="Selesaikan">
|
|
||||||
<i class="fas fa-check-double"></i>
|
|
||||||
</button>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if(in_array($item->status, ['Menunggu', 'Ditolak', 'Selesai'])): ?>
|
|
||||||
<button type="button" class="btn btn-sm btn-danger" onclick="deleteKepulangan('<?php echo e($item->id_kepulangan); ?>')" title="Hapus">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="9" style="text-align: center; padding: 22px;">
|
|
||||||
<i class="fas fa-inbox" style="font-size: 2.2rem; color: #ccc; margin-bottom: 15px;"></i>
|
|
||||||
<p style="color: #7F8C8D;">Tidak ada data kepulangan ditemukan</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($kepulangan->hasPages()): ?>
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 14px; flex-wrap: wrap; gap: 11px;">
|
|
||||||
<div>Menampilkan <?php echo e($kepulangan->firstItem() ?? 0); ?> - <?php echo e($kepulangan->lastItem() ?? 0); ?> dari <?php echo e($kepulangan->total()); ?> data</div>
|
|
||||||
<div><?php echo e($kepulangan->appends(request()->query())->links()); ?></div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="approveModal" tabindex="-1" style="display: none;">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
|
||||||
<form id="approveForm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Setujui Izin Kepulangan</h3></div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Catatan (Opsional):</label>
|
|
||||||
<textarea name="catatan" class="form-control" rows="3" placeholder="Tambahkan catatan untuk persetujuan ini..."></textarea>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('approveModal')">Batal</button>
|
|
||||||
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Setujui</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="rejectModal" tabindex="-1" style="display: none;">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
|
||||||
<form id="rejectForm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Tolak Izin Kepulangan</h3></div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Alasan Penolakan: <span style="color: #dc3545;">*</span></label>
|
|
||||||
<textarea name="alasan_penolakan" class="form-control" rows="3" placeholder="Jelaskan alasan penolakan..." required></textarea>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('rejectModal')">Batal</button>
|
|
||||||
<button type="submit" class="btn btn-danger"><i class="fas fa-times"></i> Tolak</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="deleteModal" tabindex="-1" style="display: none;">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
|
||||||
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Konfirmasi Hapus</h3></div>
|
|
||||||
<p>Apakah Anda yakin ingin menghapus data kepulangan ini?</p>
|
|
||||||
<p style="color: #dc3545; font-size: 0.9rem;">Data yang sudah dihapus tidak dapat dikembalikan.</p>
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('deleteModal')">Batal</button>
|
|
||||||
<button type="button" class="btn btn-danger" id="confirmDeleteBtn"><i class="fas fa-trash"></i> Hapus</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="completeModal" tabindex="-1" style="display: none;">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
|
|
||||||
<form id="completeForm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
<div style="margin-bottom: 14px;">
|
|
||||||
<h3 style="margin: 0; color: #2C3E50;"><i class="fas fa-check-circle" style="color: #28a745;"></i> Selesaikan Kepulangan</h3>
|
|
||||||
</div>
|
|
||||||
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
|
|
||||||
<p style="margin: 5px 0;"><strong>ID Kepulangan:</strong> <span id="completeIdKepulangan"></span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Santri:</strong> <span id="completeNamaSantri"></span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Tanggal Pulang:</strong> <span id="completeTanggalPulang"></span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Rencana Kembali:</strong> <span id="completeTanggalKembaliRencana"></span></p>
|
|
||||||
<p style="margin: 5px 0;"><strong>Durasi Rencana:</strong> <span id="completeDurasiRencana"></span> hari</p>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="tanggal_kembali_aktual">
|
|
||||||
<i class="fas fa-calendar-check"></i> Tanggal Kembali Aktual <span style="color: #dc3545;">*</span>
|
|
||||||
</label>
|
|
||||||
<input type="date" name="tanggal_kembali_aktual" id="tanggal_kembali_aktual" class="form-control" required>
|
|
||||||
<small style="color: #7F8C8D; margin-top: 5px; display: block;">Masukkan tanggal santri kembali ke pesantren.</small>
|
|
||||||
</div>
|
|
||||||
<div id="durasiAktualInfo" style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #007bff; display: none;">
|
|
||||||
<p style="margin: 0;"><strong>Durasi Aktual:</strong> <span id="durasiAktual" style="font-weight: 600; color: #007bff;">-</span> hari</p>
|
|
||||||
<p style="margin: 5px 0 0 0; font-size: 0.9rem; color: #7F8C8D;" id="selisihInfo"></p>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="closeModal('completeModal')">Batal</button>
|
|
||||||
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Selesaikan</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
|
|
||||||
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
|
|
||||||
.modal-content { max-height: 90vh; overflow-y: auto; }
|
|
||||||
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const KEPULANGAN_BASE_URL = "<?php echo e(url('admin/kepulangan')); ?>";
|
|
||||||
const CSRF_TOKEN = "<?php echo e(csrf_token()); ?>";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let currentActionId = null;
|
|
||||||
|
|
||||||
// Auto submit search
|
|
||||||
let searchTimeout;
|
|
||||||
document.getElementById('searchInput')?.addEventListener('input', function() {
|
|
||||||
clearTimeout(searchTimeout);
|
|
||||||
searchTimeout = setTimeout(() => document.getElementById('filterForm').submit(), 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===== APPROVE =====
|
|
||||||
function approveKepulangan(id) {
|
|
||||||
currentActionId = id;
|
|
||||||
document.getElementById('approveModal').style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('approveForm').addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const formData = new FormData(this);
|
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
|
||||||
const originalText = submitBtn.innerHTML;
|
|
||||||
submitBtn.disabled = true;
|
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
|
||||||
|
|
||||||
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
|
||||||
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}/approve`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
|
||||||
})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) { closeModal('approveModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
|
||||||
else showAlert('danger', data.message);
|
|
||||||
})
|
|
||||||
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
|
||||||
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===== REJECT =====
|
|
||||||
function rejectKepulangan(id) {
|
|
||||||
currentActionId = id;
|
|
||||||
document.getElementById('rejectModal').style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('rejectForm').addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const formData = new FormData(this);
|
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
|
||||||
const originalText = submitBtn.innerHTML;
|
|
||||||
submitBtn.disabled = true;
|
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
|
||||||
|
|
||||||
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
|
||||||
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}/reject`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
|
||||||
})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) { closeModal('rejectModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
|
||||||
else showAlert('danger', data.message);
|
|
||||||
})
|
|
||||||
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
|
||||||
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===== COMPLETE =====
|
|
||||||
let currentCompleteData = {};
|
|
||||||
|
|
||||||
function completeKepulangan(id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana) {
|
|
||||||
currentCompleteData = { id, namaSantri, tanggalPulang, tanggalKembaliRencana, durasiRencana };
|
|
||||||
document.getElementById('completeIdKepulangan').textContent = id;
|
|
||||||
document.getElementById('completeNamaSantri').textContent = namaSantri;
|
|
||||||
document.getElementById('completeTanggalPulang').textContent = formatTanggal(tanggalPulang);
|
|
||||||
document.getElementById('completeTanggalKembaliRencana').textContent = formatTanggal(tanggalKembaliRencana);
|
|
||||||
document.getElementById('completeDurasiRencana').textContent = durasiRencana;
|
|
||||||
const today = new Date().toISOString().split('T')[0];
|
|
||||||
document.getElementById('tanggal_kembali_aktual').value = today;
|
|
||||||
document.getElementById('tanggal_kembali_aktual').min = tanggalPulang;
|
|
||||||
calculateDurasiAktual();
|
|
||||||
document.getElementById('completeModal').style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateDurasiAktual() {
|
|
||||||
const tanggalKembaliAktual = document.getElementById('tanggal_kembali_aktual').value;
|
|
||||||
if (!tanggalKembaliAktual || !currentCompleteData.tanggalPulang) return;
|
|
||||||
const startDate = new Date(currentCompleteData.tanggalPulang);
|
|
||||||
const endDate = new Date(tanggalKembaliAktual);
|
|
||||||
if (endDate < startDate) { document.getElementById('durasiAktualInfo').style.display = 'none'; return; }
|
|
||||||
const durasiAktual = Math.ceil(Math.abs(endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
|
|
||||||
const durasiRencana = currentCompleteData.durasiRencana;
|
|
||||||
document.getElementById('durasiAktual').textContent = durasiAktual;
|
|
||||||
document.getElementById('durasiAktualInfo').style.display = 'block';
|
|
||||||
let selisihText = '', selisihColor = '#007bff';
|
|
||||||
if (durasiAktual < durasiRencana) {
|
|
||||||
selisihText = `Santri pulang ${durasiRencana - durasiAktual} hari lebih cepat. Kuota akan berkurang ${durasiAktual} hari.`;
|
|
||||||
selisihColor = '#28a745';
|
|
||||||
} else if (durasiAktual > durasiRencana) {
|
|
||||||
selisihText = `Santri pulang ${durasiAktual - durasiRencana} hari lebih lambat. Kuota akan bertambah.`;
|
|
||||||
selisihColor = '#ffc107';
|
|
||||||
} else {
|
|
||||||
selisihText = `Sesuai rencana (${durasiAktual} hari).`;
|
|
||||||
}
|
|
||||||
document.getElementById('selisihInfo').textContent = selisihText;
|
|
||||||
document.getElementById('selisihInfo').style.color = selisihColor;
|
|
||||||
document.getElementById('durasiAktual').style.color = selisihColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('tanggal_kembali_aktual')?.addEventListener('change', calculateDurasiAktual);
|
|
||||||
|
|
||||||
document.getElementById('completeForm')?.addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const formData = new FormData(this);
|
|
||||||
const submitBtn = this.querySelector('button[type="submit"]');
|
|
||||||
const originalText = submitBtn.innerHTML;
|
|
||||||
submitBtn.disabled = true;
|
|
||||||
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
|
||||||
|
|
||||||
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
|
||||||
fetch(`${KEPULANGAN_BASE_URL}/${currentCompleteData.id}/complete`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData,
|
|
||||||
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
|
||||||
})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) { closeModal('completeModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1500); }
|
|
||||||
else showAlert('danger', data.message);
|
|
||||||
})
|
|
||||||
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
|
||||||
.finally(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalText; });
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===== DELETE =====
|
|
||||||
function deleteKepulangan(id) {
|
|
||||||
currentActionId = id;
|
|
||||||
document.getElementById('deleteModal').style.display = 'flex';
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
|
|
||||||
const btn = this;
|
|
||||||
const originalText = btn.innerHTML;
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menghapus...';
|
|
||||||
|
|
||||||
// ✅ FIX: pakai KEPULANGAN_BASE_URL
|
|
||||||
fetch(`${KEPULANGAN_BASE_URL}/${currentActionId}`, {
|
|
||||||
method: 'DELETE',
|
|
||||||
headers: { 'X-CSRF-TOKEN': CSRF_TOKEN }
|
|
||||||
})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) { closeModal('deleteModal'); showAlert('success', data.message); setTimeout(() => location.reload(), 1000); }
|
|
||||||
else showAlert('danger', data.message);
|
|
||||||
})
|
|
||||||
.catch(e => showAlert('danger', 'Error: ' + e.message))
|
|
||||||
.finally(() => { btn.disabled = false; btn.innerHTML = originalText; });
|
|
||||||
});
|
|
||||||
|
|
||||||
// ===== HELPERS =====
|
|
||||||
function formatTanggal(dateString) {
|
|
||||||
return new Date(dateString).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' });
|
|
||||||
}
|
|
||||||
function closeModal(modalId) { document.getElementById(modalId).style.display = 'none'; }
|
|
||||||
function showAlert(type, message) {
|
|
||||||
const alertDiv = document.createElement('div');
|
|
||||||
alertDiv.className = `alert alert-${type}`;
|
|
||||||
alertDiv.innerHTML = `<i class="fas fa-${type === 'success' ? 'check' : 'exclamation'}-circle"></i> ${message}`;
|
|
||||||
document.querySelector('.page-header').insertAdjacentElement('afterend', alertDiv);
|
|
||||||
setTimeout(() => alertDiv.remove(), 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('keydown', e => { if (e.key === 'Escape') document.querySelectorAll('.modal.fade').forEach(m => m.style.display = 'none'); });
|
|
||||||
document.querySelectorAll('.modal.fade').forEach(modal => {
|
|
||||||
modal.addEventListener('click', function(e) { if (e.target === this) this.style.display = 'none'; });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kepulangan/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,456 +0,0 @@
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<style>
|
|
||||||
/* ============================================================
|
|
||||||
RIWAYAT KEGIATAN — INDEX (v3)
|
|
||||||
============================================================ */
|
|
||||||
|
|
||||||
.rw-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:16px; flex-wrap:wrap; gap:10px; }
|
|
||||||
.rw-header h2 { margin:0; font-size:1.35rem; color:var(--primary-dark); display:flex; align-items:center; gap:9px; }
|
|
||||||
.rw-header h2 i { color:var(--primary-color); }
|
|
||||||
|
|
||||||
/* Filter */
|
|
||||||
.rw-filter { background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); padding:14px 18px; margin-bottom:14px; }
|
|
||||||
.rw-mode-tabs { display:flex; gap:6px; margin-bottom:14px; flex-wrap:wrap; }
|
|
||||||
.rw-tab { padding:7px 18px; border-radius:22px; border:1.5px solid #e2e8f0; background:#fff;
|
|
||||||
font-size:0.82rem; font-weight:600; cursor:pointer; text-decoration:none;
|
|
||||||
color:#64748b; transition:all .18s; display:inline-flex; align-items:center; gap:6px; }
|
|
||||||
.rw-tab:hover { border-color:var(--primary-color); color:var(--primary-color); background:#f0fdf4; }
|
|
||||||
.rw-tab.active { background:var(--primary-color); color:#fff; border-color:var(--primary-color); box-shadow:0 2px 8px rgba(16,185,129,.25); }
|
|
||||||
.rw-filter-row { display:flex; gap:10px; align-items:flex-end; flex-wrap:wrap; }
|
|
||||||
.rw-fg { display:flex; flex-direction:column; gap:4px; }
|
|
||||||
.rw-fg label { font-size:0.78rem; font-weight:600; color:#64748b; }
|
|
||||||
.rw-fg .form-control { padding:7px 11px; font-size:0.84rem; border:1.5px solid #e2e8f0; border-radius:8px; }
|
|
||||||
.rw-fg .form-control:focus { border-color:var(--primary-color); outline:none; }
|
|
||||||
.btn-rw-apply { background:var(--primary-color); color:#fff; border:none; padding:8px 18px; border-radius:8px;
|
|
||||||
font-size:0.84rem; font-weight:600; cursor:pointer; display:inline-flex; align-items:center; gap:6px;
|
|
||||||
align-self:flex-end; white-space:nowrap; }
|
|
||||||
.btn-rw-apply:hover { background:#059669; }
|
|
||||||
.btn-rw-reset { background:#f1f5f9; color:#64748b; border:1.5px solid #e2e8f0; padding:8px 12px; border-radius:8px;
|
|
||||||
font-size:0.84rem; font-weight:600; text-decoration:none;
|
|
||||||
display:inline-flex; align-items:center; gap:6px; align-self:flex-end; }
|
|
||||||
.btn-rw-reset:hover { background:#e2e8f0; }
|
|
||||||
|
|
||||||
/* Periode label */
|
|
||||||
.rw-periode { background:linear-gradient(90deg,#f0fdf4,#e8f7f2); border-left:3px solid var(--primary-color);
|
|
||||||
border-radius:8px; padding:9px 14px; margin-bottom:14px; font-size:0.84rem; color:#374151;
|
|
||||||
display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
|
|
||||||
.rw-periode i { color:var(--primary-color); }
|
|
||||||
|
|
||||||
/* KPI strip */
|
|
||||||
.rw-kpi-strip { display:grid; grid-template-columns:repeat(auto-fit,minmax(105px,1fr)); gap:8px; margin-bottom:14px; }
|
|
||||||
.rw-kpi { background:#fff; border-radius:10px; padding:11px 14px; box-shadow:0 2px 8px rgba(0,0,0,.05); text-align:center; }
|
|
||||||
.rw-kpi-val { font-size:1.45rem; font-weight:800; line-height:1; }
|
|
||||||
.rw-kpi-lbl { font-size:0.73rem; color:#94a3b8; margin-top:4px; font-weight:500; }
|
|
||||||
.rw-kpi-sub { font-size:0.68rem; color:#cbd5e1; margin-top:2px; }
|
|
||||||
|
|
||||||
/* Per-date block */
|
|
||||||
.rw-date-block { margin-bottom:20px; }
|
|
||||||
.rw-date-header { display:flex; align-items:center; gap:10px; padding:10px 16px; flex-wrap:wrap;
|
|
||||||
background:linear-gradient(90deg,var(--primary-color),#0ea574);
|
|
||||||
border-radius:10px 10px 0 0; color:#fff; }
|
|
||||||
.rw-date-today { background:linear-gradient(90deg,#0ea574,#059669); }
|
|
||||||
.dh-date { font-size:1rem; font-weight:700; }
|
|
||||||
.dh-hari { background:rgba(255,255,255,.22); padding:2px 10px; border-radius:12px; font-size:0.78rem; font-weight:600; }
|
|
||||||
.dh-count { margin-left:auto; font-size:0.78rem; background:rgba(255,255,255,.2); padding:3px 10px; border-radius:12px; }
|
|
||||||
|
|
||||||
/* Table */
|
|
||||||
.rw-tbl-wrap { background:#fff; border-radius:0 0 10px 10px; box-shadow:0 3px 12px rgba(0,0,0,.07); overflow-x:auto; }
|
|
||||||
.rw-table { width:100%; border-collapse:collapse; min-width:680px; }
|
|
||||||
.rw-table thead th { padding:9px 13px; text-align:left; font-size:0.78rem; font-weight:700;
|
|
||||||
color:#475569; background:#f8fafc; border-bottom:1.5px solid #e2e8f0; white-space:nowrap; }
|
|
||||||
.rw-table tbody td { padding:9px 13px; font-size:0.83rem; border-bottom:1px solid #f8fafc; vertical-align:middle; }
|
|
||||||
.rw-table tbody tr:last-child td { border-bottom:none; }
|
|
||||||
.rw-table tbody tr:hover { background:#f8fafc; }
|
|
||||||
.rw-table tfoot td { padding:8px 13px; }
|
|
||||||
|
|
||||||
/* Tags */
|
|
||||||
.rw-kelas-tag { background:#e8f7f2; color:var(--primary-dark); padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; margin-right:2px; display:inline-block; }
|
|
||||||
.rw-umum-tag { background:#f1f5f9; color:#64748b; padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; display:inline-block; }
|
|
||||||
.rw-kat-tag { background:#dbeafe; color:#1e40af; padding:2px 7px; border-radius:6px; font-size:.72rem; font-weight:600; display:inline-block; }
|
|
||||||
|
|
||||||
/* Mini progress */
|
|
||||||
.rw-mini-prog { height:6px; background:#f1f5f9; border-radius:3px; overflow:hidden; display:flex; min-width:70px; }
|
|
||||||
|
|
||||||
/* Button table */
|
|
||||||
.btn-tbl-detail { padding:5px 11px; background:var(--primary-color); color:#fff; border:none; border-radius:6px;
|
|
||||||
font-size:0.76rem; font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:4px; white-space:nowrap; }
|
|
||||||
.btn-tbl-detail:hover { background:#059669; color:#fff; }
|
|
||||||
|
|
||||||
/* Cards (hari_ini) */
|
|
||||||
.rw-card { background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); border:1px solid #f0f0f0; overflow:hidden; margin-bottom:10px; }
|
|
||||||
.rw-card:hover { box-shadow:0 4px 18px rgba(0,0,0,.1); }
|
|
||||||
.rw-card-head { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:14px 18px 10px; border-bottom:1px solid #f1f5f9; flex-wrap:wrap; }
|
|
||||||
.rw-card-title { font-size:1rem; font-weight:700; color:var(--primary-dark); margin:0 0 5px; display:flex; align-items:center; gap:8px; }
|
|
||||||
.rw-card-meta { display:flex; gap:10px; flex-wrap:wrap; font-size:.8rem; color:#64748b; align-items:center; }
|
|
||||||
.rw-card-meta span{ display:inline-flex; align-items:center; gap:4px; }
|
|
||||||
.rw-status { padding:4px 12px; border-radius:20px; font-size:.76rem; font-weight:700; white-space:nowrap; flex-shrink:0; display:inline-flex; align-items:center; gap:5px; }
|
|
||||||
.rw-status.belum { background:#f1f5f9; color:#64748b; }
|
|
||||||
.rw-status.selesai{ background:#d1fae5; color:#065f46; }
|
|
||||||
.rw-status.brlgs { background:#fef9c3; color:#854d0e; }
|
|
||||||
.rw-card-body { padding:10px 18px 14px; }
|
|
||||||
.rw-stats-row { display:flex; gap:6px; flex-wrap:wrap; align-items:center; margin-bottom:10px; }
|
|
||||||
.rw-chip { padding:4px 10px; border-radius:10px; font-size:.76rem; font-weight:700; display:inline-flex; align-items:center; gap:4px; }
|
|
||||||
.rw-chip.hadir { background:#d1fae5; color:#065f46; }
|
|
||||||
.rw-chip.terlambat{ background:#fff3e0; color:#e65100; }
|
|
||||||
.rw-chip.izin { background:#fef3c7; color:#92400e; }
|
|
||||||
.rw-chip.sakit { background:#dbeafe; color:#1e40af; }
|
|
||||||
.rw-chip.alpa { background:#fee2e2; color:#991b1b; }
|
|
||||||
.rw-chip.pulang { background:#f3e8ff; color:#6b21a8; }
|
|
||||||
.rw-chip.none { background:#f1f5f9; color:#94a3b8; }
|
|
||||||
.rw-progress-wrap { height:8px; background:#f1f5f9; border-radius:4px; overflow:hidden; display:flex; margin-bottom:6px; }
|
|
||||||
.rw-prog-hadir { background:#22c55e; }
|
|
||||||
.rw-prog-terlambat{ background:#FF9800; }
|
|
||||||
.rw-prog-izin { background:#f59e0b; }
|
|
||||||
.rw-prog-sakit { background:#3b82f6; }
|
|
||||||
.rw-prog-alpa { background:#ef4444; }
|
|
||||||
.rw-prog-pulang { background:#a855f7; }
|
|
||||||
.rw-prog-belum { background:#e2e8f0; }
|
|
||||||
.rw-card-foot { display:flex; align-items:center; justify-content:space-between; padding:8px 18px; background:#fafafa; border-top:1px solid #f1f5f9; flex-wrap:wrap; gap:8px; }
|
|
||||||
.rw-total-txt { font-size:.78rem; color:#94a3b8; }
|
|
||||||
.rw-total-txt strong { color:#374151; }
|
|
||||||
.btn-rw-detail { padding:6px 16px; background:var(--primary-color); color:#fff; border:none; border-radius:7px; font-size:.82rem; font-weight:600; text-decoration:none; display:inline-flex; align-items:center; gap:5px; }
|
|
||||||
.btn-rw-detail:hover { background:#059669; color:#fff; }
|
|
||||||
|
|
||||||
/* Empty */
|
|
||||||
.rw-empty { text-align:center; padding:48px 20px; background:#fff; border-radius:12px; box-shadow:0 2px 10px rgba(0,0,0,.06); }
|
|
||||||
.rw-empty i { font-size:3rem; color:#cbd5e1; display:block; margin-bottom:12px; }
|
|
||||||
.rw-empty h3 { margin:0 0 6px; color:var(--primary-dark); }
|
|
||||||
.rw-empty p { margin:0; color:var(--text-light); font-size:.88rem; }
|
|
||||||
|
|
||||||
@media(max-width:640px) {
|
|
||||||
.rw-filter-row { flex-direction:column; }
|
|
||||||
.rw-fg { width:100%; }
|
|
||||||
.rw-fg .form-control { width:100%; }
|
|
||||||
.btn-rw-apply,.btn-rw-reset { width:100%; justify-content:center; }
|
|
||||||
.rw-kpi-strip { grid-template-columns:repeat(3,1fr); }
|
|
||||||
.dh-count { display:none; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$mode = $mode ?? 'hari_ini';
|
|
||||||
$dari = $dari ?? now()->format('Y-m-d');
|
|
||||||
$sampai = $sampai ?? now()->format('Y-m-d');
|
|
||||||
$tanggal = $tanggal ?? now()->format('Y-m-d');
|
|
||||||
$kategoriId = $kategoriId ?? '';
|
|
||||||
$passParams = ['mode' => $mode, 'dari' => $dari, 'sampai' => $sampai, 'tanggal' => $tanggal];
|
|
||||||
|
|
||||||
$totalAbsensi = $summary['total_absensi'] ?? 0;
|
|
||||||
$totalHadir = $summary['hadir'] ?? 0;
|
|
||||||
$pctHadirGlbl = $totalAbsensi > 0 ? round($totalHadir / $totalAbsensi * 100, 1) : 0;
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-header">
|
|
||||||
<h2><i class="fas fa-history"></i> Riwayat Kegiatan & Absensi</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-filter">
|
|
||||||
<div class="rw-mode-tabs">
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'hari_ini','tanggal'=>$tanggal])); ?>"
|
|
||||||
class="rw-tab <?php echo e($mode==='hari_ini'?'active':''); ?>">
|
|
||||||
<i class="fas fa-calendar-day"></i> Hari Ini
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini'])); ?>"
|
|
||||||
class="rw-tab <?php echo e($mode==='minggu_ini'?'active':''); ?>">
|
|
||||||
<i class="fas fa-calendar-week"></i> Minggu Ini
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'custom','dari'=>$dari,'sampai'=>$sampai])); ?>"
|
|
||||||
class="rw-tab <?php echo e($mode==='custom'?'active':''); ?>">
|
|
||||||
<i class="fas fa-sliders-h"></i> Rentang Tanggal
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form method="GET" action="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>">
|
|
||||||
|
|
||||||
<?php if($mode === 'hari_ini'): ?>
|
|
||||||
<input type="hidden" name="mode" value="hari_ini">
|
|
||||||
<div class="rw-filter-row">
|
|
||||||
<div class="rw-fg">
|
|
||||||
<label><i class="fas fa-calendar-alt"></i> Tanggal</label>
|
|
||||||
<input type="date" name="tanggal" class="form-control" value="<?php echo e($tanggal); ?>" style="max-width:180px;">
|
|
||||||
</div>
|
|
||||||
<div class="rw-fg">
|
|
||||||
<label><i class="fas fa-tag"></i> Kategori</label>
|
|
||||||
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
|
||||||
<option value="">Semua Kategori</option>
|
|
||||||
<?php $__currentLoopData = $kategoris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($k->kategori_id); ?>" <?php echo e($kategoriId==$k->kategori_id?'selected':''); ?>><?php echo e($k->nama_kategori); ?></option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php elseif($mode === 'minggu_ini'): ?>
|
|
||||||
<input type="hidden" name="mode" value="minggu_ini">
|
|
||||||
<div class="rw-filter-row">
|
|
||||||
<div class="rw-fg">
|
|
||||||
<label><i class="fas fa-tag"></i> Kategori</label>
|
|
||||||
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
|
||||||
<option value="">Semua Kategori</option>
|
|
||||||
<?php $__currentLoopData = $kategoris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($k->kategori_id); ?>" <?php echo e($kategoriId==$k->kategori_id?'selected':''); ?>><?php echo e($k->nama_kategori); ?></option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini'])); ?>" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<input type="hidden" name="mode" value="custom">
|
|
||||||
<div class="rw-filter-row">
|
|
||||||
<div class="rw-fg">
|
|
||||||
<label><i class="fas fa-calendar-alt"></i> Dari Tanggal</label>
|
|
||||||
<input type="date" name="dari" class="form-control" value="<?php echo e($dari); ?>" style="max-width:180px;" required>
|
|
||||||
</div>
|
|
||||||
<div class="rw-fg">
|
|
||||||
<label><i class="fas fa-calendar-alt"></i> Sampai Tanggal</label>
|
|
||||||
<input type="date" name="sampai" class="form-control" value="<?php echo e($sampai); ?>" style="max-width:180px;" required>
|
|
||||||
</div>
|
|
||||||
<div class="rw-fg">
|
|
||||||
<label><i class="fas fa-tag"></i> Kategori</label>
|
|
||||||
<select name="kategori_id" class="form-control" style="max-width:200px;">
|
|
||||||
<option value="">Semua Kategori</option>
|
|
||||||
<?php $__currentLoopData = $kategoris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<option value="<?php echo e($k->kategori_id); ?>" <?php echo e($kategoriId==$k->kategori_id?'selected':''); ?>><?php echo e($k->nama_kategori); ?></option>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit" class="btn-rw-apply"><i class="fas fa-search"></i> Tampilkan</button>
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'custom'])); ?>" class="btn-rw-reset"><i class="fas fa-undo"></i> Reset</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="rw-periode">
|
|
||||||
<i class="fas fa-calendar-check"></i>
|
|
||||||
Menampilkan: <strong><?php echo e($periodeLabel); ?></strong>
|
|
||||||
<?php if($mode !== 'hari_ini' && ($summary['jumlah_hari'] ?? 0) > 0): ?>
|
|
||||||
<span style="color:#94a3b8;">·</span>
|
|
||||||
<strong style="color:var(--primary-color);"><?php echo e($summary['jumlah_hari']); ?></strong> hari aktif
|
|
||||||
<span style="color:#94a3b8;">·</span>
|
|
||||||
<strong style="color:var(--primary-color);"><?php echo e($summary['jumlah_kegiatan']); ?></strong> sesi
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($totalAbsensi > 0): ?>
|
|
||||||
<div class="rw-kpi-strip">
|
|
||||||
<div class="rw-kpi">
|
|
||||||
<div class="rw-kpi-val" style="color:#065f46;"><?php echo e($summary['hadir']); ?></div>
|
|
||||||
<div class="rw-kpi-lbl"><i class="fas fa-check" style="color:#22c55e;"></i> Hadir Efektif</div>
|
|
||||||
<?php if($summary['terlambat'] > 0): ?>
|
|
||||||
<div class="rw-kpi-sub">+<?php echo e($summary['terlambat']); ?> terlambat</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="rw-kpi">
|
|
||||||
<div class="rw-kpi-val" style="color:#e65100;"><?php echo e($summary['terlambat']); ?></div>
|
|
||||||
<div class="rw-kpi-lbl"><i class="fas fa-clock" style="color:#FF9800;"></i> Terlambat</div>
|
|
||||||
</div>
|
|
||||||
<div class="rw-kpi">
|
|
||||||
<div class="rw-kpi-val" style="color:#92400e;"><?php echo e($summary['izin']); ?></div>
|
|
||||||
<div class="rw-kpi-lbl"><i class="fas fa-envelope" style="color:#f59e0b;"></i> Izin</div>
|
|
||||||
</div>
|
|
||||||
<div class="rw-kpi">
|
|
||||||
<div class="rw-kpi-val" style="color:#1e40af;"><?php echo e($summary['sakit']); ?></div>
|
|
||||||
<div class="rw-kpi-lbl"><i class="fas fa-heartbeat" style="color:#3b82f6;"></i> Sakit</div>
|
|
||||||
</div>
|
|
||||||
<div class="rw-kpi">
|
|
||||||
<div class="rw-kpi-val" style="color:#991b1b;"><?php echo e($summary['alpa']); ?></div>
|
|
||||||
<div class="rw-kpi-lbl"><i class="fas fa-times-circle" style="color:#ef4444;"></i> Alpa</div>
|
|
||||||
</div>
|
|
||||||
<div class="rw-kpi" style="border-top:2px solid var(--primary-color);">
|
|
||||||
<div class="rw-kpi-val" style="color:<?php echo e($pctHadirGlbl>=85?'#059669':($pctHadirGlbl>=70?'#d97706':'#dc2626')); ?>;"><?php echo e($pctHadirGlbl); ?>%</div>
|
|
||||||
<div class="rw-kpi-lbl"><i class="fas fa-chart-pie" style="color:var(--primary-color);"></i> Rata-rata</div>
|
|
||||||
<div class="rw-kpi-sub">dari <?php echo e($totalAbsensi); ?> tercatat
|
|
||||||
<?php if($mode !== 'hari_ini' && ($summary['jumlah_kegiatan']??0) > 0): ?>
|
|
||||||
· <?php echo e($summary['jumlah_kegiatan']); ?> sesi
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($mode === 'hari_ini'): ?>
|
|
||||||
|
|
||||||
<?php if($kegiatans && $kegiatans->count() > 0): ?>
|
|
||||||
<?php $__currentLoopData = $kegiatans; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php echo $__env->make('admin.kegiatan.riwayat._card', ['kegiatan' => $kegiatan, 'passParams' => $passParams], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<div style="margin-top:16px;"><?php echo $kegiatans->appends(request()->query())->links('pagination::simple-bootstrap-4'); ?></div>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="rw-empty">
|
|
||||||
<i class="fas fa-calendar-times"></i>
|
|
||||||
<h3>Tidak Ada Kegiatan</h3>
|
|
||||||
<p>Tidak ada kegiatan pada <strong><?php echo e($periodeLabel); ?></strong>.</p>
|
|
||||||
<p style="margin-top:8px; font-size:.82rem;">
|
|
||||||
Coba tanggal lain atau lihat <a href="<?php echo e(route('admin.riwayat-kegiatan.index', ['mode'=>'minggu_ini'])); ?>" style="color:var(--primary-color);">riwayat minggu ini</a>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
|
|
||||||
<?php if($kegiatanPerTanggal && $kegiatanPerTanggal->count() > 0): ?>
|
|
||||||
|
|
||||||
<?php $__currentLoopData = $kegiatanPerTanggal; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $tgl => $items): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$tglCarbon = \Carbon\Carbon::parse($tgl);
|
|
||||||
$isHariIni = ($tgl === now()->format('Y-m-d'));
|
|
||||||
$hariLabel = $tglCarbon->locale('id')->isoFormat('dddd');
|
|
||||||
$tglLabel = $tglCarbon->locale('id')->isoFormat('D MMMM Y');
|
|
||||||
$tglHadir = $items->sum('hadir') + $items->sum('terlambat');
|
|
||||||
$tglTotal = $items->sum('total_absensi');
|
|
||||||
$tglPct = $tglTotal > 0 ? round($tglHadir / $tglTotal * 100) : 0;
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="rw-date-block">
|
|
||||||
<div class="rw-date-header <?php echo e($isHariIni ? 'rw-date-today' : ''); ?>">
|
|
||||||
<span class="dh-date"><?php echo e($tglLabel); ?></span>
|
|
||||||
<span class="dh-hari"><?php echo e($hariLabel); ?><?php echo e($isHariIni ? ' · Hari Ini' : ''); ?></span>
|
|
||||||
<span class="dh-count">
|
|
||||||
<?php echo e($items->count()); ?> kegiatan
|
|
||||||
·
|
|
||||||
<strong><?php echo e($tglHadir); ?></strong>/<?php echo e($tglTotal); ?> hadir
|
|
||||||
<?php if($tglTotal > 0): ?>
|
|
||||||
<span style="background:rgba(255,255,255,.15); padding:1px 7px; border-radius:8px; margin-left:4px;"><?php echo e($tglPct); ?>%</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="rw-tbl-wrap">
|
|
||||||
<table class="rw-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th style="width:36px; text-align:center;">No</th>
|
|
||||||
<th>Nama Kegiatan</th>
|
|
||||||
<th style="width:95px;">Waktu</th>
|
|
||||||
<th style="width:110px;">Kategori</th>
|
|
||||||
<th style="width:140px;">Kelas</th>
|
|
||||||
<th style="width:58px; text-align:center; color:#22c55e;" title="Hadir efektif (termasuk terlambat)">Hadir</th>
|
|
||||||
<th style="width:52px; text-align:center; color:#FF9800;" title="Terlambat">Tlbt</th>
|
|
||||||
<th style="width:48px; text-align:center; color:#f59e0b;" title="Izin">Izin</th>
|
|
||||||
<th style="width:48px; text-align:center; color:#3b82f6;" title="Sakit">Skt</th>
|
|
||||||
<th style="width:48px; text-align:center; color:#ef4444;" title="Alpa">Alpa</th>
|
|
||||||
<th style="width:90px;">Progress</th>
|
|
||||||
<th style="width:88px; text-align:center;">Aksi</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php $__currentLoopData = $items; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $idx => $kegiatan): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php
|
|
||||||
$hadirEfektif = $kegiatan->hadir + $kegiatan->terlambat;
|
|
||||||
$totalKeg = $kegiatan->total_absensi;
|
|
||||||
$kelasNames = $kegiatan->kelasKegiatan->pluck('nama_kelas');
|
|
||||||
$isUmum = $kelasNames->isEmpty();
|
|
||||||
?>
|
|
||||||
<tr>
|
|
||||||
<td style="color:#94a3b8; font-size:.76rem; text-align:center;"><?php echo e($idx + 1); ?></td>
|
|
||||||
<td>
|
|
||||||
<div style="font-weight:700; font-size:.87rem; color:var(--primary-dark);"><?php echo e($kegiatan->nama_kegiatan); ?></div>
|
|
||||||
</td>
|
|
||||||
<td style="font-size:.79rem; color:#64748b; white-space:nowrap;">
|
|
||||||
<?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?><br>
|
|
||||||
<span style="color:#94a3b8; font-size:.7rem;">s/d <?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?></span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($kegiatan->kategori): ?>
|
|
||||||
<span class="rw-kat-tag"><?php echo e($kegiatan->kategori->nama_kategori); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<?php if($isUmum): ?>
|
|
||||||
<span class="rw-umum-tag"><i class="fas fa-globe-asia"></i> Umum</span>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php $__currentLoopData = $kelasNames->take(2); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kn): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<span class="rw-kelas-tag"><?php echo e($kn); ?></span>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($kelasNames->count() > 2): ?>
|
|
||||||
<span class="rw-umum-tag">+<?php echo e($kelasNames->count()-2); ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center; font-weight:700; color:#065f46;"><?php echo e($hadirEfektif ?: '–'); ?></td>
|
|
||||||
<td style="text-align:center; color:#e65100;"><?php echo e($kegiatan->terlambat ?: '–'); ?></td>
|
|
||||||
<td style="text-align:center; color:#92400e;"><?php echo e($kegiatan->izin ?: '–'); ?></td>
|
|
||||||
<td style="text-align:center; color:#1e40af;"><?php echo e($kegiatan->sakit ?: '–'); ?></td>
|
|
||||||
<td style="text-align:center; color:#991b1b; font-weight:700;"><?php echo e($kegiatan->alpa ?: '–'); ?></td>
|
|
||||||
<td>
|
|
||||||
<?php if($totalKeg > 0): ?>
|
|
||||||
<?php
|
|
||||||
$segs = [
|
|
||||||
['w'=>round($kegiatan->hadir/$totalKeg*100), 'c'=>'#22c55e'],
|
|
||||||
['w'=>round($kegiatan->terlambat/$totalKeg*100), 'c'=>'#FF9800'],
|
|
||||||
['w'=>round($kegiatan->izin/$totalKeg*100), 'c'=>'#f59e0b'],
|
|
||||||
['w'=>round($kegiatan->sakit/$totalKeg*100), 'c'=>'#3b82f6'],
|
|
||||||
['w'=>round($kegiatan->alpa/$totalKeg*100), 'c'=>'#ef4444'],
|
|
||||||
];
|
|
||||||
?>
|
|
||||||
<div class="rw-mini-prog">
|
|
||||||
<?php $__currentLoopData = $segs; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<?php if($s['w'] > 0): ?><div style="width:<?php echo e($s['w']); ?>%;background:<?php echo e($s['c']); ?>;"></div><?php endif; ?>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<div style="font-size:.67rem; color:#94a3b8; margin-top:2px;"><?php echo e($hadirEfektif); ?>/<?php echo e($totalKeg); ?></div>
|
|
||||||
<?php else: ?>
|
|
||||||
<span style="color:#cbd5e1; font-size:.76rem;">–</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center;">
|
|
||||||
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kegiatan->id)); ?>?mode=hari_ini&tanggal=<?php echo e($tgl); ?>&dari=<?php echo e($tgl); ?>&sampai=<?php echo e($tgl); ?>"
|
|
||||||
class="btn-tbl-detail">
|
|
||||||
<i class="fas fa-users"></i> Santri
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</tbody>
|
|
||||||
<?php if($items->count() > 1): ?>
|
|
||||||
<tfoot>
|
|
||||||
<tr style="background:#f0fdf4; border-top:1.5px solid #bbf7d0;">
|
|
||||||
<td colspan="5" style="font-size:.78rem; font-weight:700; color:#065f46; padding:8px 13px;">
|
|
||||||
<i class="fas fa-layer-group"></i> Total <?php echo e($tglLabel); ?>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td style="text-align:center; font-weight:800; color:#065f46;"><?php echo e($tglHadir); ?></td>
|
|
||||||
<td style="text-align:center; font-weight:700; color:#e65100;"><?php echo e($items->sum('terlambat')); ?></td>
|
|
||||||
<td style="text-align:center; font-weight:700; color:#92400e;"><?php echo e($items->sum('izin')); ?></td>
|
|
||||||
<td style="text-align:center; font-weight:700; color:#1e40af;"><?php echo e($items->sum('sakit')); ?></td>
|
|
||||||
<td style="text-align:center; font-weight:700; color:#991b1b;"><?php echo e($items->sum('alpa')); ?></td>
|
|
||||||
<td colspan="2" style="font-size:.75rem; color:#94a3b8; padding:8px 13px;">
|
|
||||||
<?php echo e($tglTotal); ?> tercatat · <?php echo e($tglPct); ?>% hadir
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
<?php endif; ?>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="rw-empty">
|
|
||||||
<i class="fas fa-calendar-times"></i>
|
|
||||||
<h3>Tidak Ada Data Absensi</h3>
|
|
||||||
<p>Tidak ada absensi yang tercatat pada periode <strong><?php echo e($periodeLabel); ?></strong>.</p>
|
|
||||||
<?php if($mode === 'custom'): ?>
|
|
||||||
<p style="margin-top:8px; font-size:.82rem; color:#6b7280;">
|
|
||||||
Pastikan rentang tanggal sudah benar dan ada data absensi di periode tersebut.
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/riwayat/index.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Laporan Pembayaran SPP'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('content'); ?>
|
|
||||||
<div class="page-header">
|
|
||||||
<h2><i class="fas fa-file-pdf"></i> Laporan Pembayaran SPP</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row-cards">
|
|
||||||
<!-- Laporan Semua Data -->
|
|
||||||
<div class="card card-primary hover-lift">
|
|
||||||
<h3>Laporan Semua Data</h3>
|
|
||||||
<p style="margin: 10px 0; color: var(--text-light);">
|
|
||||||
Cetak laporan semua pembayaran SPP atau dengan filter tertentu
|
|
||||||
</p>
|
|
||||||
<form action="<?php echo e(route('admin.pembayaran-spp.cetak-laporan')); ?>" method="GET" target="_blank">
|
|
||||||
<div class="form-group">
|
|
||||||
<label><i class="fas fa-calendar form-icon"></i> Bulan (Opsional)</label>
|
|
||||||
<select name="bulan" class="form-control">
|
|
||||||
<option value="">Semua Bulan</option>
|
|
||||||
<?php for($i = 1; $i <= 12; $i++): ?>
|
|
||||||
<option value="<?php echo e($i); ?>"><?php echo e(DateTime::createFromFormat('!m', $i)->format('F')); ?></option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label><i class="fas fa-calendar-alt form-icon"></i> Tahun (Opsional)</label>
|
|
||||||
<select name="tahun" class="form-control">
|
|
||||||
<option value="">Semua Tahun</option>
|
|
||||||
<?php for($year = date('Y'); $year >= 2020; $year--): ?>
|
|
||||||
<option value="<?php echo e($year); ?>"><?php echo e($year); ?></option>
|
|
||||||
<?php endfor; ?>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label><i class="fas fa-info-circle form-icon"></i> Status (Opsional)</label>
|
|
||||||
<select name="status" class="form-control">
|
|
||||||
<option value="">Semua Status</option>
|
|
||||||
<option value="Lunas">Lunas</option>
|
|
||||||
<option value="Belum Lunas">Belum Lunas</option>
|
|
||||||
<option value="Telat">Telat</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary hover-shadow" style="width: 100%;">
|
|
||||||
<i class="fas fa-print"></i> Cetak Laporan
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<div class="content-box" style="margin-top: 25px;">
|
|
||||||
<a href="<?php echo e(route('admin.pembayaran-spp.index')); ?>" class="btn btn-secondary">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startPush('scripts'); ?>
|
|
||||||
<script>
|
|
||||||
// Update form action saat santri dipilih
|
|
||||||
document.getElementById('select-santri').addEventListener('change', function() {
|
|
||||||
const form = document.getElementById('form-santri');
|
|
||||||
const selectedId = this.value;
|
|
||||||
if (selectedId) {
|
|
||||||
form.action = "<?php echo e(route('admin.pembayaran-spp.cetak-laporan-santri', ':id')); ?>".replace(':id', selectedId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php $__env->stopPush(); ?>
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/pembayaran-spp/laporan.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('title', 'Data Santri'); ?>
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-users"></i> Data Santri</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if(session('success')): ?>
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<!-- Header Actions -->
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: flex-start; gap: 11px; margin-bottom: 14px; flex-wrap: wrap;">
|
||||||
|
<!-- Tombol Tambah -->
|
||||||
|
<a href="<?php echo e(route('admin.santri.create')); ?>" class="btn btn-primary btn-sm">
|
||||||
|
<i class="fas fa-plus"></i> Tambah Santri
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Form Search & Filter -->
|
||||||
|
<form action="<?php echo e(route('admin.santri.index')); ?>" method="GET" style="display: flex; gap: 8px; flex-wrap: wrap; align-items: center;">
|
||||||
|
<input type="text" name="search" class="form-control" placeholder="Cari nama, NIS, atau ID..." value="<?php echo e(request('search')); ?>" style="width: 220px; height: 38px;">
|
||||||
|
|
||||||
|
<select name="status" class="form-control" style="width: 150px; height: 38px;">
|
||||||
|
<option value=""> Semua Status</option>
|
||||||
|
<option value="Aktif" <?php echo e(request('status') == 'Aktif' ? 'selected' : ''); ?>>Aktif</option>
|
||||||
|
<option value="Lulus" <?php echo e(request('status') == 'Lulus' ? 'selected' : ''); ?>>Lulus</option>
|
||||||
|
<option value="Tidak Aktif" <?php echo e(request('status') == 'Tidak Aktif' ? 'selected' : ''); ?>>Tidak Aktif</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select name="id_kelas" class="form-control" style="width: 180px; height: 38px;">
|
||||||
|
<option value=""> Semua Kelas</option>
|
||||||
|
<?php $__currentLoopData = $kelompokKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelompok): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php if($kelompok->kelas && $kelompok->kelas->count() > 0): ?>
|
||||||
|
<optgroup label="<?php echo e($kelompok->nama_kelompok); ?>">
|
||||||
|
<?php $__currentLoopData = $kelompok->kelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<option value="<?php echo e($kelas->id); ?>" <?php echo e(request('id_kelas') == $kelas->id ? 'selected' : ''); ?>>
|
||||||
|
<?php echo e($kelas->nama_kelas); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</optgroup>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary btn-sm" style="height: 38px; padding: 0 16px;">
|
||||||
|
<i class="fas fa-search"></i> Cari
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<?php if(request('search') || request('status') || request('id_kelas')): ?>
|
||||||
|
<a href="<?php echo e(route('admin.santri.index')); ?>" class="btn btn-secondary btn-sm" style="height: 38px; padding: 0 16px; display: inline-flex; align-items: center;">
|
||||||
|
<i class="fas fa-redo"></i> Reset
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-wrapper">
|
||||||
|
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>No</th>
|
||||||
|
<th>Foto</th>
|
||||||
|
<th>ID Santri</th>
|
||||||
|
<th>NIS</th>
|
||||||
|
<th>Nama Lengkap</th>
|
||||||
|
<th>Jenis Kelamin</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php $__empty_1 = true; $__currentLoopData = $santris; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo e($santris->firstItem() + $index); ?></td>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
<?php if($santri->foto): ?>
|
||||||
|
<img src="<?php echo e(asset('storage/' . $santri->foto)); ?>"
|
||||||
|
alt="Foto <?php echo e($santri->nama_lengkap); ?>"
|
||||||
|
style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; border: 2px solid var(--primary-color);"
|
||||||
|
loading="lazy">
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="santri-avatar-initial" style="width: 40px; height: 40px; border-radius: 50%; background: var(--primary-color); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 0.9rem;">
|
||||||
|
<?php echo e(strtoupper(substr($santri->nama_lengkap, 0, 1))); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
|
||||||
|
<td><?php echo e($santri->nis ?? '-'); ?></td>
|
||||||
|
<td><?php echo e($santri->nama_lengkap); ?></td>
|
||||||
|
<td><?php echo e($santri->jenis_kelamin); ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if($santri->status == 'Aktif'): ?>
|
||||||
|
<span style="padding: 6px 12px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%); color: #2C5F4F; display: inline-block;">
|
||||||
|
<i class="fas fa-check-circle"></i> <?php echo e($santri->status); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<?php elseif($santri->status == 'Lulus'): ?>
|
||||||
|
<span style="padding: 6px 12px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; background: linear-gradient(135deg, #E3F2FD 0%, #D1E9F9 100%); color: #2D4A7C; display: inline-block;">
|
||||||
|
<i class="fas fa-graduation-cap"></i> <?php echo e($santri->status); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="padding: 6px 12px; border-radius: 6px; font-size: 0.85rem; font-weight: 600; background: linear-gradient(135deg, #E8ECF0 0%, #D1D8E0 100%); color: #555; display: inline-block;">
|
||||||
|
<i class="fas fa-times-circle"></i> <?php echo e($santri->status); ?>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="<?php echo e(route('admin.santri.show', $santri)); ?>" class="btn btn-sm btn-primary">
|
||||||
|
<i class="fas fa-eye"></i></a>
|
||||||
|
<a href="<?php echo e(route('admin.santri.edit', $santri)); ?>" class="btn btn-sm btn-warning">
|
||||||
|
<i class="fas fa-edit"></i></a>
|
||||||
|
<form action="<?php echo e(route('admin.santri.destroy', $santri)); ?>" method="POST" style="display:inline;">
|
||||||
|
<?php echo csrf_field(); ?>
|
||||||
|
<?php echo method_field('DELETE'); ?>
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Yakin ingin menghapus data santri <?php echo e($santri->nama_lengkap); ?>?')">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="8" class="text-center" style="padding: 22px;">
|
||||||
|
<i class="fas fa-inbox" style="font-size: 2.2rem; color: #ccc; margin-bottom: 15px; display: block;"></i>
|
||||||
|
<?php if(request('search') || request('status') || request('id_kelas')): ?>
|
||||||
|
<strong>Data tidak ditemukan.</strong><br>
|
||||||
|
<small>Coba ubah kata kunci pencarian atau filter yang digunakan.</small>
|
||||||
|
<?php else: ?>
|
||||||
|
<strong>Belum ada data santri.</strong><br>
|
||||||
|
<small>Klik tombol "Tambah Santri" untuk menambahkan data baru.</small>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if($santris->count() > 0): ?>
|
||||||
|
<div style="margin-top: 14px; padding-top: 20px; border-top: 1px solid #E8F7F2;">
|
||||||
|
<p style="color: #7F8C8D; font-size: 0.9rem;">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
Menampilkan <strong><?php echo e($santris->count()); ?></strong> dari <strong><?php echo e($santris->total()); ?></strong> data santri
|
||||||
|
<?php if(request('search') || request('status') || request('id_kelas')): ?>
|
||||||
|
(hasil pencarian/filter)
|
||||||
|
<?php endif; ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- Pagination -->
|
||||||
|
<?php if(method_exists($santris, 'links')): ?>
|
||||||
|
<div style="margin-top: 14px;">
|
||||||
|
<?php echo e($santris->links()); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', ['isAdmin' => true], \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/santri/index.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -0,0 +1,465 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-clipboard-check"></i> Input Absensi: <?php echo e($kegiatan->nama_kegiatan); ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom: 14px;">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 11px;">
|
||||||
|
<div>
|
||||||
|
<h3 style="margin: 0; color: var(--primary-color);"><?php echo e($kegiatan->nama_kegiatan); ?></h3>
|
||||||
|
<p style="margin: 5px 0 0 0; color: var(--text-light);">
|
||||||
|
<i class="fas fa-calendar-day"></i> <?php echo e($kegiatan->hari); ?> |
|
||||||
|
<i class="fas fa-clock"></i> <?php echo e(date('H:i', strtotime($kegiatan->waktu_mulai))); ?> - <?php echo e(date('H:i', strtotime($kegiatan->waktu_selesai))); ?> |
|
||||||
|
<i class="fas fa-list-alt"></i> <?php echo e($kegiatan->kategori->nama_kategori); ?>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; gap: 10px;">
|
||||||
|
<button type="button" id="btnModeManual" class="btn btn-primary" onclick="setMode('manual')">
|
||||||
|
<i class="fas fa-hand-pointer"></i> Mode Manual
|
||||||
|
</button>
|
||||||
|
<button type="button" id="btnModeRfid" class="btn btn-secondary" onclick="setMode('rfid')">
|
||||||
|
<i class="fas fa-id-card"></i> Mode RFID
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="info-box" style="margin-bottom: 14px; border-left: 4px solid var(--primary-color);">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
<?php if($kegiatanInfo['is_umum']): ?>
|
||||||
|
<strong>Kegiatan Umum</strong> - Diikuti oleh semua santri aktif (<?php echo e($santris->count()); ?> santri)
|
||||||
|
<?php else: ?>
|
||||||
|
<strong>Kegiatan Khusus</strong> - Untuk kelas:
|
||||||
|
<strong style="color: var(--primary-color);"><?php echo e($kegiatanInfo['kelas_list']); ?></strong>
|
||||||
|
(<?php echo e($kegiatanInfo['jumlah_kelas']); ?> kelas)
|
||||||
|
| Total semua santri aktif: <strong><?php echo e($santris->count()); ?> santri</strong>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$sudahAdaData = count($absensiData) > 0;
|
||||||
|
?>
|
||||||
|
<?php if($sudahAdaData): ?>
|
||||||
|
<div class="alert alert-info" style="margin-bottom: 14px;">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
<strong>Mode Edit</strong> - Data absensi untuk tanggal ini sudah ada
|
||||||
|
(<strong><?php echo e(count($absensiData)); ?></strong> dari <strong><?php echo e($santris->count()); ?></strong> santri sudah diinput,
|
||||||
|
<strong style="color: <?php echo e(($santris->count() - count($absensiData)) > 0 ? '#dc2626' : '#059669'); ?>;"><?php echo e($santris->count() - count($absensiData)); ?> belum absen</strong>).
|
||||||
|
Anda dapat mengubah status absensi lalu klik Simpan.
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<!-- MODE MANUAL -->
|
||||||
|
<div id="modeManual" class="content-box">
|
||||||
|
<form action="<?php echo e(route('admin.absensi-kegiatan.simpan')); ?>" method="POST">
|
||||||
|
<?php echo csrf_field(); ?>
|
||||||
|
<input type="hidden" name="kegiatan_id" value="<?php echo e($kegiatan->kegiatan_id); ?>">
|
||||||
|
|
||||||
|
<div class="filter-form-inline" style="margin-bottom: 14px; gap: 12px;">
|
||||||
|
<div class="filter-form-inline" style="gap: 8px;">
|
||||||
|
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
||||||
|
<i class="fas fa-calendar"></i> Tanggal:
|
||||||
|
</label>
|
||||||
|
<input type="date" name="tanggal" id="tanggal" class="form-control"
|
||||||
|
value="<?php echo e($tanggal); ?>" required style="max-width: 170px;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-form-inline" style="gap: 8px;">
|
||||||
|
<label style="font-weight: 600; white-space: nowrap; margin: 0;">
|
||||||
|
<i class="fas fa-school"></i> Pilih Kelas:
|
||||||
|
</label>
|
||||||
|
<select id="kelasFilter" class="form-control" onchange="filterKelas(this.value)" style="max-width: 220px;">
|
||||||
|
<option value="semua">-- Tampilkan Semua Kelas --</option>
|
||||||
|
<?php $__currentLoopData = $santriGrouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelasNama => $santriKelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<option value="<?php echo e($kelasNama); ?>"><?php echo e($kelasNama); ?> (<?php echo e($santriKelas->count()); ?> santri)</option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap;">
|
||||||
|
<button type="button" class="btn btn-sm btn-info" onclick="setAllStatus('Hadir')">
|
||||||
|
<i class="fas fa-check-double"></i> Semua Hadir
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm" style="background: #FF9800; color: white;" onclick="setAllStatus('Terlambat')">
|
||||||
|
<i class="fas fa-clock"></i> Semua Terlambat
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-danger" onclick="setAllStatus('Alpa')">
|
||||||
|
<i class="fas fa-times"></i> Semua Alpa
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary" onclick="clearAllStatus()">
|
||||||
|
<i class="fas fa-eraser"></i> Kosongkan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box" style="margin-bottom: 14px;">
|
||||||
|
<p style="margin: 0;"><i class="fas fa-info-circle"></i> Pilih kelas terlebih dahulu untuk menampilkan daftar santri. Santri tanpa pilihan status akan <strong>dilewati</strong>. Santri yang <strong>sedang pulang</strong> otomatis ditandai.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__currentLoopData = $santriGrouped; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $kelasNama => $santriKelas): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$hadirCount = 0;
|
||||||
|
$totalKelas = $santriKelas->count();
|
||||||
|
foreach ($santriKelas as $s) {
|
||||||
|
$st = $absensiData[$s->id_santri] ?? null;
|
||||||
|
if ($st === 'Hadir') $hadirCount++;
|
||||||
|
}
|
||||||
|
$sudahInputKelas = false;
|
||||||
|
foreach ($santriKelas as $s) {
|
||||||
|
if (isset($absensiData[$s->id_santri])) { $sudahInputKelas = true; break; }
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div class="kelas-group" data-kelas="<?php echo e($kelasNama); ?>" style="margin-bottom: 20px; display: none;">
|
||||||
|
<div style="background: var(--primary-light); padding: 10px 14px; border-radius: 8px 8px 0 0; display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<h4 style="margin: 0; color: var(--primary-color); font-size: 0.95rem;">
|
||||||
|
<i class="fas fa-users"></i> <?php echo e($kelasNama); ?>
|
||||||
|
|
||||||
|
</h4>
|
||||||
|
<div style="display: flex; gap: 8px; align-items: center;">
|
||||||
|
<?php if($sudahInputKelas): ?>
|
||||||
|
<span class="badge badge-info"><i class="fas fa-edit"></i> <?php echo e($hadirCount); ?>/<?php echo e($totalKelas); ?> hadir</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<span class="badge badge-primary"><?php echo e($totalKelas); ?> santri</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<table class="data-table" style="margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 50px;">No</th>
|
||||||
|
<th style="width: 100px;">ID Santri</th>
|
||||||
|
<th>Nama Santri</th>
|
||||||
|
<th style="width: 420px; text-align: center;">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php $__currentLoopData = $santriKelas; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<?php
|
||||||
|
$isPulang = in_array($santri->id_santri, $santriSedangPulang ?? []);
|
||||||
|
$currentStatus = $absensiData[$santri->id_santri] ?? ($isPulang ? 'Pulang' : '');
|
||||||
|
?>
|
||||||
|
<tr <?php if($isPulang): ?> style="background: #FFF8E1; opacity: 0.85;" <?php endif; ?>>
|
||||||
|
<td><?php echo e($loop->iteration); ?></td>
|
||||||
|
<td><strong><?php echo e($santri->id_santri); ?></strong></td>
|
||||||
|
<td>
|
||||||
|
<?php echo e($santri->nama_lengkap); ?>
|
||||||
|
|
||||||
|
<?php if($isPulang): ?>
|
||||||
|
<span class="badge" style="background: #FFF3E0; color: #E65100; font-size: 0.75rem; margin-left: 6px;">
|
||||||
|
<i class="fas fa-home"></i> Sedang Pulang
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if(isset($absensiData[$santri->id_santri])): ?>
|
||||||
|
<span class="badge badge-secondary" style="font-size: 0.7rem; margin-left: 4px;">
|
||||||
|
<i class="fas fa-edit"></i> Sudah input
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<?php if($isPulang): ?>
|
||||||
|
<input type="hidden" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Pulang" class="absensi-input">
|
||||||
|
<span class="badge" style="background: #FFF3E0; color: #E65100; padding: 6px 14px; font-size: 0.85rem;">
|
||||||
|
<i class="fas fa-home"></i> Pulang
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<div style="display: flex; gap: 5px; justify-content: center; flex-wrap: wrap;">
|
||||||
|
<label style="margin: 0; cursor: pointer;">
|
||||||
|
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Hadir"
|
||||||
|
<?php echo e($currentStatus == 'Hadir' ? 'checked' : ''); ?> class="absensi-radio absensi-input">
|
||||||
|
<span class="badge badge-success">Hadir</span>
|
||||||
|
</label>
|
||||||
|
<label style="margin: 0; cursor: pointer;">
|
||||||
|
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Terlambat"
|
||||||
|
<?php echo e($currentStatus == 'Terlambat' ? 'checked' : ''); ?> class="absensi-radio absensi-input">
|
||||||
|
<span class="badge" style="background: #FF9800; color: white;">Terlambat</span>
|
||||||
|
</label>
|
||||||
|
<label style="margin: 0; cursor: pointer;">
|
||||||
|
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Izin"
|
||||||
|
<?php echo e($currentStatus == 'Izin' ? 'checked' : ''); ?> class="absensi-radio absensi-input">
|
||||||
|
<span class="badge badge-warning">Izin</span>
|
||||||
|
</label>
|
||||||
|
<label style="margin: 0; cursor: pointer;">
|
||||||
|
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Sakit"
|
||||||
|
<?php echo e($currentStatus == 'Sakit' ? 'checked' : ''); ?> class="absensi-radio absensi-input">
|
||||||
|
<span class="badge badge-info">Sakit</span>
|
||||||
|
</label>
|
||||||
|
<label style="margin: 0; cursor: pointer;">
|
||||||
|
<input type="radio" name="absensi[<?php echo e($santri->id_santri); ?>]" value="Alpa"
|
||||||
|
<?php echo e($currentStatus == 'Alpa' ? 'checked' : ''); ?> class="absensi-radio absensi-input">
|
||||||
|
<span class="badge badge-danger">Alpa</span>
|
||||||
|
</label>
|
||||||
|
<?php if($currentStatus): ?>
|
||||||
|
<label style="margin: 0; cursor: pointer;" title="Hapus pilihan">
|
||||||
|
<button type="button" class="btn btn-sm" style="padding: 2px 8px; font-size: 0.75rem; background: #f1f1f1;" onclick="clearRadio('<?php echo e($santri->id_santri); ?>')">
|
||||||
|
<i class="fas fa-undo"></i>
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
|
||||||
|
<div id="noKelasSelected" class="empty-state" style="padding: 40px 20px;">
|
||||||
|
<i class="fas fa-hand-pointer"></i>
|
||||||
|
<h3>Pilih Kelas Terlebih Dahulu</h3>
|
||||||
|
<p>Silakan pilih kelas pada dropdown di atas untuk menampilkan daftar santri yang akan diabsen.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group" style="margin-top: 14px;">
|
||||||
|
<button type="submit" class="btn btn-success">
|
||||||
|
<i class="fas fa-save"></i> <?php echo e($sudahAdaData ? 'Update Absensi' : 'Simpan Absensi'); ?>
|
||||||
|
|
||||||
|
</button>
|
||||||
|
<a href="<?php echo e(route('admin.kegiatan.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- MODE RFID -->
|
||||||
|
<div id="modeRfid" class="content-box" style="display: none;">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="tanggalRfid">
|
||||||
|
<i class="fas fa-calendar form-icon"></i>
|
||||||
|
Tanggal Absensi
|
||||||
|
</label>
|
||||||
|
<input type="date" id="tanggalRfid" class="form-control" value="<?php echo e($tanggal); ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-box">
|
||||||
|
<p><i class="fas fa-id-card"></i> Tempelkan kartu RFID santri ke reader. Absensi akan otomatis tersimpan sebagai <strong>Hadir</strong>.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background: linear-gradient(135deg, var(--primary-light) 0%, #D4F1E3 100%); padding: 22px; border-radius: var(--border-radius); text-align: center; margin-bottom: 14px;">
|
||||||
|
<div id="rfidStatus" style="font-size: 1.5rem; font-weight: 600; color: var(--primary-color); margin-bottom: 15px;">
|
||||||
|
<i class="fas fa-wifi"></i> Siap Scan RFID
|
||||||
|
</div>
|
||||||
|
<input type="text" id="rfidInput" placeholder="Fokus di sini untuk scan RFID..."
|
||||||
|
style="width: 100%; padding: 15px; font-size: 1.2rem; border: 3px solid var(--primary-color); border-radius: var(--border-radius-sm); text-align: center;"
|
||||||
|
autofocus>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="rfidLog" style="max-height: 400px; overflow-y: auto; background: white; border-radius: var(--border-radius-sm); padding: 15px; border: 1px solid var(--primary-light);">
|
||||||
|
<h4 style="margin: 0 0 15px 0; color: var(--primary-color);"><i class="fas fa-history"></i> Log Absensi</h4>
|
||||||
|
<div id="rfidLogContent">
|
||||||
|
<p style="text-align: center; color: var(--text-light);">Belum ada absensi...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group" style="margin-top: 14px;">
|
||||||
|
<button type="button" class="btn btn-warning" onclick="clearLog()">
|
||||||
|
<i class="fas fa-trash"></i> Bersihkan Log
|
||||||
|
</button>
|
||||||
|
<a href="<?php echo e(route('admin.kegiatan.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// -- Kelas Filter --
|
||||||
|
function filterKelas(value) {
|
||||||
|
var groups = document.querySelectorAll('.kelas-group');
|
||||||
|
var emptyMsg = document.getElementById('noKelasSelected');
|
||||||
|
|
||||||
|
if (value === 'semua') {
|
||||||
|
for (var i = 0; i < groups.length; i++) {
|
||||||
|
groups[i].style.display = 'block';
|
||||||
|
toggleGroupInputs(groups[i], true);
|
||||||
|
}
|
||||||
|
emptyMsg.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
var found = false;
|
||||||
|
for (var i = 0; i < groups.length; i++) {
|
||||||
|
if (groups[i].getAttribute('data-kelas') === value) {
|
||||||
|
groups[i].style.display = 'block';
|
||||||
|
toggleGroupInputs(groups[i], true);
|
||||||
|
found = true;
|
||||||
|
} else {
|
||||||
|
groups[i].style.display = 'none';
|
||||||
|
toggleGroupInputs(groups[i], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emptyMsg.style.display = found ? 'none' : 'block';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable/disable all inputs in a kelas group so hidden groups don't submit
|
||||||
|
function toggleGroupInputs(group, enabled) {
|
||||||
|
var inputs = group.querySelectorAll('.absensi-input');
|
||||||
|
for (var i = 0; i < inputs.length; i++) {
|
||||||
|
inputs[i].disabled = !enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Set All Status (for visible groups only) --
|
||||||
|
function setAllStatus(status) {
|
||||||
|
var groups = document.querySelectorAll('.kelas-group');
|
||||||
|
for (var i = 0; i < groups.length; i++) {
|
||||||
|
if (groups[i].style.display !== 'none') {
|
||||||
|
var radios = groups[i].querySelectorAll('input.absensi-radio[value="' + status + '"]');
|
||||||
|
for (var j = 0; j < radios.length; j++) {
|
||||||
|
radios[j].checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Clear radio selection for a specific santri --
|
||||||
|
function clearRadio(santriId) {
|
||||||
|
var radios = document.querySelectorAll('input[name="absensi[' + santriId + ']"]');
|
||||||
|
for (var i = 0; i < radios.length; i++) {
|
||||||
|
radios[i].checked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Clear all selections in visible groups --
|
||||||
|
function clearAllStatus() {
|
||||||
|
var groups = document.querySelectorAll('.kelas-group');
|
||||||
|
for (var i = 0; i < groups.length; i++) {
|
||||||
|
if (groups[i].style.display !== 'none') {
|
||||||
|
var radios = groups[i].querySelectorAll('input.absensi-radio');
|
||||||
|
for (var j = 0; j < radios.length; j++) {
|
||||||
|
radios[j].checked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Mode Switch --
|
||||||
|
var currentMode = 'manual';
|
||||||
|
var kegiatanId = '<?php echo e($kegiatan->kegiatan_id); ?>';
|
||||||
|
|
||||||
|
function setMode(mode) {
|
||||||
|
currentMode = mode;
|
||||||
|
var modeManualEl = document.getElementById('modeManual');
|
||||||
|
var modeRfidEl = document.getElementById('modeRfid');
|
||||||
|
var btnManual = document.getElementById('btnModeManual');
|
||||||
|
var btnRfid = document.getElementById('btnModeRfid');
|
||||||
|
|
||||||
|
if (mode === 'manual') {
|
||||||
|
modeManualEl.style.display = 'block';
|
||||||
|
modeRfidEl.style.display = 'none';
|
||||||
|
btnManual.className = 'btn btn-primary';
|
||||||
|
btnRfid.className = 'btn btn-secondary';
|
||||||
|
} else {
|
||||||
|
modeManualEl.style.display = 'none';
|
||||||
|
modeRfidEl.style.display = 'block';
|
||||||
|
btnManual.className = 'btn btn-secondary';
|
||||||
|
btnRfid.className = 'btn btn-success';
|
||||||
|
document.getElementById('rfidInput').focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- RFID Scanner --
|
||||||
|
document.getElementById('rfidInput').addEventListener('keypress', function(e) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
var rfidUid = this.value.trim();
|
||||||
|
if (rfidUid) {
|
||||||
|
scanRfid(rfidUid);
|
||||||
|
this.value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function scanRfid(rfidUid) {
|
||||||
|
var tanggal = document.getElementById('tanggalRfid').value;
|
||||||
|
var statusEl = document.getElementById('rfidStatus');
|
||||||
|
|
||||||
|
statusEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Memproses...';
|
||||||
|
statusEl.style.color = 'var(--warning-color)';
|
||||||
|
|
||||||
|
fetch('<?php echo e(route("admin.absensi-kegiatan.scan-rfid")); ?>', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-TOKEN': '<?php echo e(csrf_token()); ?>'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
rfid_uid: rfidUid,
|
||||||
|
kegiatan_id: kegiatanId,
|
||||||
|
tanggal: tanggal
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function(response) { return response.json(); })
|
||||||
|
.then(function(data) {
|
||||||
|
if (data.success) {
|
||||||
|
statusEl.innerHTML = '<i class="fas fa-check-circle"></i> ' + data.message;
|
||||||
|
statusEl.style.color = 'var(--success-color)';
|
||||||
|
addLogEntry(data.data, 'success');
|
||||||
|
} else {
|
||||||
|
statusEl.innerHTML = '<i class="fas fa-exclamation-circle"></i> ' + data.message;
|
||||||
|
statusEl.style.color = 'var(--danger-color)';
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
statusEl.innerHTML = '<i class="fas fa-wifi"></i> Siap Scan RFID';
|
||||||
|
statusEl.style.color = 'var(--primary-color)';
|
||||||
|
}, 2000);
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
statusEl.innerHTML = '<i class="fas fa-times-circle"></i> Koneksi error';
|
||||||
|
statusEl.style.color = 'var(--danger-color)';
|
||||||
|
console.error('Error:', error);
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
statusEl.innerHTML = '<i class="fas fa-wifi"></i> Siap Scan RFID';
|
||||||
|
statusEl.style.color = 'var(--primary-color)';
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addLogEntry(data, type) {
|
||||||
|
var logContent = document.getElementById('rfidLogContent');
|
||||||
|
|
||||||
|
if (logContent.querySelector('p')) {
|
||||||
|
logContent.innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = document.createElement('div');
|
||||||
|
entry.style.cssText = 'padding: 12px; margin-bottom: 10px; border-radius: 8px; background: ' +
|
||||||
|
(type === 'success' ? 'linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%)' : 'linear-gradient(135deg, #FFE8EA 0%, #FFD5D8 100%)') +
|
||||||
|
'; border-left: 4px solid ' + (type === 'success' ? 'var(--success-color)' : 'var(--danger-color)');
|
||||||
|
|
||||||
|
entry.innerHTML = '<div style="display: flex; justify-content: space-between; align-items: center;">' +
|
||||||
|
'<div><strong>' + data.nama + '</strong> (' + data.id_santri + ')' +
|
||||||
|
'<div style="font-size: 0.85rem; color: var(--text-light); margin-top: 3px;">Kelas: ' + data.kelas + ' | Waktu: ' + data.waktu + '</div></div>' +
|
||||||
|
'<span class="badge badge-success"><i class="fas fa-check"></i> Hadir</span></div>';
|
||||||
|
|
||||||
|
logContent.insertBefore(entry, logContent.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLog() {
|
||||||
|
if (confirm('Yakin ingin membersihkan log?')) {
|
||||||
|
document.getElementById('rfidLogContent').innerHTML = '<p style="text-align: center; color: var(--text-light);">Belum ada absensi...</p>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Auto-focus RFID input --
|
||||||
|
setInterval(function() {
|
||||||
|
if (currentMode === 'rfid') {
|
||||||
|
var rfidInput = document.getElementById('rfidInput');
|
||||||
|
if (document.activeElement !== rfidInput) {
|
||||||
|
rfidInput.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/absensi/input.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,373 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Register Admin'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('auth-content'); ?>
|
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:opsz,wght@9..40,300;400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body.auth-page {
|
|
||||||
background: #F8FDFB !important;
|
|
||||||
font-family: 'DM Sans', sans-serif !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
align-items: stretch !important;
|
|
||||||
min-height: 100vh !important;
|
|
||||||
}
|
|
||||||
.auth-container {
|
|
||||||
width: 100vw !important; max-width: 100vw !important;
|
|
||||||
min-height: 100vh !important; background: transparent !important;
|
|
||||||
padding: 0 !important; border-radius: 0 !important; box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rv2-wrap {
|
|
||||||
position: relative; width: 100%; min-height: 100vh;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
overflow: hidden; font-family: 'DM Sans', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rv2-bg {
|
|
||||||
position: absolute; inset: 0; z-index: 0;
|
|
||||||
background:
|
|
||||||
radial-gradient(ellipse 80% 60% at 30% 50%, rgba(111,186,157,.12) 0%, transparent 60%),
|
|
||||||
radial-gradient(ellipse 50% 80% at 90% 20%, rgba(111,186,157,.08) 0%, transparent 55%),
|
|
||||||
#F8FDFB;
|
|
||||||
}
|
|
||||||
.rv2-bg::before {
|
|
||||||
content: ''; position: absolute; inset: 0;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(rgba(111,186,157,.055) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(111,186,157,.055) 1px, transparent 1px);
|
|
||||||
background-size: 48px 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rv2-ring {
|
|
||||||
position: absolute; border-radius: 50%;
|
|
||||||
border: 1.5px solid rgba(111,186,157,.18); pointer-events: none;
|
|
||||||
}
|
|
||||||
.rv2-ring.r1 { width:420px; height:420px; top:-110px; left:-110px; }
|
|
||||||
.rv2-ring.r2 { width:270px; height:270px; top:50px; left:60px; border-color:rgba(111,186,157,.10); }
|
|
||||||
.rv2-ring.r3 { width:200px; height:200px; bottom:-50px; right:60px; border-color:rgba(111,186,157,.14); }
|
|
||||||
.rv2-dot { position:absolute; border-radius:50%; background:#6FBA9D; pointer-events:none; }
|
|
||||||
.rv2-dot.d1 { width:8px; height:8px; top:22%; left:18%; opacity:.14; }
|
|
||||||
.rv2-dot.d2 { width:5px; height:5px; bottom:40%; left:30%; opacity:.09; }
|
|
||||||
.rv2-dot.d3 { width:11px; height:11px; top:55%; right:15%; opacity:.08; }
|
|
||||||
.rv2-line { position:absolute; height:1px; background:linear-gradient(90deg,transparent,rgba(111,186,157,.14),transparent); pointer-events:none; }
|
|
||||||
.rv2-line.l1 { width:280px; top:28%; right:-60px; transform:rotate(15deg); }
|
|
||||||
.rv2-line.l2 { width:220px; bottom:30%; left:-40px; transform:rotate(-18deg); }
|
|
||||||
|
|
||||||
.rv2-layout {
|
|
||||||
position: relative; z-index: 2;
|
|
||||||
display: flex; align-items: center;
|
|
||||||
width: 100%; max-width: 1100px;
|
|
||||||
padding: 40px 60px; gap: 80px;
|
|
||||||
animation: rv2In .6s ease both;
|
|
||||||
}
|
|
||||||
@keyframes rv2In {
|
|
||||||
from { opacity:0; transform:translateY(20px); }
|
|
||||||
to { opacity:1; transform:translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Form kiri dulu di register */
|
|
||||||
.rv2-form-panel { flex: 1; max-width: 430px; order: 1; }
|
|
||||||
.rv2-brand { flex: 0 0 320px; order: 2; }
|
|
||||||
|
|
||||||
/* CARD */
|
|
||||||
.rv2-card {
|
|
||||||
background: #fff; border-radius: 24px;
|
|
||||||
padding: 42px 38px;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(111,186,157,.1),
|
|
||||||
0 4px 6px rgba(15,33,24,.03),
|
|
||||||
0 20px 44px rgba(15,33,24,.08);
|
|
||||||
position: relative; overflow: hidden;
|
|
||||||
}
|
|
||||||
.rv2-card::before {
|
|
||||||
content: ''; position:absolute; top:0; left:0; right:0; height:3px;
|
|
||||||
background: linear-gradient(90deg, #6FBA9D, #A8D8C6, #6FBA9D);
|
|
||||||
}
|
|
||||||
.rv2-card::after {
|
|
||||||
content: ''; position:absolute; bottom:-50px; left:-50px;
|
|
||||||
width:140px; height:140px; border-radius:50%;
|
|
||||||
background: radial-gradient(circle, rgba(111,186,157,.06) 0%, transparent 70%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rv2-card-lbl {
|
|
||||||
font-size:.67rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.rv2-card-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:1.85rem; color:#0F2118; line-height:1.1; margin-bottom:5px;
|
|
||||||
}
|
|
||||||
.rv2-card-desc { font-size:.79rem; color:#8AADA0; line-height:1.6; margin-bottom:26px; }
|
|
||||||
|
|
||||||
/* Alert */
|
|
||||||
.rv2-alert {
|
|
||||||
border-radius:10px; padding:10px 13px; font-size:.79rem;
|
|
||||||
margin-bottom:18px; background:#FFF3F3; color:#c62828; border-left:3px solid #e53935;
|
|
||||||
}
|
|
||||||
.rv2-alert p { display:flex; align-items:center; gap:7px; margin:2px 0; }
|
|
||||||
|
|
||||||
/* Fields */
|
|
||||||
.rv2-field { margin-bottom:15px; }
|
|
||||||
.rv2-lbl {
|
|
||||||
display:block; font-size:.7rem; font-weight:700;
|
|
||||||
letter-spacing:.8px; text-transform:uppercase; color:#2A4235; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.rv2-shell { position:relative; display:flex; align-items:center; }
|
|
||||||
.rv2-shell .fi { position:absolute; left:15px; color:#A8D8C6; font-size:.8rem; pointer-events:none; transition:color .2s; }
|
|
||||||
.rv2-shell input {
|
|
||||||
width:100%; padding:12px 15px 12px 40px;
|
|
||||||
background:#EBF7F2; border:1.5px solid transparent;
|
|
||||||
border-radius:11px; font-family:inherit; font-size:.87rem; color:#0F2118; outline:none;
|
|
||||||
transition:all .2s;
|
|
||||||
}
|
|
||||||
.rv2-shell input::placeholder { color:#8AADA0; font-size:.83rem; }
|
|
||||||
.rv2-shell input:focus {
|
|
||||||
background:#fff; border-color:#6FBA9D;
|
|
||||||
box-shadow:0 0 0 4px rgba(111,186,157,.12);
|
|
||||||
}
|
|
||||||
.rv2-show {
|
|
||||||
position:absolute; right:13px;
|
|
||||||
background:none; border:none; font-size:.68rem; font-weight:800;
|
|
||||||
letter-spacing:.8px; color:#5EA98C; cursor:pointer; font-family:inherit;
|
|
||||||
}
|
|
||||||
.rv2-show:hover { color:#3D8A6E; }
|
|
||||||
.rv2-ferr { font-size:.72rem; color:#e53935; margin-top:4px; padding-left:3px; }
|
|
||||||
|
|
||||||
/* Strength */
|
|
||||||
.rv2-strength { display:flex; gap:4px; margin-top:7px; }
|
|
||||||
.rv2-bar { height:3px; flex:1; border-radius:3px; background:#D6EDE5; transition:background .3s; }
|
|
||||||
.rv2-bar.w { background:#e53935; }
|
|
||||||
.rv2-bar.m { background:#FB8C00; }
|
|
||||||
.rv2-bar.s { background:#6FBA9D; }
|
|
||||||
|
|
||||||
/* Buttons */
|
|
||||||
.rv2-btn {
|
|
||||||
width:100%; padding:13px;
|
|
||||||
background:linear-gradient(135deg, #6FBA9D, #5EA98C);
|
|
||||||
color:#fff; border:none; border-radius:12px;
|
|
||||||
font-family:inherit; font-size:.89rem; font-weight:700;
|
|
||||||
cursor:pointer; letter-spacing:.3px; margin-top:6px;
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:8px;
|
|
||||||
box-shadow:0 4px 18px rgba(94,169,140,.35);
|
|
||||||
transition:all .25s;
|
|
||||||
}
|
|
||||||
.rv2-btn:hover { transform:translateY(-2px); box-shadow:0 8px 26px rgba(94,169,140,.45); }
|
|
||||||
.rv2-btn:active { transform:none; }
|
|
||||||
|
|
||||||
.rv2-foot { text-align:center; font-size:.77rem; color:#8AADA0; margin-top:20px; }
|
|
||||||
.rv2-foot a { color:#5EA98C; font-weight:700; text-decoration:none; }
|
|
||||||
.rv2-foot a:hover { text-decoration:underline; }
|
|
||||||
|
|
||||||
/* Brand */
|
|
||||||
.rv2-logo { width:72px; height:72px; margin-bottom:20px; border-radius:16px; box-shadow:0 4px 20px rgba(111,186,157,.2); object-fit:contain; background:#fff; }
|
|
||||||
.rv2-eyebrow {
|
|
||||||
display:inline-flex; align-items:center; gap:8px;
|
|
||||||
font-size:.68rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:18px;
|
|
||||||
}
|
|
||||||
.rv2-eyebrow::before {
|
|
||||||
content:''; display:inline-block; width:22px; height:2px;
|
|
||||||
background:#6FBA9D; border-radius:2px;
|
|
||||||
}
|
|
||||||
.rv2-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:3.2rem; line-height:1.05; color:#0F2118; margin-bottom:6px;
|
|
||||||
}
|
|
||||||
.rv2-title em { font-style:italic; color:#5EA98C; }
|
|
||||||
.rv2-sub { font-size:.9rem; font-weight:500; color:#8AADA0; margin-bottom:32px; line-height:1.6; }
|
|
||||||
.rv2-divider { width:44px; height:3px; background:linear-gradient(90deg,#6FBA9D,#A8D8C6); border-radius:3px; margin-bottom:24px; }
|
|
||||||
.rv2-desc { font-size:.81rem; color:#8AADA0; line-height:1.8; max-width:270px; margin-bottom:32px; }
|
|
||||||
.rv2-features { display:flex; flex-direction:column; gap:11px; }
|
|
||||||
.rv2-feat { display:flex; align-items:center; gap:11px; font-size:.79rem; color:#2A4235; font-weight:500; }
|
|
||||||
.rv2-feat-ico {
|
|
||||||
width:30px; height:30px; border-radius:8px; background:#EBF7F2;
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
color:#3D8A6E; font-size:.73rem; flex-shrink:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.rv2-layout { gap:48px; padding:32px 36px; }
|
|
||||||
.rv2-brand { flex:0 0 260px; }
|
|
||||||
.rv2-title { font-size:2.7rem; }
|
|
||||||
}
|
|
||||||
@media (max-width: 720px) {
|
|
||||||
body.auth-page { align-items:flex-start !important; overflow-y:auto !important; }
|
|
||||||
.rv2-wrap { align-items:flex-start; min-height:auto; padding:24px 0 40px; }
|
|
||||||
.rv2-layout { flex-direction:column; padding:0 20px; gap:28px; }
|
|
||||||
.rv2-form-panel { order:2; max-width:100%; }
|
|
||||||
.rv2-brand { order:1; flex:none; }
|
|
||||||
.rv2-title { font-size:2.2rem; }
|
|
||||||
.rv2-logo { width:56px; height:56px; margin:0 auto 14px; display:block; }
|
|
||||||
.rv2-features, .rv2-desc, .rv2-divider { display:none; }
|
|
||||||
.rv2-sub { margin-bottom:0; }
|
|
||||||
.rv2-card { padding:28px 20px; }
|
|
||||||
.rv2-ring.r1 { width:260px; height:260px; top:-70px; left:-70px; }
|
|
||||||
.rv2-ring.r2 { display:none; }
|
|
||||||
}
|
|
||||||
@media (max-width: 420px) {
|
|
||||||
.rv2-title { font-size:1.85rem; }
|
|
||||||
.rv2-card { padding:24px 16px; border-radius:16px; }
|
|
||||||
.rv2-card-title { font-size:1.5rem; }
|
|
||||||
}
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.rv2-layout { max-width:1160px; padding:40px 80px; }
|
|
||||||
.rv2-brand { flex:0 0 360px; }
|
|
||||||
.rv2-title { font-size:3.6rem; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="rv2-wrap">
|
|
||||||
<div class="rv2-bg"></div>
|
|
||||||
<div class="rv2-ring r1"></div>
|
|
||||||
<div class="rv2-ring r2"></div>
|
|
||||||
<div class="rv2-ring r3"></div>
|
|
||||||
<div class="rv2-dot d1"></div>
|
|
||||||
<div class="rv2-dot d2"></div>
|
|
||||||
<div class="rv2-dot d3"></div>
|
|
||||||
<div class="rv2-line l1"></div>
|
|
||||||
<div class="rv2-line l2"></div>
|
|
||||||
|
|
||||||
<div class="rv2-layout">
|
|
||||||
|
|
||||||
<!-- Form (kiri) -->
|
|
||||||
<div class="rv2-form-panel">
|
|
||||||
<div class="rv2-card">
|
|
||||||
<div class="rv2-card-lbl">Pendaftaran Admin</div>
|
|
||||||
<div class="rv2-card-title">Buat Akun Baru</div>
|
|
||||||
<div class="rv2-card-desc">Isi data berikut untuk mendaftarkan akun admin Anda.</div>
|
|
||||||
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="rv2-alert">
|
|
||||||
<?php $__currentLoopData = $errors->all(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $error): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<p><i class="fas fa-circle-exclamation"></i> <?php echo e($error); ?></p>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form method="POST" action="<?php echo e(route('admin.register')); ?>">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="rv2-field">
|
|
||||||
<label class="rv2-lbl">Email Admin</label>
|
|
||||||
<div class="rv2-shell">
|
|
||||||
<i class="fas fa-envelope fi" id="ico-e"></i>
|
|
||||||
<input type="email" id="email" name="email"
|
|
||||||
value="<?php echo e(old('email')); ?>"
|
|
||||||
placeholder="nama@institusi.com"
|
|
||||||
autocomplete="email" required autofocus
|
|
||||||
onfocus="document.getElementById('ico-e').style.color='#6FBA9D'"
|
|
||||||
onblur="document.getElementById('ico-e').style.color=''">
|
|
||||||
</div>
|
|
||||||
<?php $__errorArgs = ['email'];
|
|
||||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
|
||||||
if ($__bag->has($__errorArgs[0])) :
|
|
||||||
if (isset($message)) { $__messageOriginal = $message; }
|
|
||||||
$message = $__bag->first($__errorArgs[0]); ?><div class="rv2-ferr"><?php echo e($message); ?></div><?php unset($message);
|
|
||||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
|
||||||
endif;
|
|
||||||
unset($__errorArgs, $__bag); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="rv2-field">
|
|
||||||
<label class="rv2-lbl">Password</label>
|
|
||||||
<div class="rv2-shell">
|
|
||||||
<i class="fas fa-lock fi" id="ico-pw"></i>
|
|
||||||
<input type="password" id="password" name="password"
|
|
||||||
placeholder="Buat password yang kuat"
|
|
||||||
oninput="rv2Str(this.value)" required
|
|
||||||
onfocus="document.getElementById('ico-pw').style.color='#6FBA9D'"
|
|
||||||
onblur="document.getElementById('ico-pw').style.color=''">
|
|
||||||
<button type="button" class="rv2-show" id="rv2TglBtn">SHOW</button>
|
|
||||||
</div>
|
|
||||||
<div class="rv2-strength">
|
|
||||||
<div class="rv2-bar" id="rv2b1"></div>
|
|
||||||
<div class="rv2-bar" id="rv2b2"></div>
|
|
||||||
<div class="rv2-bar" id="rv2b3"></div>
|
|
||||||
<div class="rv2-bar" id="rv2b4"></div>
|
|
||||||
</div>
|
|
||||||
<?php $__errorArgs = ['password'];
|
|
||||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
|
||||||
if ($__bag->has($__errorArgs[0])) :
|
|
||||||
if (isset($message)) { $__messageOriginal = $message; }
|
|
||||||
$message = $__bag->first($__errorArgs[0]); ?><div class="rv2-ferr"><?php echo e($message); ?></div><?php unset($message);
|
|
||||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
|
||||||
endif;
|
|
||||||
unset($__errorArgs, $__bag); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="rv2-field" style="margin-bottom:22px;">
|
|
||||||
<label class="rv2-lbl">Konfirmasi Password</label>
|
|
||||||
<div class="rv2-shell">
|
|
||||||
<i class="fas fa-lock-open fi" id="ico-c"></i>
|
|
||||||
<input type="password" id="password_confirmation"
|
|
||||||
name="password_confirmation"
|
|
||||||
placeholder="Ulangi password Anda" required
|
|
||||||
onfocus="document.getElementById('ico-c').style.color='#6FBA9D'"
|
|
||||||
onblur="document.getElementById('ico-c').style.color=''">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="rv2-btn">
|
|
||||||
<i class="fas fa-user-plus"></i>
|
|
||||||
Daftarkan Akun Admin
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="rv2-foot">
|
|
||||||
Sudah punya akun? <a href="<?php echo e(route('admin.login')); ?>">Login di sini</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Brand (kanan) -->
|
|
||||||
<div class="rv2-brand">
|
|
||||||
<img src="<?php echo e(asset('images/logo.png')); ?>" alt="Logo PKPPS" class="rv2-logo">
|
|
||||||
<div class="rv2-eyebrow">Bergabung Sekarang</div>
|
|
||||||
<h1 class="rv2-title">Bergabung<br>Bersama<br><em>Kami.</em></h1>
|
|
||||||
<p class="rv2-sub">PKPPS Riyadlul Jannah</p>
|
|
||||||
<div class="rv2-divider"></div>
|
|
||||||
<p class="rv2-desc">Daftarkan akun admin baru dengan aman. Gunakan email dan password kuat untuk menjaga keamanan sistem pesantren.</p>
|
|
||||||
<div class="rv2-features">
|
|
||||||
<div class="rv2-feat">
|
|
||||||
<div class="rv2-feat-ico"><i class="fas fa-envelope"></i></div>
|
|
||||||
<span>Gunakan email institusi yang valid</span>
|
|
||||||
</div>
|
|
||||||
<div class="rv2-feat">
|
|
||||||
<div class="rv2-feat-ico"><i class="fas fa-key"></i></div>
|
|
||||||
<span>Password minimal 8 karakter campuran</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const btn = document.getElementById('rv2TglBtn');
|
|
||||||
const pw = document.getElementById('password');
|
|
||||||
if (btn && pw) {
|
|
||||||
btn.addEventListener('click', () => {
|
|
||||||
const isP = pw.type === 'password';
|
|
||||||
pw.type = isP ? 'text' : 'password';
|
|
||||||
btn.textContent = isP ? 'HIDE' : 'SHOW';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function rv2Str(v) {
|
|
||||||
const bars = ['rv2b1','rv2b2','rv2b3','rv2b4'].map(id => document.getElementById(id));
|
|
||||||
bars.forEach(b => b.className = 'rv2-bar');
|
|
||||||
let s = 0;
|
|
||||||
if (v.length >= 6) s++;
|
|
||||||
if (v.length >= 10) s++;
|
|
||||||
if (/[A-Z]/.test(v) && /[0-9]/.test(v)) s++;
|
|
||||||
if (/[^A-Za-z0-9]/.test(v)) s++;
|
|
||||||
const cls = s <= 1 ? 'w' : s <= 2 ? 'm' : 's';
|
|
||||||
for (let i = 0; i < s; i++) bars[i].classList.add(cls);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('auth.auth_layout', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/auth/register.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<?php if($paginator->hasPages()): ?>
|
|
||||||
<nav>
|
|
||||||
<ul class="pagination">
|
|
||||||
|
|
||||||
<?php if($paginator->onFirstPage()): ?>
|
|
||||||
<li class="page-item disabled" aria-disabled="true">
|
|
||||||
<span class="page-link"><?php echo app('translator')->get('pagination.previous'); ?></span>
|
|
||||||
</li>
|
|
||||||
<?php else: ?>
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="<?php echo e($paginator->previousPageUrl()); ?>" rel="prev"><?php echo app('translator')->get('pagination.previous'); ?></a>
|
|
||||||
</li>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
<?php if($paginator->hasMorePages()): ?>
|
|
||||||
<li class="page-item">
|
|
||||||
<a class="page-link" href="<?php echo e($paginator->nextPageUrl()); ?>" rel="next"><?php echo app('translator')->get('pagination.next'); ?></a>
|
|
||||||
</li>
|
|
||||||
<?php else: ?>
|
|
||||||
<li class="page-item disabled" aria-disabled="true">
|
|
||||||
<span class="page-link"><?php echo app('translator')->get('pagination.next'); ?></span>
|
|
||||||
</li>
|
|
||||||
<?php endif; ?>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/vendor/pagination/simple-bootstrap-4.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,680 @@
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
OVERRIDE SELECT2 agar sesuai tema
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.select2-container--default .select2-selection--single {
|
||||||
|
height: 44px;
|
||||||
|
border: 1.5px solid #d1d9e0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: border-color .2s, box-shadow .2s;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single:hover {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
}
|
||||||
|
.select2-container--default.select2-container--focus .select2-selection--single,
|
||||||
|
.select2-container--default.select2-container--open .select2-selection--single {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
box-shadow: 0 0 0 3px rgba(111,186,157,.18);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||||
|
line-height: 1.4;
|
||||||
|
color: #333;
|
||||||
|
padding: 0;
|
||||||
|
font-size: .93rem;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||||
|
height: 42px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: var(--primary-color, #6FBA9D);
|
||||||
|
}
|
||||||
|
.select2-dropdown {
|
||||||
|
border: 1.5px solid var(--primary-color, #6FBA9D);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0,0,0,.12);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.select2-search--dropdown .select2-search__field {
|
||||||
|
border: 1.5px solid #d1d9e0;
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 7px 10px;
|
||||||
|
font-size: .88rem;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.select2-search--dropdown .select2-search__field:focus {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
}
|
||||||
|
.select2-results__option {
|
||||||
|
padding: 9px 14px;
|
||||||
|
font-size: .88rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
LABEL FIELD
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.field-label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: .8rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: .5px;
|
||||||
|
color: var(--text-light, #888);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.field-label .fi { margin-right: 5px; color: var(--primary-color, #6FBA9D); }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
CARD PILIH JENIS TRANSAKSI
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.jenis-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
.jenis-card {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 14px;
|
||||||
|
border: 2.5px solid #e0e7ef;
|
||||||
|
padding: 18px 16px 16px;
|
||||||
|
transition: border-color .2s, box-shadow .2s, transform .15s, background .2s;
|
||||||
|
background: #fff;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
}
|
||||||
|
.jenis-card:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,.09); }
|
||||||
|
.jenis-card input[type="radio"] { position:absolute; opacity:0; width:0; height:0; }
|
||||||
|
.jenis-card .ji-wrap {
|
||||||
|
width: 46px; height: 46px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-bottom: 11px;
|
||||||
|
transition: background .2s;
|
||||||
|
}
|
||||||
|
.jenis-card .ji-title { font-weight: 700; font-size: .93rem; margin-bottom: 4px; transition: color .2s; }
|
||||||
|
.jenis-card .ji-desc { font-size: .75rem; color: #b0b8c4; line-height: 1.4; }
|
||||||
|
.jenis-card .ji-check {
|
||||||
|
position: absolute; top: 12px; right: 12px;
|
||||||
|
width: 22px; height: 22px; border-radius: 50%;
|
||||||
|
border: 2px solid #d1d9e0;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
font-size: .68rem; color: transparent;
|
||||||
|
transition: all .2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pemasukan aktif */
|
||||||
|
.jenis-card.pemasukan.active {
|
||||||
|
border-color: #6FBA9D;
|
||||||
|
background: linear-gradient(135deg, #f0fdf7 0%, #e6f9f2 100%);
|
||||||
|
box-shadow: 0 4px 18px rgba(111,186,157,.22);
|
||||||
|
}
|
||||||
|
.jenis-card.pemasukan .ji-wrap { background: #edf9f4; color: #6FBA9D; }
|
||||||
|
.jenis-card.pemasukan.active .ji-wrap { background: rgba(111,186,157,.2); color: #38a169; }
|
||||||
|
.jenis-card.pemasukan.active .ji-title { color: #38a169; }
|
||||||
|
.jenis-card.pemasukan.active .ji-check { background: #6FBA9D; border-color: #6FBA9D; color: #fff; }
|
||||||
|
|
||||||
|
/* Pengeluaran aktif */
|
||||||
|
.jenis-card.pengeluaran.active {
|
||||||
|
border-color: #FF8B94;
|
||||||
|
background: linear-gradient(135deg, #fff5f6 0%, #ffe9eb 100%);
|
||||||
|
box-shadow: 0 4px 18px rgba(255,139,148,.22);
|
||||||
|
}
|
||||||
|
.jenis-card.pengeluaran .ji-wrap { background: #fff0f1; color: #FF8B94; }
|
||||||
|
.jenis-card.pengeluaran.active .ji-wrap { background: rgba(255,139,148,.2); color: #e53e3e; }
|
||||||
|
.jenis-card.pengeluaran.active .ji-title { color: #e53e3e; }
|
||||||
|
.jenis-card.pengeluaran.active .ji-check { background: #FF8B94; border-color: #FF8B94; color: #fff; }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
BOX PERINGATAN SALDO
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
#warning-saldo {
|
||||||
|
display: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1.5px solid #FC8181;
|
||||||
|
background: linear-gradient(135deg, #fff5f5 0%, #ffecec 100%);
|
||||||
|
padding: 13px 16px;
|
||||||
|
margin-top: 10px;
|
||||||
|
animation: warnIn .22s ease;
|
||||||
|
}
|
||||||
|
@keyframes warnIn {
|
||||||
|
from { opacity: 0; transform: translateY(-6px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
#warning-saldo .wt { font-weight: 700; color: #c53030; font-size: .87rem; margin-bottom: 5px; }
|
||||||
|
#warning-saldo .wb { font-size: .8rem; color: #742a2a; line-height: 1.55; }
|
||||||
|
#warning-saldo .ws-grid {
|
||||||
|
display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 10px;
|
||||||
|
}
|
||||||
|
#warning-saldo .ws-cell {
|
||||||
|
background: rgba(255,255,255,.75); border-radius: 8px;
|
||||||
|
padding: 8px 10px; text-align: center;
|
||||||
|
}
|
||||||
|
#warning-saldo .ws-cell small { display:block; font-size:.68rem; color:#aaa; margin-bottom:3px; }
|
||||||
|
#warning-saldo .ws-cell strong { font-size:.86rem; font-weight:700; }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
INPUT NOMINAL
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
.nominal-wrap { position: relative; display: flex; align-items: center; }
|
||||||
|
.nominal-prefix {
|
||||||
|
position: absolute; left: 14px;
|
||||||
|
font-weight: 700; color: #aaa;
|
||||||
|
pointer-events: none; font-size: .93rem; z-index: 1;
|
||||||
|
}
|
||||||
|
.nominal-wrap input {
|
||||||
|
padding-left: 44px !important;
|
||||||
|
font-size: 1rem; font-weight: 600; letter-spacing: .3px;
|
||||||
|
height: 44px; border-radius: 10px;
|
||||||
|
border: 1.5px solid #d1d9e0;
|
||||||
|
transition: border-color .2s, box-shadow .2s;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.nominal-wrap input:focus {
|
||||||
|
border-color: var(--primary-color, #6FBA9D);
|
||||||
|
box-shadow: 0 0 0 3px rgba(111,186,157,.18);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.nominal-wrap.danger input {
|
||||||
|
border-color: #FC8181 !important;
|
||||||
|
box-shadow: 0 0 0 3px rgba(255,139,148,.18) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* form-control radius konsisten */
|
||||||
|
.form-control { border-radius: 10px !important; border: 1.5px solid #d1d9e0; transition: border-color .2s, box-shadow .2s; }
|
||||||
|
.form-control:focus {
|
||||||
|
border-color: var(--primary-color, #6FBA9D) !important;
|
||||||
|
box-shadow: 0 0 0 3px rgba(111,186,157,.18) !important;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
textarea.form-control { height: auto; }
|
||||||
|
|
||||||
|
/* ═══════════════════════════════════════════
|
||||||
|
INFO CARD SANTRI
|
||||||
|
═══════════════════════════════════════════ */
|
||||||
|
#santri-info {
|
||||||
|
border-radius: 12px; overflow: hidden;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1.5px solid var(--primary-color, #6FBA9D);
|
||||||
|
box-shadow: 0 4px 14px rgba(111,186,157,.13);
|
||||||
|
animation: fadeUp .22s ease;
|
||||||
|
}
|
||||||
|
@keyframes fadeUp {
|
||||||
|
from { opacity:0; transform:translateY(6px); }
|
||||||
|
to { opacity:1; transform:translateY(0); }
|
||||||
|
}
|
||||||
|
.si-header {
|
||||||
|
background: linear-gradient(90deg, #6FBA9D 0%, #38a169 100%);
|
||||||
|
padding: 10px 16px;
|
||||||
|
display: flex; align-items: center; gap: 8px;
|
||||||
|
color: #fff; font-weight: 700;
|
||||||
|
font-size: .8rem; text-transform: uppercase; letter-spacing: .45px;
|
||||||
|
}
|
||||||
|
.si-body { padding: 14px 16px; background: #f9fdfb; }
|
||||||
|
.si-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 12px; }
|
||||||
|
.si-stat {
|
||||||
|
background: #fff; border-radius: 9px;
|
||||||
|
padding: 10px 12px; text-align: center;
|
||||||
|
border: 1px solid #e8f5ef;
|
||||||
|
}
|
||||||
|
.si-stat small { display:block; font-size:.68rem; color:#aaa; text-transform:uppercase; letter-spacing:.3px; margin-bottom:4px; }
|
||||||
|
.si-val { font-size: .93rem; font-weight: 800; }
|
||||||
|
|
||||||
|
.form-group { margin-bottom: 20px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-plus-circle"></i> Tambah Transaksi Uang Saku</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-container">
|
||||||
|
<form action="<?php echo e(route('admin.uang-saku.store')); ?>" method="POST" id="transaksiForm">
|
||||||
|
<?php echo csrf_field(); ?>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="field-label" for="id_santri">
|
||||||
|
<i class="fas fa-user fi"></i> Pilih Santri
|
||||||
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
|
</label>
|
||||||
|
<select name="id_santri" id="id_santri"
|
||||||
|
class="form-control <?php $__errorArgs = ['id_santri'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>" required>
|
||||||
|
<option value="">Cari ID atau nama santri...</option>
|
||||||
|
<?php $__currentLoopData = $santriList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $santri): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<option value="<?php echo e($santri->id_santri); ?>"
|
||||||
|
<?php echo e((old('id_santri', request('id_santri')) == $santri->id_santri) ? 'selected' : ''); ?>>
|
||||||
|
<?php echo e($santri->id_santri); ?> — <?php echo e($santri->nama_lengkap); ?>
|
||||||
|
|
||||||
|
</option>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</select>
|
||||||
|
<?php $__errorArgs = ['id_santri'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="santri-info" style="display:none;">
|
||||||
|
<div class="si-header">
|
||||||
|
<i class="fas fa-id-card"></i>
|
||||||
|
<span id="info-nama">—</span>
|
||||||
|
</div>
|
||||||
|
<div class="si-body">
|
||||||
|
<div class="si-stats">
|
||||||
|
<div class="si-stat">
|
||||||
|
<small>Saldo Saat Ini</small>
|
||||||
|
<div class="si-val" id="info-saldo">—</div>
|
||||||
|
</div>
|
||||||
|
<div class="si-stat">
|
||||||
|
<small>Masuk Bln Ini</small>
|
||||||
|
<div class="si-val" id="info-masuk" style="color:#6FBA9D;">—</div>
|
||||||
|
</div>
|
||||||
|
<div class="si-stat">
|
||||||
|
<small>Keluar Bln Ini</small>
|
||||||
|
<div class="si-val" id="info-keluar" style="color:#FF8B94;">—</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="info-riwayat"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="field-label">
|
||||||
|
<i class="fas fa-exchange-alt fi"></i> Jenis Transaksi
|
||||||
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
|
||||||
|
<select name="jenis_transaksi" id="jenis_transaksi" style="display:none;"
|
||||||
|
class="<?php $__errorArgs = ['jenis_transaksi'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>" required>
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="pemasukan" <?php echo e(old('jenis_transaksi') == 'pemasukan' ? 'selected' : ''); ?>>pemasukan</option>
|
||||||
|
<option value="pengeluaran" <?php echo e(old('jenis_transaksi') == 'pengeluaran' ? 'selected' : ''); ?>>pengeluaran</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<div class="jenis-cards">
|
||||||
|
<div class="jenis-card pemasukan <?php echo e(old('jenis_transaksi') == 'pemasukan' ? 'active' : ''); ?>"
|
||||||
|
id="card-pemasukan" onclick="pilihJenis('pemasukan')" role="button" tabindex="0"
|
||||||
|
onkeydown="if(event.key==='Enter'||event.key===' ')pilihJenis('pemasukan')">
|
||||||
|
<input type="radio" name="_jenis_ui" value="pemasukan"
|
||||||
|
<?php echo e(old('jenis_transaksi') == 'pemasukan' ? 'checked' : ''); ?>>
|
||||||
|
<div class="ji-wrap"><i class="fas fa-arrow-circle-down"></i></div>
|
||||||
|
<div class="ji-title">Pemasukan</div>
|
||||||
|
<div class="ji-desc">Santri menerima uang saku dari wali / pesantren</div>
|
||||||
|
<div class="ji-check"><i class="fas fa-check"></i></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="jenis-card pengeluaran <?php echo e(old('jenis_transaksi') == 'pengeluaran' ? 'active' : ''); ?>"
|
||||||
|
id="card-pengeluaran" onclick="pilihJenis('pengeluaran')" role="button" tabindex="0"
|
||||||
|
onkeydown="if(event.key==='Enter'||event.key===' ')pilihJenis('pengeluaran')">
|
||||||
|
<input type="radio" name="_jenis_ui" value="pengeluaran"
|
||||||
|
<?php echo e(old('jenis_transaksi') == 'pengeluaran' ? 'checked' : ''); ?>>
|
||||||
|
<div class="ji-wrap"><i class="fas fa-arrow-circle-up"></i></div>
|
||||||
|
<div class="ji-title">Pengeluaran</div>
|
||||||
|
<div class="ji-desc">Santri menggunakan uang saku untuk keperluan</div>
|
||||||
|
<div class="ji-check"><i class="fas fa-check"></i></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php $__errorArgs = ['jenis_transaksi'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div style="color:#e53e3e;font-size:.82rem;margin-top:6px;">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> <?php echo e($message); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="field-label" for="nominal_display">
|
||||||
|
<i class="fas fa-money-bill-wave fi"></i> Nominal (Rp)
|
||||||
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="nominal-wrap" id="nominalWrap">
|
||||||
|
<span class="nominal-prefix">Rp</span>
|
||||||
|
<input type="text"
|
||||||
|
id="nominal_display"
|
||||||
|
class="<?php $__errorArgs = ['nominal'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>"
|
||||||
|
placeholder="0"
|
||||||
|
autocomplete="off"
|
||||||
|
inputmode="numeric"
|
||||||
|
value="<?php echo e(old('nominal') ? number_format((int)old('nominal'), 0, ',', '.') : ''); ?>">
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="nominal" id="nominal" value="<?php echo e(old('nominal')); ?>">
|
||||||
|
|
||||||
|
<?php $__errorArgs = ['nominal'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div style="color:#e53e3e;font-size:.82rem;margin-top:5px;">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> <?php echo e($message); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="warning-saldo">
|
||||||
|
<div class="wt">
|
||||||
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
|
Peringatan: Saldo Tidak Mencukupi!
|
||||||
|
</div>
|
||||||
|
<div class="wb">
|
||||||
|
Nominal pengeluaran yang dimasukkan melebihi saldo santri saat ini.
|
||||||
|
Sistem akan menolak transaksi ini. Silakan kurangi nominal atau pastikan
|
||||||
|
data saldo sudah benar.
|
||||||
|
</div>
|
||||||
|
<div class="ws-grid">
|
||||||
|
<div class="ws-cell">
|
||||||
|
<small>Saldo Tersedia</small>
|
||||||
|
<strong id="warn-saldo" style="color:#38a169;">—</strong>
|
||||||
|
</div>
|
||||||
|
<div class="ws-cell">
|
||||||
|
<small>Nominal Diinput</small>
|
||||||
|
<strong id="warn-nominal" style="color:#c53030;">—</strong>
|
||||||
|
</div>
|
||||||
|
<div class="ws-cell">
|
||||||
|
<small>Kekurangan</small>
|
||||||
|
<strong id="warn-kurang" style="color:#c53030;">—</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="field-label" for="tanggal_transaksi">
|
||||||
|
<i class="fas fa-calendar fi"></i> Tanggal Transaksi
|
||||||
|
<span style="color:#e53e3e;font-weight:700;">*</span>
|
||||||
|
</label>
|
||||||
|
<input type="date" name="tanggal_transaksi" id="tanggal_transaksi"
|
||||||
|
class="form-control <?php $__errorArgs = ['tanggal_transaksi'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>"
|
||||||
|
value="<?php echo e(old('tanggal_transaksi', date('Y-m-d'))); ?>" required>
|
||||||
|
<?php $__errorArgs = ['tanggal_transaksi'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="field-label" for="keterangan">
|
||||||
|
<i class="fas fa-sticky-note fi"></i> Keterangan
|
||||||
|
<span style="font-weight:400;text-transform:none;letter-spacing:0;color:#bbb;">(opsional)</span>
|
||||||
|
</label>
|
||||||
|
<textarea name="keterangan" id="keterangan"
|
||||||
|
class="form-control <?php $__errorArgs = ['keterangan'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?> is-invalid <?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Contoh: Uang saku januari"><?php echo e(old('keterangan')); ?></textarea>
|
||||||
|
<?php $__errorArgs = ['keterangan'];
|
||||||
|
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
||||||
|
if ($__bag->has($__errorArgs[0])) :
|
||||||
|
if (isset($message)) { $__messageOriginal = $message; }
|
||||||
|
$message = $__bag->first($__errorArgs[0]); ?>
|
||||||
|
<div class="invalid-feedback"><?php echo e($message); ?></div>
|
||||||
|
<?php unset($message);
|
||||||
|
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
||||||
|
endif;
|
||||||
|
unset($__errorArgs, $__bag); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="submit" class="btn btn-success hover-lift" id="btnSubmit">
|
||||||
|
<i class="fas fa-save"></i> Simpan Transaksi
|
||||||
|
</button>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||||
|
<script>
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// STATE GLOBAL
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
var saldoSantri = 0; // saldo raw santri terpilih
|
||||||
|
var jenisAktif = ''; // 'pemasukan' | 'pengeluaran' | ''
|
||||||
|
var nominalBersih = 0; // nominal tanpa titik
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// FORMAT HELPER
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
function formatRibuan(val) {
|
||||||
|
var b = String(val).replace(/\D/g, '');
|
||||||
|
return b ? b.replace(/\B(?=(\d{3})+(?!\d))/g, '.') : '';
|
||||||
|
}
|
||||||
|
function stripRibuan(val) { return String(val).replace(/\./g, ''); }
|
||||||
|
function rpStr(angka) { return 'Rp\u00a0' + formatRibuan(angka); }
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// PILIH JENIS (kartu)
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
function pilihJenis(jenis) {
|
||||||
|
jenisAktif = jenis;
|
||||||
|
document.getElementById('jenis_transaksi').value = jenis;
|
||||||
|
document.getElementById('card-pemasukan').classList.toggle('active', jenis === 'pemasukan');
|
||||||
|
document.getElementById('card-pengeluaran').classList.toggle('active', jenis === 'pengeluaran');
|
||||||
|
cekPeringatan();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// CEK PERINGATAN SALDO
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
function cekPeringatan() {
|
||||||
|
var box = document.getElementById('warning-saldo');
|
||||||
|
var wrap = document.getElementById('nominalWrap');
|
||||||
|
var btn = document.getElementById('btnSubmit');
|
||||||
|
|
||||||
|
var kurang = nominalBersih - saldoSantri;
|
||||||
|
var tampil = jenisAktif === 'pengeluaran' && nominalBersih > 0 && kurang > 0;
|
||||||
|
|
||||||
|
if (tampil) {
|
||||||
|
document.getElementById('warn-saldo').textContent = rpStr(saldoSantri);
|
||||||
|
document.getElementById('warn-nominal').textContent = rpStr(nominalBersih);
|
||||||
|
document.getElementById('warn-kurang').textContent = rpStr(kurang);
|
||||||
|
box.style.display = 'block';
|
||||||
|
wrap.classList.add('danger');
|
||||||
|
btn.style.opacity = '.6';
|
||||||
|
btn.title = 'Saldo tidak mencukupi — transaksi akan ditolak!';
|
||||||
|
} else {
|
||||||
|
box.style.display = 'none';
|
||||||
|
wrap.classList.remove('danger');
|
||||||
|
btn.style.opacity = '1';
|
||||||
|
btn.title = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// INPUT NOMINAL — auto titik ribuan
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
var dispEl = document.getElementById('nominal_display');
|
||||||
|
var hiddenEl = document.getElementById('nominal');
|
||||||
|
|
||||||
|
dispEl.addEventListener('input', function () {
|
||||||
|
var bersih = stripRibuan(this.value);
|
||||||
|
var diformat = formatRibuan(bersih);
|
||||||
|
|
||||||
|
// Jaga posisi kursor agar tidak melompat
|
||||||
|
var pos = this.selectionStart;
|
||||||
|
var dotBef = (this.value.substring(0, pos).match(/\./g) || []).length;
|
||||||
|
this.value = diformat;
|
||||||
|
var dotAft = (diformat.substring(0, pos).match(/\./g) || []).length;
|
||||||
|
try { this.setSelectionRange(pos + dotAft - dotBef, pos + dotAft - dotBef); } catch(e) {}
|
||||||
|
|
||||||
|
nominalBersih = parseInt(bersih) || 0;
|
||||||
|
hiddenEl.value = nominalBersih || '';
|
||||||
|
cekPeringatan();
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// SUBMIT — konfirmasi ekstra jika saldo kurang
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
document.getElementById('transaksiForm').addEventListener('submit', function (e) {
|
||||||
|
hiddenEl.value = stripRibuan(dispEl.value) || '';
|
||||||
|
|
||||||
|
if (jenisAktif === 'pengeluaran' && nominalBersih > saldoSantri) {
|
||||||
|
var lanjut = confirm(
|
||||||
|
'\u26a0\ufe0f PERINGATAN: Saldo Tidak Mencukupi!\n\n' +
|
||||||
|
'Saldo santri : ' + rpStr(saldoSantri) + '\n' +
|
||||||
|
'Nominal input : ' + rpStr(nominalBersih) + '\n' +
|
||||||
|
'Kekurangan : ' + rpStr(nominalBersih - saldoSantri) + '\n\n' +
|
||||||
|
'Transaksi ini akan DITOLAK oleh sistem.\n' +
|
||||||
|
'Yakin tetap ingin melanjutkan?'
|
||||||
|
);
|
||||||
|
if (!lanjut) { e.preventDefault(); return false; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
// SELECT2 + AJAX INFO SANTRI
|
||||||
|
// ═══════════════════════════════════════════
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
$('#id_santri').select2({
|
||||||
|
placeholder: 'Cari ID atau nama santri...',
|
||||||
|
allowClear: true,
|
||||||
|
width: '100%',
|
||||||
|
language: {
|
||||||
|
noResults: function () { return 'Santri tidak ditemukan'; },
|
||||||
|
searching: function () { return 'Mencari...'; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#id_santri').on('change', function () {
|
||||||
|
var infoBox = document.getElementById('santri-info');
|
||||||
|
var val = this.value;
|
||||||
|
|
||||||
|
saldoSantri = 0;
|
||||||
|
cekPeringatan();
|
||||||
|
|
||||||
|
if (!val) { infoBox.style.display = 'none'; return; }
|
||||||
|
|
||||||
|
fetch('<?php echo e(url("admin/uang-saku/santri-info")); ?>/' + val)
|
||||||
|
.then(function (r) { return r.json(); })
|
||||||
|
.then(function (d) {
|
||||||
|
saldoSantri = d.saldo_raw;
|
||||||
|
|
||||||
|
document.getElementById('info-nama').textContent = d.nama;
|
||||||
|
|
||||||
|
var sc = d.saldo_raw >= 100000 ? '#38a169'
|
||||||
|
: d.saldo_raw >= 20000 ? '#f5a623' : '#e53e3e';
|
||||||
|
document.getElementById('info-saldo').innerHTML =
|
||||||
|
'<span style="color:' + sc + '">Rp\u00a0' + d.saldo_terakhir + '</span>';
|
||||||
|
document.getElementById('info-masuk').textContent = 'Rp\u00a0' + d.total_pemasukan_bulan_ini;
|
||||||
|
document.getElementById('info-keluar').textContent = 'Rp\u00a0' + d.total_pengeluaran_bulan_ini;
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
if (d.transaksi_terakhir.length > 0) {
|
||||||
|
html = '<div style="font-size:.7rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:7px;">3 Transaksi Terakhir</div>';
|
||||||
|
html += '<table class="data-table" style="font-size:.81rem;"><thead><tr>';
|
||||||
|
html += '<th>Tanggal</th><th>Jenis</th><th>Nominal</th><th>Keterangan</th>';
|
||||||
|
html += '</tr></thead><tbody>';
|
||||||
|
d.transaksi_terakhir.forEach(function (t) {
|
||||||
|
var badge = t.jenis === 'pemasukan'
|
||||||
|
? '<span class="badge badge-success">Masuk</span>'
|
||||||
|
: '<span class="badge badge-danger">Keluar</span>';
|
||||||
|
html += '<tr><td>' + t.tanggal + '</td><td>' + badge +
|
||||||
|
'</td><td>Rp\u00a0' + t.nominal + '</td><td>' + t.keterangan + '</td></tr>';
|
||||||
|
});
|
||||||
|
html += '</tbody></table>';
|
||||||
|
} else {
|
||||||
|
html = '<p style="font-size:.8rem;color:#aaa;margin:0;">Belum ada riwayat transaksi.</p>';
|
||||||
|
}
|
||||||
|
document.getElementById('info-riwayat').innerHTML = html;
|
||||||
|
infoBox.style.display = 'block';
|
||||||
|
|
||||||
|
cekPeringatan();
|
||||||
|
})
|
||||||
|
.catch(function () {
|
||||||
|
document.getElementById('santri-info').style.display = 'none';
|
||||||
|
saldoSantri = 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trigger jika sudah ada pilihan (dari ?id_santri=xxx atau old())
|
||||||
|
if ($('#id_santri').val()) $('#id_santri').trigger('change');
|
||||||
|
|
||||||
|
// Restore jenis dari old() setelah validasi server gagal
|
||||||
|
var oldJenis = '<?php echo e(old("jenis_transaksi", "")); ?>';
|
||||||
|
if (oldJenis) pilihJenis(oldJenis);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/uang-saku/create.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,258 +0,0 @@
|
||||||
|
|
||||||
<?php
|
|
||||||
$total = ($spp['lunas'] ?? 0) + ($spp['belum'] ?? 0);
|
|
||||||
$persenLunas = $total > 0 ? round(($spp['lunas'] / $total) * 100) : 0;
|
|
||||||
$terkumpul = (float) ($spp['terkumpul'] ?? 0);
|
|
||||||
$totalTagihan = (float) ($spp['totalTagihan'] ?? 0);
|
|
||||||
$persenNominal = $totalTagihan > 0 ? min(100, round($terkumpul / $totalTagihan * 100)) : 0;
|
|
||||||
|
|
||||||
$pemasukanLain = (float) ($spp['pemasukanLain'] ?? 0);
|
|
||||||
$pengeluaran = (float) ($spp['pengeluaran'] ?? 0);
|
|
||||||
$totalPemasukan = $terkumpul + $pemasukanLain;
|
|
||||||
$sisaKas = $totalPemasukan - $pengeluaran;
|
|
||||||
|
|
||||||
$kasMax = max($totalPemasukan, $pengeluaran, 1);
|
|
||||||
$pBarMasuk = min(100, round($totalPemasukan / $kasMax * 100));
|
|
||||||
$pBarKeluar = min(100, round($pengeluaran / $kasMax * 100));
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:10px;">
|
|
||||||
<span style="display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;
|
|
||||||
background:linear-gradient(135deg,var(--primary-color),var(--secondary-color));border-radius:6px;flex-shrink:0;">
|
|
||||||
<i class="fas fa-wallet" style="font-size:.7rem;color:#fff;"></i>
|
|
||||||
</span>
|
|
||||||
<span style="font-size:.88rem;font-weight:700;color:var(--text-color);">Keuangan Bulan Ini</span>
|
|
||||||
<a href="<?php echo e(route('admin.keuangan.laporan', ['bulan'=>date('n'),'tahun'=>date('Y')])); ?>"
|
|
||||||
style="margin-left:auto;font-size:.72rem;color:var(--primary-color);font-weight:600;text-decoration:none;display:flex;align-items:center;gap:4px;">
|
|
||||||
Lihat Neraca <i class="fas fa-arrow-right" style="font-size:.6rem;"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="dash-fin-grid">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="display:flex;flex-direction:column;gap:0;">
|
|
||||||
|
|
||||||
<h4 style="margin:0 0 14px;font-size:.8rem;font-weight:700;color:var(--primary-dark);
|
|
||||||
display:flex;align-items:center;gap:6px;">
|
|
||||||
<i class="fas fa-money-check-alt" style="color:var(--primary-color);"></i>
|
|
||||||
Status Pembayaran SPP
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:14px;">
|
|
||||||
|
|
||||||
|
|
||||||
<div style="position:relative;width:110px;height:110px;flex-shrink:0;">
|
|
||||||
<canvas id="sppRingChart"></canvas>
|
|
||||||
<div style="position:absolute;inset:0;display:flex;flex-direction:column;
|
|
||||||
align-items:center;justify-content:center;pointer-events:none;">
|
|
||||||
<span style="font-size:1.5rem;font-weight:800;color:var(--text-color);line-height:1;"><?php echo e($persenLunas); ?>%</span>
|
|
||||||
<span style="font-size:.6rem;color:var(--text-light);font-weight:500;">lunas</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;flex-direction:column;gap:8px;flex:1;min-width:100px;">
|
|
||||||
<div style="display:flex;align-items:center;gap:8px;">
|
|
||||||
<span style="width:10px;height:10px;border-radius:50%;background:var(--primary-color);flex-shrink:0;display:inline-block;"></span>
|
|
||||||
<span style="font-size:.72rem;color:var(--text-light);flex:1;">Lunas</span>
|
|
||||||
<strong style="font-size:.82rem;color:var(--primary-color);"><?php echo e($spp['lunas'] ?? 0); ?></strong>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;align-items:center;gap:8px;">
|
|
||||||
<span style="width:10px;height:10px;border-radius:50%;background:var(--danger-color);flex-shrink:0;display:inline-block;"></span>
|
|
||||||
<span style="font-size:.72rem;color:var(--text-light);flex:1;">Belum Lunas</span>
|
|
||||||
<strong style="font-size:.82rem;color:var(--danger-color);"><?php echo e($spp['belum'] ?? 0); ?></strong>
|
|
||||||
</div>
|
|
||||||
<div style="height:1px;background:var(--primary-light);margin:2px 0;"></div>
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;">
|
|
||||||
<span style="font-size:.68rem;color:var(--text-light);">Terkumpul</span>
|
|
||||||
<span style="font-size:.72rem;font-weight:700;color:var(--text-color);">Rp <?php echo e(number_format($terkumpul/1000000,1)); ?>jt</span>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;">
|
|
||||||
<span style="font-size:.68rem;color:var(--text-light);">Target</span>
|
|
||||||
<span style="font-size:.72rem;font-weight:600;color:var(--text-light);">Rp <?php echo e(number_format($totalTagihan/1000000,1)); ?>jt</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="margin-bottom:14px;">
|
|
||||||
<div style="display:flex;justify-content:space-between;font-size:.68rem;color:var(--text-light);margin-bottom:4px;">
|
|
||||||
<span>Nominal terkumpul</span>
|
|
||||||
<span style="font-weight:700;color:var(--text-color);"><?php echo e($persenNominal); ?>%</span>
|
|
||||||
</div>
|
|
||||||
<div class="progress-bar-wrap">
|
|
||||||
<div class="progress-bar-fill" style="width:<?php echo e($persenNominal); ?>%;
|
|
||||||
background:linear-gradient(90deg,var(--primary-color),var(--primary-dark));"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;">
|
|
||||||
<a href="<?php echo e(route('admin.pembayaran-spp.index', ['tab'=>'belum-bayar','bulan'=>date('n'),'tahun'=>date('Y')])); ?>"
|
|
||||||
class="btn btn-danger btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
|
||||||
<i class="fas fa-exclamation-circle"></i> Belum (<?php echo e($spp['belum'] ?? 0); ?>)
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.pembayaran-spp.generate')); ?>"
|
|
||||||
class="btn btn-warning btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
|
||||||
<i class="fas fa-cogs"></i> Generate
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.pembayaran-spp.index', ['tab'=>'sudah-bayar','bulan'=>date('n'),'tahun'=>date('Y')])); ?>"
|
|
||||||
class="btn btn-success btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
|
||||||
<i class="fas fa-check-circle"></i> Lunas (<?php echo e($spp['lunas'] ?? 0); ?>)
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box" style="display:flex;flex-direction:column;gap:0;">
|
|
||||||
|
|
||||||
<h4 style="margin:0 0 14px;font-size:.8rem;font-weight:700;color:var(--primary-dark);
|
|
||||||
display:flex;align-items:center;gap:6px;">
|
|
||||||
<i class="fas fa-landmark" style="color:var(--info-color);"></i>
|
|
||||||
Neraca Kas Pondok
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;flex-direction:column;gap:14px;margin-bottom:14px;">
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;">
|
|
||||||
<span style="font-size:.72rem;color:var(--text-light);font-weight:600;display:flex;align-items:center;gap:6px;">
|
|
||||||
<span style="width:10px;height:10px;border-radius:50%;background:var(--success-color);display:inline-block;flex-shrink:0;"></span>
|
|
||||||
SPP + Pemasukan
|
|
||||||
</span>
|
|
||||||
<strong style="font-size:.78rem;color:var(--success-color);">
|
|
||||||
Rp <?php echo e(number_format($totalPemasukan,0,',','.')); ?>
|
|
||||||
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div class="progress-bar-wrap" style="height:10px;">
|
|
||||||
<div class="progress-bar-fill" style="width:<?php echo e($pBarMasuk); ?>%;height:100%;
|
|
||||||
background:linear-gradient(90deg,var(--primary-color),#38ef7d);"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;">
|
|
||||||
<span style="font-size:.72rem;color:var(--text-light);font-weight:600;display:flex;align-items:center;gap:6px;">
|
|
||||||
<span style="width:10px;height:10px;border-radius:50%;background:var(--danger-color);display:inline-block;flex-shrink:0;"></span>
|
|
||||||
Pengeluaran
|
|
||||||
</span>
|
|
||||||
<strong style="font-size:.78rem;color:var(--danger-color);">
|
|
||||||
Rp <?php echo e(number_format($pengeluaran,0,',','.')); ?>
|
|
||||||
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div class="progress-bar-wrap" style="height:10px;">
|
|
||||||
<div class="progress-bar-fill" style="width:<?php echo e($pBarKeluar); ?>%;height:100%;
|
|
||||||
background:linear-gradient(90deg,var(--danger-color),#FF6B7A);"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if($pemasukanLain > 0): ?>
|
|
||||||
|
|
||||||
<div style="opacity:.8;">
|
|
||||||
<?php $pBarSpp = min(100, round($terkumpul / $kasMax * 100)); ?>
|
|
||||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:5px;">
|
|
||||||
<span style="font-size:.68rem;color:var(--text-light);display:flex;align-items:center;gap:6px;">
|
|
||||||
<span style="width:8px;height:8px;border-radius:50%;background:var(--info-color);display:inline-block;flex-shrink:0;"></span>
|
|
||||||
└ dari SPP saja
|
|
||||||
</span>
|
|
||||||
<span style="font-size:.7rem;color:var(--info-color);font-weight:600;">
|
|
||||||
Rp <?php echo e(number_format($terkumpul,0,',','.')); ?>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="progress-bar-wrap" style="height:7px;">
|
|
||||||
<div class="progress-bar-fill" style="width:<?php echo e($pBarSpp); ?>%;height:100%;
|
|
||||||
background:linear-gradient(90deg,var(--info-color),#5FAFE0);"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="padding:11px 14px;border-radius:var(--border-radius-sm);margin-bottom:14px;
|
|
||||||
background:<?php echo e($sisaKas >= 0 ? 'linear-gradient(135deg,#E8F7F2,#D4F1E3)' : 'linear-gradient(135deg,#FFE8EA,#FFD5D8)'); ?>;
|
|
||||||
border-left:4px solid <?php echo e($sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)'); ?>;
|
|
||||||
display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:6px;">
|
|
||||||
<span style="font-size:.75rem;font-weight:700;color:var(--text-color);display:flex;align-items:center;gap:6px;">
|
|
||||||
<i class="fas fa-<?php echo e($sisaKas >= 0 ? 'piggy-bank' : 'exclamation-triangle'); ?>"
|
|
||||||
style="color:<?php echo e($sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)'); ?>;"></i>
|
|
||||||
Sisa Kas Bulan Ini
|
|
||||||
</span>
|
|
||||||
<strong style="font-size:1rem;font-weight:800;color:<?php echo e($sisaKas >= 0 ? 'var(--success-color)' : 'var(--danger-color)'); ?>;word-break:break-all;">
|
|
||||||
<?php echo e($sisaKas >= 0 ? '+' : ''); ?>Rp <?php echo e(number_format($sisaKas,0,',','.')); ?>
|
|
||||||
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:auto;">
|
|
||||||
<a href="<?php echo e(route('admin.keuangan.index')); ?>"
|
|
||||||
class="btn btn-info btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
|
||||||
<i class="fas fa-book-open"></i> Buku Kas
|
|
||||||
</a>
|
|
||||||
<a href="<?php echo e(route('admin.keuangan.laporan', ['bulan'=>date('n'),'tahun'=>date('Y')])); ?>"
|
|
||||||
class="btn btn-warning btn-sm" style="flex:1 1 0;min-width:0;justify-content:center;">
|
|
||||||
<i class="fas fa-chart-bar"></i> Laporan
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var SPP_LUNAS = <?php echo e((int)($spp['lunas'] ?? 0)); ?>;
|
|
||||||
var SPP_BELUM = <?php echo e((int)($spp['belum'] ?? 0)); ?>;
|
|
||||||
|
|
||||||
function initRing() {
|
|
||||||
if (typeof Chart === 'undefined') { setTimeout(initRing, 50); return; }
|
|
||||||
var el = document.getElementById('sppRingChart');
|
|
||||||
if (!el) return;
|
|
||||||
if (el._ci) { el._ci.destroy(); }
|
|
||||||
var allZero = (SPP_LUNAS === 0 && SPP_BELUM === 0);
|
|
||||||
el._ci = new Chart(el, {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels : allZero ? ['Belum ada data'] : ['Lunas', 'Belum Lunas'],
|
|
||||||
datasets: [{
|
|
||||||
data : allZero ? [1] : [SPP_LUNAS, SPP_BELUM],
|
|
||||||
backgroundColor: allZero ? ['#E8F7F2'] : ['#6FBA9D', '#FF8B94'],
|
|
||||||
borderWidth : allZero ? 0 : 3,
|
|
||||||
borderColor : '#fff',
|
|
||||||
hoverOffset : allZero ? 0 : 6
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true, maintainAspectRatio: false,
|
|
||||||
cutout: '70%',
|
|
||||||
plugins: {
|
|
||||||
legend: { display: false },
|
|
||||||
tooltip: {
|
|
||||||
enabled: !allZero,
|
|
||||||
callbacks: {
|
|
||||||
label: function (ctx) {
|
|
||||||
var total = ctx.dataset.data.reduce(function(a,b){return a+b;},0);
|
|
||||||
var pct = total > 0 ? Math.round(ctx.parsed/total*100) : 0;
|
|
||||||
return ' '+ctx.label+': '+ctx.formattedValue+' ('+pct+'%)';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initRing);
|
|
||||||
} else { initRing(); }
|
|
||||||
})();
|
|
||||||
</script><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/dashboard/_ringkasan-spp.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,512 @@
|
||||||
|
|
||||||
|
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-history"></i> Riwayat Uang Saku — <?php echo e($santri->nama_lengkap); ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
|
<form method="GET" action="<?php echo e(route('admin.uang-saku.riwayat', $santri->id_santri)); ?>" id="filterPeriode">
|
||||||
|
<div style="display:flex;align-items:flex-end;gap:11px;flex-wrap:wrap;">
|
||||||
|
<div class="form-group" style="margin-bottom:0;flex:1;min-width:200px;">
|
||||||
|
<label for="tanggal_dari" style="display:block;margin-bottom:5px;font-weight:600;">
|
||||||
|
<i class="fas fa-calendar-alt"></i> Dari Tanggal
|
||||||
|
</label>
|
||||||
|
<input type="date" name="tanggal_dari" id="tanggal_dari"
|
||||||
|
class="form-control" value="<?php echo e($tanggalDari); ?>" max="<?php echo e(date('Y-m-d')); ?>">
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-bottom:0;flex:1;min-width:200px;">
|
||||||
|
<label for="tanggal_sampai" style="display:block;margin-bottom:5px;font-weight:600;">
|
||||||
|
<i class="fas fa-calendar-check"></i> Sampai Tanggal
|
||||||
|
</label>
|
||||||
|
<input type="date" name="tanggal_sampai" id="tanggal_sampai"
|
||||||
|
class="form-control" value="<?php echo e($tanggalSampai); ?>" max="<?php echo e(date('Y-m-d')); ?>">
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;gap:10px;">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
<i class="fas fa-filter"></i> Terapkan
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-success" onclick="setBulanIni()">
|
||||||
|
<i class="fas fa-calendar-day"></i> Bulan Ini
|
||||||
|
</button>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.riwayat', $santri->id_santri)); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-redo"></i> Reset
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div style="margin-bottom:10px;">
|
||||||
|
<div style="font-size:.78rem;font-weight:600;color:var(--text-light);
|
||||||
|
text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px;">
|
||||||
|
<i class="fas fa-calculator" style="color:var(--primary-color);"></i>
|
||||||
|
Ringkasan Periode:
|
||||||
|
<strong style="color:var(--text-color);">
|
||||||
|
<?php echo e($periodeDari->format('d M Y')); ?> – <?php echo e($periodeSampai->format('d M Y')); ?>
|
||||||
|
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:grid;
|
||||||
|
grid-template-columns: 1fr 32px 1fr 32px 1fr 32px 1fr;
|
||||||
|
gap:0;align-items:stretch;
|
||||||
|
border-radius:12px;overflow:hidden;
|
||||||
|
border:1.5px solid #e2e8f0;background:#fff;
|
||||||
|
margin-bottom:10px;">
|
||||||
|
|
||||||
|
|
||||||
|
<div style="padding:14px 16px;border-right:1px solid #e2e8f0;">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Saldo Awal Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;color:#4a5568;">
|
||||||
|
Rp <?php echo e(number_format($saldoAwalPeriode, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">
|
||||||
|
per <?php echo e($periodeDari->format('d M Y')); ?>
|
||||||
|
|
||||||
|
<?php if($saldoAwalPeriode == 0): ?>
|
||||||
|
<span style="color:#f5a623;">(belum ada saldo sebelumnya)</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:flex;align-items:center;justify-content:center;
|
||||||
|
font-size:1.3rem;font-weight:300;color:#6FBA9D;
|
||||||
|
border-right:1px solid #e2e8f0;">+</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="padding:14px 16px;border-right:1px solid #e2e8f0;">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Pemasukan Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;color:#6FBA9D;">
|
||||||
|
Rp <?php echo e(number_format($totalPemasukan, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">uang masuk di periode ini</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:flex;align-items:center;justify-content:center;
|
||||||
|
font-size:1.3rem;font-weight:300;color:#FF8B94;
|
||||||
|
border-right:1px solid #e2e8f0;">−</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="padding:14px 16px;border-right:1px solid #e2e8f0;">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Pengeluaran Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;color:#FF8B94;">
|
||||||
|
Rp <?php echo e(number_format($totalPengeluaran, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">uang keluar di periode ini</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display:flex;align-items:center;justify-content:center;
|
||||||
|
font-size:1.3rem;font-weight:300;color:#718096;
|
||||||
|
border-right:1px solid #e2e8f0;">=</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="padding:14px 16px;background:linear-gradient(135deg,#f0fdf7 0%,#e6f9f2 100%);">
|
||||||
|
<div style="font-size:.66rem;color:#aaa;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;">
|
||||||
|
Saldo Akhir Periode
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1rem;font-weight:800;
|
||||||
|
color:<?php echo e($saldoAkhirPeriode >= 0 ? '#38a169' : '#e53e3e'); ?>;">
|
||||||
|
Rp <?php echo e(number_format($saldoAkhirPeriode, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.66rem;color:#bbb;margin-top:3px;">
|
||||||
|
per <?php echo e($periodeSampai->format('d M Y')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if(round($saldoAkhirPeriode) !== round($saldoTerakhir)): ?>
|
||||||
|
<div style="background:#fffbeb;border:1px solid #fbd38d;border-radius:9px;
|
||||||
|
padding:10px 14px;font-size:.8rem;color:#744210;margin-bottom:10px;
|
||||||
|
display:flex;align-items:flex-start;gap:8px;">
|
||||||
|
<i class="fas fa-exclamation-triangle" style="color:#f5a623;margin-top:2px;flex-shrink:0;"></i>
|
||||||
|
<div>
|
||||||
|
<strong>Catatan:</strong>
|
||||||
|
Saldo akhir periode (Rp <?php echo e(number_format($saldoAkhirPeriode, 0, ',', '.')); ?>)
|
||||||
|
berbeda dengan <strong>Saldo Saat Ini (Rp <?php echo e(number_format($saldoTerakhir, 0, ',', '.')); ?>)</strong>
|
||||||
|
karena ada transaksi di luar rentang
|
||||||
|
<?php echo e($periodeDari->format('d M')); ?>–<?php echo e($periodeSampai->format('d M Y')); ?>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="background:linear-gradient(135deg,#ebf8ff 0%,#bee3f8 40%,#ebf8ff 100%);
|
||||||
|
border:1.5px solid #90cdf4;border-radius:12px;
|
||||||
|
padding:14px 18px;display:flex;justify-content:space-between;
|
||||||
|
align-items:center;flex-wrap:wrap;gap:10px;">
|
||||||
|
<div>
|
||||||
|
<div style="font-size:.66rem;color:#2b6cb0;text-transform:uppercase;
|
||||||
|
letter-spacing:.5px;margin-bottom:4px;font-weight:600;">
|
||||||
|
<i class="fas fa-wallet"></i> Saldo Saat Ini (Akumulasi Semua Waktu)
|
||||||
|
</div>
|
||||||
|
<div style="font-size:1.4rem;font-weight:900;
|
||||||
|
color:<?php echo e($saldoTerakhir >= 0 ? '#2b6cb0' : '#e53e3e'); ?>;">
|
||||||
|
Rp <?php echo e(number_format($saldoTerakhir, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="font-size:.78rem;color:#2c5282;text-align:right;max-width:300px;line-height:1.5;">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
Total uang santri saat ini, dihitung dari <strong>seluruh transaksi sejak awal</strong>,
|
||||||
|
bukan hanya periode yang ditampilkan.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom:22px;">
|
||||||
|
<div style="display:flex;justify-content:space-between;align-items:flex-start;
|
||||||
|
flex-wrap:wrap;gap:8px;margin-bottom:16px;">
|
||||||
|
<div>
|
||||||
|
<h3 style="margin:0 0 4px;color:var(--primary-color);">
|
||||||
|
<i class="fas fa-chart-area"></i> Perjalanan Saldo
|
||||||
|
</h3>
|
||||||
|
<div style="font-size:.78rem;color:var(--text-light);">
|
||||||
|
<?php echo e($periodeDari->format('d M Y')); ?> – <?php echo e($periodeSampai->format('d M Y')); ?>
|
||||||
|
|
||||||
|
• Grafik menunjukkan nilai saldo aktual setiap hari
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display:flex;gap:14px;align-items:center;font-size:.78rem;color:var(--text-light);">
|
||||||
|
<span>
|
||||||
|
<span style="display:inline-block;width:24px;height:3px;background:#6FBA9D;
|
||||||
|
vertical-align:middle;border-radius:2px;margin-right:5px;"></span>
|
||||||
|
Saldo naik (pemasukan)
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<span style="display:inline-block;width:24px;height:3px;background:#FF8B94;
|
||||||
|
vertical-align:middle;border-radius:2px;margin-right:5px;"></span>
|
||||||
|
Saldo turun (pengeluaran)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<canvas id="chartSaldo" style="max-height:380px;"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box" style="margin-bottom:14px;">
|
||||||
|
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:11px;">
|
||||||
|
<div style="display:flex;gap:10px;flex-wrap:wrap;">
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo e(route('admin.santri.show', $santri->id)); ?>" class="btn btn-primary">
|
||||||
|
<i class="fas fa-user"></i> Profil Santri
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.create')); ?>?id_santri=<?php echo e($santri->id_santri); ?>"
|
||||||
|
class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<h3 style="margin-bottom:12px;color:var(--text-color);">
|
||||||
|
<i class="fas fa-list"></i> Daftar Transaksi
|
||||||
|
<?php if($transaksi->total() > 0): ?>
|
||||||
|
<span style="color:var(--text-light);font-weight:400;">
|
||||||
|
(<?php echo e($transaksi->total()); ?> transaksi)
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<?php if($transaksi->count() > 0): ?>
|
||||||
|
<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;
|
||||||
|
padding:9px 14px;margin-bottom:12px;font-size:.78rem;color:var(--text-light);">
|
||||||
|
<i class="fas fa-info-circle" style="color:var(--primary-color);"></i>
|
||||||
|
<strong>Saldo Sebelum</strong> & <strong>Saldo Sesudah</strong>
|
||||||
|
menunjukkan saldo kumulatif santri sebelum dan setelah tiap transaksi.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-wrapper">
|
||||||
|
<table class="data-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width:4%;">No</th>
|
||||||
|
<th style="width:11%;">ID</th>
|
||||||
|
<th style="width:10%;">Tanggal</th>
|
||||||
|
<th style="width:10%;">Jenis</th>
|
||||||
|
<th style="width:13%;">Nominal</th>
|
||||||
|
<th style="width:13%;">Saldo Sebelum</th>
|
||||||
|
<th style="width:13%;">Saldo Sesudah</th>
|
||||||
|
<th style="width:20%;">Keterangan</th>
|
||||||
|
<th style="width:6%;" class="text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php $__currentLoopData = $transaksi; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $index => $item): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo e($transaksi->firstItem() + $index); ?></td>
|
||||||
|
<td><strong><?php echo e($item->id_uang_saku); ?></strong></td>
|
||||||
|
<td><?php echo e($item->tanggal_transaksi->format('d/m/Y')); ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if($item->jenis_transaksi === 'pemasukan'): ?>
|
||||||
|
<span class="badge badge-success">
|
||||||
|
<i class="fas fa-arrow-down"></i> Masuk
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge badge-danger">
|
||||||
|
<i class="fas fa-arrow-up"></i> Keluar
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="nominal-highlight"><?php echo e($item->nominal_format); ?></td>
|
||||||
|
<td style="color:#718096;">
|
||||||
|
Rp <?php echo e(number_format($item->saldo_sebelum, 0, ',', '.')); ?>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong style="color:<?php echo e($item->saldo_sesudah >= 0 ? '#38a169' : '#e53e3e'); ?>;">
|
||||||
|
<?php echo e($item->saldo_sesudah_format); ?>
|
||||||
|
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td><div class="content-preview"><?php echo e($item->keterangan ?? '-'); ?></div></td>
|
||||||
|
<td class="text-center">
|
||||||
|
<div style="display:flex;gap:4px;justify-content:center;">
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.show', $item->id)); ?>"
|
||||||
|
class="btn btn-primary btn-sm" title="Detail">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.edit', $item->id)); ?>"
|
||||||
|
class="btn btn-warning btn-sm" title="Edit">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:14px;"><?php echo e($transaksi->links()); ?></div>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="empty-state">
|
||||||
|
<i class="fas fa-calendar-times"></i>
|
||||||
|
<h3>Tidak Ada Transaksi</h3>
|
||||||
|
<p>
|
||||||
|
Tidak ada transaksi pada periode
|
||||||
|
<?php echo e($periodeDari->format('d F Y')); ?> – <?php echo e($periodeSampai->format('d F Y')); ?>.
|
||||||
|
</p>
|
||||||
|
<?php if(round($saldoTerakhir) > 0): ?>
|
||||||
|
<p style="font-size:.85rem;color:var(--text-light);">
|
||||||
|
Santri memiliki saldo
|
||||||
|
<strong>Rp <?php echo e(number_format($saldoTerakhir, 0, ',', '.')); ?></strong>
|
||||||
|
dari transaksi di periode lain.
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.create')); ?>?id_santri=<?php echo e($santri->id_santri); ?>"
|
||||||
|
class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Tambah Transaksi
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||||
|
<script>
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// DATA dari Laravel
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const rawData = <?php echo json_encode($dataGrafikSaldo, 15, 512) ?>;
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Bangun dataset perjalanan saldo
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
const labels = [];
|
||||||
|
const saldoArr = [];
|
||||||
|
|
||||||
|
rawData.forEach((d, i) => {
|
||||||
|
const dt = new Date(d.tanggal + 'T00:00:00');
|
||||||
|
const opt = { day: 'numeric', month: 'short' };
|
||||||
|
labels.push(
|
||||||
|
d.is_awal
|
||||||
|
? dt.toLocaleDateString('id-ID', opt) + ' (Awal)'
|
||||||
|
: dt.toLocaleDateString('id-ID', opt)
|
||||||
|
);
|
||||||
|
saldoArr.push(d.saldo);
|
||||||
|
});
|
||||||
|
|
||||||
|
function segmentColor(ctx, naik, turun, flat) {
|
||||||
|
const i = ctx.p1DataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
if (cur > prv) return naik;
|
||||||
|
if (cur < prv) return turun;
|
||||||
|
return flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildGradient(ctx) {
|
||||||
|
const chart = ctx.chart;
|
||||||
|
const { chartArea } = chart;
|
||||||
|
if (!chartArea) return 'rgba(111,186,157,0.15)';
|
||||||
|
const gradient = chart.ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
|
||||||
|
gradient.addColorStop(0, 'rgba(111,186,157,0.25)');
|
||||||
|
gradient.addColorStop(0.6, 'rgba(111,186,157,0.06)');
|
||||||
|
gradient.addColorStop(1, 'rgba(111,186,157,0.0)');
|
||||||
|
return gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = document.getElementById('chartSaldo').getContext('2d');
|
||||||
|
|
||||||
|
new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Saldo',
|
||||||
|
data: saldoArr,
|
||||||
|
borderWidth: 3,
|
||||||
|
tension: 0.35,
|
||||||
|
fill: true,
|
||||||
|
backgroundColor: buildGradient,
|
||||||
|
pointRadius: function(ctx) {
|
||||||
|
const i = ctx.dataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
return cur !== prv || i === 0 || i === saldoArr.length - 1 ? 6 : 3;
|
||||||
|
},
|
||||||
|
pointHoverRadius: 8,
|
||||||
|
pointBackgroundColor: function(ctx) {
|
||||||
|
const i = ctx.dataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
if (i === 0) return '#718096';
|
||||||
|
if (cur > prv) return '#6FBA9D';
|
||||||
|
if (cur < prv) return '#FF8B94';
|
||||||
|
return '#d1d9e0';
|
||||||
|
},
|
||||||
|
pointBorderColor: '#fff',
|
||||||
|
pointBorderWidth: 2,
|
||||||
|
segment: {
|
||||||
|
borderColor: ctx => segmentColor(ctx, '#6FBA9D', '#FF8B94', '#d1d9e0'),
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: true,
|
||||||
|
interaction: { intersect: false, mode: 'index' },
|
||||||
|
plugins: {
|
||||||
|
legend: { display: false },
|
||||||
|
tooltip: {
|
||||||
|
backgroundColor: 'rgba(30,41,59,0.92)',
|
||||||
|
padding: 13,
|
||||||
|
cornerRadius: 10,
|
||||||
|
titleFont: { size: 13, weight: 'bold' },
|
||||||
|
bodyFont: { size: 13 },
|
||||||
|
callbacks: {
|
||||||
|
title: items => items[0].label,
|
||||||
|
label: item => {
|
||||||
|
const i = item.dataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
const diff = cur - prv;
|
||||||
|
const fmt = v => 'Rp\u00a0' + new Intl.NumberFormat('id-ID').format(v);
|
||||||
|
|
||||||
|
let lines = [' Saldo: ' + fmt(cur)];
|
||||||
|
if (i > 0 && diff !== 0) {
|
||||||
|
const sign = diff > 0 ? '▲ +' : '▼ ';
|
||||||
|
lines.push(' ' + sign + fmt(Math.abs(diff))
|
||||||
|
+ (diff > 0 ? ' (pemasukan)' : ' (pengeluaran)'));
|
||||||
|
} else if (i > 0) {
|
||||||
|
lines.push(' — tidak ada transaksi');
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
},
|
||||||
|
labelColor: item => {
|
||||||
|
const i = item.dataIndex;
|
||||||
|
const cur = saldoArr[i];
|
||||||
|
const prv = saldoArr[i - 1] ?? cur;
|
||||||
|
const c = i === 0 ? '#718096'
|
||||||
|
: cur > prv ? '#6FBA9D'
|
||||||
|
: cur < prv ? '#FF8B94' : '#d1d9e0';
|
||||||
|
return { borderColor: c, backgroundColor: c, borderRadius: 3 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
min: function() {
|
||||||
|
const minVal = Math.min(...saldoArr);
|
||||||
|
return Math.max(0, Math.floor(minVal * 0.8 / 10000) * 10000);
|
||||||
|
}(),
|
||||||
|
ticks: {
|
||||||
|
callback: v => 'Rp\u00a0' + new Intl.NumberFormat('id-ID', {
|
||||||
|
notation: 'compact', compactDisplay: 'short'
|
||||||
|
}).format(v),
|
||||||
|
font: { size: 12 },
|
||||||
|
maxTicksLimit: 8,
|
||||||
|
},
|
||||||
|
grid: { color: 'rgba(0,0,0,.05)', drawBorder: false }
|
||||||
|
},
|
||||||
|
x: {
|
||||||
|
grid: { display: false, drawBorder: false },
|
||||||
|
ticks: {
|
||||||
|
font: { size: 11 },
|
||||||
|
maxRotation: 45,
|
||||||
|
minRotation: 45,
|
||||||
|
maxTicksLimit: rawData.length > 20 ? 12 : rawData.length,
|
||||||
|
autoSkip: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animation: { duration: 1200, easing: 'easeInOutQuart' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// Helpers
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
function setBulanIni() {
|
||||||
|
const today = new Date();
|
||||||
|
const first = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||||
|
const last = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
||||||
|
document.getElementById('tanggal_dari').value = first.toISOString().split('T')[0];
|
||||||
|
document.getElementById('tanggal_sampai').value = last.toISOString().split('T')[0];
|
||||||
|
document.getElementById('filterPeriode').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('tanggal_sampai').addEventListener('change', function () {
|
||||||
|
const dari = document.getElementById('tanggal_dari').value;
|
||||||
|
if (dari && this.value && this.value < dari) {
|
||||||
|
alert('Tanggal sampai tidak boleh lebih kecil dari tanggal dari!');
|
||||||
|
this.value = dari;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/uang-saku/riwayat.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,387 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Login Santri'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('auth-content'); ?>
|
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:opsz,wght@9..40,300;400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body.auth-page {
|
|
||||||
background: #F8FDFB !important;
|
|
||||||
font-family: 'DM Sans', sans-serif !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
align-items: stretch !important;
|
|
||||||
min-height: 100vh !important;
|
|
||||||
}
|
|
||||||
.auth-container {
|
|
||||||
width: 100vw !important; max-width: 100vw !important;
|
|
||||||
min-height: 100vh !important; background: transparent !important;
|
|
||||||
padding: 0 !important; border-radius: 0 !important; box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Wrapper & Background ── */
|
|
||||||
.sl-wrap {
|
|
||||||
position: relative; width: 100%; min-height: 100vh;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
overflow: hidden; font-family: 'DM Sans', sans-serif;
|
|
||||||
}
|
|
||||||
.sl-bg {
|
|
||||||
position: absolute; inset: 0; z-index: 0;
|
|
||||||
background:
|
|
||||||
radial-gradient(ellipse 80% 60% at 70% 50%, rgba(111,186,157,.12) 0%, transparent 60%),
|
|
||||||
radial-gradient(ellipse 50% 80% at 10% 80%, rgba(111,186,157,.08) 0%, transparent 55%),
|
|
||||||
#F8FDFB;
|
|
||||||
}
|
|
||||||
.sl-bg::before {
|
|
||||||
content: ''; position: absolute; inset: 0;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(rgba(111,186,157,.055) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(111,186,157,.055) 1px, transparent 1px);
|
|
||||||
background-size: 48px 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decorations */
|
|
||||||
.sl-ring { position: absolute; border-radius: 50%; border: 1.5px solid rgba(111,186,157,.18); pointer-events: none; }
|
|
||||||
.sl-ring.r1 { width:420px; height:420px; top:-110px; right:-110px; }
|
|
||||||
.sl-ring.r2 { width:270px; height:270px; bottom:50px; right:60px; border-color:rgba(111,186,157,.10); }
|
|
||||||
.sl-ring.r3 { width:200px; height:200px; bottom:-50px; left:60px; border-color:rgba(111,186,157,.14); }
|
|
||||||
.sl-dot { position:absolute; border-radius:50%; background:#6FBA9D; pointer-events:none; }
|
|
||||||
.sl-dot.d1 { width:8px; height:8px; top:22%; right:18%; opacity:.14; }
|
|
||||||
.sl-dot.d2 { width:5px; height:5px; bottom:40%; right:30%; opacity:.09; }
|
|
||||||
.sl-dot.d3 { width:11px; height:11px; top:55%; left:15%; opacity:.08; }
|
|
||||||
.sl-line { position:absolute; height:1px; background:linear-gradient(90deg,transparent,rgba(111,186,157,.14),transparent); pointer-events:none; }
|
|
||||||
.sl-line.l1 { width:280px; top:28%; left:-60px; transform:rotate(-15deg); }
|
|
||||||
.sl-line.l2 { width:220px; bottom:30%; right:-40px; transform:rotate(18deg); }
|
|
||||||
|
|
||||||
/* Layout */
|
|
||||||
.sl-layout {
|
|
||||||
position: relative; z-index: 2;
|
|
||||||
display: flex; align-items: center;
|
|
||||||
width: 100%; max-width: 1100px;
|
|
||||||
padding: 40px 60px; gap: 80px;
|
|
||||||
animation: slIn .6s ease both;
|
|
||||||
}
|
|
||||||
@keyframes slIn {
|
|
||||||
from { opacity:0; transform:translateY(20px); }
|
|
||||||
to { opacity:1; transform:translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Brand left, Form right */
|
|
||||||
.sl-brand { flex: 0 0 340px; order: 1; }
|
|
||||||
.sl-form-panel { flex: 1; max-width: 430px; order: 2; }
|
|
||||||
|
|
||||||
/* ── Brand section ── */
|
|
||||||
.sl-logo { width:72px; height:72px; margin-bottom:20px; border-radius:16px; box-shadow:0 4px 20px rgba(111,186,157,.2); object-fit:contain; background:#fff; }
|
|
||||||
.sl-eyebrow {
|
|
||||||
display:inline-flex; align-items:center; gap:8px;
|
|
||||||
font-size:.68rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:18px;
|
|
||||||
}
|
|
||||||
.sl-eyebrow::before {
|
|
||||||
content:''; display:inline-block; width:22px; height:2px;
|
|
||||||
background:#6FBA9D; border-radius:2px;
|
|
||||||
}
|
|
||||||
.sl-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:3.2rem; line-height:1.05; color:#0F2118; margin-bottom:6px;
|
|
||||||
}
|
|
||||||
.sl-title em { font-style:italic; color:#5EA98C; }
|
|
||||||
.sl-sub { font-size:.9rem; font-weight:500; color:#8AADA0; margin-bottom:32px; line-height:1.6; }
|
|
||||||
.sl-divider { width:44px; height:3px; background:linear-gradient(90deg,#6FBA9D,#A8D8C6); border-radius:3px; margin-bottom:24px; }
|
|
||||||
.sl-desc { font-size:.81rem; color:#8AADA0; line-height:1.8; max-width:290px; margin-bottom:32px; }
|
|
||||||
.sl-features { display:flex; flex-direction:column; gap:11px; }
|
|
||||||
.sl-feat { display:flex; align-items:center; gap:11px; font-size:.79rem; color:#2A4235; font-weight:500; }
|
|
||||||
.sl-feat-ico {
|
|
||||||
width:30px; height:30px; border-radius:8px; background:#EBF7F2;
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
color:#3D8A6E; font-size:.73rem; flex-shrink:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Card ── */
|
|
||||||
.sl-card {
|
|
||||||
background: #fff; border-radius: 24px;
|
|
||||||
padding: 42px 38px;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(111,186,157,.1),
|
|
||||||
0 4px 6px rgba(15,33,24,.03),
|
|
||||||
0 20px 44px rgba(15,33,24,.08);
|
|
||||||
position: relative; overflow: hidden;
|
|
||||||
}
|
|
||||||
.sl-card::before {
|
|
||||||
content: ''; position:absolute; top:0; left:0; right:0; height:3px;
|
|
||||||
background: linear-gradient(90deg, #6FBA9D, #A8D8C6, #6FBA9D);
|
|
||||||
}
|
|
||||||
.sl-card::after {
|
|
||||||
content: ''; position:absolute; bottom:-50px; right:-50px;
|
|
||||||
width:140px; height:140px; border-radius:50%;
|
|
||||||
background: radial-gradient(circle, rgba(111,186,157,.06) 0%, transparent 70%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sl-card-lbl {
|
|
||||||
font-size:.67rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.sl-card-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:1.85rem; color:#0F2118; line-height:1.1; margin-bottom:5px;
|
|
||||||
}
|
|
||||||
.sl-card-desc { font-size:.79rem; color:#8AADA0; line-height:1.6; margin-bottom:26px; }
|
|
||||||
|
|
||||||
/* Alert */
|
|
||||||
.sl-alert {
|
|
||||||
border-radius:10px; padding:10px 13px; font-size:.79rem;
|
|
||||||
margin-bottom:18px; border-left:3px solid;
|
|
||||||
}
|
|
||||||
.sl-alert.danger { background:#FFF3F3; color:#c62828; border-color:#e53935; }
|
|
||||||
.sl-alert.success { background:#F0FFF4; color:#2E7D32; border-color:#43A047; }
|
|
||||||
.sl-alert p { display:flex; align-items:center; gap:7px; margin:2px 0; }
|
|
||||||
|
|
||||||
/* Fields */
|
|
||||||
.sl-field { margin-bottom:18px; }
|
|
||||||
.sl-lbl {
|
|
||||||
display:block; font-size:.7rem; font-weight:700;
|
|
||||||
letter-spacing:.8px; text-transform:uppercase; color:#2A4235; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.sl-shell { position:relative; display:flex; align-items:center; }
|
|
||||||
.sl-shell .fi { position:absolute; left:15px; color:#A8D8C6; font-size:.8rem; pointer-events:none; transition:color .2s; }
|
|
||||||
.sl-shell input {
|
|
||||||
width:100%; padding:12px 15px 12px 40px;
|
|
||||||
background:#EBF7F2; border:1.5px solid transparent;
|
|
||||||
border-radius:11px; font-family:inherit; font-size:.87rem; color:#0F2118; outline:none;
|
|
||||||
transition:all .2s;
|
|
||||||
}
|
|
||||||
.sl-shell input::placeholder { color:#8AADA0; font-size:.83rem; }
|
|
||||||
.sl-shell input:focus {
|
|
||||||
background:#fff; border-color:#6FBA9D;
|
|
||||||
box-shadow:0 0 0 4px rgba(111,186,157,.12);
|
|
||||||
}
|
|
||||||
.sl-show {
|
|
||||||
position:absolute; right:13px;
|
|
||||||
background:none; border:none; font-size:.68rem; font-weight:800;
|
|
||||||
letter-spacing:.8px; color:#5EA98C; cursor:pointer; font-family:inherit;
|
|
||||||
}
|
|
||||||
.sl-show:hover { color:#3D8A6E; }
|
|
||||||
.sl-ferr { font-size:.72rem; color:#e53935; margin-top:4px; padding-left:3px; }
|
|
||||||
|
|
||||||
/* Remember */
|
|
||||||
.sl-remember {
|
|
||||||
display:flex; align-items:center; gap:9px;
|
|
||||||
margin-bottom:20px; cursor:pointer;
|
|
||||||
}
|
|
||||||
.sl-remember input[type="checkbox"] {
|
|
||||||
width:16px; height:16px; accent-color:#6FBA9D; cursor:pointer;
|
|
||||||
border-radius:4px;
|
|
||||||
}
|
|
||||||
.sl-remember span {
|
|
||||||
font-size:.8rem; color:#5A7E6E; font-weight:500; user-select:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Button */
|
|
||||||
.sl-btn {
|
|
||||||
width:100%; padding:13px;
|
|
||||||
background:linear-gradient(135deg, #6FBA9D, #5EA98C);
|
|
||||||
color:#fff; border:none; border-radius:12px;
|
|
||||||
font-family:inherit; font-size:.89rem; font-weight:700;
|
|
||||||
cursor:pointer; letter-spacing:.3px; margin-top:4px;
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:8px;
|
|
||||||
box-shadow:0 4px 18px rgba(94,169,140,.35);
|
|
||||||
transition:all .25s;
|
|
||||||
}
|
|
||||||
.sl-btn:hover { transform:translateY(-2px); box-shadow:0 8px 26px rgba(94,169,140,.45); }
|
|
||||||
.sl-btn:active { transform:none; }
|
|
||||||
|
|
||||||
.sl-foot { text-align:center; font-size:.77rem; color:#8AADA0; margin-top:20px; }
|
|
||||||
.sl-foot a { color:#5EA98C; font-weight:700; text-decoration:none; }
|
|
||||||
.sl-foot a:hover { text-decoration:underline; }
|
|
||||||
|
|
||||||
.sl-note {
|
|
||||||
text-align:center; font-size:.73rem; color:#A8C4B8; margin-top:14px;
|
|
||||||
line-height:1.5;
|
|
||||||
}
|
|
||||||
.sl-note i { margin-right:4px; }
|
|
||||||
|
|
||||||
/* ── Responsive ── */
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.sl-layout { gap:48px; padding:32px 36px; }
|
|
||||||
.sl-brand { flex:0 0 260px; }
|
|
||||||
.sl-title { font-size:2.7rem; }
|
|
||||||
}
|
|
||||||
@media (max-width: 720px) {
|
|
||||||
body.auth-page { align-items:flex-start !important; overflow-y:auto !important; }
|
|
||||||
.sl-wrap { align-items:flex-start; min-height:auto; padding:24px 0 40px; }
|
|
||||||
.sl-layout { flex-direction:column; padding:0 20px; gap:28px; }
|
|
||||||
.sl-form-panel { order:2; max-width:100%; }
|
|
||||||
.sl-brand { order:1; flex:none; text-align:center; }
|
|
||||||
.sl-title { font-size:2.2rem; }
|
|
||||||
.sl-logo { width:56px; height:56px; margin:0 auto 14px; display:block; }
|
|
||||||
.sl-features, .sl-desc, .sl-divider { display:none; }
|
|
||||||
.sl-sub { margin-bottom:0; }
|
|
||||||
.sl-card { padding:28px 20px; }
|
|
||||||
.sl-ring.r1 { width:260px; height:260px; top:-70px; right:-70px; }
|
|
||||||
.sl-ring.r2 { display:none; }
|
|
||||||
}
|
|
||||||
@media (max-width: 420px) {
|
|
||||||
.sl-title { font-size:1.85rem; }
|
|
||||||
.sl-card { padding:24px 16px; border-radius:16px; }
|
|
||||||
.sl-card-title { font-size:1.5rem; }
|
|
||||||
}
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.sl-layout { max-width:1160px; padding:40px 80px; }
|
|
||||||
.sl-brand { flex:0 0 360px; }
|
|
||||||
.sl-title { font-size:3.6rem; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="sl-wrap">
|
|
||||||
<div class="sl-bg"></div>
|
|
||||||
<div class="sl-ring r1"></div>
|
|
||||||
<div class="sl-ring r2"></div>
|
|
||||||
<div class="sl-ring r3"></div>
|
|
||||||
<div class="sl-dot d1"></div>
|
|
||||||
<div class="sl-dot d2"></div>
|
|
||||||
<div class="sl-dot d3"></div>
|
|
||||||
<div class="sl-line l1"></div>
|
|
||||||
<div class="sl-line l2"></div>
|
|
||||||
|
|
||||||
<div class="sl-layout">
|
|
||||||
|
|
||||||
<!-- Brand (kiri) -->
|
|
||||||
<div class="sl-brand">
|
|
||||||
<img src="<?php echo e(asset('images/logo.png')); ?>" alt="Logo PKPPS" class="sl-logo">
|
|
||||||
<div class="sl-eyebrow">Portal Santri</div>
|
|
||||||
<h1 class="sl-title">Welcome Back<br><em>SIM Santri</em></h1>
|
|
||||||
<p class="sl-sub">PKPPS Riyadlul Jannah</p>
|
|
||||||
<div class="sl-divider"></div>
|
|
||||||
<p class="sl-desc">Akses nilai, absensi, jadwal, dan seluruh progres pembelajaran santri secara mudah dan aman.</p>
|
|
||||||
<div class="sl-features">
|
|
||||||
<div class="sl-feat">
|
|
||||||
<div class="sl-feat-ico"><i class="fas fa-user-graduate"></i></div>
|
|
||||||
<span>Pantau progres akademik santri</span>
|
|
||||||
</div>
|
|
||||||
<div class="sl-feat">
|
|
||||||
<div class="sl-feat-ico"><i class="fas fa-calendar-check"></i></div>
|
|
||||||
<span>Lihat jadwal & absensi harian</span>
|
|
||||||
</div>
|
|
||||||
<div class="sl-feat">
|
|
||||||
<div class="sl-feat-ico"><i class="fas fa-chart-line"></i></div>
|
|
||||||
<span>Laporan capaian & perkembangan</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Form (kanan) -->
|
|
||||||
<div class="sl-form-panel">
|
|
||||||
<div class="sl-card">
|
|
||||||
<div class="sl-card-lbl">Login Santri</div>
|
|
||||||
<div class="sl-card-title">Masuk ke Akun</div>
|
|
||||||
<div class="sl-card-desc">Gunakan username dan password yang diberikan oleh admin pesantren.</div>
|
|
||||||
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="sl-alert danger">
|
|
||||||
<?php $__currentLoopData = $errors->all(); $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $error): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
<p><i class="fas fa-circle-exclamation"></i> <?php echo e($error); ?></p>
|
|
||||||
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="sl-alert success">
|
|
||||||
<p><i class="fas fa-check-circle"></i> <?php echo e(session('success')); ?></p>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form method="POST" action="<?php echo e(route('santri.login')); ?>">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="sl-field">
|
|
||||||
<label class="sl-lbl">Username / ID Santri</label>
|
|
||||||
<div class="sl-shell">
|
|
||||||
<i class="fas fa-user fi" id="sl-ico-u"></i>
|
|
||||||
<input type="text" id="username" name="username"
|
|
||||||
value="<?php echo e(old('username')); ?>"
|
|
||||||
placeholder="Masukkan username Anda"
|
|
||||||
autocomplete="username" required autofocus
|
|
||||||
onfocus="document.getElementById('sl-ico-u').style.color='#6FBA9D'"
|
|
||||||
onblur="document.getElementById('sl-ico-u').style.color=''">
|
|
||||||
</div>
|
|
||||||
<?php $__errorArgs = ['username'];
|
|
||||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
|
||||||
if ($__bag->has($__errorArgs[0])) :
|
|
||||||
if (isset($message)) { $__messageOriginal = $message; }
|
|
||||||
$message = $__bag->first($__errorArgs[0]); ?><div class="sl-ferr"><?php echo e($message); ?></div><?php unset($message);
|
|
||||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
|
||||||
endif;
|
|
||||||
unset($__errorArgs, $__bag); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sl-field">
|
|
||||||
<label class="sl-lbl">Password</label>
|
|
||||||
<div class="sl-shell">
|
|
||||||
<i class="fas fa-lock fi" id="sl-ico-pw"></i>
|
|
||||||
<input type="password" id="password" name="password"
|
|
||||||
placeholder="Masukkan password Anda"
|
|
||||||
autocomplete="current-password" required
|
|
||||||
onfocus="document.getElementById('sl-ico-pw').style.color='#6FBA9D'"
|
|
||||||
onblur="document.getElementById('sl-ico-pw').style.color=''">
|
|
||||||
<button type="button" class="sl-show" id="slTglBtn">SHOW</button>
|
|
||||||
</div>
|
|
||||||
<?php $__errorArgs = ['password'];
|
|
||||||
$__bag = $errors->getBag($__errorArgs[1] ?? 'default');
|
|
||||||
if ($__bag->has($__errorArgs[0])) :
|
|
||||||
if (isset($message)) { $__messageOriginal = $message; }
|
|
||||||
$message = $__bag->first($__errorArgs[0]); ?><div class="sl-ferr"><?php echo e($message); ?></div><?php unset($message);
|
|
||||||
if (isset($__messageOriginal)) { $message = $__messageOriginal; }
|
|
||||||
endif;
|
|
||||||
unset($__errorArgs, $__bag); ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<label class="sl-remember">
|
|
||||||
<input type="checkbox" name="remember" id="remember" <?php echo e(old('remember') ? 'checked' : ''); ?>>
|
|
||||||
<span>Ingat Saya</span>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<button type="submit" class="sl-btn">
|
|
||||||
<i class="fas fa-sign-in-alt"></i>
|
|
||||||
Masuk
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sl-note">
|
|
||||||
<i class="fas fa-info-circle"></i>
|
|
||||||
Lupa akun? Silakan hubungi admin pesantren untuk bantuan.
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Toggle password
|
|
||||||
const btn = document.getElementById('slTglBtn');
|
|
||||||
const pw = document.getElementById('password');
|
|
||||||
if (btn && pw) {
|
|
||||||
btn.addEventListener('click', () => {
|
|
||||||
const isP = pw.type === 'password';
|
|
||||||
pw.type = isP ? 'text' : 'password';
|
|
||||||
btn.textContent = isP ? 'HIDE' : 'SHOW';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto-hide success alert
|
|
||||||
const successAlert = document.querySelector('.sl-alert.success');
|
|
||||||
if (successAlert) {
|
|
||||||
setTimeout(() => {
|
|
||||||
successAlert.style.transition = 'opacity .5s ease';
|
|
||||||
successAlert.style.opacity = '0';
|
|
||||||
setTimeout(() => successAlert.remove(), 500);
|
|
||||||
}, 4000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
|
|
||||||
<?php echo $__env->make('auth.auth_layout', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/santri/auth/login.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
<?php $__env->startSection('content'); ?>
|
||||||
|
<div class="page-header">
|
||||||
|
<h2><i class="fas fa-info-circle"></i> Detail Transaksi Uang Saku</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-box">
|
||||||
|
<div class="detail-header">
|
||||||
|
<h3><?php echo e($transaksi->id_uang_saku); ?></h3>
|
||||||
|
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.riwayat', $transaksi->id_santri)); ?>" class="btn btn-primary">
|
||||||
|
<i class="fas fa-history"></i> Lihat Riwayat
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.edit', $transaksi->id)); ?>" class="btn btn-warning">
|
||||||
|
<i class="fas fa-edit"></i> Edit
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.index')); ?>" class="btn btn-secondary">
|
||||||
|
<i class="fas fa-arrow-left"></i> Kembali
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-section">
|
||||||
|
<h4><i class="fas fa-file-alt"></i> Informasi Transaksi</h4>
|
||||||
|
<table class="detail-table">
|
||||||
|
<tr>
|
||||||
|
<th>ID Transaksi</th>
|
||||||
|
<td><strong><?php echo e($transaksi->id_uang_saku); ?></strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Santri</th>
|
||||||
|
<td>
|
||||||
|
<strong><?php echo e($transaksi->santri->nama_lengkap); ?></strong><br>
|
||||||
|
<small class="text-muted"><?php echo e($transaksi->santri->id_santri); ?> - <?php echo e($transaksi->santri->kelas); ?></small>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Jenis Transaksi</th>
|
||||||
|
<td>
|
||||||
|
<?php if($transaksi->jenis_transaksi === 'pemasukan'): ?>
|
||||||
|
<span class="badge badge-success badge-lg">
|
||||||
|
<i class="fas fa-arrow-down"></i> Pemasukan
|
||||||
|
</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge badge-danger badge-lg">
|
||||||
|
<i class="fas fa-arrow-up"></i> Pengeluaran
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Nominal</th>
|
||||||
|
<td class="nominal-highlight" style="font-size: 1.3rem;">
|
||||||
|
<?php echo e($transaksi->nominal_format); ?>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Tanggal Transaksi</th>
|
||||||
|
<td><?php echo e($transaksi->tanggal_transaksi->format('d F Y')); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Keterangan</th>
|
||||||
|
<td><?php echo e($transaksi->keterangan ?? '-'); ?></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-section">
|
||||||
|
<h4><i class="fas fa-calculator"></i> Rincian Saldo</h4>
|
||||||
|
<table class="detail-table">
|
||||||
|
<tr>
|
||||||
|
<th>Saldo Sebelum</th>
|
||||||
|
<td>
|
||||||
|
<strong>Rp <?php echo e(number_format($transaksi->saldo_sebelum, 0, ',', '.')); ?></strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th><?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? 'Pemasukan' : 'Pengeluaran'); ?></th>
|
||||||
|
<td style="color: <?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? '#6FBA9D' : '#FF8B94'); ?>;">
|
||||||
|
<strong>
|
||||||
|
<?php echo e($transaksi->jenis_transaksi === 'pemasukan' ? '+' : '-'); ?>
|
||||||
|
<?php echo e($transaksi->nominal_format); ?>
|
||||||
|
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="background: linear-gradient(135deg, #E8F7F2 0%, #D4F1E3 100%);">
|
||||||
|
<th>Saldo Sesudah</th>
|
||||||
|
<td>
|
||||||
|
<strong style="font-size: 1.2rem; color: <?php echo e($transaksi->saldo_sesudah >= 0 ? '#6FBA9D' : '#FF8B94'); ?>">
|
||||||
|
<?php echo e($transaksi->saldo_sesudah_format); ?>
|
||||||
|
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="detail-section">
|
||||||
|
<h4><i class="fas fa-clock"></i> Informasi Waktu</h4>
|
||||||
|
<table class="detail-table">
|
||||||
|
<tr>
|
||||||
|
<th>Dibuat Pada</th>
|
||||||
|
<td><?php echo e($transaksi->created_at->format('d F Y, H:i')); ?> WIB</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Terakhir Diubah</th>
|
||||||
|
<td><?php echo e($transaksi->updated_at->format('d F Y, H:i')); ?> WIB</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px; flex-wrap: wrap;">
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.riwayat', $transaksi->id_santri)); ?>" class="btn btn-primary">
|
||||||
|
<i class="fas fa-history"></i> Lihat Riwayat
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<?php if($canCrud): ?>
|
||||||
|
<a href="<?php echo e(route('admin.uang-saku.edit', $transaksi->id)); ?>" class="btn btn-warning">
|
||||||
|
<i class="fas fa-edit"></i> Edit Transaksi
|
||||||
|
</a>
|
||||||
|
<form action="<?php echo e(route('admin.uang-saku.destroy', $transaksi->id)); ?>"
|
||||||
|
method="POST"
|
||||||
|
style="display: inline;"
|
||||||
|
onsubmit="return confirm('Yakin ingin menghapus transaksi ini?\n\nPerhatian: Saldo transaksi setelahnya akan di-recalculate otomatis.')">
|
||||||
|
<?php echo csrf_field(); ?>
|
||||||
|
<?php echo method_field('DELETE'); ?>
|
||||||
|
<button type="submit" class="btn btn-danger">
|
||||||
|
<i class="fas fa-trash"></i> Hapus
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php $__env->stopSection(); ?>
|
||||||
|
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/uang-saku/show.blade.php ENDPATH**/ ?>
|
||||||
|
|
@ -1,315 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php $__env->startSection('title', 'Lupa Password'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('auth-content'); ?>
|
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:opsz,wght@9..40,300;400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body.auth-page {
|
|
||||||
background: #F8FDFB !important;
|
|
||||||
font-family: 'DM Sans', sans-serif !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
align-items: stretch !important;
|
|
||||||
min-height: 100vh !important;
|
|
||||||
}
|
|
||||||
.auth-container {
|
|
||||||
width: 100vw !important; max-width: 100vw !important;
|
|
||||||
min-height: 100vh !important; background: transparent !important;
|
|
||||||
padding: 0 !important; border-radius: 0 !important; box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fp-wrap {
|
|
||||||
position: relative; width: 100%; min-height: 100vh;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
overflow: hidden; font-family: 'DM Sans', sans-serif;
|
|
||||||
}
|
|
||||||
.fp-bg {
|
|
||||||
position: absolute; inset: 0; z-index: 0;
|
|
||||||
background:
|
|
||||||
radial-gradient(ellipse 80% 60% at 70% 50%, rgba(111,186,157,.12) 0%, transparent 60%),
|
|
||||||
radial-gradient(ellipse 50% 80% at 10% 80%, rgba(111,186,157,.08) 0%, transparent 55%),
|
|
||||||
#F8FDFB;
|
|
||||||
}
|
|
||||||
.fp-bg::before {
|
|
||||||
content: ''; position: absolute; inset: 0;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(rgba(111,186,157,.055) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(111,186,157,.055) 1px, transparent 1px);
|
|
||||||
background-size: 48px 48px;
|
|
||||||
}
|
|
||||||
.fp-ring { position: absolute; border-radius: 50%; border: 1.5px solid rgba(111,186,157,.18); pointer-events: none; }
|
|
||||||
.fp-ring.r1 { width:420px; height:420px; top:-110px; right:-110px; }
|
|
||||||
.fp-ring.r2 { width:270px; height:270px; bottom:50px; left:60px; border-color:rgba(111,186,157,.10); }
|
|
||||||
.fp-dot { position:absolute; border-radius:50%; background:#6FBA9D; pointer-events:none; }
|
|
||||||
.fp-dot.d1 { width:8px; height:8px; top:22%; right:18%; opacity:.14; }
|
|
||||||
.fp-dot.d2 { width:11px; height:11px; top:55%; left:15%; opacity:.08; }
|
|
||||||
.fp-line { position:absolute; height:1px; background:linear-gradient(90deg,transparent,rgba(111,186,157,.14),transparent); pointer-events:none; }
|
|
||||||
.fp-line.l1 { width:280px; top:28%; left:-60px; transform:rotate(-15deg); }
|
|
||||||
|
|
||||||
.fp-layout {
|
|
||||||
position: relative; z-index: 2;
|
|
||||||
display: flex; align-items: center;
|
|
||||||
width: 100%; max-width: 1100px;
|
|
||||||
padding: 40px 60px; gap: 80px;
|
|
||||||
animation: fpIn .6s ease both;
|
|
||||||
}
|
|
||||||
@keyframes fpIn {
|
|
||||||
from { opacity:0; transform:translateY(20px); }
|
|
||||||
to { opacity:1; transform:translateY(0); }
|
|
||||||
}
|
|
||||||
.fp-brand { flex: 0 0 340px; order: 1; }
|
|
||||||
.fp-form-panel { flex: 1; max-width: 430px; order: 2; }
|
|
||||||
|
|
||||||
/* Brand */
|
|
||||||
.fp-logo { width:72px; height:72px; margin-bottom:20px; border-radius:16px; box-shadow:0 4px 20px rgba(111,186,157,.2); object-fit:contain; background:#fff; }
|
|
||||||
.fp-eyebrow {
|
|
||||||
display:inline-flex; align-items:center; gap:8px;
|
|
||||||
font-size:.68rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:18px;
|
|
||||||
}
|
|
||||||
.fp-eyebrow::before { content:''; display:inline-block; width:22px; height:2px; background:#6FBA9D; border-radius:2px; }
|
|
||||||
.fp-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:3.2rem; line-height:1.05; color:#0F2118; margin-bottom:6px;
|
|
||||||
}
|
|
||||||
.fp-title em { font-style:italic; color:#5EA98C; }
|
|
||||||
.fp-sub { font-size:.9rem; font-weight:500; color:#8AADA0; margin-bottom:32px; line-height:1.6; }
|
|
||||||
.fp-divider { width:44px; height:3px; background:linear-gradient(90deg,#6FBA9D,#A8D8C6); border-radius:3px; margin-bottom:24px; }
|
|
||||||
.fp-desc { font-size:.81rem; color:#8AADA0; line-height:1.8; max-width:290px; margin-bottom:32px; }
|
|
||||||
|
|
||||||
/* Steps */
|
|
||||||
.fp-steps { display:flex; flex-direction:column; gap:14px; }
|
|
||||||
.fp-step { display:flex; align-items:flex-start; gap:12px; }
|
|
||||||
.fp-step-num {
|
|
||||||
width:28px; height:28px; border-radius:50%;
|
|
||||||
background:linear-gradient(135deg,#6FBA9D,#5EA98C);
|
|
||||||
color:#fff; font-size:.72rem; font-weight:800;
|
|
||||||
display:flex; align-items:center; justify-content:center; flex-shrink:0;
|
|
||||||
}
|
|
||||||
.fp-step-num.active { box-shadow:0 0 0 4px rgba(111,186,157,.2); }
|
|
||||||
.fp-step-text { font-size:.78rem; color:#2A4235; font-weight:500; line-height:1.5; padding-top:3px; }
|
|
||||||
.fp-step-text small { display:block; color:#8AADA0; font-weight:400; font-size:.72rem; }
|
|
||||||
|
|
||||||
/* Card */
|
|
||||||
.fp-card {
|
|
||||||
background: #fff; border-radius: 24px;
|
|
||||||
padding: 42px 38px;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(111,186,157,.1),
|
|
||||||
0 4px 6px rgba(15,33,24,.03),
|
|
||||||
0 20px 44px rgba(15,33,24,.08);
|
|
||||||
position: relative; overflow: hidden;
|
|
||||||
}
|
|
||||||
.fp-card::before {
|
|
||||||
content: ''; position:absolute; top:0; left:0; right:0; height:3px;
|
|
||||||
background: linear-gradient(90deg, #e57373, #ef9a9a, #e57373);
|
|
||||||
}
|
|
||||||
.fp-card::after {
|
|
||||||
content: ''; position:absolute; bottom:-50px; right:-50px;
|
|
||||||
width:140px; height:140px; border-radius:50%;
|
|
||||||
background: radial-gradient(circle, rgba(229,115,115,.06) 0%, transparent 70%);
|
|
||||||
}
|
|
||||||
.fp-card-icon {
|
|
||||||
width:54px; height:54px; border-radius:14px;
|
|
||||||
background:linear-gradient(135deg,#FFEBEE,#FFCDD2);
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
font-size:1.3rem; color:#e53935; margin-bottom:16px;
|
|
||||||
}
|
|
||||||
.fp-card-lbl {
|
|
||||||
font-size:.67rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#e57373; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.fp-card-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:1.85rem; color:#0F2118; line-height:1.1; margin-bottom:5px;
|
|
||||||
}
|
|
||||||
.fp-card-desc { font-size:.79rem; color:#8AADA0; line-height:1.6; margin-bottom:26px; }
|
|
||||||
|
|
||||||
/* Alert */
|
|
||||||
.fp-alert-danger {
|
|
||||||
border-radius:10px; padding:10px 13px; font-size:.79rem;
|
|
||||||
margin-bottom:18px; background:#FFF3F3; color:#c62828; border-left:3px solid #e53935;
|
|
||||||
display:flex; align-items:center; gap:7px;
|
|
||||||
}
|
|
||||||
.fp-alert-success {
|
|
||||||
border-radius:10px; padding:10px 13px; font-size:.79rem;
|
|
||||||
margin-bottom:18px; background:#F0FFF4; color:#2E7D32; border-left:3px solid #43A047;
|
|
||||||
display:flex; align-items:center; gap:7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Field */
|
|
||||||
.fp-field { margin-bottom:18px; }
|
|
||||||
.fp-lbl { display:block; font-size:.7rem; font-weight:700; letter-spacing:.8px; text-transform:uppercase; color:#2A4235; margin-bottom:7px; }
|
|
||||||
.fp-shell { position:relative; display:flex; align-items:center; }
|
|
||||||
.fp-shell .fi { position:absolute; left:15px; color:#A8D8C6; font-size:.8rem; pointer-events:none; transition:color .2s; }
|
|
||||||
.fp-shell input {
|
|
||||||
width:100%; padding:12px 15px 12px 40px;
|
|
||||||
background:#EBF7F2; border:1.5px solid transparent;
|
|
||||||
border-radius:11px; font-family:inherit; font-size:.87rem; color:#0F2118; outline:none;
|
|
||||||
transition:all .2s;
|
|
||||||
}
|
|
||||||
.fp-shell input::placeholder { color:#8AADA0; font-size:.83rem; }
|
|
||||||
.fp-shell input:focus { background:#fff; border-color:#e57373; box-shadow:0 0 0 4px rgba(229,115,115,.12); }
|
|
||||||
.fp-shell .fi.active { color:#e57373; }
|
|
||||||
|
|
||||||
/* Button */
|
|
||||||
.fp-btn {
|
|
||||||
width:100%; padding:13px;
|
|
||||||
background:linear-gradient(135deg, #e57373, #ef5350);
|
|
||||||
color:#fff; border:none; border-radius:12px;
|
|
||||||
font-family:inherit; font-size:.89rem; font-weight:700;
|
|
||||||
cursor:pointer; letter-spacing:.3px;
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:8px;
|
|
||||||
box-shadow:0 4px 18px rgba(229,115,115,.35);
|
|
||||||
transition:all .25s;
|
|
||||||
}
|
|
||||||
.fp-btn:hover { transform:translateY(-2px); box-shadow:0 8px 26px rgba(229,115,115,.45); }
|
|
||||||
.fp-btn:active { transform:none; }
|
|
||||||
|
|
||||||
.fp-back {
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:6px;
|
|
||||||
margin-top:20px; font-size:.78rem; color:#5EA98C; font-weight:600; text-decoration:none;
|
|
||||||
transition:color .2s;
|
|
||||||
}
|
|
||||||
.fp-back:hover { color:#3D8A6E; text-decoration:underline; }
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.fp-layout { gap:48px; padding:32px 36px; }
|
|
||||||
.fp-brand { flex:0 0 260px; }
|
|
||||||
.fp-title { font-size:2.7rem; }
|
|
||||||
}
|
|
||||||
@media (max-width: 720px) {
|
|
||||||
body.auth-page { align-items:flex-start !important; overflow-y:auto !important; }
|
|
||||||
.fp-wrap { align-items:flex-start; min-height:auto; padding:24px 0 40px; }
|
|
||||||
.fp-layout { flex-direction:column; padding:0 20px; gap:28px; }
|
|
||||||
.fp-form-panel { order:2; max-width:100%; }
|
|
||||||
.fp-brand { order:1; flex:none; text-align:center; }
|
|
||||||
.fp-title { font-size:2.2rem; }
|
|
||||||
.fp-steps, .fp-desc, .fp-divider { display:none; }
|
|
||||||
.fp-sub { margin-bottom:0; }
|
|
||||||
.fp-card { padding:28px 20px; }
|
|
||||||
.fp-logo { width:56px; height:56px; margin:0 auto 14px; display:block; }
|
|
||||||
}
|
|
||||||
@media (max-width: 420px) {
|
|
||||||
.fp-title { font-size:1.85rem; }
|
|
||||||
.fp-card { padding:24px 16px; border-radius:16px; }
|
|
||||||
.fp-card-title { font-size:1.5rem; }
|
|
||||||
}
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.fp-layout { max-width:1160px; padding:40px 80px; }
|
|
||||||
.fp-brand { flex:0 0 360px; }
|
|
||||||
.fp-title { font-size:3.6rem; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="fp-wrap">
|
|
||||||
<div class="fp-bg"></div>
|
|
||||||
<div class="fp-ring r1"></div>
|
|
||||||
<div class="fp-ring r2"></div>
|
|
||||||
<div class="fp-dot d1"></div>
|
|
||||||
<div class="fp-dot d2"></div>
|
|
||||||
<div class="fp-line l1"></div>
|
|
||||||
|
|
||||||
<div class="fp-layout">
|
|
||||||
|
|
||||||
<!-- ═══ Brand (kiri) ═══ -->
|
|
||||||
<div class="fp-brand">
|
|
||||||
<img src="<?php echo e(asset('images/logo.png')); ?>" alt="Logo PKPPS" class="fp-logo">
|
|
||||||
<div class="fp-eyebrow">Reset Akses</div>
|
|
||||||
<h1 class="fp-title">Lupa<br><em>Password?</em></h1>
|
|
||||||
<p class="fp-sub">Jangan khawatir, kami bantu pulihkan.</p>
|
|
||||||
<div class="fp-divider"></div>
|
|
||||||
<p class="fp-desc">Ikuti langkah berikut untuk mengatur ulang password akun Super Admin Anda.</p>
|
|
||||||
|
|
||||||
<div class="fp-steps">
|
|
||||||
<div class="fp-step">
|
|
||||||
<div class="fp-step-num active">1</div>
|
|
||||||
<div class="fp-step-text">Masukkan email terdaftar <small>Kami kirim kode OTP 6 digit</small></div>
|
|
||||||
</div>
|
|
||||||
<div class="fp-step">
|
|
||||||
<div class="fp-step-num">2</div>
|
|
||||||
<div class="fp-step-text">Verifikasi kode OTP <small>Cek email masuk / spam</small></div>
|
|
||||||
</div>
|
|
||||||
<div class="fp-step">
|
|
||||||
<div class="fp-step-num">3</div>
|
|
||||||
<div class="fp-step-text">Buat password baru <small>Minimal 8 karakter</small></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ═══ Form (kanan) ═══ -->
|
|
||||||
<div class="fp-form-panel">
|
|
||||||
<div class="fp-card">
|
|
||||||
<div class="fp-card-icon">
|
|
||||||
<i class="fas fa-envelope-open-text"></i>
|
|
||||||
</div>
|
|
||||||
<div class="fp-card-lbl">Langkah 1 dari 3</div>
|
|
||||||
<div class="fp-card-title">Masukkan Email</div>
|
|
||||||
<div class="fp-card-desc">Masukkan email Super Admin yang terdaftar di sistem. Kami akan mengirim kode OTP ke email tersebut.</div>
|
|
||||||
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="fp-alert-danger">
|
|
||||||
<i class="fas fa-exclamation-circle"></i>
|
|
||||||
<?php echo e($errors->first()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="fp-alert-success" id="fpSuccessAlert">
|
|
||||||
<i class="fas fa-check-circle"></i>
|
|
||||||
<?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form method="POST" action="<?php echo e(route('admin.forgot.send_otp')); ?>">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="fp-field">
|
|
||||||
<label class="fp-lbl">Email Super Admin</label>
|
|
||||||
<div class="fp-shell">
|
|
||||||
<i class="fas fa-envelope fi" id="ico-email"></i>
|
|
||||||
<input type="email" id="email" name="email"
|
|
||||||
value="<?php echo e(old('email')); ?>"
|
|
||||||
placeholder="contoh@email.com"
|
|
||||||
required autofocus
|
|
||||||
onfocus="document.getElementById('ico-email').classList.add('active')"
|
|
||||||
onblur="document.getElementById('ico-email').classList.remove('active')">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="fp-btn">
|
|
||||||
<i class="fas fa-paper-plane"></i>
|
|
||||||
Kirim Kode OTP
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<a href="<?php echo e(route('admin.login')); ?>" class="fp-back">
|
|
||||||
<i class="fas fa-arrow-left"></i> Kembali ke Login
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
const sa = document.getElementById('fpSuccessAlert');
|
|
||||||
if (sa) {
|
|
||||||
setTimeout(() => {
|
|
||||||
sa.style.transition = 'opacity .5s ease';
|
|
||||||
sa.style.opacity = '0';
|
|
||||||
setTimeout(() => sa.remove(), 500);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
|
|
||||||
<?php echo $__env->make('auth.auth_layout', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/auth/forgot_password.blade.php ENDPATH**/ ?>
|
|
||||||
|
|
@ -1,426 +0,0 @@
|
||||||
<?php $__env->startSection('title', 'Login Admin'); ?>
|
|
||||||
|
|
||||||
<?php $__env->startSection('auth-content'); ?>
|
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:opsz,wght@9..40,300;400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body.auth-page {
|
|
||||||
background: #F8FDFB !important;
|
|
||||||
font-family: 'DM Sans', sans-serif !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
align-items: stretch !important;
|
|
||||||
min-height: 100vh !important;
|
|
||||||
}
|
|
||||||
.auth-container {
|
|
||||||
width: 100vw !important; max-width: 100vw !important;
|
|
||||||
min-height: 100vh !important; background: transparent !important;
|
|
||||||
padding: 0 !important; border-radius: 0 !important; box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Wrapper & Background ── */
|
|
||||||
.lg-wrap {
|
|
||||||
position: relative; width: 100%; min-height: 100vh;
|
|
||||||
display: flex; align-items: center; justify-content: center;
|
|
||||||
overflow: hidden; font-family: 'DM Sans', sans-serif;
|
|
||||||
}
|
|
||||||
.lg-bg {
|
|
||||||
position: absolute; inset: 0; z-index: 0;
|
|
||||||
background:
|
|
||||||
radial-gradient(ellipse 80% 60% at 70% 50%, rgba(111,186,157,.12) 0%, transparent 60%),
|
|
||||||
radial-gradient(ellipse 50% 80% at 10% 80%, rgba(111,186,157,.08) 0%, transparent 55%),
|
|
||||||
#F8FDFB;
|
|
||||||
}
|
|
||||||
.lg-bg::before {
|
|
||||||
content: ''; position: absolute; inset: 0;
|
|
||||||
background-image:
|
|
||||||
linear-gradient(rgba(111,186,157,.055) 1px, transparent 1px),
|
|
||||||
linear-gradient(90deg, rgba(111,186,157,.055) 1px, transparent 1px);
|
|
||||||
background-size: 48px 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decorations */
|
|
||||||
.lg-ring { position: absolute; border-radius: 50%; border: 1.5px solid rgba(111,186,157,.18); pointer-events: none; }
|
|
||||||
.lg-ring.r1 { width:420px; height:420px; top:-110px; right:-110px; }
|
|
||||||
.lg-ring.r2 { width:270px; height:270px; bottom:50px; right:60px; border-color:rgba(111,186,157,.10); }
|
|
||||||
.lg-ring.r3 { width:200px; height:200px; bottom:-50px; left:60px; border-color:rgba(111,186,157,.14); }
|
|
||||||
.lg-dot { position:absolute; border-radius:50%; background:#6FBA9D; pointer-events:none; }
|
|
||||||
.lg-dot.d1 { width:8px; height:8px; top:22%; right:18%; opacity:.14; }
|
|
||||||
.lg-dot.d2 { width:5px; height:5px; bottom:40%; right:30%; opacity:.09; }
|
|
||||||
.lg-dot.d3 { width:11px; height:11px; top:55%; left:15%; opacity:.08; }
|
|
||||||
.lg-line { position:absolute; height:1px; background:linear-gradient(90deg,transparent,rgba(111,186,157,.14),transparent); pointer-events:none; }
|
|
||||||
.lg-line.l1 { width:280px; top:28%; left:-60px; transform:rotate(-15deg); }
|
|
||||||
.lg-line.l2 { width:220px; bottom:30%; right:-40px; transform:rotate(18deg); }
|
|
||||||
|
|
||||||
/* Layout */
|
|
||||||
.lg-layout {
|
|
||||||
position: relative; z-index: 2;
|
|
||||||
display: flex; align-items: center;
|
|
||||||
width: 100%; max-width: 1100px;
|
|
||||||
padding: 40px 60px; gap: 80px;
|
|
||||||
animation: lgIn .6s ease both;
|
|
||||||
}
|
|
||||||
@keyframes lgIn {
|
|
||||||
from { opacity:0; transform:translateY(20px); }
|
|
||||||
to { opacity:1; transform:translateY(0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Brand left, Form right */
|
|
||||||
.lg-brand { flex: 0 0 340px; order: 1; }
|
|
||||||
.lg-form-panel { flex: 1; max-width: 430px; order: 2; }
|
|
||||||
|
|
||||||
/* ── Brand section ── */
|
|
||||||
.lg-logo { width:72px; height:72px; margin-bottom:20px; border-radius:16px; box-shadow:0 4px 20px rgba(111,186,157,.2); object-fit:contain; background:#fff; }
|
|
||||||
.lg-eyebrow {
|
|
||||||
display:inline-flex; align-items:center; gap:8px;
|
|
||||||
font-size:.68rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:18px;
|
|
||||||
}
|
|
||||||
.lg-eyebrow::before {
|
|
||||||
content:''; display:inline-block; width:22px; height:2px;
|
|
||||||
background:#6FBA9D; border-radius:2px;
|
|
||||||
}
|
|
||||||
.lg-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:3.2rem; line-height:1.05; color:#0F2118; margin-bottom:6px;
|
|
||||||
}
|
|
||||||
.lg-title em { font-style:italic; color:#5EA98C; }
|
|
||||||
.lg-sub { font-size:.9rem; font-weight:500; color:#8AADA0; margin-bottom:32px; line-height:1.6; }
|
|
||||||
.lg-divider { width:44px; height:3px; background:linear-gradient(90deg,#6FBA9D,#A8D8C6); border-radius:3px; margin-bottom:24px; }
|
|
||||||
.lg-desc { font-size:.81rem; color:#8AADA0; line-height:1.8; max-width:290px; margin-bottom:32px; }
|
|
||||||
.lg-features { display:flex; flex-direction:column; gap:11px; }
|
|
||||||
.lg-feat { display:flex; align-items:center; gap:11px; font-size:.79rem; color:#2A4235; font-weight:500; }
|
|
||||||
.lg-feat-ico {
|
|
||||||
width:30px; height:30px; border-radius:8px; background:#EBF7F2;
|
|
||||||
display:flex; align-items:center; justify-content:center;
|
|
||||||
color:#3D8A6E; font-size:.73rem; flex-shrink:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Card ── */
|
|
||||||
.lg-card {
|
|
||||||
background: #fff; border-radius: 24px;
|
|
||||||
padding: 42px 38px;
|
|
||||||
box-shadow:
|
|
||||||
0 0 0 1px rgba(111,186,157,.1),
|
|
||||||
0 4px 6px rgba(15,33,24,.03),
|
|
||||||
0 20px 44px rgba(15,33,24,.08);
|
|
||||||
position: relative; overflow: hidden;
|
|
||||||
}
|
|
||||||
.lg-card::before {
|
|
||||||
content: ''; position:absolute; top:0; left:0; right:0; height:3px;
|
|
||||||
background: linear-gradient(90deg, #6FBA9D, #A8D8C6, #6FBA9D);
|
|
||||||
}
|
|
||||||
.lg-card::after {
|
|
||||||
content: ''; position:absolute; bottom:-50px; right:-50px;
|
|
||||||
width:140px; height:140px; border-radius:50%;
|
|
||||||
background: radial-gradient(circle, rgba(111,186,157,.06) 0%, transparent 70%);
|
|
||||||
}
|
|
||||||
.lg-card-lbl {
|
|
||||||
font-size:.67rem; font-weight:700; letter-spacing:2px;
|
|
||||||
text-transform:uppercase; color:#6FBA9D; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.lg-card-title {
|
|
||||||
font-family:'DM Serif Display',serif;
|
|
||||||
font-size:1.85rem; color:#0F2118; line-height:1.1; margin-bottom:5px;
|
|
||||||
}
|
|
||||||
.lg-card-desc { font-size:.79rem; color:#8AADA0; line-height:1.6; margin-bottom:26px; }
|
|
||||||
|
|
||||||
/* Alert */
|
|
||||||
.lg-alert-danger {
|
|
||||||
border-radius:10px; padding:10px 13px; font-size:.79rem;
|
|
||||||
margin-bottom:18px; background:#FFF3F3; color:#c62828; border-left:3px solid #e53935;
|
|
||||||
display:flex; align-items:center; gap:7px;
|
|
||||||
}
|
|
||||||
.lg-alert-success {
|
|
||||||
border-radius:10px; padding:10px 13px; font-size:.79rem;
|
|
||||||
margin-bottom:18px; background:#F0FFF4; color:#2E7D32; border-left:3px solid #43A047;
|
|
||||||
display:flex; align-items:center; gap:7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fields */
|
|
||||||
.lg-field { margin-bottom:15px; }
|
|
||||||
.lg-lbl {
|
|
||||||
display:block; font-size:.7rem; font-weight:700;
|
|
||||||
letter-spacing:.8px; text-transform:uppercase; color:#2A4235; margin-bottom:7px;
|
|
||||||
}
|
|
||||||
.lg-shell { position:relative; display:flex; align-items:center; }
|
|
||||||
.lg-shell .fi { position:absolute; left:15px; color:#A8D8C6; font-size:.8rem; pointer-events:none; transition:color .2s; }
|
|
||||||
.lg-shell input {
|
|
||||||
width:100%; padding:12px 15px 12px 40px;
|
|
||||||
background:#EBF7F2; border:1.5px solid transparent;
|
|
||||||
border-radius:11px; font-family:inherit; font-size:.87rem; color:#0F2118; outline:none;
|
|
||||||
transition:all .2s;
|
|
||||||
}
|
|
||||||
.lg-shell input::placeholder { color:#8AADA0; font-size:.83rem; }
|
|
||||||
.lg-shell input:focus {
|
|
||||||
background:#fff; border-color:#6FBA9D;
|
|
||||||
box-shadow:0 0 0 4px rgba(111,186,157,.12);
|
|
||||||
}
|
|
||||||
.lg-shell .fi.active { color:#6FBA9D; }
|
|
||||||
.lg-show {
|
|
||||||
position:absolute; right:13px;
|
|
||||||
background:none; border:none; font-size:.68rem; font-weight:800;
|
|
||||||
letter-spacing:.8px; color:#5EA98C; cursor:pointer; font-family:inherit;
|
|
||||||
}
|
|
||||||
.lg-show:hover { color:#3D8A6E; }
|
|
||||||
|
|
||||||
/* Remember + Forgot row */
|
|
||||||
.lg-options {
|
|
||||||
display:flex; align-items:center; justify-content:space-between;
|
|
||||||
margin-bottom:18px; font-size:.78rem;
|
|
||||||
}
|
|
||||||
.lg-remember { display:flex; align-items:center; gap:7px; color:#2A4235; font-weight:500; cursor:pointer; }
|
|
||||||
.lg-remember input[type="checkbox"] {
|
|
||||||
width:16px; height:16px; accent-color:#6FBA9D; cursor:pointer;
|
|
||||||
}
|
|
||||||
.lg-forgot { color:#e57373; font-weight:600; text-decoration:none; transition:color .2s; }
|
|
||||||
.lg-forgot:hover { color:#c62828; text-decoration:underline; }
|
|
||||||
|
|
||||||
/* Buttons */
|
|
||||||
.lg-btn {
|
|
||||||
width:100%; padding:13px;
|
|
||||||
background:linear-gradient(135deg, #6FBA9D, #5EA98C);
|
|
||||||
color:#fff; border:none; border-radius:12px;
|
|
||||||
font-family:inherit; font-size:.89rem; font-weight:700;
|
|
||||||
cursor:pointer; letter-spacing:.3px; margin-top:6px;
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:8px;
|
|
||||||
box-shadow:0 4px 18px rgba(94,169,140,.35);
|
|
||||||
transition:all .25s;
|
|
||||||
}
|
|
||||||
.lg-btn:hover { transform:translateY(-2px); box-shadow:0 8px 26px rgba(94,169,140,.45); }
|
|
||||||
.lg-btn:active { transform:none; }
|
|
||||||
|
|
||||||
.lg-foot { text-align:center; font-size:.77rem; color:#8AADA0; margin-top:20px; }
|
|
||||||
.lg-foot a { color:#5EA98C; font-weight:700; text-decoration:none; }
|
|
||||||
.lg-foot a:hover { text-decoration:underline; }
|
|
||||||
|
|
||||||
/* Santri separator */
|
|
||||||
.lg-sep {
|
|
||||||
display:flex; align-items:center; gap:12px; margin-top:22px;
|
|
||||||
font-size:.7rem; color:#B8D4C8; letter-spacing:1px; text-transform:uppercase; font-weight:600;
|
|
||||||
}
|
|
||||||
.lg-sep::before, .lg-sep::after {
|
|
||||||
content:''; flex:1; height:1px; background:linear-gradient(90deg,transparent,#D6EDE5,transparent);
|
|
||||||
}
|
|
||||||
.lg-santri-link {
|
|
||||||
display:flex; align-items:center; justify-content:center; gap:8px;
|
|
||||||
margin-top:12px; padding:10px;
|
|
||||||
background:#EBF7F2; border:1.5px solid transparent; border-radius:10px;
|
|
||||||
font-size:.8rem; font-weight:600; color:#3D8A6E; text-decoration:none;
|
|
||||||
transition:all .2s;
|
|
||||||
}
|
|
||||||
.lg-santri-link:hover {
|
|
||||||
border-color:#6FBA9D; background:#fff; box-shadow:0 0 0 3px rgba(111,186,157,.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.lg-layout { gap:48px; padding:32px 36px; }
|
|
||||||
.lg-brand { flex:0 0 260px; }
|
|
||||||
.lg-title { font-size:2.7rem; }
|
|
||||||
}
|
|
||||||
@media (max-width: 720px) {
|
|
||||||
body.auth-page { align-items:flex-start !important; overflow-y:auto !important; }
|
|
||||||
.lg-wrap { align-items:flex-start; min-height:auto; padding:24px 0 40px; }
|
|
||||||
.lg-layout { flex-direction:column; padding:0 20px; gap:28px; }
|
|
||||||
.lg-form-panel { order:2; max-width:100%; }
|
|
||||||
.lg-brand { order:1; flex:none; text-align:center; }
|
|
||||||
.lg-title { font-size:2.2rem; }
|
|
||||||
.lg-features, .lg-desc, .lg-divider { display:none; }
|
|
||||||
.lg-sub { margin-bottom:0; }
|
|
||||||
.lg-card { padding:28px 20px; }
|
|
||||||
.lg-ring.r1 { width:260px; height:260px; top:-70px; right:-70px; }
|
|
||||||
.lg-ring.r2 { display:none; }
|
|
||||||
.lg-logo { width:56px; height:56px; margin:0 auto 14px; display:block; }
|
|
||||||
}
|
|
||||||
@media (max-width: 420px) {
|
|
||||||
.lg-title { font-size:1.85rem; }
|
|
||||||
.lg-card { padding:24px 16px; border-radius:16px; }
|
|
||||||
.lg-card-title { font-size:1.5rem; }
|
|
||||||
.lg-options { flex-direction:column; align-items:flex-start; gap:10px; }
|
|
||||||
}
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.lg-layout { max-width:1160px; padding:40px 80px; }
|
|
||||||
.lg-brand { flex:0 0 360px; }
|
|
||||||
.lg-title { font-size:3.6rem; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="lg-wrap">
|
|
||||||
<div class="lg-bg"></div>
|
|
||||||
<div class="lg-ring r1"></div>
|
|
||||||
<div class="lg-ring r2"></div>
|
|
||||||
<div class="lg-ring r3"></div>
|
|
||||||
<div class="lg-dot d1"></div>
|
|
||||||
<div class="lg-dot d2"></div>
|
|
||||||
<div class="lg-dot d3"></div>
|
|
||||||
<div class="lg-line l1"></div>
|
|
||||||
<div class="lg-line l2"></div>
|
|
||||||
|
|
||||||
<div class="lg-layout">
|
|
||||||
|
|
||||||
<!-- ═══ Brand (kiri) ═══ -->
|
|
||||||
<div class="lg-brand">
|
|
||||||
<img src="<?php echo e(asset('images/logo.png')); ?>" alt="Logo PKPPS" class="lg-logo">
|
|
||||||
<div class="lg-eyebrow">Selamat Datang</div>
|
|
||||||
<h1 class="lg-title">Masuk ke<br>Panel<br><em>Admin.</em></h1>
|
|
||||||
<p class="lg-sub">PKPPS Riyadlul Jannah</p>
|
|
||||||
<div class="lg-divider"></div>
|
|
||||||
<p class="lg-desc">Kelola data santri, absensi, keuangan, dan seluruh aktivitas pesantren dalam satu sistem terpadu.</p>
|
|
||||||
<div class="lg-features">
|
|
||||||
<div class="lg-feat">
|
|
||||||
<div class="lg-feat-ico"><i class="fas fa-chart-line"></i></div>
|
|
||||||
<span>Dashboard monitoring real-time</span>
|
|
||||||
</div>
|
|
||||||
<div class="lg-feat">
|
|
||||||
<div class="lg-feat-ico"><i class="fas fa-shield-alt"></i></div>
|
|
||||||
<span>Akses aman berbasis role</span>
|
|
||||||
</div>
|
|
||||||
<div class="lg-feat">
|
|
||||||
<div class="lg-feat-ico"><i class="fas fa-mobile-alt"></i></div>
|
|
||||||
<span>Terintegrasi aplikasi mobile wali</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ═══ Form (kanan) ═══ -->
|
|
||||||
<div class="lg-form-panel">
|
|
||||||
<div class="lg-card">
|
|
||||||
<div class="lg-card-lbl">Login Admin</div>
|
|
||||||
<div class="lg-card-title">Masuk Akun</div>
|
|
||||||
<div class="lg-card-desc">Masukkan username dan password untuk mengakses panel admin.</div>
|
|
||||||
|
|
||||||
<?php if($errors->any()): ?>
|
|
||||||
<div class="lg-alert-danger">
|
|
||||||
<i class="fas fa-exclamation-circle"></i>
|
|
||||||
<?php echo e($errors->first()); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if(session('success')): ?>
|
|
||||||
<div class="lg-alert-success" id="lgSuccessAlert">
|
|
||||||
<i class="fas fa-check-circle"></i>
|
|
||||||
<?php echo e(session('success')); ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form method="POST" action="<?php echo e(route('admin.login')); ?>" id="adminLoginForm">
|
|
||||||
<?php echo csrf_field(); ?>
|
|
||||||
|
|
||||||
<div class="lg-field">
|
|
||||||
<label class="lg-lbl">Username</label>
|
|
||||||
<div class="lg-shell">
|
|
||||||
<i class="fas fa-user fi" id="ico-u"></i>
|
|
||||||
<input type="text" id="username" name="username"
|
|
||||||
value="<?php echo e(old('username')); ?>"
|
|
||||||
placeholder="Masukkan username admin"
|
|
||||||
autocomplete="username" required autofocus
|
|
||||||
onfocus="document.getElementById('ico-u').classList.add('active')"
|
|
||||||
onblur="document.getElementById('ico-u').classList.remove('active')">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="lg-field">
|
|
||||||
<label class="lg-lbl">Password</label>
|
|
||||||
<div class="lg-shell">
|
|
||||||
<i class="fas fa-lock fi" id="ico-p"></i>
|
|
||||||
<input type="password" id="password" name="password"
|
|
||||||
placeholder="Masukkan password"
|
|
||||||
autocomplete="current-password" required
|
|
||||||
onfocus="document.getElementById('ico-p').classList.add('active')"
|
|
||||||
onblur="document.getElementById('ico-p').classList.remove('active')">
|
|
||||||
<button type="button" class="lg-show" id="lgTglBtn">SHOW</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="lg-options">
|
|
||||||
<label class="lg-remember">
|
|
||||||
<input type="checkbox" name="remember" id="remember"> Ingat Saya
|
|
||||||
</label>
|
|
||||||
<a href="<?php echo e(route('admin.forgot.email_form')); ?>" class="lg-forgot">
|
|
||||||
<i class="fas fa-key"></i> Lupa Password?
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="lg-btn">
|
|
||||||
<i class="fas fa-sign-in-alt"></i>
|
|
||||||
Login
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="lg-foot">
|
|
||||||
Admin baru? <a href="<?php echo e(route('admin.register')); ?>">Daftar Sekarang</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="lg-sep">atau</div>
|
|
||||||
<a href="<?php echo e(route('santri.login')); ?>" class="lg-santri-link">
|
|
||||||
<i class="fas fa-user-graduate"></i> Login sebagai Santri / Wali
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Toggle password
|
|
||||||
const btn = document.getElementById('lgTglBtn');
|
|
||||||
const pw = document.getElementById('password');
|
|
||||||
if (btn && pw) {
|
|
||||||
btn.addEventListener('click', () => {
|
|
||||||
const isP = pw.type === 'password';
|
|
||||||
pw.type = isP ? 'text' : 'password';
|
|
||||||
btn.textContent = isP ? 'HIDE' : 'SHOW';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// CSRF check
|
|
||||||
const form = document.getElementById('adminLoginForm');
|
|
||||||
if (form) {
|
|
||||||
form.addEventListener('submit', function(e) {
|
|
||||||
const csrf = document.querySelector('input[name="_token"]');
|
|
||||||
if (!csrf || !csrf.value || csrf.value.length < 40) {
|
|
||||||
e.preventDefault();
|
|
||||||
alert('Session expired. Halaman akan dimuat ulang.');
|
|
||||||
window.location.reload();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear error on input
|
|
||||||
const alertBox = document.querySelector('.lg-alert-danger');
|
|
||||||
if (alertBox) {
|
|
||||||
['username','password'].forEach(id => {
|
|
||||||
const el = document.getElementById(id);
|
|
||||||
if (el) el.addEventListener('input', () => alertBox.style.display = 'none');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto-hide success
|
|
||||||
const sa = document.getElementById('lgSuccessAlert');
|
|
||||||
if (sa) {
|
|
||||||
setTimeout(() => {
|
|
||||||
sa.style.transition = 'opacity .5s ease';
|
|
||||||
sa.style.opacity = '0';
|
|
||||||
setTimeout(() => sa.remove(), 500);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Focus management
|
|
||||||
const u = document.getElementById('username');
|
|
||||||
const p = document.getElementById('password');
|
|
||||||
if (u && !u.value) u.focus();
|
|
||||||
if (u && p) {
|
|
||||||
u.addEventListener('keypress', e => {
|
|
||||||
if (e.key === 'Enter') { e.preventDefault(); p.focus(); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php $__env->stopSection(); ?>
|
|
||||||
<?php echo $__env->make('auth.auth_layout', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/auth/login.blade.php ENDPATH**/ ?>
|
|
||||||
Loading…
Reference in New Issue