From 0fbd3cc24729f99203c5de53ff63893f4b3883f5 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sun, 30 Aug 2026 17:28:12 +0700 Subject: [PATCH] feat: add current semester field to student management and update related components --- .../Admin/Users/Student/StudentRequest.php | 6 + app/Services/Admin/Users/StudentService.php | 6 +- ...026_08_03_000007_create_students_table.php | 1 + database/seeders/UserSeeder.php | 4 + .../js/pages/admin/users/students/columns.tsx | 6 + .../js/pages/admin/users/students/create.tsx | 172 ++++++++++-------- .../js/pages/admin/users/students/edit.tsx | 33 +++- resources/js/types/user.ts | 1 + 8 files changed, 148 insertions(+), 81 deletions(-) diff --git a/app/Http/Requests/Admin/Users/Student/StudentRequest.php b/app/Http/Requests/Admin/Users/Student/StudentRequest.php index 2c7dd55..b0603b0 100644 --- a/app/Http/Requests/Admin/Users/Student/StudentRequest.php +++ b/app/Http/Requests/Admin/Users/Student/StudentRequest.php @@ -64,6 +64,12 @@ public function rules(): array 'integer', 'digits:4', ], + 'current_semester' => [ + 'required', + 'integer', + 'min:1', + 'max:14', + ], 'academic_advisor_id' => [ 'required', 'integer', diff --git a/app/Services/Admin/Users/StudentService.php b/app/Services/Admin/Users/StudentService.php index 3844401..54fbc5a 100644 --- a/app/Services/Admin/Users/StudentService.php +++ b/app/Services/Admin/Users/StudentService.php @@ -14,7 +14,7 @@ class StudentService { public function getAllForSelect(?string $status = null): Collection { - return Student::select(['id', 'user_id', 'student_number', 'department_id']) + return Student::select(['id', 'user_id', 'student_number', 'department_id', 'current_semester']) ->with([ 'user:id,username', 'user.profile:id,user_id,full_name', @@ -53,7 +53,7 @@ private function filteredQuery(string $search, ?string $gender, ?int $department return User::select(['id', 'username', 'email', 'is_active']) ->with([ 'profile:id,user_id,full_name,phone_number,gender,birth_place,birth_date,address', - 'student:id,user_id,student_number,department_id,enrollment_year,status', + 'student:id,user_id,student_number,department_id,enrollment_year,current_semester,status', 'student.department:id,name', ]) ->whereHas('roles', fn ($q) => $q->where('name', 'mahasiswa')) @@ -93,6 +93,7 @@ public function create(array $data): User 'student_number' => $data['student_number'], 'department_id' => $data['department_id'], 'enrollment_year' => $data['enrollment_year'], + 'current_semester' => $data['current_semester'], 'academic_advisor_id' => $data['academic_advisor_id'], 'status' => 'active', ]); @@ -122,6 +123,7 @@ public function update(User $user, array $data): User 'student_number' => $data['student_number'], 'department_id' => $data['department_id'], 'enrollment_year' => $data['enrollment_year'], + 'current_semester' => $data['current_semester'], 'academic_advisor_id' => $data['academic_advisor_id'], ]); }); diff --git a/database/migrations/2026_08_03_000007_create_students_table.php b/database/migrations/2026_08_03_000007_create_students_table.php index 8f7e8d3..b12a87b 100644 --- a/database/migrations/2026_08_03_000007_create_students_table.php +++ b/database/migrations/2026_08_03_000007_create_students_table.php @@ -15,6 +15,7 @@ public function up(): void $table->string('student_number', 10)->unique(); $table->foreignId('department_id')->constrained()->cascadeOnDelete(); $table->integer('enrollment_year'); + $table->unsignedTinyInteger('current_semester')->default(1); $table->foreignId('academic_advisor_id')->nullable()->constrained('lecturers')->nullOnDelete(); $table->enum('status', StudentStatus::values())->nullable()->default(StudentStatus::Active->value); $table->timestamps(); diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index f995403..0241834 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -34,6 +34,7 @@ public function run(): void 'student_number' => '23010001', 'department_id' => 1, 'enrollment_year' => 2023, + 'current_semester' => 5, 'academic_advisor_id' => null, 'status' => StudentStatus::Active, ], @@ -54,6 +55,7 @@ public function run(): void 'student_number' => '23020002', 'department_id' => 1, 'enrollment_year' => 2023, + 'current_semester' => 5, 'academic_advisor_id' => null, 'status' => StudentStatus::Active, ], @@ -74,6 +76,7 @@ public function run(): void 'student_number' => '24010003', 'department_id' => 1, 'enrollment_year' => 2024, + 'current_semester' => 3, 'academic_advisor_id' => null, 'status' => StudentStatus::Active, ], @@ -94,6 +97,7 @@ public function run(): void 'student_number' => '24020004', 'department_id' => 1, 'enrollment_year' => 2024, + 'current_semester' => 3, 'academic_advisor_id' => null, 'status' => StudentStatus::Active, ], diff --git a/resources/js/pages/admin/users/students/columns.tsx b/resources/js/pages/admin/users/students/columns.tsx index 3e49a8c..631c7e4 100644 --- a/resources/js/pages/admin/users/students/columns.tsx +++ b/resources/js/pages/admin/users/students/columns.tsx @@ -15,6 +15,7 @@ export type Student = { student_number: string; department: { name: string } | null; enrollment_year: number; + current_semester: number; status: string | null; } | null; }; @@ -77,6 +78,11 @@ export function createStudentColumns( header: () => Angkatan, cell: ({ row }) => row.original.student?.enrollment_year ?? '-', }, + { + accessorKey: 'student.current_semester', + header: () => Semester, + cell: ({ row }) => row.original.student?.current_semester ?? '-', + }, { accessorKey: 'student.status', header: () => Status, diff --git a/resources/js/pages/admin/users/students/create.tsx b/resources/js/pages/admin/users/students/create.tsx index 5cfe60e..0ebcae2 100644 --- a/resources/js/pages/admin/users/students/create.tsx +++ b/resources/js/pages/admin/users/students/create.tsx @@ -1,7 +1,3 @@ -import { Form, Head, Link } from '@inertiajs/react'; -import { format } from 'date-fns'; -import { ArrowLeft, Save } from 'lucide-react'; -import { useState } from 'react'; import { DatePicker } from '@/components/date-picker'; import InputError from '@/components/input-error'; import { PageHeader } from '@/components/page-header'; @@ -29,6 +25,10 @@ import { import { Textarea } from '@/components/ui/textarea'; import { index, store } from '@/routes/admin/users/students'; import { formatDepartmentLabel } from '@/types/department'; +import { Form, Head, Link } from '@inertiajs/react'; +import { format } from 'date-fns'; +import { ArrowLeft, Save } from 'lucide-react'; +import { useState } from 'react'; type Department = { id: number; name: string; degree_level: string | null }; type Lecturer = { @@ -216,9 +216,9 @@ export default function StudentCreate({ departments, lecturers }: Props) { value={ birthDate ? format( - birthDate, - 'yyyy-MM-dd', - ) + birthDate, + 'yyyy-MM-dd', + ) : '' } /> @@ -301,75 +301,97 @@ export default function StudentCreate({ departments, lecturers }: Props) { message={errors.department_id} /> -
- - - -
-
- - - - `${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}` - } - isItemEqualToValue={(a, b) => - a.id === b.id - } - > - +
+ + - - - Dosen tidak ditemukan. - - - {(lect: Lecturer) => ( - - {lect.user?.profile - ?.full_name ?? - 'N/A'}{' '} - -{' '} - { - lect.lecturer_number - } - - )} - - - - + +
+
+ + + +
+
+ + + + `${lect.user?.profile?.full_name ?? 'N/A'} - ${lect.lecturer_number}` + } + isItemEqualToValue={(a, b) => + a.id === b.id + } + > + + + + Dosen tidak ditemukan. + + + {(lect: Lecturer) => ( + + {lect.user?.profile + ?.full_name ?? + 'N/A'}{' '} + -{' '} + { + lect.lecturer_number + } + + )} + + + + +
diff --git a/resources/js/pages/admin/users/students/edit.tsx b/resources/js/pages/admin/users/students/edit.tsx index 5eaec59..025f25f 100644 --- a/resources/js/pages/admin/users/students/edit.tsx +++ b/resources/js/pages/admin/users/students/edit.tsx @@ -1,7 +1,3 @@ -import { Form, Head, Link } from '@inertiajs/react'; -import { format } from 'date-fns'; -import { ArrowLeft, Save } from 'lucide-react'; -import { useState } from 'react'; import { DatePicker } from '@/components/date-picker'; import InputError from '@/components/input-error'; import { PageHeader } from '@/components/page-header'; @@ -29,6 +25,10 @@ import { import { Textarea } from '@/components/ui/textarea'; import { index, update } from '@/routes/admin/users/students'; import { formatDepartmentLabel } from '@/types/department'; +import { Form, Head, Link } from '@inertiajs/react'; +import { format } from 'date-fns'; +import { ArrowLeft, Save } from 'lucide-react'; +import { useState } from 'react'; type Department = { id: number; name: string; degree_level: string | null }; type Lecturer = { @@ -53,6 +53,7 @@ type User = { student_number: string; department_id: number; enrollment_year: number; + current_semester: number; academic_advisor_id: number; } | null; }; @@ -348,6 +349,7 @@ export default function StudentEdit({ user, departments, lecturers }: Props) { message={errors.department_id} /> +
+
+ + + +
+
diff --git a/resources/js/types/user.ts b/resources/js/types/user.ts index 8145880..7dbbc8c 100644 --- a/resources/js/types/user.ts +++ b/resources/js/types/user.ts @@ -53,6 +53,7 @@ export type Student = { student_number: string; department: Department | null; enrollment_year: number; + current_semester: number; academic_advisor: Lecturer | null; status: StudentStatus; };