route('login'); })->name('home'); // Auth Route::get('/login', [LoginController::class, 'showLoginForm'])->name('login'); Route::post('/login', [LoginController::class, 'login']); Route::post('/logout', [LoginController::class, 'logout'])->name('logout'); // ===== Protected Routes (auth required) ===== Route::middleware('auth')->group(function () { // ===== Umum (permission-based) ===== Route::middleware('permission:access-dashboard')->group(function () { Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard'); Route::get('/calendar/data', [DashboardController::class, 'getCalendarData'])->name('calendar.data'); }); Route::middleware('permission:view-notifications')->group(function () { Route::get('/notifications/unread-count', [DashboardController::class, 'getUnreadCount'])->name('notifications.unread-count'); Route::get('/notifications/recent', [DashboardController::class, 'getRecentNotifications'])->name('notifications.recent'); Route::post('/notifications/{id}/read', [DashboardController::class, 'markNotificationRead'])->name('notifications.read'); Route::post('/notifications/read-all', [DashboardController::class, 'markAllNotificationsRead'])->name('notifications.read-all'); Route::get('/notifications', [DashboardController::class, 'notificationsIndex'])->name('notifications.index'); }); Route::middleware('permission:input-violations')->group(function () { Route::get('/violations/create', [ViolationController::class, 'create'])->name('violations.create'); Route::post('/violations', [ViolationController::class, 'store'])->name('violations.store'); }); // Face ID: scan wajah (permission khusus) Route::middleware('permission:face-scan')->group(function () { Route::get('/face/scan', [FaceIdController::class, 'scan'])->name('face.scan'); Route::post('/face/scan', [FaceIdController::class, 'scanVerify'])->name('face.scan.verify'); }); // Face ID: registrasi wajah (permission khusus) Route::middleware('permission:face-register')->group(function () { Route::get('/face/register', [FaceIdController::class, 'register'])->name('face.register'); Route::post('/face/register', [FaceIdController::class, 'registerStore'])->name('face.register.store'); Route::post('/face/register/quick', [FaceIdController::class, 'registerQuick'])->name('face.register.quick'); }); Route::middleware('permission:view-violations')->group(function () { Route::get('/violations', [ViolationController::class, 'index'])->name('violations.index'); Route::get('/violations/{violation}', [ViolationController::class, 'show'])->name('violations.show'); Route::post('/violations/{violation}/verify', [ViolationController::class, 'verify'])->name('violations.verify'); Route::delete('/violations/{violation}', [ViolationController::class, 'destroy'])->name('violations.destroy'); Route::post('/violations/{violation}/handling', [ViolationController::class, 'storeHandling'])->name('violations.handling.store'); Route::post('/violations/{violation}/resolve', [ViolationController::class, 'resolveHandling'])->name('violations.resolve'); Route::delete('/violations/{violation}/handling/{handling}', [ViolationController::class, 'destroyHandling'])->name('violations.handling.destroy'); Route::get('/api/students/search', [ViolationController::class, 'searchStudents'])->name('api.students.search'); }); // Notifikasi WA ke orang tua (permission khusus) Route::middleware('permission:notify-parent-wa')->group(function () { Route::get('/violations/{violation}/notify-wa', [ViolationController::class, 'notifyParentWa'])->name('violations.notify-wa'); }); Route::middleware('permission:view-students')->group(function () { Route::get('/students', [StudentReportController::class, 'index'])->name('students.index'); Route::get('/students/{student}', [StudentReportController::class, 'show'])->name('students.show'); Route::get('/students/{student}/pdf', [StudentReportController::class, 'pdf'])->name('students.pdf'); Route::put('/students/{student}', [StudentReportController::class, 'update'])->name('students.update'); }); Route::middleware('permission:manage-attendance')->group(function () { Route::get('/attendances', [\App\Http\Controllers\AttendanceController::class, 'index'])->name('attendances.index'); Route::get('/attendances/create', [\App\Http\Controllers\AttendanceController::class, 'create'])->name('attendances.create'); Route::get('/attendances/availability', [\App\Http\Controllers\AttendanceController::class, 'availability'])->name('attendances.availability'); Route::post('/attendances', [\App\Http\Controllers\AttendanceController::class, 'store'])->name('attendances.store'); Route::get('/attendances/recap', [\App\Http\Controllers\AttendanceController::class, 'recap'])->name('attendances.recap'); Route::get('/attendances/calendar-data', [\App\Http\Controllers\AttendanceController::class, 'calendarData'])->name('attendances.calendar-data'); Route::get('/attendances/export-weekly', [\App\Http\Controllers\AttendanceController::class, 'exportWeekly'])->name('attendances.export-weekly'); Route::get('/attendances/export-monthly', [\App\Http\Controllers\AttendanceController::class, 'exportMonthly'])->name('attendances.export-monthly'); }); Route::middleware('permission:view-sp-letters')->group(function () { Route::get('/sp-letters', [SpLetterController::class, 'index'])->name('sp-letters.index'); Route::get('/sp-letters/export-pdf', [SpLetterController::class, 'exportPdf'])->name('sp-letters.export-pdf'); Route::get('/sp-letters/{spLetter}', [SpLetterController::class, 'show'])->name('sp-letters.show'); Route::get('/sp-letters/{spLetter}/print', [SpLetterController::class, 'print'])->name('sp-letters.print'); Route::get('/sp-letters/{spLetter}/pdf', [SpLetterController::class, 'pdf'])->name('sp-letters.pdf'); }); // ===== Master Data (permission-based) ===== Route::middleware('permission:categories-manage')->group(function () { Route::get('/settings/categories', [MasterDataController::class, 'categories'])->name('settings.categories'); Route::post('/settings/categories', [MasterDataController::class, 'storeCategory'])->name('settings.categories.store'); Route::put('/settings/categories/{category}', [MasterDataController::class, 'updateCategory'])->name('settings.categories.update'); Route::delete('/settings/categories/{category}', [MasterDataController::class, 'destroyCategory'])->name('settings.categories.destroy'); }); Route::middleware('permission:violation-types-manage')->group(function () { Route::get('/settings/violation-types', [MasterDataController::class, 'types'])->name('settings.violation-types'); Route::post('/settings/violation-types', [MasterDataController::class, 'storeType'])->name('settings.violation-types.store'); Route::put('/settings/violation-types/{type}', [MasterDataController::class, 'updateType'])->name('settings.violation-types.update'); Route::delete('/settings/violation-types/{type}', [MasterDataController::class, 'destroyType'])->name('settings.violation-types.destroy'); Route::get('/settings/handling-types', [MasterDataController::class, 'handlingTypes'])->name('settings.handling-types'); Route::post('/settings/handling-types', [MasterDataController::class, 'storeHandlingType'])->name('settings.handling-types.store'); Route::post('/settings/handling-types/reorder', [MasterDataController::class, 'reorderHandlingTypes'])->name('settings.handling-types.reorder'); Route::put('/settings/handling-types/{type}', [MasterDataController::class, 'updateHandlingType'])->name('settings.handling-types.update'); Route::delete('/settings/handling-types/{type}', [MasterDataController::class, 'destroyHandlingType'])->name('settings.handling-types.destroy'); Route::post('/settings/handling-roles', [MasterDataController::class, 'storeHandlingRole'])->name('settings.handling-roles.store'); Route::post('/settings/handling-roles/reorder', [MasterDataController::class, 'reorderHandlingRoles'])->name('settings.handling-roles.reorder'); Route::delete('/settings/handling-roles/{role}', [MasterDataController::class, 'destroyHandlingRole'])->name('settings.handling-roles.destroy'); Route::get('/settings/homeroom', [MasterDataController::class, 'homeroomTeachers'])->name('settings.homeroom'); Route::put('/settings/homeroom', [MasterDataController::class, 'updateHomeroomTeacher'])->name('settings.homeroom.update'); }); Route::middleware('permission:thresholds-manage')->group(function () { Route::get('/settings/thresholds', [MasterDataController::class, 'thresholds'])->name('settings.thresholds'); Route::put('/settings/thresholds', [MasterDataController::class, 'updateThresholds'])->name('settings.thresholds.update'); Route::post('/settings/thresholds', [MasterDataController::class, 'storeThreshold'])->name('settings.thresholds.store'); Route::delete('/settings/thresholds/{threshold}', [MasterDataController::class, 'destroyThreshold'])->name('settings.thresholds.destroy'); }); Route::middleware('permission:violations-export')->group(function () { Route::get('/export/violations', [\App\Http\Controllers\Admin\ViolationExportController::class, 'export'])->name('violations.export'); Route::get('/reports/violations', [\App\Http\Controllers\Admin\ViolationReportController::class, 'index'])->name('reports.violations'); Route::get('/reports/violations/pdf', [\App\Http\Controllers\Admin\ViolationReportController::class, 'pdf'])->name('reports.violations.pdf'); }); Route::middleware('permission:view-point-audit')->group(function () { Route::get('/point-audit', [\App\Http\Controllers\Admin\PointAuditController::class, 'index'])->name('point-audit.index'); }); Route::middleware('permission:parents-verify')->group(function () { Route::get('/parents', [\App\Http\Controllers\Admin\WaliMuridController::class, 'index'])->name('parents.index'); Route::delete('/parents/{user}', [\App\Http\Controllers\Admin\WaliMuridController::class, 'destroy'])->name('parents.destroy'); Route::post('/parents/{user}/force-logout', [\App\Http\Controllers\Admin\WaliMuridController::class, 'forceLogout'])->name('parents.force-logout'); Route::get('/parents/verification', [\App\Http\Controllers\Admin\ParentVerificationController::class, 'index'])->name('parents.verification'); Route::post('/parents/verification/{link}/approve', [\App\Http\Controllers\Admin\ParentVerificationController::class, 'approve'])->name('parents.verification.approve'); Route::post('/parents/verification/{link}/reject', [\App\Http\Controllers\Admin\ParentVerificationController::class, 'reject'])->name('parents.verification.reject'); }); Route::middleware('permission:manage-school-info')->group(function () { Route::get('/settings/school-info', [\App\Http\Controllers\Admin\SchoolInformationController::class, 'index'])->name('settings.school-info'); Route::post('/settings/school-info', [\App\Http\Controllers\Admin\SchoolInformationController::class, 'store'])->name('settings.school-info.store'); Route::put('/settings/school-info/{info}', [\App\Http\Controllers\Admin\SchoolInformationController::class, 'update'])->name('settings.school-info.update'); Route::delete('/settings/school-info/{info}', [\App\Http\Controllers\Admin\SchoolInformationController::class, 'destroy'])->name('settings.school-info.destroy'); }); // ===== Administrasi (permission-based) ===== Route::middleware('permission:settings-manage')->group(function () { Route::get('/settings', [SettingsController::class, 'index'])->name('settings.index'); Route::post('/settings', [SettingsController::class, 'update'])->name('settings.update'); }); Route::middleware('permission:import-data')->group(function () { Route::get('/settings/import/template', [ImportController::class, 'downloadTemplate'])->name('settings.import.template'); Route::get('/settings/export/violation-types', [ImportController::class, 'exportViolationTypes'])->name('settings.export.violation-types'); Route::post('/settings/import/violation-types', [ImportController::class, 'importViolationTypes'])->name('settings.import.violation-types'); }); Route::middleware('permission:backup-database')->group(function () { Route::get('/settings/backup', [\App\Http\Controllers\Admin\BackupController::class, 'index'])->name('settings.backup'); Route::post('/settings/backup/create', [\App\Http\Controllers\Admin\BackupController::class, 'create'])->name('settings.backup.create'); Route::get('/settings/backup/download/{filename}', [\App\Http\Controllers\Admin\BackupController::class, 'download'])->name('settings.backup.download'); Route::delete('/settings/backup/{filename}', [\App\Http\Controllers\Admin\BackupController::class, 'destroy'])->name('settings.backup.destroy'); Route::post('/settings/backup/restore', [\App\Http\Controllers\Admin\BackupController::class, 'restore'])->name('settings.backup.restore'); }); Route::middleware('permission:sync-data')->group(function () { Route::get('/settings/sync', [SyncController::class, 'index'])->name('settings.sync'); Route::post('/settings/sync', [SyncController::class, 'syncNow'])->name('settings.sync.run'); Route::post('/settings/sync/test', [SyncController::class, 'testKesiswaanConnection'])->name('settings.sync.test'); Route::post('/settings/sync/ejurnal-token', [SyncController::class, 'saveEjurnalToken'])->name('settings.sync.ejurnal-token'); Route::post('/settings/sync/ejurnal-token/generate', [SyncController::class, 'generateEjurnalToken'])->name('settings.sync.ejurnal-token.generate'); }); Route::middleware('permission:users-manage')->group(function () { Route::get('/users', [UserController::class, 'index'])->name('users.index'); Route::post('/users', [UserController::class, 'store'])->name('users.store'); Route::put('/users/{user}', [UserController::class, 'update'])->name('users.update'); Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy'); Route::post('/users/{user}/reset-password', [UserController::class, 'resetPassword'])->name('users.reset-password'); Route::post('/users/{user}/send-wa', [UserController::class, 'sendWa'])->name('users.send-wa'); Route::post('/users/{user}/force-logout', [UserController::class, 'forceLogout'])->name('users.force-logout'); Route::get('/settings/permissions', [\App\Http\Controllers\Admin\PermissionController::class, 'index'])->name('settings.permissions'); Route::post('/settings/permissions', [\App\Http\Controllers\Admin\PermissionController::class, 'update'])->name('settings.permissions.update'); }); Route::middleware('permission:reset-application')->group(function () { Route::get('/settings/reset', [\App\Http\Controllers\Admin\ResetController::class, 'index'])->name('settings.reset'); Route::post('/settings/reset', [\App\Http\Controllers\Admin\ResetController::class, 'reset'])->name('settings.reset.run'); }); // Profile (all roles — no permission needed, manage own account) Route::get('/profile', [ProfileController::class, 'index'])->name('profile.index'); Route::post('/profile', [ProfileController::class, 'update'])->name('profile.update'); }); // ===== API: Internal Sync (token auth, not session) ===== Route::post('/api/v1/attendance/sync', [App\Http\Controllers\Api\AttendanceSyncController::class, 'sync']) ->name('api.attendance.sync'); Route::get('/api/v1/attendance/ping', [App\Http\Controllers\Api\AttendanceSyncController::class, 'ping']) ->name('api.attendance.ping');