middleware('auth:siswa'); } public function index() { $siswa = Auth::guard('siswa')->user(); $semuaTugas = Tugas::with(['mengajar.mapel', 'mengajar.guru']) ->whereHas('mengajar', function ($q) use ($siswa) { $q->where('id_kelas', $siswa->id_kelas); }) ->orderBy('deadline', 'asc') ->get(); $now = Carbon::now(); $tugasList = $semuaTugas->map(function ($tugas) use ($siswa, $now) { $pengumpulan = PengumpulanTugas::where('id_tugas', $tugas->id_tugas) ->where('id_siswa', $siswa->id_siswa) ->first(); $deadline = Carbon::parse($tugas->deadline); if ($pengumpulan && $pengumpulan->lampiran_tugas !== null) { $status = $pengumpulan->tanggal_submit && Carbon::parse($pengumpulan->tanggal_submit)->lessThanOrEqualTo($deadline) ? 'dikumpulkan' : 'terlambat'; $sudahKumpul = true; } else { $status = $now->greaterThan($deadline) ? 'terlambat' : 'belum'; $sudahKumpul = false; } return [ 'id_tugas' => $tugas->id_tugas, 'judul' => $tugas->judul_tugas, 'keterangan' => $tugas->keterangan, 'deadline' => $deadline, 'nama_mapel' => optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-', 'nama_guru' => optional(optional($tugas->mengajar)->guru)->nama ?? '-', 'status' => $status, 'sudah_kumpul' => $sudahKumpul, 'lampiran' => $pengumpulan?->lampiran_tugas, 'exp' => $pengumpulan?->exp ?? 0, 'file_tugas' => $tugas->lampiran, ]; }); $tugasBelum = $tugasList->filter(fn($t) => !$t['sudah_kumpul'] && $t['status'] !== 'terlambat'); $tugasTerlambat = $tugasList->filter(fn($t) => !$t['sudah_kumpul'] && $t['status'] === 'terlambat'); $tugasSelesai = $tugasList->filter(fn($t) => $t['sudah_kumpul']); return view('siswa.tugas.index', compact('tugasBelum', 'tugasTerlambat', 'tugasSelesai')); } public function show($id_tugas) { $siswa = Auth::guard('siswa')->user(); $tugas = Tugas::with(['mengajar.mapel', 'mengajar.guru']) ->whereHas('mengajar', function ($q) use ($siswa) { $q->where('id_kelas', $siswa->id_kelas); }) ->where('id_tugas', $id_tugas) ->firstOrFail(); $pengumpulan = PengumpulanTugas::where('id_tugas', $id_tugas) ->where('id_siswa', $siswa->id_siswa) ->first(); $sudahKumpul = $pengumpulan && $pengumpulan->lampiran_tugas !== null; $terlambat = Carbon::now()->greaterThan(Carbon::parse($tugas->deadline)); return view('siswa.tugas.show', compact('tugas', 'pengumpulan', 'sudahKumpul', 'terlambat')); } /** * Submit tugas. * * EXP tidak lagi diupdate ke leaderboard di sini. * EXP dihitung dinamis di LeaderboardController::hitungExpSiswa() * berdasarkan tanggal_submit vs deadline secara real-time. */ public function submit(Request $request, $id_tugas) { $siswa = Auth::guard('siswa')->user(); $request->validate([ 'lampiran_tugas' => 'required|file|mimes:pdf,doc,docx,jpg,jpeg,png|max:5120', ], [ 'lampiran_tugas.required' => 'File jawaban wajib diupload.', 'lampiran_tugas.mimes' => 'Format file harus pdf, doc, docx, jpg, atau png.', 'lampiran_tugas.max' => 'Ukuran file maksimal 5MB.', ]); $tugas = Tugas::whereHas('mengajar', function ($q) use ($siswa) { $q->where('id_kelas', $siswa->id_kelas); }) ->where('id_tugas', $id_tugas) ->firstOrFail(); $sudahAda = PengumpulanTugas::where('id_tugas', $id_tugas) ->where('id_siswa', $siswa->id_siswa) ->whereNotNull('lampiran_tugas') ->exists(); if ($sudahAda) { return back()->with('error', 'Kamu sudah mengumpulkan tugas ini.'); } $file = $request->file('lampiran_tugas'); $filename = 'tugas_' . $siswa->id_siswa . '_' . $id_tugas . '_' . time() . '.' . $file->getClientOriginalExtension(); $path = $file->storeAs('pengumpulan_tugas', $filename, 'public'); $now = Carbon::now(); $deadline = Carbon::parse($tugas->deadline); $terlambat = $now->greaterThan($deadline); $status = $terlambat ? 'terlambat' : 'dikumpulkan'; PengumpulanTugas::updateOrCreate( ['id_tugas' => $id_tugas, 'id_siswa' => $siswa->id_siswa], [ 'lampiran_tugas' => $path, 'tanggal_submit' => $now, 'exp' => $terlambat ? -5 : 10, // catatan saja, tidak dipakai di leaderboard 'status' => $status, ] ); if (!$terlambat) { $badgeSebelum = SiswaBadge::where('id_siswa', $siswa->id_siswa)->pluck('id_badge')->toArray(); app(BadgeService::class)->checkTugasBadges($siswa->id_siswa); $badgeSesudah = SiswaBadge::where('id_siswa', $siswa->id_siswa)->pluck('id_badge')->toArray(); $idBadgeBaru = array_diff($badgeSesudah, $badgeSebelum); if (!empty($idBadgeBaru)) { session()->flash('badge_baru', Badge::whereIn('id_badge', $idBadgeBaru)->get()); } } $pesan = $terlambat ? 'Tugas berhasil dikumpulkan (terlambat). Kamu mendapat penalti -5 poin. 😔' : 'Tugas berhasil dikumpulkan! Kamu mendapat +10 poin! 🎉'; return redirect()->route('siswa.tugas.index')->with('success', $pesan); } public function gantiFile(Request $request, $id_tugas) { $siswa = Auth::guard('siswa')->user(); $request->validate([ 'lampiran_tugas' => 'required|file|mimes:pdf,doc,docx,jpg,jpeg,png|max:5120', ]); $tugas = Tugas::whereHas('mengajar', function ($q) use ($siswa) { $q->where('id_kelas', $siswa->id_kelas); }) ->where('id_tugas', $id_tugas) ->firstOrFail(); if (Carbon::now()->greaterThan(Carbon::parse($tugas->deadline))) { return back()->with('error_ganti', 'Deadline sudah lewat, file tidak dapat diganti.'); } $pengumpulan = PengumpulanTugas::where('id_tugas', $id_tugas) ->where('id_siswa', $siswa->id_siswa) ->firstOrFail(); if ($pengumpulan->lampiran_tugas) { Storage::disk('public')->delete($pengumpulan->lampiran_tugas); } $file = $request->file('lampiran_tugas'); $filename = 'tugas_' . $siswa->id_siswa . '_' . $id_tugas . '_' . time() . '.' . $file->getClientOriginalExtension(); $path = $file->storeAs('pengumpulan_tugas', $filename, 'public'); $pengumpulan->update([ 'lampiran_tugas' => $path, 'tanggal_submit' => Carbon::now(), 'status' => 'dikumpulkan', 'exp' => 10, ]); return back()->with('success', 'File jawaban berhasil diganti! ✅'); } }