diff --git a/app/Exports/StudentsExport.php b/app/Exports/StudentsExport.php index 419df0b..6a8d846 100644 --- a/app/Exports/StudentsExport.php +++ b/app/Exports/StudentsExport.php @@ -22,6 +22,7 @@ public function __construct( private readonly ?string $gender = null, private readonly ?int $departmentId = null, private readonly ?string $status = null, + private readonly ?int $enrollmentYear = null, ) {} public function title(): string @@ -31,7 +32,7 @@ public function title(): string public function collection(): Enumerable { - return app(StudentService::class)->forExport($this->search, $this->gender, $this->departmentId, $this->status); + return app(StudentService::class)->forExport($this->search, $this->gender, $this->departmentId, $this->status, $this->enrollmentYear); } public function headings(): array diff --git a/app/Http/Controllers/Admin/Users/StudentController.php b/app/Http/Controllers/Admin/Users/StudentController.php index ebe74f6..17e4c4a 100644 --- a/app/Http/Controllers/Admin/Users/StudentController.php +++ b/app/Http/Controllers/Admin/Users/StudentController.php @@ -35,10 +35,12 @@ public function index(PaginatedRequest $request): Response gender: $request->validated('gender'), departmentId: $request->validated('department_id'), status: $request->validated('status'), + enrollmentYear: $request->validated('enrollment_year'), ), 'departments' => $this->departmentService->getAllForSelect(), 'statuses' => StudentStatus::options(), - 'filters' => $request->only(['gender', 'department_id', 'status']), + 'enrollmentYears' => $this->service->getEnrollmentYears(), + 'filters' => $request->only(['gender', 'department_id', 'status', 'enrollment_year']), ]); } @@ -114,6 +116,7 @@ public function export(PaginatedRequest $request): BinaryFileResponse gender: $request->validated('gender'), departmentId: $request->validated('department_id'), status: $request->validated('status'), + enrollmentYear: $request->validated('enrollment_year'), ), 'mahasiswa.xlsx'); } } diff --git a/app/Http/Requests/PaginatedRequest.php b/app/Http/Requests/PaginatedRequest.php index 33d386f..a5373b3 100644 --- a/app/Http/Requests/PaginatedRequest.php +++ b/app/Http/Requests/PaginatedRequest.php @@ -24,6 +24,7 @@ public function rules(): array 'gender' => ['nullable', 'string', Rule::in(Gender::values())], 'department_id' => ['nullable', 'integer'], 'status' => ['nullable', 'string'], + 'enrollment_year' => ['nullable', 'integer'], 'semester' => ['nullable', 'string', Rule::in(Semester::values())], 'is_active' => ['nullable', Rule::in(['true', 'false'])], 'academic_term_id' => ['nullable', 'integer'], diff --git a/app/Services/Admin/Users/StudentService.php b/app/Services/Admin/Users/StudentService.php index fba3b62..cf1651c 100644 --- a/app/Services/Admin/Users/StudentService.php +++ b/app/Services/Admin/Users/StudentService.php @@ -23,21 +23,31 @@ public function getAllForSelect(): Collection ->get(); } - public function paginated(int $perPage = 25, string $search = '', ?string $gender = null, ?int $departmentId = null, ?string $status = null): LengthAwarePaginator + public function getEnrollmentYears(): array { - return $this->filteredQuery($search, $gender, $departmentId, $status) + return Student::query() + ->select('enrollment_year') + ->distinct() + ->orderByDesc('enrollment_year') + ->pluck('enrollment_year') + ->all(); + } + + public function paginated(int $perPage = 25, string $search = '', ?string $gender = null, ?int $departmentId = null, ?string $status = null, ?int $enrollmentYear = null): LengthAwarePaginator + { + return $this->filteredQuery($search, $gender, $departmentId, $status, $enrollmentYear) ->latest() ->paginate($perPage); } - public function forExport(string $search = '', ?string $gender = null, ?int $departmentId = null, ?string $status = null): Collection + public function forExport(string $search = '', ?string $gender = null, ?int $departmentId = null, ?string $status = null, ?int $enrollmentYear = null): Collection { - return $this->filteredQuery($search, $gender, $departmentId, $status) + return $this->filteredQuery($search, $gender, $departmentId, $status, $enrollmentYear) ->orderBy('created_at', 'desc') ->get(); } - private function filteredQuery(string $search, ?string $gender, ?int $departmentId, ?string $status): Builder + private function filteredQuery(string $search, ?string $gender, ?int $departmentId, ?string $status, ?int $enrollmentYear = null): Builder { return User::select(['id', 'username', 'email', 'is_active']) ->with([ @@ -54,7 +64,8 @@ private function filteredQuery(string $search, ?string $gender, ?int $department })) ->when($gender, fn ($q) => $q->whereHas('profile', fn ($q) => $q->where('gender', $gender))) ->when($departmentId, fn ($q) => $q->whereHas('student', fn ($q) => $q->where('department_id', $departmentId))) - ->when($status, fn ($q) => $q->whereHas('student', fn ($q) => $q->where('status', $status))); + ->when($status, fn ($q) => $q->whereHas('student', fn ($q) => $q->where('status', $status))) + ->when($enrollmentYear, fn ($q) => $q->whereHas('student', fn ($q) => $q->where('enrollment_year', $enrollmentYear))); } public function create(array $data): User diff --git a/resources/js/pages/admin/users/students/index.tsx b/resources/js/pages/admin/users/students/index.tsx index ccedebb..aa39512 100644 --- a/resources/js/pages/admin/users/students/index.tsx +++ b/resources/js/pages/admin/users/students/index.tsx @@ -37,10 +37,12 @@ type Props = { }; departments: Department[]; statuses: StatusOption[]; + enrollmentYears: number[]; filters: { gender?: string; department_id?: string; status?: string; + enrollment_year?: string; }; }; @@ -48,6 +50,7 @@ export default function StudentIndex({ students, departments, statuses, + enrollmentYears, filters, }: Props) { const [deleting, setDeleting] = useState(null); @@ -75,6 +78,14 @@ export default function StudentIndex({ label: 'Status', options: statuses, }, + { + key: 'enrollment_year', + label: 'Angkatan', + options: enrollmentYears.map((year) => ({ + value: String(year), + label: String(year), + })), + }, ]; const pagination: PaginationState = {