From 6d157a17c9746c019a6e0099fc2622e0f52d693a Mon Sep 17 00:00:00 2001 From: GuavaPopper Date: Wed, 3 Jun 2026 20:59:08 +0700 Subject: [PATCH] feat: add bulk delete for ibadah and miskin with checkboxes (admin-only) --- app/Http/Controllers/IbadahController.php | 14 +++++ app/Http/Controllers/MiskinController.php | 14 +++++ resources/views/data.blade.php | 75 ++++++++++++++++++++++- routes/web.php | 3 + 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/IbadahController.php b/app/Http/Controllers/IbadahController.php index 4719eef..580a937 100644 --- a/app/Http/Controllers/IbadahController.php +++ b/app/Http/Controllers/IbadahController.php @@ -72,4 +72,18 @@ class IbadahController extends Controller ActivityLog::record('delete', "Menghapus rumah ibadah: {$ibadah->nama}", 'ibadah', $id); return response()->json(['success' => true]); } + + public function bulkDestroy(Request $request) + { + $validated = $request->validate([ + 'ids' => 'required|array|min:1', + 'ids.*' => 'integer', + ]); + + $count = RumahIbadah::whereIn('id', $validated['ids'])->count(); + RumahIbadah::whereIn('id', $validated['ids'])->delete(); + + ActivityLog::record('bulk_delete', "Menghapus massal {$count} rumah ibadah", 'ibadah'); + return response()->json(['success' => true, 'deleted' => $count]); + } } diff --git a/app/Http/Controllers/MiskinController.php b/app/Http/Controllers/MiskinController.php index 30fc537..72d95ef 100644 --- a/app/Http/Controllers/MiskinController.php +++ b/app/Http/Controllers/MiskinController.php @@ -62,4 +62,18 @@ class MiskinController extends Controller ActivityLog::record('delete', "Menghapus keluarga miskin: {$id_rumah}", 'miskin', $id_rumah); return response()->json(['success' => true]); } + + public function bulkDestroy(Request $request) + { + $validated = $request->validate([ + 'ids' => 'required|array|min:1', + 'ids.*' => 'string', + ]); + + $count = RumahMiskin::whereIn('id_rumah', $validated['ids'])->count(); + RumahMiskin::whereIn('id_rumah', $validated['ids'])->delete(); + + ActivityLog::record('bulk_delete', "Menghapus massal {$count} keluarga miskin", 'miskin'); + return response()->json(['success' => true, 'deleted' => $count]); + } } diff --git a/resources/views/data.blade.php b/resources/views/data.blade.php index fe21041..bc9741e 100644 --- a/resources/views/data.blade.php +++ b/resources/views/data.blade.php @@ -132,10 +132,19 @@
+ @if(auth()->user()->hasRole('administrator')) + + @endif
+ @if(auth()->user()->hasRole('administrator')) + + @endif @@ -152,10 +161,19 @@
+ @if(auth()->user()->hasRole('administrator')) + + @endif
# Nama Jenis
+ @if(auth()->user()->hasRole('administrator')) + + @endif @@ -308,6 +326,9 @@ const canEditIbadah = ['administrator', 'pengurus_ibadah'].includes(authUserRole); const canEditMiskin = ['administrator', 'petugas_pendataan'].includes(authUserRole); const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); + const isAdmin = authUserRole === 'administrator'; + let selectedIbadah = new Set(); + let selectedMiskin = new Set(); let ibadahData = [], miskinData = []; document.addEventListener('DOMContentLoaded', loadAllData); @@ -340,6 +361,7 @@ const canEditThis = canEditIbadah && (authUserRole === 'administrator' || item.user_id === authUserId); return ` + ${isAdmin ? `` : ''} `; - }).join('') : ''; + }).join('') : ''; // Miskin Table const bodyM = document.getElementById('bodyMiskin'); bodyM.innerHTML = dataM.length ? dataM.map(item => ` + ${isAdmin ? `` : ''} - `).join('') : ''; + `).join('') : ''; } function filterData() { @@ -532,6 +555,54 @@ } } + // ── BULK DELETE ───────────────────────────────────────────── + function toggleSelect(type, id, checked) { + const set = type === 'ibadah' ? selectedIbadah : selectedMiskin; + if (checked) set.add(String(id)); else set.delete(String(id)); + updateBulkBar(type); + } + + function toggleSelectAll(type, checked) { + const set = type === 'ibadah' ? selectedIbadah : selectedMiskin; + set.clear(); + if (checked) { + (type === 'ibadah' ? ibadahData : miskinData).forEach(it => + set.add(String(type === 'ibadah' ? it.id : it.id_rumah))); + } + renderTables(); + updateBulkBar(type); + } + + function updateBulkBar(type) { + const set = type === 'ibadah' ? selectedIbadah : selectedMiskin; + const bar = document.getElementById(`bulkBar_${type}`); + if (!bar) return; + bar.classList.toggle('hidden', set.size === 0); + document.getElementById(`bulkCount_${type}`).textContent = set.size; + } + + async function bulkDelete(type) { + const set = type === 'ibadah' ? selectedIbadah : selectedMiskin; + const ids = [...set]; + if (!ids.length) return; + if (!confirm(`Hapus ${ids.length} data terpilih secara permanen?`)) return; + + const res = await fetch(`{{ url('/api/admin') }}/${type}/bulk-delete`, { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, + body: JSON.stringify({ ids }), + }); + const json = await res.json(); + if (json.success) { + showToast(`${json.deleted} data dihapus`, 'success'); + set.clear(); + updateBulkBar(type); + loadAllData(); + } else { + showToast('Gagal hapus massal', 'error'); + } + } + let deleteTarget = null; function prepDelete(type, id) { deleteTarget = { type, id }; diff --git a/routes/web.php b/routes/web.php index 4553b2d..0d7997d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -57,6 +57,9 @@ Route::middleware('auth')->group(function () { Route::put('/users/{id}', [AdminUserController::class, 'update']); Route::delete('/users/{id}', [AdminUserController::class, 'destroy']); Route::put('/users/{id}/password', [AdminUserController::class, 'resetPassword']); + + Route::post('/ibadah/bulk-delete', [IbadahController::class, 'bulkDestroy']); + Route::post('/miskin/bulk-delete', [MiskinController::class, 'bulkDestroy']); }); }); });
ID Nama KK KK/Jiwa
${i + 1}
${item.nama}
@@ -359,12 +381,13 @@
Belum ada data
Belum ada data
${item.id_rumah}
${item.nama_kk || '-'}
@@ -384,7 +407,7 @@
Belum ada data
Belum ada data