MIF_E31221225/app/Http/Controllers/Guru/UjianController.php

281 lines
8.9 KiB
PHP

<?php
namespace App\Http\Controllers\Guru;
use App\Http\Controllers\Controller;
use App\Models\Ujian;
use App\Models\Kelas;
use App\Models\Guru;
use App\Models\Mapel;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use App\Models\HasilUjian;
use Illuminate\Support\Facades\DB;
class UjianController extends Controller
{
protected function getGuruId()
{
$guru = Guru::where('user_id', auth()->id())->firstOrFail();
return $guru->id;
}
public function index(Request $request)
{
$guruId = $this->getGuruId(); // Mendapatkan ID guru yang login
$kelasId = $request->get('kelas_id'); // ID kelas yang difilter (jika ada)
// Ambil semua mapel yang diajar guru, bisa difilter juga berdasarkan kelas
$mapelIds = \App\Models\GuruMapel::where('guru_id', $guruId)
->when($kelasId, fn($q) => $q->where('kelas_id', $kelasId))
->pluck('mapel_id');
// Ambil ujian-ujian yang mapelnya diajar oleh guru
$ujians = \App\Models\Ujian::with('kelas', 'mapel')
->whereIn('mapel_id', $mapelIds)
->when($kelasId, function ($query) use ($kelasId) {
$query->whereHas('kelas', fn($q) => $q->where('kelas.id', $kelasId));
})
->get();
// Ambil daftar kelas untuk dropdown filter (kelas yang benar-benar diajar guru)
$daftarKelas = \App\Models\Kelas::whereIn('id', \App\Models\GuruMapel::where('guru_id', $guruId)->pluck('kelas_id'))
->get();
return view('guru.ujian.index', compact('ujians', 'daftarKelas', 'kelasId'));
}
public function show(Ujian $ujian)
{
return redirect()->route('guru.ujian.preview', $ujian->id);
}
public function detail(Ujian $ujian)
{
$ujian->load([
'soalPilgan',
'soalEssay',
'kelas' => function ($query) {
$query->withPivot('deadline', 'terbit');
}
]);
return view('guru.ujian.detail', compact('ujian'));
}
public function create()
{
$guru = auth()->user()->guru;
if (!$guru) {
return redirect()->route('guru.dashboard')->with('error', 'Data guru tidak ditemukan.');
}
$mapels = $guru->mapel;
$kelas = Kelas::all();
return view('guru.ujian.create', compact('mapels', 'kelas'));
}
public function store(Request $request)
{
$guru = auth()->user()->guru;
$request->validate([
'mapel_id' => [
'required',
'exists:mapels,id',
// Validasi custom supaya mapel yang dipilih adalah mapel yang diampu guru
function ($attribute, $value, $fail) use ($guru) {
if (!$guru->mapel->pluck('id')->contains($value)) {
$fail('Mapel yang dipilih tidak valid.');
}
},
],
'judul' => 'required',
'waktu' => 'required|numeric',
'deskripsi' => 'nullable|string',
'soal' => 'nullable|string',
'bobot_pg' => 'nullable|integer',
'bobot_essay' => 'nullable|integer',
'kelas' => 'required|array',
'kelas.*.deadline' => 'nullable|date',
'kelas.*.terbit' => 'nullable|boolean',
]);
$ujian = Ujian::create([
'mapel_id' => $request->mapel_id,
'judul' => $request->judul,
'deskripsi' => $request->deskripsi,
'tanggal_post' => now(),
'waktu' => $request->waktu,
'soal' => $request->soal ?? '',
'terbit' => false,
'bobot_pg' => $request->bobot_pg ?? 0,
'bobot_essay' => $request->bobot_essay ?? 0,
]);
$attachData = [];
foreach ($request->kelas as $kelas_id => $kelasData) {
$attachData[$kelas_id] = [
'deadline' => $kelasData['deadline'] ?? null,
'terbit' => $kelasData['terbit'] ?? false,
];
}
$ujian->kelas()->attach($attachData);
return redirect()->route('guru.ujian.index')->with('success', 'Ujian berhasil dibuat.');
}
public function edit(Ujian $ujian)
{
$ujian->load(['soalPilgan', 'soalEssay', 'kelas']);
$kelas = Kelas::all();
$kelasDeadline = $ujian->kelas->keyBy('id')->map(function ($kelas) {
return $kelas->pivot->deadline;
});
$kelasTerbit = $ujian->kelas->keyBy('id')->map(function ($kelas) {
return $kelas->pivot->terbit;
});
return view('guru.ujian.edit', compact('ujian', 'kelas', 'kelasDeadline', 'kelasTerbit'));
}
public function update(Request $request, Ujian $ujian)
{
$request->validate([
'judul' => 'required',
'waktu' => 'required|numeric',
'deskripsi' => 'nullable|string',
'soal' => 'nullable|string',
'bobot_pg' => 'nullable|integer',
'bobot_essay' => 'nullable|integer',
'kelas' => 'required|array',
'kelas.*.deadline' => 'nullable|date',
'kelas.*.terbit' => 'nullable|boolean',
]);
$ujian->update([
'judul' => $request->judul,
'deskripsi' => $request->deskripsi,
'waktu' => $request->waktu,
'soal' => $request->soal ?? '',
'bobot_pg' => $request->bobot_pg ?? 0,
'bobot_essay' => $request->bobot_essay ?? 0,
]);
$syncData = [];
foreach ($request->kelas as $kelas_id => $kelasData) {
$syncData[$kelas_id] = [
'deadline' => $kelasData['deadline'] ?? null,
'terbit' => $kelasData['terbit'] ?? false,
];
}
$ujian->kelas()->sync($syncData);
return redirect()->route('guru.ujian.index')->with('success', 'Ujian berhasil diperbarui.');
}
public function updateStatus(Ujian $ujian)
{
$ujian->terbit = !$ujian->terbit;
$ujian->save();
return redirect()->route('guru.ujian.index')->with('success', 'Status ujian berhasil diperbarui.');
}
public function destroy(Ujian $ujian)
{
$ujian->kelas()->detach();
$ujian->delete();
return back()->with('success', 'Ujian berhasil dihapus.');
}
public function preview($id)
{
$ujian = Ujian::with('kelas')->findOrFail($id);
return view('guru.ujian.preview', compact('ujian'));
}
public function daftarHasil(Request $request)
{
$guruId = $this->getGuruId(); // Ambil ID guru login
$kelasId = $request->get('kelas_id');
// Ambil mapel yang diajar guru
$mapelIds = \App\Models\GuruMapel::where('guru_id', $guruId)
->when($kelasId, fn($q) => $q->where('kelas_id', $kelasId))
->pluck('mapel_id');
// Ambil semua ujian yang punya hasil, dibuat oleh guru login
$ujians = \App\Models\Ujian::withCount('hasilUjian')
->whereIn('mapel_id', $mapelIds)
->whereHas('hasilUjian')
->when($kelasId, function ($query) use ($kelasId) {
$query->whereHas('kelas', fn($q) => $q->where('kelas.id', $kelasId));
})
->get();
// Ambil daftar kelas untuk dropdown
$daftarKelas = \App\Models\Kelas::whereIn('id', \App\Models\GuruMapel::where('guru_id', $guruId)->pluck('kelas_id'))->get();
return view('guru.ujian.daftar-hasil', compact('ujians', 'daftarKelas', 'kelasId'));
}
public function hasil(Request $request, $ujian_id)
{
$guruId = $this->getGuruId();
$kelasId = $request->get('kelas_id');
// Ambil mapel yang diajar oleh guru
$mapelIds = \App\Models\GuruMapel::where('guru_id', $guruId)->pluck('mapel_id');
// Validasi bahwa ujian benar-benar milik guru login
$ujian = \App\Models\Ujian::with(['hasilUjian.siswa', 'kelas'])
->where('id', $ujian_id)
->whereIn('mapel_id', $mapelIds)
->firstOrFail();
// Filter hasilUjian berdasarkan kelas jika diminta
if ($kelasId) {
$ujian->setRelation('hasilUjian', $ujian->hasilUjian->filter(function ($hasil) use ($kelasId) {
return $hasil->siswa->kelas_id == $kelasId;
}));
}
// Ambil daftar kelas dari relasi ujian
$daftarKelas = $ujian->kelas;
return view('guru.ujian.hasil', compact('ujian', 'daftarKelas', 'kelasId'));
}
public function grafik(Request $request)
{
$kelasId = $request->kelas_id;
if (!$kelasId) {
return redirect()->route('guru.ujian.hasil.index')->with('error', 'Silakan pilih kelas terlebih dahulu.');
}
$kelas = Kelas::find($kelasId); // ambil data kelas
$data = HasilUjian::select('ujian_id', DB::raw('AVG(nilai_total) as rata_rata'))
->whereNotNull('nilai_total')
->whereHas('siswa', fn($q) => $q->where('kelas_id', $kelasId))
->groupBy('ujian_id')
->with('ujian:id,judul')
->get();
$labels = $data->map(fn($item) => $item->ujian->judul);
$values = $data->map(fn($item) => round($item->rata_rata, 2));
return view('guru.ujian.grafik', compact('labels', 'values', 'kelasId', 'kelas'));
}
}