From 10c3e42228eb4e8f4167f5e70bb12048581a4fda Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Tue, 1 Sep 2026 14:27:02 +0700 Subject: [PATCH] feat: add open_semesters field to AcademicTerm model and request, update related services and migration --- .../Admin/Master/AcademicTermRequest.php | 2 + app/Models/AcademicTerm.php | 1 + .../Admin/Master/AcademicTermService.php | 25 ++++++++--- ..._03_000003_create_academic_terms_table.php | 1 + .../admin/master/academic-terms/index.tsx | 41 +++++++++++++++++++ resources/js/types/academic-term.ts | 1 + 6 files changed, 65 insertions(+), 6 deletions(-) diff --git a/app/Http/Requests/Admin/Master/AcademicTermRequest.php b/app/Http/Requests/Admin/Master/AcademicTermRequest.php index 22bebc4..53d6f0a 100644 --- a/app/Http/Requests/Admin/Master/AcademicTermRequest.php +++ b/app/Http/Requests/Admin/Master/AcademicTermRequest.php @@ -79,6 +79,8 @@ function ($attribute, $value, $fail) { }, ], 'is_active' => ['boolean'], + 'open_semesters' => ['nullable', 'array'], + 'open_semesters.*' => ['integer', 'between:1,8'], ]; } } diff --git a/app/Models/AcademicTerm.php b/app/Models/AcademicTerm.php index 692f3ae..472977e 100644 --- a/app/Models/AcademicTerm.php +++ b/app/Models/AcademicTerm.php @@ -28,6 +28,7 @@ protected function casts(): array 'start_date' => 'date', 'end_date' => 'date', 'is_active' => 'boolean', + 'open_semesters' => 'array', ]; } diff --git a/app/Services/Admin/Master/AcademicTermService.php b/app/Services/Admin/Master/AcademicTermService.php index 0d4dc71..39a82a5 100644 --- a/app/Services/Admin/Master/AcademicTermService.php +++ b/app/Services/Admin/Master/AcademicTermService.php @@ -11,7 +11,7 @@ class AcademicTermService { public function getAllForSelect(): Collection { - return AcademicTerm::select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active'])->latest()->get(); + return AcademicTerm::select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters'])->latest()->get(); } /** @@ -27,17 +27,20 @@ public function getActive(): ?AcademicTerm public function paginated(int $perPage = 25, string $search = '', ?string $semester = null, ?bool $isActive = null): LengthAwarePaginator { return AcademicTerm::query() - ->select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active']) - ->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%")) - ->when($semester, fn ($q) => $q->where('semester', $semester)) - ->when($isActive !== null, fn ($q) => $q->where('is_active', $isActive)) + ->select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters']) + ->when($search, fn($q) => $q->where('name', 'like', "%{$search}%")) + ->when($semester, fn($q) => $q->where('semester', $semester)) + ->when($isActive !== null, fn($q) => $q->where('is_active', $isActive)) ->latest() ->paginate($perPage); } public function create(array $data): AcademicTerm { - return AcademicTerm::create($data); + return AcademicTerm::create([ + ...$data, + 'open_semesters' => $this->normalizeOpenSemesters($data['open_semesters'] ?? []), + ]); } public function update(AcademicTerm $academicTerm, array $data): AcademicTerm @@ -47,6 +50,7 @@ public function update(AcademicTerm $academicTerm, array $data): AcademicTerm $academicTerm->start_date = $data['start_date']; $academicTerm->end_date = $data['end_date']; $academicTerm->is_active = $data['is_active']; + $academicTerm->open_semesters = $this->normalizeOpenSemesters($data['open_semesters'] ?? []); $academicTerm->update(); return $academicTerm; @@ -67,4 +71,13 @@ public function updateActiveStatus(AcademicTerm $academicTerm, bool $isActive): $academicTerm->update(['is_active' => $isActive]); }); } + + /** + * @param array $openSemesters + * @return array + */ + private function normalizeOpenSemesters(array $openSemesters): array + { + return array_values(array_unique(array_map('intval', $openSemesters))); + } } diff --git a/database/migrations/2026_08_03_000003_create_academic_terms_table.php b/database/migrations/2026_08_03_000003_create_academic_terms_table.php index 53d372d..28091ea 100644 --- a/database/migrations/2026_08_03_000003_create_academic_terms_table.php +++ b/database/migrations/2026_08_03_000003_create_academic_terms_table.php @@ -16,6 +16,7 @@ public function up(): void $table->date('start_date'); $table->date('end_date'); $table->boolean('is_active')->default(false); + $table->json('open_semesters')->nullable(); $table->timestamps(); }); } diff --git a/resources/js/pages/admin/master/academic-terms/index.tsx b/resources/js/pages/admin/master/academic-terms/index.tsx index 2697870..cf34edc 100644 --- a/resources/js/pages/admin/master/academic-terms/index.tsx +++ b/resources/js/pages/admin/master/academic-terms/index.tsx @@ -329,6 +329,7 @@ function CreateForm({ + )} @@ -467,9 +468,49 @@ function EditForm({ /> + ) } ); } + +function OpenSemestersField({ + idPrefix, + defaultValue = [], +}: { + idPrefix: string; + defaultValue?: number[]; +}) { + return ( +
+ +

+ Kosongkan untuk menutup semua semester. Centang semester + tertentu untuk membuka pendaftaran KRS pada semester itu. +

+
+ {[1, 2, 3, 4, 5, 6, 7, 8].map((semester) => ( +
+ + +
+ ))} +
+
+ ); +} diff --git a/resources/js/types/academic-term.ts b/resources/js/types/academic-term.ts index 1b2b769..f9b537b 100644 --- a/resources/js/types/academic-term.ts +++ b/resources/js/types/academic-term.ts @@ -17,6 +17,7 @@ export type AcademicTerm = { end_date: string; formatted_end_date: string; is_active: boolean; + open_semesters: number[] | null; created_at: string; updated_at: string; };