Files
database-kesiswaan/app/Http/Controllers/StudentAchievementController.php
T

214 lines
9.2 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\AcademicYear;
use App\Models\SchoolClass;
use App\Models\Student;
use App\Models\StudentAchievement;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
class StudentAchievementController extends Controller
{
public function index(Request $request): View
{
$search = trim((string) $request->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',
];
}
}