get('search')); $academicYearId = $request->get('academic_year_id'); $classId = $request->get('class_id'); $level = trim((string) $request->get('level')); $category = trim((string) $request->get('category')); $achievementsQuery = StudentAchievement::query() ->with(['student.academicYear', 'student.department', 'student.classRoom']) ->when($search !== '', function ($query) use ($search) { $query->where(function ($subQuery) use ($search) { $subQuery->where('achievement_name', 'like', "%{$search}%") ->orWhere('category', 'like', "%{$search}%") ->orWhere('level', 'like', "%{$search}%") ->orWhereHas('student', function ($studentQuery) use ($search) { $studentQuery->where('full_name', 'like', "%{$search}%") ->orWhere('student_number', 'like', "%{$search}%") ->orWhere('nisn', 'like', "%{$search}%"); }); }); }) ->when($academicYearId, fn ($query) => $query->whereHas('student', fn ($studentQuery) => $studentQuery->where('academic_year_id', $academicYearId))) ->when($classId, fn ($query) => $query->whereHas('student', fn ($studentQuery) => $studentQuery->where('class_id', $classId))) ->when($level !== '', fn ($query) => $query->where('level', $level)) ->when($category !== '', fn ($query) => $query->where('category', $category)); $achievements = (clone $achievementsQuery) ->latest('achievement_year') ->latest('achievement_date') ->latest('id') ->paginate(15) ->withQueryString(); $levelCounts = StudentAchievement::query() ->selectRaw('COALESCE(level, ?) as level_label, COUNT(*) as total', ['Tanpa tingkat']) ->groupBy('level') ->orderByDesc('total') ->pluck('total', 'level_label'); $withCertificateCount = StudentAchievement::query()->whereNotNull('certificate_file')->count(); $withPhotoCount = StudentAchievement::query()->whereNotNull('activity_photo')->count(); $thisYearCount = StudentAchievement::query()->where('achievement_year', now()->year)->count(); $recentAchievements = StudentAchievement::query() ->with(['student:id,full_name']) ->latest('achievement_date') ->latest('achievement_year') ->latest('id') ->limit(3) ->get(); $categoryOptions = StudentAchievement::query() ->whereNotNull('category') ->where('category', '!=', '') ->distinct() ->orderBy('category') ->pluck('category', 'category'); return view('student-achievements.index', [ 'achievements' => $achievements, 'search' => $search, 'filters' => [ 'academic_year_id' => $academicYearId, 'class_id' => $classId, 'level' => $level, 'category' => $category, ], 'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'), 'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'), 'categoryOptions' => $categoryOptions, 'levelOptions' => $this->levelOptions(), 'summary' => [ 'total' => StudentAchievement::count(), 'filtered' => $achievements->total(), 'students' => StudentAchievement::distinct('student_id')->count('student_id'), 'latest_year' => StudentAchievement::max('achievement_year'), 'top_level' => $levelCounts->keys()->first(), 'top_level_total' => $levelCounts->first(), 'with_certificate' => $withCertificateCount, 'without_certificate' => max(StudentAchievement::count() - $withCertificateCount, 0), 'with_photo' => $withPhotoCount, 'this_year' => $thisYearCount, ], 'recentAchievements' => $recentAchievements, ]); } public function create(Request $request): View { $achievement = new StudentAchievement(); if ($request->filled('student_id')) { $achievement->student_id = (int) $request->integer('student_id'); } return view('student-achievements.create', [ 'achievement' => $achievement, 'students' => Student::orderBy('full_name')->get(['id', 'full_name', 'student_number', 'nisn']), 'levelOptions' => $this->levelOptions(), ]); } public function store(Request $request): RedirectResponse { $data = $this->validateAchievement($request); if ($request->hasFile('certificate_file')) { $data['certificate_file'] = $request->file('certificate_file')->store('student-achievements/certificates', 'public'); } if ($request->hasFile('activity_photo')) { $data['activity_photo'] = $request->file('activity_photo')->store('student-achievements/activity-photos', 'public'); } StudentAchievement::create($data); return redirect()->route('student-achievements.index')->with('success', 'Data siswa berprestasi berhasil ditambahkan.'); } public function edit(StudentAchievement $studentAchievement): View { return view('student-achievements.edit', [ 'achievement' => $studentAchievement, 'students' => Student::orderBy('full_name')->get(['id', 'full_name', 'student_number', 'nisn']), 'levelOptions' => $this->levelOptions(), ]); } public function update(Request $request, StudentAchievement $studentAchievement): RedirectResponse { $data = $this->validateAchievement($request); if ($request->hasFile('certificate_file')) { if ($studentAchievement->certificate_file && Storage::disk('public')->exists($studentAchievement->certificate_file)) { Storage::disk('public')->delete($studentAchievement->certificate_file); } $data['certificate_file'] = $request->file('certificate_file')->store('student-achievements/certificates', 'public'); } if ($request->hasFile('activity_photo')) { if ($studentAchievement->activity_photo && Storage::disk('public')->exists($studentAchievement->activity_photo)) { Storage::disk('public')->delete($studentAchievement->activity_photo); } $data['activity_photo'] = $request->file('activity_photo')->store('student-achievements/activity-photos', 'public'); } $studentAchievement->update($data); return redirect()->route('student-achievements.index')->with('success', 'Data siswa berprestasi berhasil diperbarui.'); } public function destroy(StudentAchievement $studentAchievement): RedirectResponse { if ($studentAchievement->certificate_file && Storage::disk('public')->exists($studentAchievement->certificate_file)) { Storage::disk('public')->delete($studentAchievement->certificate_file); } if ($studentAchievement->activity_photo && Storage::disk('public')->exists($studentAchievement->activity_photo)) { Storage::disk('public')->delete($studentAchievement->activity_photo); } $studentAchievement->delete(); return redirect()->route('student-achievements.index')->with('success', 'Data siswa berprestasi berhasil dihapus.'); } protected function validateAchievement(Request $request): array { return $request->validate([ 'student_id' => ['required', 'exists:students,id'], 'achievement_name' => ['required', 'string', 'max:150'], 'category' => ['nullable', 'string', 'max:100'], 'level' => ['nullable', 'string', 'max:50'], 'organizer' => ['nullable', 'string', 'max:150'], 'rank' => ['nullable', 'string', 'max:100'], 'achievement_date' => ['nullable', 'date'], 'achievement_year' => ['nullable', 'integer', 'min:2000', 'max:' . now()->year], 'description' => ['nullable', 'string'], 'certificate_file' => ['nullable', 'file', 'mimes:pdf,jpg,jpeg,png,webp', 'max:5120'], 'activity_photo' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:5120'], ]); } protected function levelOptions(): array { return [ 'Sekolah' => 'Sekolah', 'Kecamatan' => 'Kecamatan', 'Kabupaten/Kota' => 'Kabupaten/Kota', 'Provinsi' => 'Provinsi', 'Nasional' => 'Nasional', 'Internasional' => 'Internasional', ]; } }