feat: penanganan pelanggaran (handling system)

- Migration: handling_status, handled_at, handled_by ke violations
- Migration: tabel violation_handlings, handling_participants
- Model: ViolationHandling, HandlingParticipant + relasi
- Routes: storeHandling, resolveHandling, destroyHandling, calendar data
- ViolationController: CRUD penanganan + filter status handling
- DashboardController: data handling stats + calendar endpoint
- Dashboard view: kalender pelanggaran interaktif (Alpine.js)
- Violations index: filter status penanganan + kolom status
- Violations show: stat card penanganan + timeline + modal tambah
- Menambahkan handling_status filter di index
This commit is contained in:
Bro
2026-07-22 22:19:19 +07:00
parent f86aa84d12
commit 8529a49174
24 changed files with 2152 additions and 842 deletions
+21 -7
View File
@@ -29,7 +29,7 @@
<img src="{{ asset('storage/' . $logoPath) }}" alt="Logo" class="w-full h-full object-contain p-0.5">
@else
<div class="w-full h-full bg-gradient-to-br from-blue-500 to-sky-400 flex items-center justify-center">
<svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/></svg>
<i class="fa-solid fa-shield-halved"></i>
</div>
@endif
</div>
@@ -136,9 +136,7 @@
<div class="w-9 h-9 rounded-xl bg-gradient-to-br from-blue-500 to-sky-400 flex items-center justify-center text-white text-sm font-bold shadow-sm">
{{ strtoupper(substr(auth()->user()->name, 0, 1)) }}
</div>
<svg class="w-3.5 h-3.5 text-gray-400 transition-transform duration-200" :class="{ 'rotate-180': showUserMenu }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
<i class="fa-solid fa-chevron-down"></i>
</button>
{{-- Dropdown --}}
@@ -168,9 +166,7 @@
@csrf
<button type="submit"
class="w-full flex items-center gap-3 px-4 py-2.5 text-sm text-gray-600 hover:text-blue-600 hover:bg-red-50 transition">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"/>
</svg>
<i class="fa-solid fa-right-from-bracket"></i>
Logout
</button>
</form>
@@ -278,5 +274,23 @@
}));
});
</script>
{{-- Global helpers --}}
<script>
window.confirmSwal = async function (opts = {}) {
const result = await Swal.fire({
title: opts.title || 'Konfirmasi',
text: opts.text || 'Yakin ingin melanjutkan?',
icon: opts.icon || 'warning',
showCancelButton: true,
confirmButtonColor: opts.confirmColor || '#dc2626',
cancelButtonColor: '#6b7280',
confirmButtonText: opts.confirmText || 'Ya, hapus!',
cancelButtonText: 'Batal',
reverseButtons: true,
});
return result.isConfirmed;
};
</script>
</body>
</html>