diff --git a/app/Http/Controllers/Admin/MateriTugasController.php b/app/Http/Controllers/Admin/MateriTugasController.php new file mode 100644 index 0000000..a71096f --- /dev/null +++ b/app/Http/Controllers/Admin/MateriTugasController.php @@ -0,0 +1,117 @@ +filled('id_guru')) { + $query->whereHas('mengajar', fn($q) => $q->where('id_guru', $request->id_guru)); + } + + // Filter by mapel + if ($request->filled('id_mapel')) { + $query->whereHas('mengajar', fn($q) => $q->where('id_mapel', $request->id_mapel)); + } + + // Search judul + if ($request->filled('search')) { + $query->where('judul_materi', 'like', '%' . $request->search . '%'); + } + + $materiList = $query->orderBy('created_at', 'desc')->paginate(15)->appends($request->all()); + $gurus = Guru::orderBy('nama')->get(); + + return view('admin.materi.history', compact('materiList', 'gurus')); + } + + /** + * Hapus materi (admin) + */ + public function destroyMateri($id) + { + $materi = Materi::findOrFail($id); + + if ($materi->lampiran_materi && \Storage::disk('public')->exists($materi->lampiran_materi)) { + \Storage::disk('public')->delete($materi->lampiran_materi); + } + + $materi->delete(); + + return redirect()->route('admin.materi.history') + ->with('success', 'Materi berhasil dihapus.'); + } + + // =================================================== + // TUGAS + // =================================================== + + /** + * History semua tugas dari semua guru + */ + public function historyTugas(Request $request) + { + $query = Tugas::with(['mengajar.mapel', 'mengajar.kelas', 'mengajar.guru', 'pengumpulanTugas']); + + // Filter by guru + if ($request->filled('id_guru')) { + $query->whereHas('mengajar', fn($q) => $q->where('id_guru', $request->id_guru)); + } + + // Search judul + if ($request->filled('search')) { + $query->where('judul_tugas', 'like', '%' . $request->search . '%'); + } + + $tugasList = $query->orderBy('created_at', 'desc')->paginate(15)->appends($request->all()); + $gurus = Guru::orderBy('nama')->get(); + + return view('admin.tugas.history', compact('tugasList', 'gurus')); + } + + /** + * Detail tugas + daftar pengumpulan siswa + */ + public function detailTugas($id) + { + $tugas = Tugas::with([ + 'mengajar.mapel', + 'mengajar.kelas', + 'mengajar.guru', + 'pengumpulanTugas.siswa', + ]) + ->findOrFail($id); + + return view('admin.tugas.detail', compact('tugas')); + } + + /** + * Hapus tugas (admin) + */ + public function destroyTugas($id) + { + $tugas = Tugas::findOrFail($id); + $tugas->delete(); + + return redirect()->route('admin.tugas.history') + ->with('success', 'Tugas berhasil dihapus.'); + } +} \ No newline at end of file diff --git a/resources/views/admin/layouts/app.blade.php b/resources/views/admin/layouts/app.blade.php index a525549..e9871d5 100644 --- a/resources/views/admin/layouts/app.blade.php +++ b/resources/views/admin/layouts/app.blade.php @@ -5,7 +5,6 @@ @yield('title', 'Admin Panel') - @@ -16,13 +15,8 @@ margin: 0; } - /* WRAPPER */ - .admin-wrapper { - display: flex; - min-height: 100vh; - } + .admin-wrapper { display: flex; min-height: 100vh; } - /* SIDEBAR */ .sidebar { width: 260px; background: #ffffff; @@ -32,19 +26,10 @@ flex-direction: column; } - .sidebar-logo { - text-align: center; - margin-bottom: 40px; - } + .sidebar-logo { text-align: center; margin-bottom: 40px; } + .sidebar-logo img { width: 90px; } - .sidebar-logo img { - width: 90px; - } - - .sidebar-menu { - display: flex; - flex-direction: column; - } + .sidebar-menu { display: flex; flex-direction: column; } .sidebar-link { display: flex; @@ -59,25 +44,23 @@ transition: all 0.2s ease; } - .sidebar-link:hover { - background: #e6f0ff; - color: #1d4ed8; + .sidebar-link:hover { background: #e6f0ff; color: #1d4ed8; } + .sidebar-link.active { background: #e6f0ff; color: #1d4ed8; } + + .sidebar-icon { width: 20px; height: 20px; flex-shrink: 0; } + + .sidebar-section { + font-size: 10px; + font-weight: 700; + color: #94a3b8; + letter-spacing: 1px; + text-transform: uppercase; + padding: 4px 18px; + margin-bottom: 6px; + margin-top: 6px; } - .sidebar-link.active { - background: #e6f0ff; - color: #1d4ed8; - } - - .sidebar-icon { - width: 20px; - height: 20px; - flex-shrink: 0; - } - - .sidebar-logout { - margin-top: auto; - } + .sidebar-logout { margin-top: auto; } .sidebar-logout button { width: 100%; @@ -89,15 +72,8 @@ text-align: left; } - /* MAIN */ - .main { - flex: 1; - background: #f5f9ff; - display: flex; - flex-direction: column; - } + .main { flex: 1; background: #f5f9ff; display: flex; flex-direction: column; } - /* TOPBAR */ .topbar { background: #2b8ef3; margin: 20px; @@ -109,35 +85,19 @@ align-items: center; } - .topbar-left { - font-weight: 600; - font-size: 16px; - } + .topbar-left { font-weight: 600; font-size: 16px; } + .topbar-right { display: flex; align-items: center; gap: 16px; } + .topbar-icon { width: 24px; height: 24px; cursor: pointer; } - .topbar-right { - display: flex; - align-items: center; - gap: 16px; - } - - .topbar-icon { - width: 24px; - height: 24px; - cursor: pointer; - } - - /* CONTENT */ - .content { - padding: 20px 30px; - flex: 1; - } + .content { padding: 20px 30px; flex: 1; } + + @stack('styles')
- -
- -
👋 Hai, {{ Auth::guard('admin')->user()->username ?? 'Admin' }}
-
Notification Profile
-
@yield('content')
-
+@stack('scripts') - + \ No newline at end of file diff --git a/resources/views/admin/materi/history.blade.php b/resources/views/admin/materi/history.blade.php new file mode 100644 index 0000000..0fbaf68 --- /dev/null +++ b/resources/views/admin/materi/history.blade.php @@ -0,0 +1,257 @@ +@extends('admin.layouts.app') + +@section('title', 'History Materi') + +@section('content') + + + +

HISTORY MATERI

+ +@if(session('success')) +
✅ {{ session('success') }}
+@endif + +
+ + {{-- FILTER & SEARCH --}} +
+ + + + + @if(request()->hasAny(['id_guru', 'search'])) + ✕ Reset + @endif + + + Total: {{ $materiList->total() }} materi + +
+ + @if($materiList->isEmpty()) +
+
📭
+

Tidak ada materi ditemukan.

+
+ @else +
+ + + + + + + + + + + + + + + @foreach($materiList as $i => $materi) + + + + + + + + + + + @endforeach + +
NoJudul MateriGuruMata PelajaranKelasTgl UploadFileAksi
{{ $materiList->firstItem() + $i }} +
{{ $materi->judul_materi }}
+ @if($materi->deskripsi) +
+ {{ Str::limit($materi->deskripsi, 55) }} +
+ @endif +
+ + {{ optional(optional($materi->mengajar)->guru)->nama ?? '-' }} + + + + {{ optional(optional($materi->mengajar)->mapel)->nama_mapel ?? '-' }} + + + + {{ optional(optional($materi->mengajar)->kelas)->tingkat }} + {{ optional(optional($materi->mengajar)->kelas)->nama_kelas ?? '-' }} + + + {{ \Carbon\Carbon::parse($materi->tanggal_upload ?? $materi->created_at)->format('d M Y') }} +
+ {{ \Carbon\Carbon::parse($materi->tanggal_upload ?? $materi->created_at)->format('H:i') }} +
+
+ @if($materi->lampiran_materi) + @php + $ext = strtolower(pathinfo($materi->lampiran_materi, PATHINFO_EXTENSION)); + $icon = match(true) { + in_array($ext, ['pdf']) => '📄', + in_array($ext, ['doc','docx']) => '📝', + in_array($ext, ['ppt','pptx']) => '📊', + in_array($ext, ['jpg','jpeg','png']) => '🖼️', + default => '📎', + }; + @endphp + + {{ $icon }} Unduh + + @else + Tidak ada + @endif + +
+ @csrf + @method('DELETE') + +
+
+
+ +
+ {{ $materiList->links() }} +
+ @endif + +
+ +@endsection \ No newline at end of file diff --git a/resources/views/admin/tugas/detail.blade.php b/resources/views/admin/tugas/detail.blade.php new file mode 100644 index 0000000..66da78a --- /dev/null +++ b/resources/views/admin/tugas/detail.blade.php @@ -0,0 +1,331 @@ +@extends('admin.layouts.app') + +@section('title', 'Detail Tugas') + +@section('content') + + + +@php + $isLewat = \Carbon\Carbon::parse($tugas->deadline)->isPast(); + $tepat = $tugas->pengumpulanTugas->where('status', 'dikumpulkan')->count(); + $terlambat = $tugas->pengumpulanTugas->where('status', 'terlambat')->count(); + $totalKumpul = $tugas->pengumpulanTugas->count(); +@endphp + +← Kembali ke History Tugas + +{{-- INFO TUGAS --}} +
+

{{ $tugas->judul_tugas }}

+ +
+ + 👨‍🏫 {{ optional(optional($tugas->mengajar)->guru)->nama ?? '-' }} + + + 📚 {{ optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-' }} + + + 🏫 {{ optional(optional($tugas->mengajar)->kelas)->tingkat }} + {{ optional(optional($tugas->mengajar)->kelas)->nama_kelas ?? '-' }} + + + ⏰ {{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }} + — {{ $isLewat ? 'Sudah lewat' : 'Masih aktif' }} + +
+ + @if($tugas->keterangan) +
+ {!! nl2br(e($tugas->keterangan)) !!} +
+ @endif +
+ +{{-- STATISTIK --}} +
+
+

{{ $tepat }}

+

Tepat Waktu

+
+
+

{{ $terlambat }}

+

Terlambat

+
+
+

{{ $totalKumpul }}

+

Total Pengumpulan

+
+
+ +{{-- DAFTAR PENGUMPULAN --}} +
+
+

📥 Daftar Pengumpulan Siswa

+ +
+ + @if($tugas->pengumpulanTugas->isEmpty()) +
+
📭
+

Belum ada siswa yang mengumpulkan tugas ini.

+
+ @else +
+ + + + + + + + + + + + + + @foreach($tugas->pengumpulanTugas as $i => $kumpul) + + + + + + + + + + @endforeach + +
NoNama SiswaNISNWaktu SubmitStatusEXP / PoinFile Jawaban
{{ $i + 1 }} + {{ optional($kumpul->siswa)->nama ?? '-' }} + + {{ optional($kumpul->siswa)->nisn ?? '-' }} + + {{ \Carbon\Carbon::parse($kumpul->tanggal_submit)->format('d M Y') }} +
+ {{ \Carbon\Carbon::parse($kumpul->tanggal_submit)->format('H:i') }} +
+
+ + @if($kumpul->status === 'dikumpulkan') ✅ Tepat Waktu + @elseif($kumpul->status === 'terlambat') ⏰ Terlambat + @else ❌ Belum + @endif + + + @if($kumpul->exp > 0) + ⭐ {{ $kumpul->exp }} EXP + @else + Belum dinilai + @endif + + @if($kumpul->lampiran_tugas) + @php + $ext = strtolower(pathinfo($kumpul->lampiran_tugas, PATHINFO_EXTENSION)); + $icon = match(true) { + in_array($ext, ['pdf']) => '📄', + in_array($ext, ['doc','docx']) => '📝', + in_array($ext, ['jpg','jpeg','png']) => '🖼️', + default => '📎', + }; + @endphp + + {{ $icon }} Unduh + + @else + - + @endif +
+
+ @endif +
+ + + +@endsection \ No newline at end of file diff --git a/resources/views/admin/tugas/history.blade.php b/resources/views/admin/tugas/history.blade.php new file mode 100644 index 0000000..7d307fc --- /dev/null +++ b/resources/views/admin/tugas/history.blade.php @@ -0,0 +1,268 @@ +@extends('admin.layouts.app') + +@section('title', 'History Tugas') + +@section('content') + + + +

HISTORY TUGAS

+ +@if(session('success')) +
✅ {{ session('success') }}
+@endif + +
+ + {{-- FILTER & SEARCH --}} +
+ + + + + @if(request()->hasAny(['id_guru', 'search'])) + ✕ Reset + @endif + + + Total: {{ $tugasList->total() }} tugas + +
+ + @if($tugasList->isEmpty()) +
+
📭
+

Tidak ada tugas ditemukan.

+
+ @else +
+ + + + + + + + + + + + + + + @foreach($tugasList as $i => $tugas) + @php + $isLewat = \Carbon\Carbon::parse($tugas->deadline)->isPast(); + $jumlahKumpul = $tugas->pengumpulanTugas->count(); + @endphp + + + + + + + + + + + @endforeach + +
NoJudul TugasGuruMata PelajaranKelasDeadlinePengumpulanAksi
{{ $tugasList->firstItem() + $i }} +
{{ $tugas->judul_tugas }}
+ @if($tugas->keterangan) +
+ {{ Str::limit($tugas->keterangan, 55) }} +
+ @endif +
+ + {{ optional(optional($tugas->mengajar)->guru)->nama ?? '-' }} + + + + {{ optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-' }} + + + + {{ optional(optional($tugas->mengajar)->kelas)->tingkat }} + {{ optional(optional($tugas->mengajar)->kelas)->nama_kelas ?? '-' }} + + + + {{ $isLewat ? '⏰ Lewat' : '✅ Aktif' }} + +
+ {{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }} +
+
+ {{ $jumlahKumpul }} + siswa + +
+ 👁️ Detail +
+ @csrf + @method('DELETE') + +
+
+
+
+ +
+ {{ $tugasList->links() }} +
+ @endif + +
+ +@endsection \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index c92b175..ae14cc1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -13,6 +13,7 @@ use App\Http\Controllers\Admin\MapelController as AdminMapelController; use App\Http\Controllers\Admin\ChallengeController as AdminChallengeController; use App\Http\Controllers\Admin\LeaderboardController as AdminLeaderboardController; +use App\Http\Controllers\Admin\MateriTugasController as AdminMateriTugasController; // GURU CONTROLLERS @@ -94,6 +95,16 @@ // CRUD AREA Route::get('/guru/kelas-by-mapel', [AdminGuruController::class, 'getKelasByMapel']) ->name('guru.kelasByMapel'); + + // History Materi + Route::get('/materi/history', [AdminMateriTugasController::class, 'historyMateri'])->name('materi.history'); + Route::delete('/materi/{id}', [AdminMateriTugasController::class, 'destroyMateri'])->name('materi.destroy'); + + // History Tugas + Route::get('/tugas/history', [AdminMateriTugasController::class, 'historyTugas'])->name('tugas.history'); + Route::get('/tugas/{id}/detail', [AdminMateriTugasController::class, 'detailTugas'])->name('tugas.detail'); + Route::delete('/tugas/{id}', [AdminMateriTugasController::class, 'destroyTugas'])->name('tugas.destroy'); + Route::resource('guru', AdminGuruController::class); Route::resource('siswa', AdminSiswaController::class); Route::resource('kelas', AdminKelasController::class);