Merge pull request 'feat: add academic advising logs and letter requests management' (#41) from refactor/organized-folder-structure into dev

Reviewed-on: #41
This commit is contained in:
pangestu 2026-08-26 00:05:50 +08:00
commit 0a7d1e793d
64 changed files with 203 additions and 195 deletions

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Academic;
namespace App\Http\Controllers\Admin\AcademicClasses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Academic\AssignmentRequest;
use App\Http\Requests\Admin\AcademicClasses\AssignmentRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\Assignment;
use App\Services\Admin\Manage\Academic\AssignmentService;
use App\Services\Admin\Manage\Course\CourseClassService;
use App\Services\Admin\AcademicClasses\AssignmentService;
use App\Services\Admin\Manage\CourseClassService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
@ -21,7 +21,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/assignments/index', [
return Inertia::render('admin/academic-classes/assignments/index', [
'assignments' => $this->service->paginated(...$request->validatedWithDefaults()),
'courseClasses' => $this->courseClassService->getAllForSelect(),
]);
@ -33,7 +33,7 @@ public function store(AssignmentRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Tugas berhasil ditambahkan.']);
return to_route('admin.manage.assignments.index');
return to_route('admin.academic-classes.assignments.index');
}
public function update(AssignmentRequest $request, Assignment $assignment): RedirectResponse
@ -42,7 +42,7 @@ public function update(AssignmentRequest $request, Assignment $assignment): Redi
Inertia::flash('toast', ['type' => 'success', 'message' => 'Tugas berhasil diperbarui.']);
return to_route('admin.manage.assignments.index');
return to_route('admin.academic-classes.assignments.index');
}
public function destroy(Assignment $assignment): RedirectResponse

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Academic;
namespace App\Http\Controllers\Admin\AcademicClasses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Academic\AttendanceStoreRequest;
use App\Http\Requests\Admin\AcademicClasses\AttendanceStoreRequest;
use App\Models\CourseClass;
use App\Services\Admin\Manage\Academic\AttendanceService;
use App\Services\Admin\Manage\Course\CourseClassService;
use App\Services\Admin\AcademicClasses\AttendanceService;
use App\Services\Admin\Manage\CourseClassService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
@ -20,7 +20,7 @@ public function __construct(
public function index(): Response
{
return Inertia::render('admin/manage/attendances/index', [
return Inertia::render('admin/academic-classes/attendances/index', [
'sessions' => $this->service->sessions(),
'courseClasses' => $this->courseClassService->getAllForSelect(),
]);
@ -31,7 +31,7 @@ public function session(CourseClass $courseClass, int $meetingNumber): Response
$courseClass->load('course');
$data = $this->service->session($courseClass, $meetingNumber);
return Inertia::render('admin/manage/attendances/session', [
return Inertia::render('admin/academic-classes/attendances/session', [
'courseClass' => $courseClass,
'meetingNumber' => $meetingNumber,
'roster' => $data['roster'],
@ -45,7 +45,7 @@ public function store(AttendanceStoreRequest $request, CourseClass $courseClass,
Inertia::flash('toast', ['type' => 'success', 'message' => 'Kehadiran berhasil disimpan.']);
return to_route('admin.manage.attendances.session', [$courseClass->id, $meetingNumber]);
return to_route('admin.academic-classes.attendances.session', [$courseClass->id, $meetingNumber]);
}
public function destroy(CourseClass $courseClass, int $meetingNumber): RedirectResponse
@ -54,6 +54,6 @@ public function destroy(CourseClass $courseClass, int $meetingNumber): RedirectR
Inertia::flash('toast', ['type' => 'success', 'message' => 'Sesi kehadiran berhasil dihapus.']);
return to_route('admin.manage.attendances.index');
return to_route('admin.academic-classes.attendances.index');
}
}

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Academic;
namespace App\Http\Controllers\Admin\AcademicClasses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Academic\CourseRegistrationRequest;
use App\Http\Requests\Admin\AcademicClasses\CourseRegistrationRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\CourseRegistration;
use App\Services\Admin\Manage\Academic\CourseRegistrationService;
use App\Services\Admin\Manage\Course\CourseClassService;
use App\Services\Admin\AcademicClasses\CourseRegistrationService;
use App\Services\Admin\Manage\CourseClassService;
use App\Services\Admin\Master\AcademicTermService;
use App\Services\Admin\Users\LecturerService;
use App\Services\Admin\Users\StudentService;
@ -27,7 +27,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/course-registrations/index', [
return Inertia::render('admin/academic-classes/course-registrations/index', [
'registrations' => $this->service->paginated(...$request->validatedWithDefaults()),
'students' => $this->studentService->getAllForSelect(),
'academicTerms' => $this->academicTermService->getAllForSelect(),
@ -42,7 +42,7 @@ public function store(CourseRegistrationRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Registrasi KRS berhasil ditambahkan.']);
return to_route('admin.manage.course-registrations.index');
return to_route('admin.academic-classes.course-registrations.index');
}
public function update(CourseRegistrationRequest $request, CourseRegistration $courseRegistration): RedirectResponse
@ -51,7 +51,7 @@ public function update(CourseRegistrationRequest $request, CourseRegistration $c
Inertia::flash('toast', ['type' => 'success', 'message' => 'Registrasi KRS berhasil diperbarui.']);
return to_route('admin.manage.course-registrations.index');
return to_route('admin.academic-classes.course-registrations.index');
}
public function destroy(CourseRegistration $courseRegistration): RedirectResponse

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Academic;
namespace App\Http\Controllers\Admin\AcademicClasses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Academic\MaterialRequest;
use App\Http\Requests\Admin\AcademicClasses\MaterialRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\Material;
use App\Services\Admin\Manage\Academic\MaterialService;
use App\Services\Admin\Manage\Course\CourseClassService;
use App\Services\Admin\AcademicClasses\MaterialService;
use App\Services\Admin\Manage\CourseClassService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
@ -21,7 +21,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/materials/index', [
return Inertia::render('admin/academic-classes/materials/index', [
'materials' => $this->service->paginated(...$request->validatedWithDefaults()),
'courseClasses' => $this->courseClassService->getAllForSelect(),
]);
@ -33,7 +33,7 @@ public function store(MaterialRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Materi berhasil ditambahkan.']);
return to_route('admin.manage.materials.index');
return to_route('admin.academic-classes.materials.index');
}
public function update(MaterialRequest $request, Material $material): RedirectResponse
@ -42,7 +42,7 @@ public function update(MaterialRequest $request, Material $material): RedirectRe
Inertia::flash('toast', ['type' => 'success', 'message' => 'Materi berhasil diperbarui.']);
return to_route('admin.manage.materials.index');
return to_route('admin.academic-classes.materials.index');
}
public function destroy(Material $material): RedirectResponse

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Academic;
namespace App\Http\Controllers\Admin\AcademicClasses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Academic\ScheduleRequest;
use App\Http\Requests\Admin\AcademicClasses\ScheduleRequest;
use App\Models\Schedule;
use App\Services\Admin\Manage\Academic\ScheduleService;
use App\Services\Admin\Manage\Course\CourseClassService;
use App\Services\Admin\AcademicClasses\ScheduleService;
use App\Services\Admin\Manage\CourseClassService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
@ -20,7 +20,7 @@ public function __construct(
public function index(): Response
{
return Inertia::render('admin/manage/schedules/index', [
return Inertia::render('admin/academic-classes/schedules/index', [
'schedules' => $this->service->all(),
'courseClasses' => $this->courseClassService->getAllForSelect(),
]);
@ -32,7 +32,7 @@ public function store(ScheduleRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Jadwal berhasil ditambahkan.']);
return to_route('admin.manage.schedules.index');
return to_route('admin.academic-classes.schedules.index');
}
public function update(ScheduleRequest $request, Schedule $schedule): RedirectResponse
@ -41,7 +41,7 @@ public function update(ScheduleRequest $request, Schedule $schedule): RedirectRe
Inertia::flash('toast', ['type' => 'success', 'message' => 'Jadwal berhasil diperbarui.']);
return to_route('admin.manage.schedules.index');
return to_route('admin.academic-classes.schedules.index');
}
public function destroy(Schedule $schedule): RedirectResponse

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Academic;
namespace App\Http\Controllers\Admin\AcademicClasses;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Academic\SubmissionRequest;
use App\Http\Requests\Admin\AcademicClasses\SubmissionRequest;
use App\Models\Assignment;
use App\Models\Submission;
use App\Services\Admin\Manage\Academic\SubmissionService;
use App\Services\Admin\AcademicClasses\SubmissionService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
@ -21,7 +21,7 @@ public function index(Assignment $assignment): Response
{
$assignment->load(['courseClass.course', 'courseClass.lecturer.user.profile', 'courseClass.academicTerm']);
return Inertia::render('admin/manage/assignments/submissions', [
return Inertia::render('admin/academic-classes/assignments/submissions', [
'assignment' => $assignment,
'submissions' => $this->service->forAssignment($assignment),
'availableStudents' => $this->service->availableStudents($assignment),

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Announcement;
namespace App\Http\Controllers\Admin\Announcements;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Announcement\AnnouncementRequest;
use App\Http\Requests\Admin\Announcements\AnnouncementRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\Announcement;
use App\Services\Admin\Manage\Announcement\AnnouncementService;
use App\Services\Admin\Announcements\AnnouncementService;
use App\Services\Admin\Master\DepartmentService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
@ -21,7 +21,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/announcements/index', [
return Inertia::render('admin/announcements/index', [
'announcements' => $this->service->paginated(...$request->validatedWithDefaults()),
'departments' => $this->departmentService->getAllForSelect(),
]);
@ -33,7 +33,7 @@ public function store(AnnouncementRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengumuman berhasil ditambahkan.']);
return to_route('admin.manage.announcements.index');
return to_route('admin.announcements.index');
}
public function update(AnnouncementRequest $request, Announcement $announcement): RedirectResponse
@ -42,7 +42,7 @@ public function update(AnnouncementRequest $request, Announcement $announcement)
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengumuman berhasil diperbarui.']);
return to_route('admin.manage.announcements.index');
return to_route('admin.announcements.index');
}
public function destroy(Announcement $announcement): RedirectResponse

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Finance;
namespace App\Http\Controllers\Admin\Finances;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Finance\TuitionInvoiceRequest;
use App\Http\Requests\Admin\Finances\TuitionInvoiceRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\TuitionInvoice;
use App\Services\Admin\Manage\Finance\TuitionInvoiceService;
use App\Services\Admin\Finances\TuitionInvoiceService;
use App\Services\Admin\Master\AcademicTermService;
use App\Services\Admin\Users\StudentService;
use Illuminate\Http\RedirectResponse;
@ -23,7 +23,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/tuition-invoices/index', [
return Inertia::render('admin/finances/tuition-invoices/index', [
'invoices' => $this->service->paginated(...$request->validatedWithDefaults()),
'students' => $this->studentService->getAllForSelect(),
'academicTerms' => $this->academicTermService->getAllForSelect(),
@ -36,7 +36,7 @@ public function store(TuitionInvoiceRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Tagihan berhasil ditambahkan.']);
return to_route('admin.manage.tuition-invoices.index');
return to_route('admin.finances.tuition-invoices.index');
}
public function update(TuitionInvoiceRequest $request, TuitionInvoice $tuitionInvoice): RedirectResponse
@ -45,7 +45,7 @@ public function update(TuitionInvoiceRequest $request, TuitionInvoice $tuitionIn
Inertia::flash('toast', ['type' => 'success', 'message' => 'Tagihan berhasil diperbarui.']);
return to_route('admin.manage.tuition-invoices.index');
return to_route('admin.finances.tuition-invoices.index');
}
public function destroy(TuitionInvoice $tuitionInvoice): RedirectResponse

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Finance;
namespace App\Http\Controllers\Admin\Finances;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Finance\TuitionPaymentRequest;
use App\Http\Requests\Admin\Finances\TuitionPaymentRequest;
use App\Models\TuitionInvoice;
use App\Models\TuitionPayment;
use App\Services\Admin\Manage\Finance\TuitionPaymentService;
use App\Services\Admin\Finances\TuitionPaymentService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
@ -21,7 +21,7 @@ public function index(TuitionInvoice $tuitionInvoice): Response
{
$tuitionInvoice->load(['student.user.profile', 'student.department', 'academicTerm']);
return Inertia::render('admin/manage/tuition-invoices/payments', [
return Inertia::render('admin/finances/tuition-invoices/payments', [
'invoice' => $tuitionInvoice,
'payments' => $this->service->forInvoice($tuitionInvoice),
]);

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Course;
namespace App\Http\Controllers\Admin\Manage;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Course\ClassEnrollmentRequest;
use App\Http\Requests\Admin\Manage\ClassEnrollmentRequest;
use App\Models\ClassEnrollment;
use App\Models\CourseClass;
use App\Services\Admin\Manage\Course\ClassEnrollmentService;
use App\Services\Admin\Manage\ClassEnrollmentService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Course;
namespace App\Http\Controllers\Admin\Manage;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Course\CourseClassRequest;
use App\Http\Requests\Admin\Manage\CourseClassRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\CourseClass;
use App\Services\Admin\Manage\Course\CourseClassService;
use App\Services\Admin\Manage\Course\CourseService;
use App\Services\Admin\Manage\CourseClassService;
use App\Services\Admin\Manage\CourseService;
use App\Services\Admin\Master\AcademicTermService;
use App\Services\Admin\Users\LecturerService;
use Illuminate\Http\RedirectResponse;

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Course;
namespace App\Http\Controllers\Admin\Manage;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Course\CourseRequest;
use App\Http\Requests\Admin\Manage\CourseRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\Course;
use App\Services\Admin\Manage\Course\CourseService;
use App\Services\Admin\Manage\CourseService;
use App\Services\Admin\Master\DepartmentService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Service;
namespace App\Http\Controllers\Admin\Services;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Service\AcademicAdvisingLogRequest;
use App\Http\Requests\Admin\Services\AcademicAdvisingLogRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\AcademicAdvisingLog;
use App\Services\Admin\Manage\Service\AcademicAdvisingLogService;
use App\Services\Admin\Services\AcademicAdvisingLogService;
use App\Services\Admin\Users\LecturerService;
use App\Services\Admin\Users\StudentService;
use Illuminate\Http\RedirectResponse;
@ -23,7 +23,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/academic-advising-logs/index', [
return Inertia::render('admin/services/academic-advising-logs/index', [
'logs' => $this->service->paginated(...$request->validatedWithDefaults()),
'students' => $this->studentService->getAllForSelect(),
'lecturers' => $this->lecturerService->getAllForSelect(),
@ -36,7 +36,7 @@ public function store(AcademicAdvisingLogRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Bimbingan akademik berhasil ditambahkan.']);
return to_route('admin.manage.academic-advising-logs.index');
return to_route('admin.services.academic-advising-logs.index');
}
public function update(AcademicAdvisingLogRequest $request, AcademicAdvisingLog $academicAdvisingLog): RedirectResponse
@ -45,7 +45,7 @@ public function update(AcademicAdvisingLogRequest $request, AcademicAdvisingLog
Inertia::flash('toast', ['type' => 'success', 'message' => 'Bimbingan akademik berhasil diperbarui.']);
return to_route('admin.manage.academic-advising-logs.index');
return to_route('admin.services.academic-advising-logs.index');
}
public function destroy(AcademicAdvisingLog $academicAdvisingLog): RedirectResponse

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Manage\Service;
namespace App\Http\Controllers\Admin\Services;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Manage\Service\LetterRequestRequest;
use App\Http\Requests\Admin\Services\LetterRequestRequest;
use App\Http\Requests\PaginatedRequest;
use App\Models\LetterRequest;
use App\Services\Admin\Manage\Service\LetterRequestService;
use App\Services\Admin\Services\LetterRequestService;
use App\Services\Admin\Users\StudentService;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
@ -21,7 +21,7 @@ public function __construct(
public function index(PaginatedRequest $request): Response
{
return Inertia::render('admin/manage/letter-requests/index', [
return Inertia::render('admin/services/letter-requests/index', [
'letterRequests' => $this->service->paginated(...$request->validatedWithDefaults()),
'students' => $this->studentService->getAllForSelect(),
]);
@ -33,7 +33,7 @@ public function store(LetterRequestRequest $request): RedirectResponse
Inertia::flash('toast', ['type' => 'success', 'message' => 'Surat permohonan berhasil ditambahkan.']);
return to_route('admin.manage.letter-requests.index');
return to_route('admin.services.letter-requests.index');
}
public function update(LetterRequestRequest $request, LetterRequest $letterRequest): RedirectResponse
@ -42,7 +42,7 @@ public function update(LetterRequestRequest $request, LetterRequest $letterReque
Inertia::flash('toast', ['type' => 'success', 'message' => 'Surat permohonan berhasil diperbarui.']);
return to_route('admin.manage.letter-requests.index');
return to_route('admin.services.letter-requests.index');
}
public function destroy(LetterRequest $letterRequest): RedirectResponse

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Academic;
namespace App\Http\Requests\Admin\AcademicClasses;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Academic;
namespace App\Http\Requests\Admin\AcademicClasses;
use App\Enums\AttendanceStatus;
use Illuminate\Foundation\Http\FormRequest;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Academic;
namespace App\Http\Requests\Admin\AcademicClasses;
use App\Enums\RegistrationStatus;
use Illuminate\Foundation\Http\FormRequest;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Academic;
namespace App\Http\Requests\Admin\AcademicClasses;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Academic;
namespace App\Http\Requests\Admin\AcademicClasses;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Academic;
namespace App\Http\Requests\Admin\AcademicClasses;
use App\Enums\SubmissionStatus;
use Illuminate\Foundation\Http\FormRequest;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Announcement;
namespace App\Http\Requests\Admin\Announcements;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Finance;
namespace App\Http\Requests\Admin\Finances;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Finance;
namespace App\Http\Requests\Admin\Finances;
use App\Enums\PaymentStatus;
use Illuminate\Foundation\Http\FormRequest;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Course;
namespace App\Http\Requests\Admin\Manage;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Course;
namespace App\Http\Requests\Admin\Manage;
use App\Enums\ClassMethod;
use App\Models\Course;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Course;
namespace App\Http\Requests\Admin\Manage;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Service;
namespace App\Http\Requests\Admin\Services;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Requests\Admin\Manage\Service;
namespace App\Http\Requests\Admin\Services;
use App\Enums\LetterStatus;
use Illuminate\Foundation\Http\FormRequest;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Academic;
namespace App\Services\Admin\AcademicClasses;
use App\Models\Assignment;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Academic;
namespace App\Services\Admin\AcademicClasses;
use App\Enums\AttendanceStatus;
use App\Models\Attendance;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Academic;
namespace App\Services\Admin\AcademicClasses;
use App\Enums\RegistrationStatus;
use App\Models\ClassEnrollment;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Academic;
namespace App\Services\Admin\AcademicClasses;
use App\Models\Material;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Academic;
namespace App\Services\Admin\AcademicClasses;
use App\Models\Schedule;
use Illuminate\Database\Eloquent\Collection;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Academic;
namespace App\Services\Admin\AcademicClasses;
use App\Models\Assignment;
use App\Models\Student;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Announcement;
namespace App\Services\Admin\Announcements;
use App\Models\Announcement;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Finance;
namespace App\Services\Admin\Finances;
use App\Models\TuitionInvoice;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Finance;
namespace App\Services\Admin\Finances;
use App\Models\TuitionInvoice;
use App\Models\TuitionPayment;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Course;
namespace App\Services\Admin\Manage;
use App\Models\ClassEnrollment;
use App\Models\CourseClass;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Course;
namespace App\Services\Admin\Manage;
use App\Models\CourseClass;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Course;
namespace App\Services\Admin\Manage;
use App\Models\Course;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Service;
namespace App\Services\Admin\Services;
use App\Models\AcademicAdvisingLog;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Services\Admin\Manage\Service;
namespace App\Services\Admin\Services;
use App\Enums\LetterStatus;
use App\Models\LetterRequest;

View File

@ -115,52 +115,49 @@ ## 4. Struktur modul Admin ✅
Semua fitur berada di bawah `/admin` — tidak ada lagi controller atau
halaman yang menggantung di top-level `App\Http\Controllers` /
`resources/js/pages/` di luar folder `admin/`. Setiap fitur admin baru
(CRUD) mengikuti struktur namespace yang sama, di salah satu dari lima grup:
`resources/js/pages/` di luar folder `admin/`.
| Grup | Namespace Controller/Request | Prefix route |
| ------------------ | --------------------------------------- | ------------------ |
| Master data | `Admin\Master` | `admin/master/*` |
| Data operasional | `Admin\Manage` | `admin/manage/*` |
| Manajemen pengguna | `Admin\Users` | `admin/users/*` |
| Pengaturan akun | `Admin\Settings` | `admin/settings/*` |
| Resource mandiri | `Admin` (langsung, tanpa sub-namespace) | `admin/<resource>` |
**Aturan utama: namespace/folder PHP (Controller, Request, Service) dan folder
halaman Inertia (`resources/js/pages/admin/...`) SELALU mengikuti prefix route
di `routes/admin.php` — satu grup di sidebar (`app-sidebar.tsx`) = satu prefix
route = satu namespace.** Jangan menebak dari label sidebar; selalu cek dulu
prefix route-nya sebelum menaruh file baru.
"Resource mandiri" dipakai untuk fitur yang tidak cocok masuk ke 4 grup di
atas — misalnya `Admin\FeedbackController` di `admin/feedback` (data
personal milik user yang sedang login, bukan data akademik yang dikelola
admin atas user lain).
| Grup sidebar | Namespace Controller/Request/Service | Prefix route |
| ------------ | ------------------------------------- | ---------------------------- |
| Pengguna | `Admin\Users` | `admin/users/*` |
| Master | `Admin\Master` | `admin/master/*` |
| Kelas | `Admin\AcademicClasses` | `admin/academic-classes/*` |
| Kelola | `Admin\Manage` | `admin/manage/*` |
| Pengumuman | `Admin\Announcements` | `admin/announcements` |
| Keuangan | `Admin\Finances` | `admin/finances/*` |
| Layanan | `Admin\Services` | `admin/services/*` |
| Pengaturan | `Admin\Settings` | `admin/settings/*` |
| Resource mandiri (navSecondary, bukan grup di navMain) | `Admin` (langsung, tanpa sub-namespace) | `admin/<resource>` |
"Resource mandiri" dipakai untuk fitur yang tidak masuk ke grup sidebar
manapun di navMain — misalnya `Admin\FeedbackController` di `admin/feedback`
(dari menu `navSecondary`, data personal milik user yang sedang login, bukan
data akademik yang dikelola admin atas user lain).
Nama route mengikuti pola `admin.<grup>.<resource>.<action>` (atau
`admin.<resource>.<action>` untuk resource mandiri), dan file Wayfinder
hasil generate mengikuti struktur folder yang sama di
`resources/js/routes/admin/<grup>/<resource>/`.
`admin.<resource>.<action>` untuk resource mandiri, atau `admin.<grup>.<action>`
langsung kalau grup itu cuma punya satu resource yang namanya sama dengan
grupnya sendiri — lihat pola Pengumuman/`AnnouncementController` di
`routes/admin.php`, supaya URL-nya tidak jadi `admin/announcements/announcements`
yang berulang). File Wayfinder hasil generate mengikuti struktur folder yang
sama di `resources/js/routes/admin/<grup>/<resource>/`, dan folder halaman
Inertia-nya di `resources/js/pages/admin/<grup>/<resource>/`.
Kalau satu Service dipakai lintas grup (mis. `CourseClassService` — miliknya
grup Kelola — dipakai juga oleh controller-controller di grup Kelas untuk
mengisi dropdown), itu boleh, tetap `use` dari namespace aslinya
(`App\Services\Admin\Manage\CourseClassService`) — jangan dipindah/duplikasi
hanya karena dipakai controller di grup lain.
Halaman CRUD frontend memakai pola: `PageHeader` (judul + tombol Tambah) →
`FormDialog` (Create/Edit) → `DataTable` + `columns.tsx``DeleteConfirmDialog`.
### 4.1 Sub-namespace di dalam `Admin\Manage`
`Admin\Manage` sendiri dipecah lagi jadi 5 sub-namespace, mengikuti
pengelompokan yang sama seperti grup di `app-sidebar.tsx` (Kelas, Kelola,
Pengumuman, Keuangan, Layanan). **URL/nama route tidak berubah** (tetap flat
`admin/manage/*` / `admin.manage.*`) — hanya struktur folder PHP-nya
(Controller, Request, Service) yang mengikuti sub-namespace ini.
| Sub-namespace | Grup sidebar | Resource |
| --------------------------- | ------------ | -------------------------------------------------------------------------- |
| `Admin\Manage\Course` | Kelola | Course, CourseClass, ClassEnrollment |
| `Admin\Manage\Academic` | Kelas | CourseRegistration, Material, Assignment, Submission, Schedule, Attendance |
| `Admin\Manage\Announcement` | Pengumuman | Announcement |
| `Admin\Manage\Finance` | Keuangan | TuitionInvoice, TuitionPayment |
| `Admin\Manage\Service` | Layanan | LetterRequest, AcademicAdvisingLog |
Kalau menambah resource baru di salah satu grup ini, taruh Controller di
`app/Http/Controllers/Admin/Manage/<SubNamespace>/`, Request-nya di
`app/Http/Requests/Admin/Manage/<SubNamespace>/`, dan Service-nya di
`app/Services/Admin/Manage/<SubNamespace>/` — jangan taruh langsung di
`Admin\Manage` tanpa sub-namespace lagi.
---
## 5. Service ✅

View File

@ -41,17 +41,17 @@ import {
SidebarMenuItem,
} from '@/components/ui/sidebar';
import { index as feedbackRoute } from '@/routes/admin/feedback';
import { index as academicAdvisingLogsRoute } from '@/routes/admin/manage/academic-advising-logs';
import { index as announcementsRoute } from '@/routes/admin/manage/announcements';
import { index as assignmentsRoute } from '@/routes/admin/manage/assignments';
import { index as attendancesRoute } from '@/routes/admin/manage/attendances';
import { index as academicAdvisingLogsRoute } from '@/routes/admin/services/academic-advising-logs';
import { index as announcementsRoute } from '@/routes/admin/announcements';
import { index as assignmentsRoute } from '@/routes/admin/academic-classes/assignments';
import { index as attendancesRoute } from '@/routes/admin/academic-classes/attendances';
import { index as courseClassesRoute } from '@/routes/admin/manage/course-classes';
import { index as courseRegistrationsRoute } from '@/routes/admin/manage/course-registrations';
import { index as courseRegistrationsRoute } from '@/routes/admin/academic-classes/course-registrations';
import { index as coursesRoute } from '@/routes/admin/manage/courses';
import { index as letterRequestsRoute } from '@/routes/admin/manage/letter-requests';
import { index as materialsRoute } from '@/routes/admin/manage/materials';
import { index as schedulesRoute } from '@/routes/admin/manage/schedules';
import { index as tuitionInvoicesRoute } from '@/routes/admin/manage/tuition-invoices';
import { index as letterRequestsRoute } from '@/routes/admin/services/letter-requests';
import { index as materialsRoute } from '@/routes/admin/academic-classes/materials';
import { index as schedulesRoute } from '@/routes/admin/academic-classes/schedules';
import { index as tuitionInvoicesRoute } from '@/routes/admin/finances/tuition-invoices';
import { index as academicTerm } from '@/routes/admin/master/academic-terms';
import { index as departmentsRoute } from '@/routes/admin/master/departments';
import { edit as appearanceRoute } from '@/routes/admin/settings/appearance';

View File

@ -2,7 +2,7 @@ import type { ColumnDef } from '@tanstack/react-table';
import { format } from 'date-fns';
import { ClipboardList, Paperclip, Pencil, Trash2 } from 'lucide-react';
import { RowActions } from '@/components/row-actions';
import { index as submissionsIndex } from '@/routes/admin/manage/assignments/submissions';
import { index as submissionsIndex } from '@/routes/admin/academic-classes/assignments/submissions';
import type { Assignment } from '@/types/assignment';
export type { Assignment } from '@/types/assignment';

View File

@ -26,7 +26,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/assignments';
} from '@/routes/admin/academic-classes/assignments';
import type { Assignment } from '@/types/assignment';
import { createAssignmentColumns } from './columns';

View File

@ -24,12 +24,12 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { index as assignmentIndex } from '@/routes/admin/manage/assignments';
import { index as assignmentIndex } from '@/routes/admin/academic-classes/assignments';
import {
destroy,
store,
update,
} from '@/routes/admin/manage/assignments/submissions';
} from '@/routes/admin/academic-classes/assignments/submissions';
import type { Assignment } from '@/types/assignment';
import type { Submission, SubmissionStudent } from '@/types/submission';
import { SubmissionStatusLabels, SubmissionStatuses } from '@/types/submission';

View File

@ -23,7 +23,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { destroy, session } from '@/routes/admin/manage/attendances';
import { destroy, session } from '@/routes/admin/academic-classes/attendances';
import type {
AttendanceCourseClass,
AttendanceSession,

View File

@ -10,7 +10,7 @@ import { Label } from '@/components/ui/label';
import {
index as attendanceIndex,
store,
} from '@/routes/admin/manage/attendances';
} from '@/routes/admin/academic-classes/attendances';
import type {
AttendanceCourseClass,
AttendanceRosterEntry,

View File

@ -22,7 +22,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/course-registrations';
} from '@/routes/admin/academic-classes/course-registrations';
import type {
CourseRegistration,
CourseRegistrationCourseClass,

View File

@ -25,7 +25,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/materials';
} from '@/routes/admin/academic-classes/materials';
import type { Material } from '@/types/material';
import { createMaterialColumns } from './columns';

View File

@ -19,7 +19,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { cn } from '@/lib/utils';
import { destroy, store, update } from '@/routes/admin/manage/schedules';
import { destroy, store, update } from '@/routes/admin/academic-classes/schedules';
import type { Schedule } from '@/types/schedule';
import { DayOfWeekLabels, DaysOfWeek } from '@/types/schedule';

View File

@ -24,7 +24,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/announcements';
} from '@/routes/admin/announcements';
import type {
Announcement,
AnnouncementDepartment,

View File

@ -4,7 +4,7 @@ import { CreditCard, Pencil, Trash2 } from 'lucide-react';
import { RowActions } from '@/components/row-actions';
import { Badge } from '@/components/ui/badge';
import { formatRupiah } from '@/lib/currency';
import { index as paymentsIndex } from '@/routes/admin/manage/tuition-invoices/payments';
import { index as paymentsIndex } from '@/routes/admin/finances/tuition-invoices/payments';
import type { TuitionInvoice } from '@/types/tuition-invoice';
export type { TuitionInvoice } from '@/types/tuition-invoice';

View File

@ -25,7 +25,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/tuition-invoices';
} from '@/routes/admin/finances/tuition-invoices';
import type {
TuitionInvoice,
TuitionInvoiceStudent,

View File

@ -26,12 +26,12 @@ import {
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { formatRupiah } from '@/lib/currency';
import { index as tuitionInvoiceIndex } from '@/routes/admin/manage/tuition-invoices';
import { index as tuitionInvoiceIndex } from '@/routes/admin/finances/tuition-invoices';
import {
destroy,
store,
update,
} from '@/routes/admin/manage/tuition-invoices/payments';
} from '@/routes/admin/finances/tuition-invoices/payments';
import type { TuitionInvoice } from '@/types/tuition-invoice';
import type { TuitionPayment } from '@/types/tuition-payment';
import { PaymentStatusLabels, PaymentStatuses } from '@/types/tuition-payment';

View File

@ -25,7 +25,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/academic-advising-logs';
} from '@/routes/admin/services/academic-advising-logs';
import type {
AcademicAdvisingLog,
AcademicAdvisingLogLecturer,

View File

@ -25,7 +25,7 @@ import {
destroy,
store,
update,
} from '@/routes/admin/manage/letter-requests';
} from '@/routes/admin/services/letter-requests';
import type {
LetterRequest,
LetterRequestStudent,

View File

@ -1,22 +1,22 @@
<?php
use App\Http\Controllers\Admin\AcademicClasses\AssignmentController;
use App\Http\Controllers\Admin\AcademicClasses\AttendanceController;
use App\Http\Controllers\Admin\AcademicClasses\CourseRegistrationController;
use App\Http\Controllers\Admin\AcademicClasses\MaterialController;
use App\Http\Controllers\Admin\AcademicClasses\ScheduleController;
use App\Http\Controllers\Admin\AcademicClasses\SubmissionController;
use App\Http\Controllers\Admin\Announcements\AnnouncementController;
use App\Http\Controllers\Admin\FeedbackController;
use App\Http\Controllers\Admin\Manage\Academic\AssignmentController;
use App\Http\Controllers\Admin\Manage\Academic\AttendanceController;
use App\Http\Controllers\Admin\Manage\Academic\CourseRegistrationController;
use App\Http\Controllers\Admin\Manage\Academic\MaterialController;
use App\Http\Controllers\Admin\Manage\Academic\ScheduleController;
use App\Http\Controllers\Admin\Manage\Academic\SubmissionController;
use App\Http\Controllers\Admin\Manage\Announcement\AnnouncementController;
use App\Http\Controllers\Admin\Manage\Course\ClassEnrollmentController;
use App\Http\Controllers\Admin\Manage\Course\CourseClassController;
use App\Http\Controllers\Admin\Manage\Course\CourseController;
use App\Http\Controllers\Admin\Manage\Finance\TuitionInvoiceController;
use App\Http\Controllers\Admin\Manage\Finance\TuitionPaymentController;
use App\Http\Controllers\Admin\Manage\Service\AcademicAdvisingLogController;
use App\Http\Controllers\Admin\Manage\Service\LetterRequestController;
use App\Http\Controllers\Admin\Finances\TuitionInvoiceController;
use App\Http\Controllers\Admin\Finances\TuitionPaymentController;
use App\Http\Controllers\Admin\Manage\ClassEnrollmentController;
use App\Http\Controllers\Admin\Manage\CourseClassController;
use App\Http\Controllers\Admin\Manage\CourseController;
use App\Http\Controllers\Admin\Master\AcademicTermController;
use App\Http\Controllers\Admin\Master\DepartmentController;
use App\Http\Controllers\Admin\Services\AcademicAdvisingLogController;
use App\Http\Controllers\Admin\Services\LetterRequestController;
use App\Http\Controllers\Admin\Settings\ProfileController;
use App\Http\Controllers\Admin\Settings\SecurityController;
use App\Http\Controllers\Admin\Users\AdministratorController;
@ -30,16 +30,7 @@
Route::resource('departments', DepartmentController::class)->except(['create', 'edit', 'show']);
});
Route::prefix('admin/manage')->name('admin.manage.')->group(function () {
Route::resource('courses', CourseController::class)->except(['create', 'edit', 'show']);
Route::resource('course-classes', CourseClassController::class)->except(['create', 'edit', 'show']);
Route::prefix('course-classes/{course_class}/enrollments')->name('course-classes.enrollments.')->group(function () {
Route::get('/', [ClassEnrollmentController::class, 'index'])->name('index');
Route::post('/', [ClassEnrollmentController::class, 'store'])->name('store');
Route::delete('{enrollment}', [ClassEnrollmentController::class, 'destroy'])->name('destroy');
});
Route::prefix('admin/academic-classes')->name('admin.academic-classes.')->group(function () {
Route::resource('course-registrations', CourseRegistrationController::class)->except(['create', 'edit', 'show']);
Route::resource('materials', MaterialController::class)->except(['create', 'edit', 'show']);
@ -67,7 +58,27 @@
->whereNumber('meeting_number')
->name('destroy');
});
});
Route::prefix('admin/manage')->name('admin.manage.')->group(function () {
Route::resource('courses', CourseController::class)->except(['create', 'edit', 'show']);
Route::resource('course-classes', CourseClassController::class)->except(['create', 'edit', 'show']);
Route::prefix('course-classes/{course_class}/enrollments')->name('course-classes.enrollments.')->group(function () {
Route::get('/', [ClassEnrollmentController::class, 'index'])->name('index');
Route::post('/', [ClassEnrollmentController::class, 'store'])->name('store');
Route::delete('{enrollment}', [ClassEnrollmentController::class, 'destroy'])->name('destroy');
});
});
Route::prefix('admin/announcements')->name('admin.announcements.')->group(function () {
Route::get('/', [AnnouncementController::class, 'index'])->name('index');
Route::post('/', [AnnouncementController::class, 'store'])->name('store');
Route::put('{announcement}', [AnnouncementController::class, 'update'])->name('update');
Route::delete('{announcement}', [AnnouncementController::class, 'destroy'])->name('destroy');
});
Route::prefix('admin/finances')->name('admin.finances.')->group(function () {
Route::resource('tuition-invoices', TuitionInvoiceController::class)->except(['create', 'edit', 'show']);
Route::prefix('tuition-invoices/{tuition_invoice}/payments')->name('tuition-invoices.payments.')->group(function () {
@ -76,9 +87,9 @@
Route::put('{payment}', [TuitionPaymentController::class, 'update'])->name('update');
Route::delete('{payment}', [TuitionPaymentController::class, 'destroy'])->name('destroy');
});
});
Route::resource('announcements', AnnouncementController::class)->except(['create', 'edit', 'show']);
Route::prefix('admin/services')->name('admin.services.')->group(function () {
Route::resource('letter-requests', LetterRequestController::class)->except(['create', 'edit', 'show']);
Route::resource('academic-advising-logs', AcademicAdvisingLogController::class)->except(['create', 'edit', 'show']);