refactor: remove class_name from CourseClass and related components
Some checks failed
tests / ci (pull_request) Has been cancelled

This commit is contained in:
Yoga Pangestu 2026-08-30 13:14:53 +07:00
parent 6c28782484
commit 5710a57992
25 changed files with 158 additions and 192 deletions

View File

@ -26,7 +26,6 @@ public function rules(): array
Rule::exists('lecturers', 'id')->where('department_id', $departmentId), Rule::exists('lecturers', 'id')->where('department_id', $departmentId),
], ],
'academic_term_id' => ['required', 'integer', Rule::exists('academic_terms', 'id')], 'academic_term_id' => ['required', 'integer', Rule::exists('academic_terms', 'id')],
'class_name' => ['nullable', 'string', 'max:50'],
'method' => ['nullable', 'string', Rule::in(ClassMethod::values())], 'method' => ['nullable', 'string', Rule::in(ClassMethod::values())],
]; ];
} }

View File

@ -10,7 +10,7 @@ class CourseClassService
{ {
public function getAllForSelect(): Collection public function getAllForSelect(): Collection
{ {
return CourseClass::select(['id', 'course_id', 'class_name']) return CourseClass::select(['id', 'course_id'])
->with('course:id,code,name') ->with('course:id,code,name')
->get(); ->get();
} }
@ -18,11 +18,10 @@ public function getAllForSelect(): Collection
public function paginated(int $perPage = 25, string $search = '', ?int $academicTermId = null, ?string $method = null): LengthAwarePaginator public function paginated(int $perPage = 25, string $search = '', ?int $academicTermId = null, ?string $method = null): LengthAwarePaginator
{ {
return CourseClass::query() return CourseClass::query()
->select(['id', 'course_id', 'lecturer_id', 'academic_term_id', 'class_name', 'method']) ->select(['id', 'course_id', 'lecturer_id', 'academic_term_id', 'method'])
->withCount('enrollments') ->withCount('enrollments')
->with(['course:id,code,name,department_id', 'lecturer.user.profile', 'academicTerm:id,name,semester,start_date,end_date']) ->with(['course:id,code,name,department_id', 'lecturer.user.profile', 'academicTerm:id,name,semester,start_date,end_date'])
->when($search, fn ($q) => $q->where('class_name', 'like', "%{$search}%") ->when($search, fn ($q) => $q->whereHas('course', fn ($q) => $q->where('name', 'like', "%{$search}%")->orWhere('code', 'like', "%{$search}%")))
->orWhereHas('course', fn ($q) => $q->where('name', 'like', "%{$search}%")->orWhere('code', 'like', "%{$search}%")))
->when($academicTermId, fn ($q) => $q->where('academic_term_id', $academicTermId)) ->when($academicTermId, fn ($q) => $q->where('academic_term_id', $academicTermId))
->when($method, fn ($q) => $q->where('method', $method)) ->when($method, fn ($q) => $q->where('method', $method))
->latest() ->latest()
@ -39,7 +38,6 @@ public function update(CourseClass $courseClass, array $data): CourseClass
$courseClass->course_id = $data['course_id']; $courseClass->course_id = $data['course_id'];
$courseClass->lecturer_id = $data['lecturer_id']; $courseClass->lecturer_id = $data['lecturer_id'];
$courseClass->academic_term_id = $data['academic_term_id']; $courseClass->academic_term_id = $data['academic_term_id'];
$courseClass->class_name = $data['class_name'] ?? null;
$courseClass->method = $data['method'] ?? null; $courseClass->method = $data['method'] ?? null;
$courseClass->update(); $courseClass->update();

View File

@ -18,6 +18,7 @@ public function getAllForSelect(): Collection
->with([ ->with([
'user:id,username', 'user:id,username',
'user.profile:id,user_id,full_name', 'user.profile:id,user_id,full_name',
'departments:id,name',
]) ])
->get(); ->get();
} }

View File

@ -14,7 +14,6 @@ public function up(): void
$table->foreignId('course_id')->constrained()->cascadeOnDelete(); $table->foreignId('course_id')->constrained()->cascadeOnDelete();
$table->foreignId('lecturer_id')->constrained()->cascadeOnDelete(); $table->foreignId('lecturer_id')->constrained()->cascadeOnDelete();
$table->foreignId('academic_term_id')->constrained()->cascadeOnDelete(); $table->foreignId('academic_term_id')->constrained()->cascadeOnDelete();
$table->string('class_name', 50)->nullable();
$table->enum('method', ClassMethod::values())->nullable()->default(ClassMethod::Hybrid->value); $table->enum('method', ClassMethod::values())->nullable()->default(ClassMethod::Hybrid->value);
$table->timestamps(); $table->timestamps();
$table->softDeletes(); $table->softDeletes();

View File

@ -14,7 +14,6 @@ public function run(): void
'course_id' => 1, 'course_id' => 1,
'lecturer_id' => 1, 'lecturer_id' => 1,
'academic_term_id' => 2, 'academic_term_id' => 2,
'class_name' => 'SI-5A',
'method' => 'hybrid', 'method' => 'hybrid',
'created_at' => '2026-01-10 08:00:00', 'created_at' => '2026-01-10 08:00:00',
'updated_at' => '2026-01-10 08:00:00', 'updated_at' => '2026-01-10 08:00:00',
@ -23,7 +22,6 @@ public function run(): void
'course_id' => 2, 'course_id' => 2,
'lecturer_id' => 2, 'lecturer_id' => 2,
'academic_term_id' => 2, 'academic_term_id' => 2,
'class_name' => 'TI-3A',
'method' => 'offline', 'method' => 'offline',
'created_at' => '2026-01-10 08:00:00', 'created_at' => '2026-01-10 08:00:00',
'updated_at' => '2026-01-10 08:00:00', 'updated_at' => '2026-01-10 08:00:00',

View File

@ -107,6 +107,16 @@ const data: {
}, },
], ],
}, },
{
label: 'Kelola',
items: [
{
name: 'Kelas Mata Kuliah',
url: courseClassesRoute.url(),
icon: School,
},
],
},
{ {
label: 'Kelas', label: 'Kelas',
items: [ items: [
@ -137,16 +147,6 @@ const data: {
}, },
], ],
}, },
{
label: 'Kelola',
items: [
{
name: 'Kelas Mata Kuliah',
url: courseClassesRoute.url(),
icon: School,
},
],
},
{ {
label: 'Pengumuman', label: 'Pengumuman',
items: [ items: [

View File

@ -28,7 +28,7 @@ export function createAssignmentColumns(
), ),
}, },
{ {
accessorKey: 'course_class.class_name', accessorKey: 'course_class.course.name',
header: () => <span>Kelas</span>, header: () => <span>Kelas</span>,
cell: ({ row }) => { cell: ({ row }) => {
const courseClass = row.original.course_class; const courseClass = row.original.course_class;
@ -37,11 +37,7 @@ export function createAssignmentColumns(
return '-'; return '-';
} }
const label = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${label}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
}, },
}, },
{ {

View File

@ -34,7 +34,6 @@ import { createAssignmentColumns } from './columns';
type CourseClassOption = { type CourseClassOption = {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
}; };
@ -54,11 +53,7 @@ type Props = {
}; };
function courseClassLabel(courseClass: CourseClassOption): string { function courseClassLabel(courseClass: CourseClassOption): string {
const namePart = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${namePart}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
} }
export default function AssignmentIndex({ export default function AssignmentIndex({

View File

@ -175,11 +175,7 @@ export default function SubmissionIndex({
</CardHeader> </CardHeader>
<CardContent className="grid gap-1 text-sm text-muted-foreground"> <CardContent className="grid gap-1 text-sm text-muted-foreground">
<p> <p>
Kelas:{' '} Kelas: {assignment.course_class?.course?.code}{' '}
{assignment.course_class?.class_name
? `${assignment.course_class.class_name} - `
: ''}
{assignment.course_class?.course?.code}{' '}
{assignment.course_class?.course?.name} {assignment.course_class?.course?.name}
</p> </p>
<p> <p>

View File

@ -35,11 +35,7 @@ type Props = {
}; };
function courseClassLabel(courseClass: AttendanceCourseClass): string { function courseClassLabel(courseClass: AttendanceCourseClass): string {
const namePart = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${namePart}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
} }
export default function AttendanceIndex({ sessions, courseClasses }: Props) { export default function AttendanceIndex({ sessions, courseClasses }: Props) {

View File

@ -26,11 +26,7 @@ type Props = {
}; };
function courseClassLabel(courseClass: AttendanceCourseClass): string { function courseClassLabel(courseClass: AttendanceCourseClass): string {
const namePart = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${namePart}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
} }
export default function AttendanceSession({ export default function AttendanceSession({

View File

@ -54,9 +54,6 @@ export function createCourseRegistrationColumns(
</p> </p>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
{courseClass?.course?.code} {courseClass?.course?.code}
{courseClass?.class_name
? ` · ${courseClass.class_name}`
: ''}
</p> </p>
</div> </div>
); );

View File

@ -68,9 +68,8 @@ function studentLabel(student: CourseRegistrationStudent): string {
function courseClassLabel(courseClass: CourseRegistrationCourseClass): string { function courseClassLabel(courseClass: CourseRegistrationCourseClass): string {
const course = courseClass.course; const course = courseClass.course;
const suffix = courseClass.class_name ? ` (${courseClass.class_name})` : '';
return `${course?.code ?? '-'} - ${course?.name ?? 'N/A'}${suffix}`; return `${course?.code ?? '-'} - ${course?.name ?? 'N/A'}`;
} }
function lecturerLabel(lecturer: LecturerOption): string { function lecturerLabel(lecturer: LecturerOption): string {

View File

@ -49,7 +49,7 @@ export function createMaterialColumns(
), ),
}, },
{ {
accessorKey: 'course_class.class_name', accessorKey: 'course_class.course.name',
header: () => <span>Kelas</span>, header: () => <span>Kelas</span>,
cell: ({ row }) => { cell: ({ row }) => {
const courseClass = row.original.course_class; const courseClass = row.original.course_class;
@ -58,11 +58,7 @@ export function createMaterialColumns(
return '-'; return '-';
} }
const label = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${label}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
}, },
}, },
{ {

View File

@ -33,7 +33,6 @@ import { createMaterialColumns } from './columns';
type CourseClassOption = { type CourseClassOption = {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
}; };
@ -53,11 +52,7 @@ type Props = {
}; };
function courseClassLabel(courseClass: CourseClassOption): string { function courseClassLabel(courseClass: CourseClassOption): string {
const namePart = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${namePart}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
} }
export default function MaterialIndex({ export default function MaterialIndex({

View File

@ -19,13 +19,16 @@ import {
SelectValue, SelectValue,
} from '@/components/ui/select'; } from '@/components/ui/select';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { destroy, store, update } from '@/routes/admin/academic-classes/schedules'; import {
destroy,
store,
update,
} from '@/routes/admin/academic-classes/schedules';
import type { Schedule } from '@/types/schedule'; import type { Schedule } from '@/types/schedule';
import { DayOfWeekLabels, DaysOfWeek } from '@/types/schedule'; import { DayOfWeekLabels, DaysOfWeek } from '@/types/schedule';
type CourseClassOption = { type CourseClassOption = {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
}; };
@ -40,11 +43,7 @@ const UNSCHEDULED = '__unscheduled__';
const BOARD_COLUMNS = [...DaysOfWeek, UNSCHEDULED] as const; const BOARD_COLUMNS = [...DaysOfWeek, UNSCHEDULED] as const;
function courseClassLabel(courseClass: CourseClassOption): string { function courseClassLabel(courseClass: CourseClassOption): string {
const namePart = courseClass.class_name return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
? `${courseClass.class_name} - `
: '';
return `${namePart}${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
} }
function toTimeInput(value: string | null): string { function toTimeInput(value: string | null): string {
@ -166,8 +165,6 @@ export default function ScheduleIndex({
{courseClassLabel( {courseClassLabel(
schedule.course_class ?? { schedule.course_class ?? {
id: 0, id: 0,
class_name:
null,
course: null, course: null,
}, },
)} )}
@ -253,7 +250,7 @@ export default function ScheduleIndex({
}} }}
title="Hapus Jadwal" title="Hapus Jadwal"
description={(schedule) => description={(schedule) =>
`Apakah Anda yakin ingin menghapus jadwal "${schedule.course_class?.class_name ?? schedule.course_class?.course?.name ?? 'ini'}"? Tindakan ini tidak dapat dibatalkan.` `Apakah Anda yakin ingin menghapus jadwal "${schedule.course_class?.course?.name ?? 'ini'}"? Tindakan ini tidak dapat dibatalkan.`
} }
onConfirm={handleDelete} onConfirm={handleDelete}
/> />

View File

@ -19,15 +19,6 @@ export function createCourseClassColumns(
const { handleEdit, handleDeleteClick } = params; const { handleEdit, handleDeleteClick } = params;
return [ return [
{
accessorKey: 'class_name',
header: () => <span>Kelas</span>,
cell: ({ row }) => (
<span className="font-medium">
{(row.getValue('class_name') as string | null) ?? '-'}
</span>
),
},
{ {
accessorKey: 'course.name', accessorKey: 'course.name',
header: () => <span>Mata Kuliah</span>, header: () => <span>Mata Kuliah</span>,

View File

@ -119,9 +119,7 @@ export default function ClassEnrollmentIndex({
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle> <CardTitle>Detail Kelas Mata Kuliah</CardTitle>
{courseClass.class_name ?? courseClass.course?.name}
</CardTitle>
</CardHeader> </CardHeader>
<CardContent className="grid gap-1 text-sm text-muted-foreground"> <CardContent className="grid gap-1 text-sm text-muted-foreground">
<p> <p>

View File

@ -10,7 +10,14 @@ import { FormDialog } from '@/components/form-dialog';
import InputError from '@/components/input-error'; import InputError from '@/components/input-error';
import { PageHeader } from '@/components/page-header'; import { PageHeader } from '@/components/page-header';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from '@/components/ui/combobox';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { import {
Select, Select,
@ -34,7 +41,7 @@ type Course = { id: number; code: string; name: string; department_id: number };
type Lecturer = { type Lecturer = {
id: number; id: number;
lecturer_number: string; lecturer_number: string;
department_id: number; departments: { id: number; name: string }[];
user: { profile: { full_name: string } | null } | null; user: { profile: { full_name: string } | null } | null;
}; };
type AcademicTerm = { id: number; name: string; semester: string }; type AcademicTerm = { id: number; name: string; semester: string };
@ -189,7 +196,7 @@ export default function CourseClassIndex({
<DataTable <DataTable
columns={columns} columns={columns}
data={courseClasses.data} data={courseClasses.data}
searchKey="class_name" searchKey="course"
searchPlaceholder="Cari kelas mata kuliah..." searchPlaceholder="Cari kelas mata kuliah..."
emptyText="Belum ada data kelas mata kuliah." emptyText="Belum ada data kelas mata kuliah."
pagination={pagination} pagination={pagination}
@ -215,7 +222,7 @@ export default function CourseClassIndex({
}} }}
title="Hapus Kelas Mata Kuliah" title="Hapus Kelas Mata Kuliah"
description={(courseClass) => description={(courseClass) =>
`Apakah Anda yakin ingin menghapus kelas "${courseClass.class_name ?? courseClass.course?.name}"? Tindakan ini tidak dapat dibatalkan.` `Apakah Anda yakin ingin menghapus kelas "${courseClass.course?.name}"? Tindakan ini tidak dapat dibatalkan.`
} }
onConfirm={handleDelete} onConfirm={handleDelete}
/> />
@ -238,18 +245,21 @@ function CreateForm({
academicTerms: AcademicTerm[]; academicTerms: AcademicTerm[];
}) { }) {
const [courseId, setCourseId] = useState(''); const [courseId, setCourseId] = useState('');
const [lecturerId, setLecturerId] = useState(''); const [lecturer, setLecturer] = useState<Lecturer | null>(null);
const selectedCourse = courses.find((c) => String(c.id) === courseId); const selectedCourse = courses.find((c) => String(c.id) === courseId);
const availableLecturers = selectedCourse const availableLecturers = selectedCourse
? lecturers.filter( ? lecturers.filter((l) =>
(l) => l.department_id === selectedCourse.department_id, l.departments.some(
(department) =>
department.id === selectedCourse.department_id,
),
) )
: lecturers; : lecturers;
function reset() { function reset() {
setCourseId(''); setCourseId('');
setLecturerId(''); setLecturer(null);
} }
return ( return (
@ -266,6 +276,29 @@ function CreateForm({
> >
{({ errors }) => ( {({ errors }) => (
<div className="grid gap-4"> <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" />
<Select name="academic_term_id">
<SelectTrigger className="w-full">
<SelectValue placeholder="Pilih periode akademik" />
</SelectTrigger>
<SelectContent>
{academicTerms.map((term) => (
<SelectItem
key={term.id}
value={String(term.id)}
>
{term.name}
</SelectItem>
))}
</SelectContent>
</Select>
<InputError message={errors.academic_term_id} />
</div>
<div className="grid gap-2"> <div className="grid gap-2">
<Label> <Label>
Mata Kuliah{' '} Mata Kuliah{' '}
@ -280,7 +313,7 @@ function CreateForm({
value={courseId} value={courseId}
onValueChange={(value) => { onValueChange={(value) => {
setCourseId(value); setCourseId(value);
setLecturerId(''); setLecturer(null);
}} }}
> >
<SelectTrigger className="w-full"> <SelectTrigger className="w-full">
@ -307,67 +340,47 @@ function CreateForm({
<input <input
type="hidden" type="hidden"
name="lecturer_id" name="lecturer_id"
value={lecturerId} value={lecturer?.id ?? ''}
/> />
<Select <Combobox
value={lecturerId} items={availableLecturers}
onValueChange={setLecturerId} value={lecturer}
onValueChange={setLecturer}
itemToStringLabel={(lect) =>
`${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}`
}
isItemEqualToValue={(a, b) => a.id === b.id}
disabled={!selectedCourse}
> >
<SelectTrigger className="w-full"> <ComboboxInput
<SelectValue disabled={!selectedCourse}
placeholder={ placeholder={
selectedCourse selectedCourse
? 'Pilih dosen pengampu' ? 'Pilih dosen pengampu'
: 'Pilih mata kuliah terlebih dahulu' : 'Pilih mata kuliah terlebih dahulu'
} }
/> className="w-full"
</SelectTrigger> />
<SelectContent> <ComboboxContent>
{availableLecturers.map((lect) => ( <ComboboxEmpty>
<SelectItem Dosen tidak ditemukan.
key={lect.id} </ComboboxEmpty>
value={String(lect.id)} <ComboboxList>
> {availableLecturers.map((lect) => (
{lect.user?.profile?.full_name ?? 'N/A'}{' '} <ComboboxItem
- {lect.lecturer_number} key={lect.id}
</SelectItem> value={lect}
))} >
</SelectContent> {lect.user?.profile?.full_name ??
</Select> 'N/A'}{' '}
- {lect.lecturer_number}
</ComboboxItem>
))}
</ComboboxList>
</ComboboxContent>
</Combobox>
<InputError message={errors.lecturer_id} /> <InputError message={errors.lecturer_id} />
</div> </div>
<div className="grid gap-2">
<Label>
Periode Akademik{' '}
<span className="text-destructive">*</span>
</Label>
<input type="hidden" name="academic_term_id" />
<Select name="academic_term_id">
<SelectTrigger className="w-full">
<SelectValue placeholder="Pilih periode akademik" />
</SelectTrigger>
<SelectContent>
{academicTerms.map((term) => (
<SelectItem
key={term.id}
value={String(term.id)}
>
{term.name}
</SelectItem>
))}
</SelectContent>
</Select>
<InputError message={errors.academic_term_id} />
</div>
<div className="grid gap-2">
<Label htmlFor="class_name">Nama Kelas</Label>
<Input
id="class_name"
name="class_name"
placeholder="Contoh: SI-5A"
/>
<InputError message={errors.class_name} />
</div>
<div className="grid gap-2"> <div className="grid gap-2">
<Label>Metode</Label> <Label>Metode</Label>
<input type="hidden" name="method" /> <input type="hidden" name="method" />
@ -409,14 +422,19 @@ function EditForm({
const [courseId, setCourseId] = useState( const [courseId, setCourseId] = useState(
editing ? String(editing.course_id) : '', editing ? String(editing.course_id) : '',
); );
const [lecturerId, setLecturerId] = useState( const [lecturer, setLecturer] = useState<Lecturer | null>(
editing ? String(editing.lecturer_id) : '', editing
? (lecturers.find((l) => l.id === editing.lecturer_id) ?? null)
: null,
); );
const selectedCourse = courses.find((c) => String(c.id) === courseId); const selectedCourse = courses.find((c) => String(c.id) === courseId);
const availableLecturers = selectedCourse const availableLecturers = selectedCourse
? lecturers.filter( ? lecturers.filter((l) =>
(l) => l.department_id === selectedCourse.department_id, l.departments.some(
(department) =>
department.id === selectedCourse.department_id,
),
) )
: lecturers; : lecturers;
@ -446,7 +464,7 @@ function EditForm({
value={courseId} value={courseId}
onValueChange={(value) => { onValueChange={(value) => {
setCourseId(value); setCourseId(value);
setLecturerId(''); setLecturer(null);
}} }}
> >
<SelectTrigger className="w-full"> <SelectTrigger className="w-full">
@ -473,28 +491,45 @@ function EditForm({
<input <input
type="hidden" type="hidden"
name="lecturer_id" name="lecturer_id"
value={lecturerId} value={lecturer?.id ?? ''}
/> />
<Select <Combobox
value={lecturerId} items={availableLecturers}
onValueChange={setLecturerId} value={lecturer}
onValueChange={setLecturer}
itemToStringLabel={(lect) =>
`${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}`
}
isItemEqualToValue={(a, b) => a.id === b.id}
disabled={!selectedCourse}
> >
<SelectTrigger className="w-full"> <ComboboxInput
<SelectValue placeholder="Pilih dosen pengampu" /> disabled={!selectedCourse}
</SelectTrigger> placeholder={
<SelectContent> selectedCourse
{availableLecturers.map((lect) => ( ? 'Pilih dosen pengampu'
<SelectItem : 'Pilih mata kuliah terlebih dahulu'
key={lect.id} }
value={String(lect.id)} className="w-full"
> />
{lect.user?.profile?.full_name ?? <ComboboxContent>
'N/A'}{' '} <ComboboxEmpty>
- {lect.lecturer_number} Dosen tidak ditemukan.
</SelectItem> </ComboboxEmpty>
))} <ComboboxList>
</SelectContent> {availableLecturers.map((lect) => (
</Select> <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} /> <InputError message={errors.lecturer_id} />
</div> </div>
<div className="grid gap-2"> <div className="grid gap-2">
@ -522,16 +557,6 @@ function EditForm({
</Select> </Select>
<InputError message={errors.academic_term_id} /> <InputError message={errors.academic_term_id} />
</div> </div>
<div className="grid gap-2">
<Label htmlFor="edit-class_name">Nama Kelas</Label>
<Input
id="edit-class_name"
name="class_name"
placeholder="Contoh: SI-5A"
defaultValue={editing.class_name ?? ''}
/>
<InputError message={errors.class_name} />
</div>
<div className="grid gap-2"> <div className="grid gap-2">
<Label>Metode</Label> <Label>Metode</Label>
<Select <Select

View File

@ -3,7 +3,6 @@ export type Assignment = {
course_class_id: number; course_class_id: number;
course_class: { course_class: {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
} | null; } | null;
title: string; title: string;

View File

@ -9,7 +9,6 @@ export const AttendanceStatusLabels: Record<AttendanceStatus, string> = {
export type AttendanceCourseClass = { export type AttendanceCourseClass = {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
}; };

View File

@ -26,7 +26,6 @@ export type CourseClass = {
} | null; } | null;
academic_term_id: number; academic_term_id: number;
academic_term: { id: number; name: string; semester: string } | null; academic_term: { id: number; name: string; semester: string } | null;
class_name: string | null;
method: ClassMethod | null; method: ClassMethod | null;
enrollments_count: number; enrollments_count: number;
created_at: string; created_at: string;

View File

@ -21,7 +21,6 @@ export type CourseRegistrationStudent = {
export type CourseRegistrationCourseClass = { export type CourseRegistrationCourseClass = {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
}; };

View File

@ -3,7 +3,6 @@ export type Material = {
course_class_id: number; course_class_id: number;
course_class: { course_class: {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
} | null; } | null;
title: string; title: string;

View File

@ -25,7 +25,6 @@ export type Schedule = {
course_class_id: number; course_class_id: number;
course_class: { course_class: {
id: number; id: number;
class_name: string | null;
course: { id: number; code: string; name: string } | null; course: { id: number; code: string; name: string } | null;
} | null; } | null;
day_of_week: string | null; day_of_week: string | null;