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'],
|
'is_active' => ['boolean'],
|
||||||
|
'open_semesters' => ['nullable', 'array'],
|
||||||
|
'open_semesters.*' => ['integer', 'between:1,8'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ protected function casts(): array
|
|||||||
'start_date' => 'date',
|
'start_date' => 'date',
|
||||||
'end_date' => 'date',
|
'end_date' => 'date',
|
||||||
'is_active' => 'boolean',
|
'is_active' => 'boolean',
|
||||||
|
'open_semesters' => 'array',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class AcademicTermService
|
|||||||
{
|
{
|
||||||
public function getAllForSelect(): Collection
|
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
|
public function paginated(int $perPage = 25, string $search = '', ?string $semester = null, ?bool $isActive = null): LengthAwarePaginator
|
||||||
{
|
{
|
||||||
return AcademicTerm::query()
|
return AcademicTerm::query()
|
||||||
->select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active'])
|
->select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters'])
|
||||||
->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%"))
|
->when($search, fn($q) => $q->where('name', 'like', "%{$search}%"))
|
||||||
->when($semester, fn ($q) => $q->where('semester', $semester))
|
->when($semester, fn($q) => $q->where('semester', $semester))
|
||||||
->when($isActive !== null, fn ($q) => $q->where('is_active', $isActive))
|
->when($isActive !== null, fn($q) => $q->where('is_active', $isActive))
|
||||||
->latest()
|
->latest()
|
||||||
->paginate($perPage);
|
->paginate($perPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(array $data): AcademicTerm
|
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
|
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->start_date = $data['start_date'];
|
||||||
$academicTerm->end_date = $data['end_date'];
|
$academicTerm->end_date = $data['end_date'];
|
||||||
$academicTerm->is_active = $data['is_active'];
|
$academicTerm->is_active = $data['is_active'];
|
||||||
|
$academicTerm->open_semesters = $this->normalizeOpenSemesters($data['open_semesters'] ?? []);
|
||||||
$academicTerm->update();
|
$academicTerm->update();
|
||||||
|
|
||||||
return $academicTerm;
|
return $academicTerm;
|
||||||
@ -67,4 +71,13 @@ public function updateActiveStatus(AcademicTerm $academicTerm, bool $isActive):
|
|||||||
$academicTerm->update(['is_active' => $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('start_date');
|
||||||
$table->date('end_date');
|
$table->date('end_date');
|
||||||
$table->boolean('is_active')->default(false);
|
$table->boolean('is_active')->default(false);
|
||||||
|
$table->json('open_semesters')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -329,6 +329,7 @@ function CreateForm({
|
|||||||
<Checkbox id="is_active" name="is_active" value="1" />
|
<Checkbox id="is_active" name="is_active" value="1" />
|
||||||
<Label htmlFor="is_active">Aktif</Label>
|
<Label htmlFor="is_active">Aktif</Label>
|
||||||
</div>
|
</div>
|
||||||
|
<OpenSemestersField idPrefix="create" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</FormDialog>
|
</FormDialog>
|
||||||
@ -467,9 +468,49 @@ function EditForm({
|
|||||||
/>
|
/>
|
||||||
<Label htmlFor="edit-is_active">Aktif</Label>
|
<Label htmlFor="edit-is_active">Aktif</Label>
|
||||||
</div>
|
</div>
|
||||||
|
<OpenSemestersField
|
||||||
|
idPrefix="edit"
|
||||||
|
defaultValue={editing.open_semesters ?? []}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</FormDialog>
|
</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;
|
end_date: string;
|
||||||
formatted_end_date: string;
|
formatted_end_date: string;
|
||||||
is_active: boolean;
|
is_active: boolean;
|
||||||
|
open_semesters: number[] | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user