# eCert MBIP — Route Plan ## Admin Routes (Authenticated) ``` Prefix: /admin Middleware: auth, verified (optional) ``` ### Auth ``` GET /login → Auth\AuthenticatedSessionController@create POST /login → Auth\AuthenticatedSessionController@store POST /logout → Auth\AuthenticatedSessionController@destroy ``` ### Dashboard ``` GET /admin/dashboard → Admin\DashboardController@index ``` ### Programs ``` GET /admin/programs → Admin\ProgramController@index GET /admin/programs/create → Admin\ProgramController@create POST /admin/programs → Admin\ProgramController@store GET /admin/programs/{program:uuid} → Admin\ProgramController@show GET /admin/programs/{program:uuid}/edit → Admin\ProgramController@edit PUT /admin/programs/{program:uuid} → Admin\ProgramController@update DELETE /admin/programs/{program:uuid} → Admin\ProgramController@destroy POST /admin/programs/{program:uuid}/publish → Admin\ProgramController@publish POST /admin/programs/{program:uuid}/close → Admin\ProgramController@close ``` ### QR Code ``` GET /admin/programs/{program:uuid}/qr → Admin\QrCodeController@show POST /admin/programs/{program:uuid}/qr/generate → Admin\QrCodeController@generate GET /admin/programs/{program:uuid}/qr/download → Admin\QrCodeController@download POST /admin/programs/{program:uuid}/qr/deactivate → Admin\QrCodeController@deactivate ``` ### Participants (Pre-registered) ``` GET /admin/programs/{program:uuid}/participants → Admin\ParticipantController@index GET /admin/programs/{program:uuid}/participants/create → Admin\ParticipantController@create POST /admin/programs/{program:uuid}/participants → Admin\ParticipantController@store DELETE /admin/programs/{program:uuid}/participants/{pp} → Admin\ParticipantController@destroy GET /admin/programs/{program:uuid}/participants/import → Admin\ParticipantController@importForm POST /admin/programs/{program:uuid}/participants/import → Admin\ParticipantController@import GET /admin/programs/{program:uuid}/participants/export → Admin\ParticipantController@export ``` ### Certificate Template ``` GET /admin/programs/{program:uuid}/template → Admin\CertificateTemplateController@show POST /admin/programs/{program:uuid}/template → Admin\CertificateTemplateController@store PUT /admin/programs/{program:uuid}/template/config → Admin\CertificateTemplateController@updateConfig DELETE /admin/programs/{program:uuid}/template → Admin\CertificateTemplateController@destroy GET /admin/programs/{program:uuid}/template/preview → Admin\CertificateTemplateController@preview POST /admin/programs/{program:uuid}/template/test → Admin\CertificateTemplateController@testGenerate ``` ### Questionnaire (Attachment to Program) ``` GET /admin/programs/{program:uuid}/questionnaire → Admin\ProgramQuestionnaireController@show POST /admin/programs/{program:uuid}/questionnaire/attach → Admin\ProgramQuestionnaireController@attach POST /admin/programs/{program:uuid}/questionnaire/confirm → Admin\ProgramQuestionnaireController@confirm DELETE /admin/programs/{program:uuid}/questionnaire/detach → Admin\ProgramQuestionnaireController@detach ``` ### Statistics ``` GET /admin/programs/{program:uuid}/statistics → Admin\StatisticsController@show GET /admin/programs/{program:uuid}/statistics/export → Admin\StatisticsController@export ``` ### Questionnaire Sets (Reusable) ``` GET /admin/questionnaires → Admin\QuestionnaireSetController@index GET /admin/questionnaires/create → Admin\QuestionnaireSetController@create POST /admin/questionnaires → Admin\QuestionnaireSetController@store GET /admin/questionnaires/{set} → Admin\QuestionnaireSetController@show GET /admin/questionnaires/{set}/edit → Admin\QuestionnaireSetController@edit PUT /admin/questionnaires/{set} → Admin\QuestionnaireSetController@update DELETE /admin/questionnaires/{set} → Admin\QuestionnaireSetController@destroy POST /admin/questionnaires/{set}/publish → Admin\QuestionnaireSetController@publish POST /admin/questionnaires/{set}/archive → Admin\QuestionnaireSetController@archive ``` ### Questionnaire Questions ``` POST /admin/questionnaires/{set}/questions → Admin\QuestionController@store PUT /admin/questions/{question} → Admin\QuestionController@update DELETE /admin/questions/{question} → Admin\QuestionController@destroy POST /admin/questions/reorder → Admin\QuestionController@reorder ``` ### Certificate Generation (Admin Trigger) ``` POST /admin/programs/{program:uuid}/certificates/generate-all → Admin\CertificateController@generateAll POST /admin/programs/{program:uuid}/certificates/email-all → Admin\CertificateController@emailAll GET /admin/programs/{program:uuid}/certificates → Admin\CertificateController@index ``` --- ## Public Routes (Token-based, No Auth) ``` Prefix: none Middleware: throttle:60,1 (check-in), throttle:30,1 (download) ``` ### Check-in Flow ``` GET /p/{qr_token} → Public\CheckinController@show ↑ Papar: nama program, status, pilihan jenis peserta ↑ Redirect ke questionnaire/download jika masa download aktif POST /p/{qr_token}/staff → Public\CheckinController@staffCheckin ↑ Input: no_kp, email ↑ Semak pre-registered, rekod attendance POST /p/{qr_token}/external → Public\CheckinController@externalRegister ↑ Input: name, no_kp, email, phone, agency ↑ Daftar + rekod attendance ``` ### Questionnaire (Public) ``` GET /p/{qr_token}/questionnaire/{participant_uuid} → Public\QuestionnaireController@show ↑ Semak: attendance exists, questionnaire published, belum jawab POST /p/{qr_token}/questionnaire/{participant_uuid} → Public\QuestionnaireController@submit ↑ Simpan responses, redirect ke certificate page ``` ### Semakan Kehadiran (via QR masa download) ``` GET /p/{qr_token}/semak → Public\AttendanceCheckController@show ↑ Papar form: masukkan no_kp untuk semak POST /p/{qr_token}/semak → Public\AttendanceCheckController@check ↑ Semak kehadiran, papar status sijil ``` ### Certificate Download ``` GET /certificate/{cert_token} → Public\CertificateController@show ↑ Semak: token valid, masa download aktif, soalselidik dijawab ↑ Jika semua OK: papar download button / auto-download POST /certificate/{cert_token}/download → Public\CertificateController@download ↑ Generate if not exists, serve file, increment download_count ``` --- ## Route Logic / Decision Tree ### GET /p/{qr_token} ``` QR token valid? NO → 404 YES → Program published? NO → Papar: "Program belum dibuka" YES → Masa download aktif (ecert_download_start_at <= now)? YES → Redirect ke /p/{qr_token}/semak NO → Masa check-in aktif (checkin_start_at <= now <= checkin_end_at)? YES → Papar check-in form NO → Papar: "Check-in belum dibuka" atau "Check-in sudah ditutup" ``` ### POST /p/{qr_token}/staff ``` no_kp + email valid format? NO → Validation error YES → Jumpa dalam program_participants (pre_registered)? NO → "Tidak dijumpai dalam senarai" + pilihan daftar luar YES → Sudah check-in (attendances exists)? YES → "Anda sudah check-in" + papar masa check-in NO → Rekod attendance Papar: "Check-in berjaya! Sijil akan dihantar ke emel selepas program." ``` ### GET /certificate/{cert_token} ``` Token valid (dalam certificates table)? NO → 404 YES → Masa download aktif? NO → Papar: "Sijil belum boleh dimuat turun. Mula dari: {datetime}" YES → Soalselidik diperlukan dan belum dijawab? YES → Redirect ke /p/{qr_token}/questionnaire/{participant_uuid} NO → Sijil sudah generated? NO → Dispatch GenerateCertificateJob, papar: "Sijil sedang disediakan..." YES → Papar download page / auto-download PDF ``` --- ## Named Routes ```php // Admin 'admin.dashboard' 'admin.programs.index' 'admin.programs.create' 'admin.programs.show' 'admin.programs.edit' 'admin.programs.qr.show' 'admin.programs.qr.generate' 'admin.programs.qr.download' 'admin.programs.participants.index' 'admin.programs.participants.import' 'admin.programs.template.show' 'admin.programs.questionnaire.show' 'admin.programs.statistics.show' 'admin.questionnaires.index' 'admin.questions.store' // Public 'public.checkin.show' → /p/{qr_token} 'public.checkin.staff' → POST /p/{qr_token}/staff 'public.checkin.external' → POST /p/{qr_token}/external 'public.questionnaire.show' → /p/{qr_token}/questionnaire/{uuid} 'public.questionnaire.submit' → POST /p/{qr_token}/questionnaire/{uuid} 'public.semak.show' → /p/{qr_token}/semak 'public.semak.check' → POST /p/{qr_token}/semak 'public.certificate.show' → /certificate/{cert_token} 'public.certificate.download' → POST /certificate/{cert_token}/download ``` --- ## Middleware Stack ```php // web.php Route::middleware('auth')->prefix('admin')->name('admin.')->group(function () { // semua admin routes }); Route::middleware(['throttle:checkin'])->prefix('p')->name('public.')->group(function () { // check-in routes }); Route::middleware(['throttle:certificate'])->prefix('certificate')->name('public.certificate.')->group(function () { // download routes }); ``` Rate limiter dalam `AppServiceProvider`: ```php RateLimiter::for('checkin', fn($req) => Limit::perMinute(60)->by($req->ip())); RateLimiter::for('certificate', fn($req) => Limit::perMinute(30)->by($req->ip())); ```