- Header card gradient biru + watermark, judul extrabold
- Input/label seragam (.input, label xs bold slate)
- 5 seksi dengan icon chip: Identitas (school), Kop Surat (file-lines),
Background Login (image), Kepala Sekolah (user-tie), Template WA
(whatsapp brand)
- Tombol Simpan Pengaturan btn-primary full-width
- Perbaiki label Nama Kepala Sekolah yang sempat hilang + keseimbangan div
- Test 31/105 hijau
- Hapus overscroll-contain dari nav sidebar: kelas ini memblokir scroll
chaining ke body, sehingga saat mouse di sidebar & menu pendek, roda
scroll tidak menggulir halaman utama
- Sekarang scroll mengalir normal: menu sidebar habis → lanjut ke halaman
- Kelas kustom (.input/.btn-primary/.btn-outline/.card) dibungkus
@layer components — sebelumnya unlayered sehingga menang atas utility
Tailwind (pl-9 dll), membuat icon search menimpa placeholder
- Sekarang utility (layer utilities) bisa menimpa komponen sesuai urutan
layer CSS (base < components < utilities)
- Directive global di app.js: satu tooltip singleton di body, posisi dari
getBoundingClientRect (fixed, tidak terpotong overflow-hidden), animasi
fade + slide halus, delay 120ms anti-kedip, fallback ke bawah jika di
tepi atas viewport, clamp ke viewport
- Tooltip gelap glass: bg-slate-900/95 + ring + shadow + backdrop-blur
- Badge kalender pelanggaran ('X pelanggaran') & presensi ('X siswa, Y
alpha') beralih dari :title native ke x-tooltip
- Sembunyi otomatis saat scroll/resize/klik
- 4 KPI card gradient (siswa/alpha hari ini & bulan ini) + icon watermark
membesar saat hover — konsisten dgn dashboard
- Kalender: badge 'X presensi' bulan berjalan, tombol Hari Ini, nav pill
glass, hari ini gradient+ring+label, badge gradient emerald/merah + glow,
indikator alpha mini per tanggal, legend pill
- JS: currentMonth() + monthTotal
- Header: icon chip gradient + badge statistik 'X pelanggaran' bulan berjalan
- Tombol 'Hari Ini' (kembali ke bulan sekarang) + navigasi prev/next di
pill glass, hover efek
- Sel tanggal: lebih tinggi, hari ini = gradient biru + ring + label 'Hari Ini',
hover lift; tanggal luar bulan lebih redup
- Badge jumlah: gradient + glow shadow senada (biru/oranye/merah), hover scale
- Legend jadi pill gradient + teks '1/2/3+ pelanggaran', footer interaktif
- JS: method currentMonth() + computed monthTotal
- Ukuran standar iOS (w-11 h-6, knob 20px) — konsisten dgn toggle halaman lain
- Knob bergeser penuh dengan transisi halus; track gradient warna level + glow
saat aktif, slate + inset shadow saat nonaktif
- Reaktif via Alpine (x-model) — track & glow berubah langsung saat di-toggle
- Kartu threshold: strip gradient warna di atas, icon chip gradient, badge
poin (≥ X poin), label Nonaktif, toggle & hapus di kanan, hover lift
- Field: label uppercase tracking, suffix 'poin' di input Min Poin
- Modal tambah: header gradient biru-indigo, color picker + 8 preset swatch
interaktif (Alpine), preview warna terpilih
- Info card jadi 'Tangga SP' dinamis mengikuti data threshold asli (bukan
hardcoded), lengkap status nonaktif
- Empty state & tombol simpan pakai sistem btn-primary
- 2 smoke test baru render halaman (31 test total)
- Font Plus Jakarta Sans (Google Fonts) menggantikan font sistem default
- Sidebar: brand area gradient + nama sekolah, nav aktif jadi pill gradient
biru-indigo + chevron, label grup lebih elegan, footer badge NOCTKJ.net
- Topbar: sticky + backdrop-blur glass
- Background utama: gradient halus slate → biru samar
- Kartu standar premium (.card) + tombol (.btn-primary/.btn-outline) + input
seragam di CSS; kartu utama halaman diseragamkan rounded-2xl
- Border global diselaraskan ke palet slate; scrollbar & seleksi teks premium
- Verifikasi: 29 test / 99 assertion, blade cache OK, vite build OK
- max_points tidak pernah dipakai logika penerbitan SP (trigger hanya baca
min_points: level dgn ambang tertinggi <= total poin siswa)
- Migrasi drop kolom; model, MasterDataController, ResetController (seeder)
dibersihkan; form Ambang SP & form tambah cukup satu angka (Min Poin)
- Dashboard Ambang SP: batas atas level dihitung dari min_points level
berikutnya (level terakhir = tak terbatas), urutan dijamin orderBy min_points
- Test: 29 passed / 99 assertion
- LoginController: admin tidak ditolak saat login kedua (multi-sesi boleh)
- Middleware SingleSession: admin tidak ditendang walau sesi ≠ token aktif
- Alasan: admin terkunci = tidak ada yang bisa Paksa Logout akun lain
- 2 test baru (login kedua admin diterima; middleware tidak menendang admin)
- SESSION_LIFETIME=5 di .env (sebelumnya 120 menit idle)
- User::sessionTokenIsAlive() kini cek umur sesi (file mtime / DB last_activity)
vs masa hidup, bukan sekadar ada/tidaknya file — user yang sesinya habis
langsung bisa login lagi tanpa nunggu GC atau Paksa Logout
- 2 test baru (sesi kadaluarsa → boleh login; sesi fresh → tetap terkunci)
- Add 3 jenis rekap presensi (harian/mingguan/bulanan) per kelas
- Weekly recap: tabel H,S,I,A per hari + kolom TOTAL
- Alpha proporsional: A = jam_alpha / total_jam
- Pemisah border antar hari dan kolom TOTAL
- Export Excel rekap mingguan (.xlsx)
- Fix max_input_vars PHP limit (1000→5000)
- Fix Carbon date object issue di groupBy
- Add permissions & role_permissions tables with migration
- Add PermissionMiddleware for route-level access control
- Add CheckRole middleware for role-based fallback
- Add PermissionController with UI (Settings > Hak Akses Role)
- Add @canPermission Blade directive for view-level checks
- Convert all routes to use dynamic permission middleware
- Add canPermission() method to User model
- All access rights configurable via admin UI
- Fix: broadcasting.php config (was missing, broadcast failed)
- Fix: Echo class global scope (window.EchoClass)
- Fix: Nginx WebSocket proxy for Reverb
- Fix: Firewall port 8087 opened
- Fix: Duplicate event listener cleanup
- Fix: Mark as read functionality
- Add: CreateViolationNotification listener
- Add: Notifications index page with pagination
- Add: Timezone Asia/Jakarta support
- Add: Real-time badge across all pages
- Remove: toOthers() so recorder also gets notification
- Update: .env.example with new variables