109 lines
3.8 KiB
PHP
109 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin\AcademicClasses;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Admin\AcademicClasses\AttendanceStoreRequest;
|
|
use App\Models\CourseClass;
|
|
use App\Services\Admin\AcademicClasses\AttendanceService;
|
|
use App\Services\Admin\Master\AcademicTermService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
class AttendanceController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly AttendanceService $service,
|
|
private readonly AcademicTermService $academicTermService,
|
|
) {}
|
|
|
|
public function index(Request $request): Response
|
|
{
|
|
$academicTermId = $request->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,
|
|
);
|
|
}
|
|
}
|