feat: filter Jenis Pelanggaran di Laporan Rekap — dropdown kategori+jenis (poin), berlaku untuk tampilan & cetak PDF

This commit is contained in:
Novy San87
2026-08-06 22:43:27 +07:00
parent 7ed2d7e1b3
commit 0013facf5f
3 changed files with 33 additions and 5 deletions
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Classes;
use App\Models\Setting;
use App\Models\ViolationType;
use App\Models\Violation;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Database\Eloquent\Builder;
@@ -19,6 +20,10 @@ class ViolationReportController extends Controller
public function index(Request $request): View
{
$classes = Classes::orderBy('name')->get();
$violationTypes = ViolationType::with('category')
->orderBy('category_id')
->orderBy('name')
->get();
$filters = $this->filters($request);
$query = $this->baseQuery($filters);
@@ -30,7 +35,7 @@ class ViolationReportController extends Controller
->limit(20)
->get();
return view('reports.violations', compact('classes', 'filters', 'stats', 'recent'));
return view('reports.violations', compact('classes', 'violationTypes', 'filters', 'stats', 'recent'));
}
public function pdf(Request $request)
@@ -85,9 +90,12 @@ class ViolationReportController extends Controller
$periode = ($filters['date_from'] ?? 'Awal').' s/d '.($filters['date_to'] ?? 'Sekarang');
$filterKelas = $filters['class_id'] ? (Classes::find($filters['class_id'])?->name ?? '-') : 'Semua Kelas';
$filterJenis = $filters['violation_type_id']
? (ViolationType::find($filters['violation_type_id'])?->name ?? '-')
: 'Semua Jenis Pelanggaran';
$pdf = Pdf::loadView('reports.violation-report-pdf', compact(
'violations', 'summary', 'perJenis', 'perKelas', 'school', 'periode', 'filterKelas'
'violations', 'summary', 'perJenis', 'perKelas', 'school', 'periode', 'filterKelas', 'filterJenis'
))->setPaper('a4', 'landscape');
return $pdf->download('rekap-pelanggaran-'.now()->format('Ymd-His').'.pdf');
@@ -104,6 +112,7 @@ class ViolationReportController extends Controller
'date_from' => ['nullable', 'date'],
'date_to' => ['nullable', 'date', 'after_or_equal:date_from'],
'class_id' => ['nullable', 'integer', 'exists:classes,id'],
'violation_type_id' => ['nullable', 'integer', 'exists:violation_types,id'],
];
$data = $validate ? $request->validate($rules) : $request->validate($rules);
@@ -112,6 +121,7 @@ class ViolationReportController extends Controller
'date_from' => $data['date_from'] ?? null,
'date_to' => $data['date_to'] ?? null,
'class_id' => isset($data['class_id']) ? (int) $data['class_id'] : null,
'violation_type_id' => isset($data['violation_type_id']) ? (int) $data['violation_type_id'] : null,
];
}
@@ -124,6 +134,7 @@ class ViolationReportController extends Controller
->when($filters['date_from'], fn ($q) => $q->whereDate('violation_date', '>=', $filters['date_from']))
->when($filters['date_to'], fn ($q) => $q->whereDate('violation_date', '<=', $filters['date_to']))
->when($filters['class_id'], fn ($q) => $q->whereHas('student', fn ($qq) => $qq->where('class_id', $filters['class_id'])))
->when($filters['violation_type_id'], fn ($q) => $q->where('violation_type_id', $filters['violation_type_id']))
->when(auth()->user()->isScopedWaliKelas(), fn ($q) => $q->whereHas('student', fn ($qq) => $qq->whereIn('class_id', auth()->user()->homeroomClassIds())));
}
@@ -68,7 +68,7 @@
{{-- Judul --}}
<div class="judul">
<h2>Rekap Laporan Pelanggaran Siswa</h2>
<p>Periode: {{ $periode }} &nbsp;•&nbsp; Kelas: {{ $filterKelas }}</p>
<p>Periode: {{ $periode }} &nbsp;•&nbsp; Kelas: {{ $filterKelas }} &nbsp;•&nbsp; Jenis: {{ $filterJenis }}</p>
</div>
{{-- Ringkasan --}}
+19 -2
View File
@@ -46,7 +46,7 @@
{{-- ===== Filter Bar ===== --}}
<form method="GET" action="{{ route('reports.violations') }}" id="filter-form"
class="bg-white rounded-2xl shadow-sm border border-slate-200 p-5">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3">
<div>
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">Dari Tanggal</label>
<div class="relative">
@@ -75,6 +75,21 @@
@endforeach
</select>
<i class="fa-solid fa-chevron-down absolute right-3.5 top-1/2 -translate-y-1/2 text-gray-400 text-xs pointer-events-none"></i>
</div>
<div>
<label class="block text-xs font-semibold text-gray-500 uppercase tracking-wider mb-1.5">Jenis Pelanggaran</label>
<div class="relative">
<i class="fa-solid fa-tag absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-400 text-sm pointer-events-none"></i>
<select name="violation_type_id" x-model="jenisId"
class="w-full pl-9 pr-3 py-2.5 border border-slate-200 rounded-xl text-sm bg-gray-50/50 focus:bg-white focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition appearance-none">
<option value="">— Semua Jenis —</option>
@foreach ($violationTypes as $type)
<option value="{{ $type->id }}" @selected($filters['violation_type_id'] == $type->id)>
{{ $type->category?->name ? '['.$type->category->name.'] ' : '' }}{{ $type->name }} ({{ $type->points }} poin)
</option>
@endforeach
</select>
<i class="fa-solid fa-chevron-down absolute right-3.5 top-1/2 -translate-y-1/2 text-gray-400 text-xs pointer-events-none"></i>
</div>
</div>
<div class="flex items-end">
@@ -251,7 +266,7 @@
<span class="w-8 h-8 rounded-lg bg-amber-50 text-amber-600 flex items-center justify-center"><i class="fa-solid fa-list-check text-sm"></i></span>
Rincian Pelanggaran Terbaru
</h3>
<a href="{{ route('violations.index', request()->only(['date_from', 'date_to'])) }}"
<a href="{{ route('violations.index', request()->only(['date_from', 'date_to', 'violation_type_id'])) }}"
class="text-xs font-semibold text-blue-600 hover:text-blue-800 inline-flex items-center gap-1.5">
Lihat Semua <i class="fa-solid fa-arrow-right text-[10px]"></i>
</a>
@@ -311,6 +326,7 @@
dateFrom: {{ json_encode($filters['date_from'] ?? '') }},
dateTo: {{ json_encode($filters['date_to'] ?? '') }},
classId: {{ json_encode($filters['class_id'] ?? '') }},
jenisId: {{ json_encode($filters['violation_type_id'] ?? '') }},
applyPreset(from, to) {
this.dateFrom = from;
this.dateTo = to;
@@ -320,6 +336,7 @@
this.dateFrom = '';
this.dateTo = '';
this.classId = '';
this.jenisId = '';
this.$nextTick(() => document.getElementById('filter-form').submit());
},
};