route('login'); }); /* |-------------------------------------------------------------------------- | 2. AREA PROTEKSI AKSES UTAMA (AUTH & AUTENTIKASI) |-------------------------------------------------------------------------- */ Route::middleware(['auth'])->group(function () { // GLOBAL LOGOUT HANDLER Route::post('/logout', function (Request $request) { Auth::guard('web')->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect()->route('login'); })->name('logout'); /* * ==================================================================== * RUTE PAKSA GANTI PASSWORD (Diakses saat first login) * ==================================================================== */ Route::get('/force-change-password', function () { return view('livewire.pages.auth.force-change-password'); })->name('password.force-change'); Route::post('/force-change-password', function (Request $request) { $request->validate([ 'password' => 'required|string|min:8|confirmed', ]); $user = $request->user(); $user->password = Hash::make($request->password); $user->must_change_password = false; // Cabut status wajib ganti $user->save(); // Redirect cerdas berdasarkan role setelah ganti password if ($user->hasRole(['admin', 'trainer'])) { return redirect()->route('admin.dashboard')->with('success', 'Password default berhasil diganti!'); } return redirect()->route('cbt.dashboard')->with('success', 'Password berhasil diganti. Selamat datang!'); })->name('password.force-update'); /* * ==================================================================== * AREA APLIKASI UTAMA * (Hanya bisa diakses jika user SUDAH mengganti password default) * ==================================================================== */ Route::middleware(['force.password'])->group(function () { /* * A. AREA PANEL ADMIN & TRAINER (PREFIX: /admin) * Dilindungi oleh Spatie: Hanya admin atau trainer */ Route::prefix('admin')->name('admin.')->middleware(['role:admin|trainer'])->group(function () { // Dashboard Utama Admin Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard'); // Modul Ujian & Bank Soal Route::get('/question-bank', [ExamManagementController::class, 'questionBank'])->name('exams.questions'); Route::get('/exams', [ExamManagementController::class, 'index'])->name('exams.index'); // ---------------------------------------------------------------- // PERBAIKAN: Rute Export & Import Karyawan (Disesuaikan dengan Prefix Grup) // ---------------------------------------------------------------- Route::get('employees/export/excel', [EmployeeController::class, 'exportExcel'])->name('employees.export.excel'); Route::get('employees/export/pdf', [EmployeeController::class, 'exportPdf'])->name('employees.export.pdf'); Route::get('employees/import', [EmployeeController::class, 'importView'])->name('employees.import'); Route::get('employees/import/template', [EmployeeController::class, 'downloadTemplate'])->name('employees.import.template'); Route::post('employees/import/preview', [EmployeeController::class, 'importPreview'])->name('employees.import.preview'); Route::post('employees/import/process', [EmployeeController::class, 'importProcess'])->name('employees.import.process'); // Rute Export Master Data Route::get('departments/export/excel', [DepartmentController::class, 'exportExcel'])->name('departments.export.excel'); Route::get('departments/export/pdf', [DepartmentController::class, 'exportPdf'])->name('departments.export.pdf'); Route::get('positions/export/excel', [PositionController::class, 'exportExcel'])->name('positions.export.excel'); Route::get('positions/export/pdf', [PositionController::class, 'exportPdf'])->name('positions.export.pdf'); // Master Data & Karyawan (Resources harus diletakkan di bawah rute custom export/import) Route::resource('departments', DepartmentController::class); Route::resource('positions', PositionController::class); Route::resource('employees', EmployeeController::class); Route::get('/sops', [DashboardController::class, 'sopIndex'])->name('sops.index'); }); /* * B. AREA PANEL REPORT TRAINING * Dilindungi oleh Spatie: Hanya admin atau trainer */ Route::prefix('reports')->name('reports.')->middleware(['role:admin|trainer'])->group(function () { Route::get('/training', [ReportController::class, 'training'])->name('training'); Route::get('/training/{user}', [ReportController::class, 'showTraining'])->name('training.show'); }); /* * C. AREA PORTAL KARYAWAN / TRAINEE (PREFIX: /portal) * Dilindungi oleh Spatie: Hanya karyawan */ Route::prefix('portal')->name('cbt.')->middleware(['role:karyawan'])->group(function () { Route::get('/dashboard', [UserDashboardController::class, 'index'])->name('dashboard'); }); }); // End of force.password middleware }); // End of auth middleware /* |-------------------------------------------------------------------------- | 3. FILE AUTENTIKASI BAWAAN (LARAVEL BREEZE / VOLT) |-------------------------------------------------------------------------- */ require __DIR__.'/auth.php';