feat: add open_semesters field to AcademicTerm model and request, update related services and migration
This commit is contained in:
parent
93ddee8fd6
commit
10c3e42228
@ -79,6 +79,8 @@ function ($attribute, $value, $fail) {
|
||||
},
|
||||
],
|
||||
'is_active' => ['boolean'],
|
||||
'open_semesters' => ['nullable', 'array'],
|
||||
'open_semesters.*' => ['integer', 'between:1,8'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ protected function casts(): array
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'is_active' => 'boolean',
|
||||
'open_semesters' => 'array',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -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<int, mixed> $openSemesters
|
||||
* @return array<int, int>
|
||||
*/
|
||||
private function normalizeOpenSemesters(array $openSemesters): array
|
||||
{
|
||||
return array_values(array_unique(array_map('intval', $openSemesters)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@ -329,6 +329,7 @@ function CreateForm({
|
||||
<Checkbox id="is_active" name="is_active" value="1" />
|
||||
<Label htmlFor="is_active">Aktif</Label>
|
||||
</div>
|
||||
<OpenSemestersField idPrefix="create" />
|
||||
</div>
|
||||
)}
|
||||
</FormDialog>
|
||||
@ -467,9 +468,49 @@ function EditForm({
|
||||
/>
|
||||
<Label htmlFor="edit-is_active">Aktif</Label>
|
||||
</div>
|
||||
<OpenSemestersField
|
||||
idPrefix="edit"
|
||||
defaultValue={editing.open_semesters ?? []}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</FormDialog>
|
||||
);
|
||||
}
|
||||
|
||||
function OpenSemestersField({
|
||||
idPrefix,
|
||||
defaultValue = [],
|
||||
}: {
|
||||
idPrefix: string;
|
||||
defaultValue?: number[];
|
||||
}) {
|
||||
return (
|
||||
<div className="grid gap-2">
|
||||
<Label>Semester Dibuka untuk KRS</Label>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Kosongkan untuk menutup semua semester. Centang semester
|
||||
tertentu untuk membuka pendaftaran KRS pada semester itu.
|
||||
</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{[1, 2, 3, 4, 5, 6, 7, 8].map((semester) => (
|
||||
<div key={semester} className="flex items-center gap-2">
|
||||
<Checkbox
|
||||
id={`${idPrefix}-open-semester-${semester}`}
|
||||
name="open_semesters[]"
|
||||
value={semester}
|
||||
defaultChecked={defaultValue.includes(semester)}
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`${idPrefix}-open-semester-${semester}`}
|
||||
className="font-normal"
|
||||
>
|
||||
Semester {semester}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user