has('academic_term_id') ? $request->integer('academic_term_id') : $this->academicTermService->getActive()?->id; return Inertia::render('admin/academic-classes/attendances/index', [ 'courseClasses' => $this->service->courseClassesForUser($request->user(), $academicTermId), 'academicTerms' => $this->academicTermService->getAllForSelect(), 'filters' => [ 'academic_term_id' => $academicTermId ? (string) $academicTermId : null, ], ]); } public function mine(Request $request): Response { $student = $request->user()->student; abort_if(! $student, 403); return Inertia::render('admin/academic-classes/attendances/mine', [ 'summaries' => $this->service->forStudent($student), ]); } public function show(CourseClass $courseClass): Response { $this->abortUnlessLecturerOwnsClass($courseClass); $courseClass->load(['course', 'academicTerm']); return Inertia::render('admin/academic-classes/attendances/course-class', [ 'courseClass' => $courseClass, 'sessions' => $this->service->sessionsForClass($courseClass), 'nextMeetingNumber' => $this->service->nextMeetingNumber($courseClass), ]); } public function session(CourseClass $courseClass, int $meetingNumber): Response { $this->abortUnlessLecturerOwnsClass($courseClass); $courseClass->load('course'); $data = $this->service->session($courseClass, $meetingNumber); return Inertia::render('admin/academic-classes/attendances/session', [ 'courseClass' => $courseClass, 'meetingNumber' => $meetingNumber, 'roster' => $data['roster'], 'date' => $data['date'], ]); } public function store(AttendanceStoreRequest $request, CourseClass $courseClass, int $meetingNumber): RedirectResponse { $this->service->saveSession($courseClass->id, $meetingNumber, $request->validated('date'), $request->validated('records')); Inertia::flash('toast', ['type' => 'success', 'message' => 'Kehadiran berhasil disimpan.']); return to_route('admin.academic-classes.attendances.session', [$courseClass->id, $meetingNumber]); } public function destroy(CourseClass $courseClass, int $meetingNumber): RedirectResponse { $this->abortUnlessLecturerOwnsClass($courseClass); $this->service->deleteSession($courseClass->id, $meetingNumber); Inertia::flash('toast', ['type' => 'success', 'message' => 'Sesi kehadiran berhasil dihapus.']); return to_route('admin.academic-classes.attendances.show', [$courseClass->id]); } /** * A dosen may only take or manage attendance for classes they lecture. */ private function abortUnlessLecturerOwnsClass(CourseClass $courseClass): void { $user = request()->user(); abort_if( $user->hasRole('dosen') && $courseClass->lecturer_id !== $user->lecturer?->id, 403, ); } }