MIF_E31230356/app/Http/Controllers/Siswa/TugasController.php

205 lines
7.8 KiB
PHP

<?php
namespace App\Http\Controllers\Siswa;
use App\Http\Controllers\Controller;
use App\Models\Badge;
use App\Models\PengumpulanTugas;
use App\Models\SiswaBadge;
use App\Services\BadgeService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;
use App\Models\Tugas;
class TugasController extends Controller
{
public function __construct()
{
$this->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! ✅');
}
}