- 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)
- Per group: card terpisah dengan gradient header + icon
- Role columns: badge dengan icon (crown untuk admin)
- Checkbox: toggle button blue modern dengan ikon check
- Hover: gradient biru tipis di baris + icon group berubah warna
- Save section: gradient card dengan shadow
- Transisi mulus semua interaksi
- Tombol key (oranye) di samping edit user
- Klik → SweetAlert2 modal: input password baru + konfirmasi
- Validasi: min 6 karakter, harus cocok
- Admin tidak bisa reset password sendiri (lewat profil)
- PermissionController: tambah 'other' ke daftar role
- UserController validasi: in:admin,bk,wali_kelas,staff,other
- User model: helper isOther()
- Users view: filter dropdown + modal tambah user + label
- Role 'other' bisa diatur hak aksesnya di menu Hak Akses Role
Saat user pilih Jurusan dan/atau Tingkat Kelas, dropdown
Kelas otomatis terfilter hanya menampilkan kelas yang cocok.
Menggunakan JS client-side dengan data options dari backend.