feat: update CreateForm and EditForm to filter courses and lecturers based on selected lecturer, enhancing user experience
This commit is contained in:
parent
1b68cf6125
commit
cdd81caf22
@ -349,26 +349,19 @@ function CreateForm({
|
||||
.map((a) => a.course_id),
|
||||
);
|
||||
const selectedCourseIds = new Set(selectedCourses.map((c) => c.id));
|
||||
const availableCourses = courses.filter(
|
||||
(c) =>
|
||||
!takenCourseIds.has(c.id) &&
|
||||
!selectedCourseIds.has(c.id) &&
|
||||
courseMatchesTermParity(c, selectedTerm),
|
||||
const lecturerDepartmentIds = new Set(
|
||||
lecturer ? lecturer.departments.map((d) => d.id) : [],
|
||||
);
|
||||
const availableCourses = lecturer
|
||||
? courses.filter(
|
||||
(c) =>
|
||||
lecturerDepartmentIds.has(c.department_id) &&
|
||||
!takenCourseIds.has(c.id) &&
|
||||
!selectedCourseIds.has(c.id) &&
|
||||
courseMatchesTermParity(c, selectedTerm),
|
||||
)
|
||||
: [];
|
||||
const courseGroups = groupCoursesByDepartmentAndSemester(availableCourses);
|
||||
const selectedDepartmentIds = new Set(
|
||||
selectedCourses.map((c) => c.department_id),
|
||||
);
|
||||
const availableLecturers =
|
||||
selectedCourses.length > 0
|
||||
? lecturers.filter((l) =>
|
||||
[...selectedDepartmentIds].every((departmentId) =>
|
||||
l.departments.some(
|
||||
(department) => department.id === departmentId,
|
||||
),
|
||||
),
|
||||
)
|
||||
: lecturers;
|
||||
|
||||
function reset() {
|
||||
setAcademicTermId('');
|
||||
@ -405,7 +398,6 @@ function CreateForm({
|
||||
onValueChange={(value) => {
|
||||
setAcademicTermId(value);
|
||||
setSelectedCourses([]);
|
||||
setLecturer(null);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
@ -424,6 +416,52 @@ function CreateForm({
|
||||
</Select>
|
||||
<InputError message={errors.academic_term_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Dosen Pengampu{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="lecturer_id"
|
||||
value={lecturer?.id ?? ''}
|
||||
/>
|
||||
<Combobox
|
||||
items={lecturers}
|
||||
value={lecturer}
|
||||
onValueChange={(value) => {
|
||||
setLecturer(value);
|
||||
setSelectedCourses([]);
|
||||
}}
|
||||
itemToStringLabel={(lect) =>
|
||||
`${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}`
|
||||
}
|
||||
isItemEqualToValue={(a, b) => a.id === b.id}
|
||||
>
|
||||
<ComboboxInput
|
||||
placeholder="Pilih dosen pengampu"
|
||||
className="w-full"
|
||||
/>
|
||||
<ComboboxContent>
|
||||
<ComboboxEmpty>
|
||||
Dosen tidak ditemukan.
|
||||
</ComboboxEmpty>
|
||||
<ComboboxList>
|
||||
{(lect: Lecturer) => (
|
||||
<ComboboxItem
|
||||
key={lect.id}
|
||||
value={lect}
|
||||
>
|
||||
{lect.user?.profile?.full_name ??
|
||||
'N/A'}{' '}
|
||||
- {lect.lecturer_number}
|
||||
</ComboboxItem>
|
||||
)}
|
||||
</ComboboxList>
|
||||
</ComboboxContent>
|
||||
</Combobox>
|
||||
<InputError message={errors.lecturer_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Mata Kuliah{' '}
|
||||
@ -441,12 +479,10 @@ function CreateForm({
|
||||
items={courseGroups}
|
||||
multiple
|
||||
value={selectedCourses}
|
||||
onValueChange={(value) => {
|
||||
setSelectedCourses(value);
|
||||
setLecturer(null);
|
||||
}}
|
||||
onValueChange={setSelectedCourses}
|
||||
itemToStringLabel={(c) => `${c.code} - ${c.name}`}
|
||||
isItemEqualToValue={(a, b) => a.id === b.id}
|
||||
disabled={!lecturer}
|
||||
>
|
||||
<ComboboxChips ref={courseAnchor}>
|
||||
{selectedCourses.map((c) => (
|
||||
@ -458,10 +494,13 @@ function CreateForm({
|
||||
</ComboboxChip>
|
||||
))}
|
||||
<ComboboxChipsInput
|
||||
disabled={!lecturer}
|
||||
placeholder={
|
||||
selectedCourses.length === 0
|
||||
? 'Pilih mata kuliah (bisa lebih dari satu)'
|
||||
: ''
|
||||
!lecturer
|
||||
? 'Pilih dosen pengampu terlebih dahulu'
|
||||
: selectedCourses.length === 0
|
||||
? 'Pilih mata kuliah (bisa lebih dari satu)'
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
</ComboboxChips>
|
||||
@ -495,55 +534,6 @@ function CreateForm({
|
||||
</Combobox>
|
||||
<InputError message={errors.course_ids} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Dosen Pengampu{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="lecturer_id"
|
||||
value={lecturer?.id ?? ''}
|
||||
/>
|
||||
<Combobox
|
||||
items={availableLecturers}
|
||||
value={lecturer}
|
||||
onValueChange={setLecturer}
|
||||
itemToStringLabel={(lect) =>
|
||||
`${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}`
|
||||
}
|
||||
isItemEqualToValue={(a, b) => a.id === b.id}
|
||||
disabled={selectedCourses.length === 0}
|
||||
>
|
||||
<ComboboxInput
|
||||
disabled={selectedCourses.length === 0}
|
||||
placeholder={
|
||||
selectedCourses.length > 0
|
||||
? 'Pilih dosen pengampu'
|
||||
: 'Pilih mata kuliah terlebih dahulu'
|
||||
}
|
||||
className="w-full"
|
||||
/>
|
||||
<ComboboxContent>
|
||||
<ComboboxEmpty>
|
||||
Dosen tidak ditemukan.
|
||||
</ComboboxEmpty>
|
||||
<ComboboxList>
|
||||
{(lect: Lecturer) => (
|
||||
<ComboboxItem
|
||||
key={lect.id}
|
||||
value={lect}
|
||||
>
|
||||
{lect.user?.profile?.full_name ??
|
||||
'N/A'}{' '}
|
||||
- {lect.lecturer_number}
|
||||
</ComboboxItem>
|
||||
)}
|
||||
</ComboboxList>
|
||||
</ComboboxContent>
|
||||
</Combobox>
|
||||
<InputError message={errors.lecturer_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>Metode</Label>
|
||||
<input type="hidden" name="method" />
|
||||
@ -610,18 +600,18 @@ function EditForm({
|
||||
)
|
||||
.map((a) => a.course_id),
|
||||
);
|
||||
const availableCourses = courses.filter(
|
||||
(c) =>
|
||||
!takenCourseIds.has(c.id) && courseMatchesTermParity(c, selectedTerm),
|
||||
const lecturerDepartmentIds = new Set(
|
||||
lecturer ? lecturer.departments.map((d) => d.id) : [],
|
||||
);
|
||||
const courseGroups = groupCoursesByDepartmentAndSemester(availableCourses);
|
||||
const availableLecturers = course
|
||||
? lecturers.filter((l) =>
|
||||
l.departments.some(
|
||||
(department) => department.id === course.department_id,
|
||||
),
|
||||
const availableCourses = lecturer
|
||||
? courses.filter(
|
||||
(c) =>
|
||||
lecturerDepartmentIds.has(c.department_id) &&
|
||||
!takenCourseIds.has(c.id) &&
|
||||
courseMatchesTermParity(c, selectedTerm),
|
||||
)
|
||||
: lecturers;
|
||||
: [];
|
||||
const courseGroups = groupCoursesByDepartmentAndSemester(availableCourses);
|
||||
|
||||
return (
|
||||
<FormDialog
|
||||
@ -635,6 +625,85 @@ function EditForm({
|
||||
{({ errors }) =>
|
||||
editing && (
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Periode Akademik{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="academic_term_id"
|
||||
value={academicTermId}
|
||||
/>
|
||||
<Select
|
||||
value={academicTermId}
|
||||
onValueChange={(value) => {
|
||||
setAcademicTermId(value);
|
||||
setCourse(null);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Pilih periode akademik" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{academicTerms.map((term) => (
|
||||
<SelectItem
|
||||
key={term.id}
|
||||
value={String(term.id)}
|
||||
>
|
||||
{formatAcademicTermLabel(term)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<InputError message={errors.academic_term_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Dosen Pengampu{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="lecturer_id"
|
||||
value={lecturer?.id ?? ''}
|
||||
/>
|
||||
<Combobox
|
||||
items={lecturers}
|
||||
value={lecturer}
|
||||
onValueChange={(value) => {
|
||||
setLecturer(value);
|
||||
setCourse(null);
|
||||
}}
|
||||
itemToStringLabel={(lect) =>
|
||||
`${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}`
|
||||
}
|
||||
isItemEqualToValue={(a, b) => a.id === b.id}
|
||||
>
|
||||
<ComboboxInput
|
||||
placeholder="Pilih dosen pengampu"
|
||||
className="w-full"
|
||||
/>
|
||||
<ComboboxContent>
|
||||
<ComboboxEmpty>
|
||||
Dosen tidak ditemukan.
|
||||
</ComboboxEmpty>
|
||||
<ComboboxList>
|
||||
{(lect: Lecturer) => (
|
||||
<ComboboxItem
|
||||
key={lect.id}
|
||||
value={lect}
|
||||
>
|
||||
{lect.user?.profile
|
||||
?.full_name ?? 'N/A'}{' '}
|
||||
- {lect.lecturer_number}
|
||||
</ComboboxItem>
|
||||
)}
|
||||
</ComboboxList>
|
||||
</ComboboxContent>
|
||||
</Combobox>
|
||||
<InputError message={errors.lecturer_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Mata Kuliah{' '}
|
||||
@ -648,17 +717,20 @@ function EditForm({
|
||||
<Combobox
|
||||
items={courseGroups}
|
||||
value={course}
|
||||
onValueChange={(value) => {
|
||||
setCourse(value);
|
||||
setLecturer(null);
|
||||
}}
|
||||
onValueChange={setCourse}
|
||||
itemToStringLabel={(c) =>
|
||||
`${c.code} - ${c.name}`
|
||||
}
|
||||
isItemEqualToValue={(a, b) => a.id === b.id}
|
||||
disabled={!lecturer}
|
||||
>
|
||||
<ComboboxInput
|
||||
placeholder="Pilih mata kuliah"
|
||||
disabled={!lecturer}
|
||||
placeholder={
|
||||
lecturer
|
||||
? 'Pilih mata kuliah'
|
||||
: 'Pilih dosen pengampu terlebih dahulu'
|
||||
}
|
||||
className="w-full"
|
||||
/>
|
||||
<ComboboxContent>
|
||||
@ -692,89 +764,6 @@ function EditForm({
|
||||
</Combobox>
|
||||
<InputError message={errors.course_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Dosen Pengampu{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="lecturer_id"
|
||||
value={lecturer?.id ?? ''}
|
||||
/>
|
||||
<Combobox
|
||||
items={availableLecturers}
|
||||
value={lecturer}
|
||||
onValueChange={setLecturer}
|
||||
itemToStringLabel={(lect) =>
|
||||
`${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}`
|
||||
}
|
||||
isItemEqualToValue={(a, b) => a.id === b.id}
|
||||
disabled={!course}
|
||||
>
|
||||
<ComboboxInput
|
||||
disabled={!course}
|
||||
placeholder={
|
||||
course
|
||||
? 'Pilih dosen pengampu'
|
||||
: 'Pilih mata kuliah terlebih dahulu'
|
||||
}
|
||||
className="w-full"
|
||||
/>
|
||||
<ComboboxContent>
|
||||
<ComboboxEmpty>
|
||||
Dosen tidak ditemukan.
|
||||
</ComboboxEmpty>
|
||||
<ComboboxList>
|
||||
{(lect: Lecturer) => (
|
||||
<ComboboxItem
|
||||
key={lect.id}
|
||||
value={lect}
|
||||
>
|
||||
{lect.user?.profile
|
||||
?.full_name ?? 'N/A'}{' '}
|
||||
- {lect.lecturer_number}
|
||||
</ComboboxItem>
|
||||
)}
|
||||
</ComboboxList>
|
||||
</ComboboxContent>
|
||||
</Combobox>
|
||||
<InputError message={errors.lecturer_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
Periode Akademik{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="academic_term_id"
|
||||
value={academicTermId}
|
||||
/>
|
||||
<Select
|
||||
value={academicTermId}
|
||||
onValueChange={(value) => {
|
||||
setAcademicTermId(value);
|
||||
setCourse(null);
|
||||
setLecturer(null);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Pilih periode akademik" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{academicTerms.map((term) => (
|
||||
<SelectItem
|
||||
key={term.id}
|
||||
value={String(term.id)}
|
||||
>
|
||||
{formatAcademicTermLabel(term)}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<InputError message={errors.academic_term_id} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>Metode</Label>
|
||||
<Select
|
||||
|
||||
Loading…
Reference in New Issue
Block a user