From ce2ca560f93c85981479a59f7305c9a58599b8d8 Mon Sep 17 00:00:00 2001 From: RetasyaSalsabila Date: Sun, 8 Mar 2026 12:49:06 +0700 Subject: [PATCH] flow admin-guru --- app/Http/Controllers/Admin/GuruController.php | 162 ++++---- .../Controllers/Admin/MengajarController.php | 62 +++ .../Controllers/Guru/DashboardController.php | 23 +- app/Http/Controllers/Guru/MapelController.php | 90 ++++- app/Models/Guru.php | 2 +- resources/views/admin/guru/index.blade.php | 364 ++++++++++++++---- resources/views/guru/layouts/app.blade.php | 106 +---- resources/views/guru/mapel/index.blade.php | 355 ++++++++++++++++- resources/views/siswa/layouts/app.blade.php | 13 +- routes/web.php | 8 +- 10 files changed, 914 insertions(+), 271 deletions(-) create mode 100644 app/Http/Controllers/Admin/MengajarController.php diff --git a/app/Http/Controllers/Admin/GuruController.php b/app/Http/Controllers/Admin/GuruController.php index 922b3e2..e55fcf3 100644 --- a/app/Http/Controllers/Admin/GuruController.php +++ b/app/Http/Controllers/Admin/GuruController.php @@ -4,121 +4,153 @@ use App\Http\Controllers\Controller; use App\Models\Guru; +use App\Models\Mapel; +use App\Models\Kelas; +use App\Models\Mengajar; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class GuruController extends Controller { public function index(Request $request) -{ - $query = Guru::query(); + { + $query = Guru::with('mengajars.mapel', 'mengajars.kelas'); + + if ($request->filled('search')) { + $search = $request->search; + $query->where(function($q) use ($search) { + $q->where('nama', 'like', "%$search%") + ->orWhere('nip', 'like', "%$search%"); + }); + } - // SEARCH - if ($request->has('search')) { - $search = $request->search; - $query->where('nama', 'like', "%$search%") - ->orWhere('nip', 'like', "%$search%"); + $perPage = $request->get('perPage', 10); + $gurus = $query->paginate($perPage)->appends($request->all()); + $mapels = Mapel::all(); + $kelas = Kelas::all(); + + return view('admin.guru.index', compact('gurus', 'mapels', 'kelas')); } - // SHOW PER PAGE - $perPage = $request->get('perPage', 10); - - $gurus = $query->paginate($perPage)->appends($request->all()); - - return view('admin.guru.index', compact('gurus')); -} - - - /** - * Show the form for creating a new resource. - */ public function create() { return view('admin.guru.create'); } /** - * Store a newly created resource in storage. + * Tambah guru + bisa pilih banyak pasangan (mapel, kelas) + * Input: mapel[] dan kelas[] dengan index yang bersesuaian */ public function store(Request $request) { - $validated = $request->validate([ - 'nip' => 'required|string|max:30|unique:gurus,nip', - 'nama' => 'required|string|max:100', - 'password' => 'required|string|min:6', + $request->validate([ + 'nip' => 'required|string|max:30|unique:gurus,nip', + 'nama' => 'required|string|max:100', + 'password' => 'required|string|min:6', + 'id_mapel' => 'required|array|min:1', + 'id_mapel.*' => 'required|exists:mapels,id_mapel', + 'id_kelas' => 'required|array|min:1', + 'id_kelas.*' => 'required|exists:kelas,id_kelas', ], [ - 'nip.required' => 'NIP wajib diisi', - 'nip.unique' => 'NIP sudah terdaftar', - 'nama.required' => 'Nama wajib diisi', - 'password.required' => 'Password wajib diisi', - 'password.min' => 'Password minimal 6 karakter', + 'id_mapel.required' => 'Pilih minimal 1 mata pelajaran.', + 'id_kelas.required' => 'Pilih minimal 1 kelas.', ]); - Guru::create([ - 'nip' => $validated['nip'], - 'nama' => $validated['nama'], - 'password' => Hash::make($validated['password']), + $guru = Guru::create([ + 'nip' => $request->nip, + 'nama' => $request->nama, + 'password' => Hash::make($request->password), ]); + // Tiap mapel berpasangan dengan kelas di index yang sama + foreach ($request->id_mapel as $i => $idMapel) { + $idKelas = $request->id_kelas[$i] ?? $request->id_kelas[0]; + Mengajar::create([ + 'id_guru' => $guru->id_guru, + 'id_mapel' => $idMapel, + 'id_kelas' => $idKelas, + ]); + } + return redirect()->route('admin.guru.index') - ->with('success', 'Data guru berhasil ditambahkan!'); + ->with('success', 'Data guru berhasil ditambahkan.'); } - /** - * Display the specified resource. - */ - public function show(string $nip) + public function show(string $id) { - $guru = Guru::findOrFail($nip); + $guru = Guru::findOrFail($id); return view('admin.guru.show', compact('guru')); } - /** - * Show the form for editing the specified resource. - */ - public function edit(string $nip) + public function edit(string $id) { - $guru = Guru::findOrFail($nip); + $guru = Guru::findOrFail($id); return view('admin.guru.edit', compact('guru')); } /** - * Update the specified resource in storage. + * Update guru — hapus semua mengajar lama, insert ulang */ - public function update(Request $request, string $nip) + public function update(Request $request, string $id) { - $guru = Guru::findOrFail($nip); + $guru = Guru::findOrFail($id); - $validated = $request->validate([ - 'nama' => 'required|string|max:100', - 'password' => 'nullable|string|min:6', - ], [ - 'nama.required' => 'Nama wajib diisi', - 'password.min' => 'Password minimal 6 karakter', + $request->validate([ + 'nip' => 'required|string|max:30|unique:gurus,nip,' . $guru->id_guru . ',id_guru', + 'nama' => 'required|string|max:100', + 'password' => 'nullable|string|min:6', + 'id_mapel' => 'required|array|min:1', + 'id_mapel.*' => 'required|exists:mapels,id_mapel', + 'id_kelas' => 'required|array|min:1', + 'id_kelas.*' => 'required|exists:kelas,id_kelas', ]); - $guru->nama = $validated['nama']; - - // Update password hanya jika diisi + $guru->nip = $request->nip; + $guru->nama = $request->nama; if ($request->filled('password')) { - $guru->password = Hash::make($validated['password']); + $guru->password = Hash::make($request->password); } - $guru->save(); + // Hapus semua data mengajar lama, insert ulang + Mengajar::where('id_guru', $guru->id_guru)->delete(); + + foreach ($request->id_mapel as $i => $idMapel) { + $idKelas = $request->id_kelas[$i] ?? $request->id_kelas[0]; + Mengajar::create([ + 'id_guru' => $guru->id_guru, + 'id_mapel' => $idMapel, + 'id_kelas' => $idKelas, + ]); + } + return redirect()->route('admin.guru.index') - ->with('success', 'Data guru berhasil diupdate!'); + ->with('success', 'Data guru berhasil diupdate.'); } - /** - * Remove the specified resource from storage. - */ - public function destroy(string $nip) + public function destroy(string $id) { - $guru = Guru::findOrFail($nip); + $guru = Guru::findOrFail($id); $guru->delete(); return redirect()->route('admin.guru.index') - ->with('success', 'Data guru berhasil dihapus!'); + ->with('success', 'Data guru berhasil dihapus.'); + } + + /** + * API: Ambil kelas yang memiliki mapel tertentu (lewat tabel mengajars) + * Dipanggil via AJAX saat admin pilih mapel di modal + */ + public function getKelasByMapel(Request $request) + { + $idMapel = $request->id_mapel; + + // Cari kelas yang sudah punya mapel ini di tabel mengajars + $kelasList = Kelas::whereHas('mengajars', function ($q) use ($idMapel) { + $q->where('id_mapel', $idMapel); + }) + ->get(['id_kelas', 'nama_kelas', 'tingkat']); + + return response()->json($kelasList); } } \ No newline at end of file diff --git a/app/Http/Controllers/Admin/MengajarController.php b/app/Http/Controllers/Admin/MengajarController.php new file mode 100644 index 0000000..e6acdc6 --- /dev/null +++ b/app/Http/Controllers/Admin/MengajarController.php @@ -0,0 +1,62 @@ +get(); + $gurus = Guru::all(); + $mapels = Mapel::all(); + $kelas = Kelas::all(); + + return view('admin.mengajar.index', compact( + 'mengajars','gurus','mapels','kelas' + )); + } + + public function store(Request $request) + { + $request->validate([ + 'id_guru' => 'required', + 'id_mapel' => 'required', + 'id_kelas' => 'required', + ]); + + Mengajar::create([ + 'id_guru' => $request->id_guru, + 'id_mapel' => $request->id_mapel, + 'id_kelas' => $request->id_kelas, + ]); + + return redirect()->back()->with('success','Data mengajar berhasil ditambahkan'); + } + + public function update(Request $request, $id) + { + $mengajar = Mengajar::findOrFail($id); + + $mengajar->update([ + 'id_guru' => $request->id_guru, + 'id_mapel' => $request->id_mapel, + 'id_kelas' => $request->id_kelas, + ]); + + return redirect()->back()->with('success','Data mengajar berhasil diupdate'); + } + + public function destroy($id) + { + Mengajar::findOrFail($id)->delete(); + + return redirect()->back()->with('success','Data mengajar berhasil dihapus'); + } +} diff --git a/app/Http/Controllers/Guru/DashboardController.php b/app/Http/Controllers/Guru/DashboardController.php index 1307187..3e42dac 100644 --- a/app/Http/Controllers/Guru/DashboardController.php +++ b/app/Http/Controllers/Guru/DashboardController.php @@ -4,8 +4,6 @@ use App\Http\Controllers\Controller; use App\Models\Mengajar; -use App\Models\Guru; -use App\Models\Kelas; use App\Models\Siswa; use Illuminate\Support\Facades\Auth; @@ -14,28 +12,23 @@ class DashboardController extends Controller public function index() { $guru = Auth::guard('guru')->user(); - - // Cek table mengajars ada data atau enggak + try { - // Hitung total kelas yang diajar - $totalKelas = Mengajar::where('nip', $guru->nip) + $totalKelas = Mengajar::where('id_guru', $guru->id_guru) ->distinct('id_kelas') ->count('id_kelas'); - - // Hitung total mapel yang diajar - $totalMapel = Mengajar::where('nip', $guru->nip) + + $totalMapel = Mengajar::where('id_guru', $guru->id_guru) ->distinct('id_mapel') ->count('id_mapel'); - - // Hitung total siswa yang diajar (lewat kelas) - $kelasIds = Mengajar::where('nip', $guru->nip) + + $kelasIds = Mengajar::where('id_guru', $guru->id_guru) ->pluck('id_kelas') ->unique(); - + $totalSiswa = Siswa::whereIn('id_kelas', $kelasIds)->count(); - + } catch (\Exception $e) { - // Kalau error (table kosong atau relasi belum ada), set default 0 $totalKelas = 0; $totalMapel = 0; $totalSiswa = 0; diff --git a/app/Http/Controllers/Guru/MapelController.php b/app/Http/Controllers/Guru/MapelController.php index 1c8056d..f71cb90 100644 --- a/app/Http/Controllers/Guru/MapelController.php +++ b/app/Http/Controllers/Guru/MapelController.php @@ -4,6 +4,10 @@ use App\Http\Controllers\Controller; use App\Models\Mapel; +use App\Models\Materi; +use App\Models\Tugas; +use App\Models\Mengajar; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class MapelController extends Controller @@ -12,11 +16,85 @@ public function index() { $guru = Auth::guard('guru')->user(); - // Ambil hanya mapel yang dia ajar - $mapels = Mapel::whereHas('mengajars', function ($query) use ($guru) { - $query->where('nip', $guru->nip); - })->paginate(10); + // Ambil mengajar dengan relasi mapel & kelas + // Group by id_mapel agar tidak duplikat jika guru ajar mapel sama di kelas berbeda + $mengajars = Mengajar::with(['mapel', 'kelas']) + ->where('id_guru', $guru->id_guru) + ->get() + ->groupBy('id_mapel'); // group by mapel - return view('guru.mapel.index', compact('mapels')); + return view('guru.mapel.index', compact('mengajars')); } -} + + /** + * Simpan materi baru + */ + public function storeMateri(Request $request) + { + $guru = Auth::guard('guru')->user(); + + $request->validate([ + 'id_mengajar' => 'required|exists:mengajars,id_mengajar', + 'judul_materi' => 'required|string|max:200', + 'deskripsi' => 'nullable|string', + 'lampiran_materi' => 'nullable|file|mimes:pdf,doc,docx,jpg,jpeg,png,ppt,pptx|max:10240', + ], [ + 'lampiran_materi.mimes' => 'Format file: pdf, doc, docx, jpg, png, ppt, pptx.', + 'lampiran_materi.max' => 'Ukuran file maksimal 10MB.', + ]); + + // Pastikan mengajar ini milik guru yang login + $mengajar = Mengajar::where('id_mengajar', $request->id_mengajar) + ->where('id_guru', $guru->id_guru) + ->firstOrFail(); + + $path = null; + if ($request->hasFile('lampiran_materi')) { + $file = $request->file('lampiran_materi'); + $filename = 'materi_' . $guru->id_guru . '_' . time() . '.' . $file->getClientOriginalExtension(); + $path = $file->storeAs('materi', $filename, 'public'); + } + + Materi::create([ + 'id_mengajar' => $request->id_mengajar, + 'judul_materi' => $request->judul_materi, + 'deskripsi' => $request->deskripsi, + 'lampiran_materi' => $path, + ]); + + return redirect()->route('guru.mapel.index') + ->with('success', 'Materi berhasil diupload!'); + } + + /** + * Simpan tugas baru + */ + public function storeTugas(Request $request) + { + $guru = Auth::guard('guru')->user(); + + $request->validate([ + 'id_mengajar' => 'required|exists:mengajars,id_mengajar', + 'judul_tugas' => 'required|string|max:200', + 'keterangan' => 'nullable|string', + 'deadline' => 'required|date|after:now', + ], [ + 'deadline.after' => 'Deadline harus lebih dari waktu sekarang.', + ]); + + // Pastikan mengajar ini milik guru yang login + $mengajar = Mengajar::where('id_mengajar', $request->id_mengajar) + ->where('id_guru', $guru->id_guru) + ->firstOrFail(); + + Tugas::create([ + 'id_mengajar' => $request->id_mengajar, + 'judul_tugas' => $request->judul_tugas, + 'keterangan' => $request->keterangan, + 'deadline' => $request->deadline, + ]); + + return redirect()->route('guru.mapel.index') + ->with('success', 'Tugas berhasil dibuat!'); + } +} \ No newline at end of file diff --git a/app/Models/Guru.php b/app/Models/Guru.php index e191e66..5b35a97 100644 --- a/app/Models/Guru.php +++ b/app/Models/Guru.php @@ -27,6 +27,6 @@ class Guru extends Authenticatable // Relasi ke Mengajar public function mengajars() { - return $this->hasMany(Mengajar::class, 'nip', 'nip'); + return $this->hasMany(Mengajar::class, 'id_guru', 'id_guru'); } } diff --git a/resources/views/admin/guru/index.blade.php b/resources/views/admin/guru/index.blade.php index 15104a0..da76355 100644 --- a/resources/views/admin/guru/index.blade.php +++ b/resources/views/admin/guru/index.blade.php @@ -30,11 +30,10 @@ gap: 8px; font-size: 14px; text-decoration: none; + cursor: pointer; } - .table-header { - background: #a5e6ba; - } + .table-header { background: #a5e6ba; } .search-box { background: #a5e6ba; @@ -52,11 +51,7 @@ width: 150px; } - .action-icon { - width: 20px; - cursor: pointer; - margin: 0 5px; - } + .action-icon { width: 20px; cursor: pointer; margin: 0 5px; } .per-page-select { border-radius: 10px; @@ -64,8 +59,6 @@ border: 1px solid #ccc; } - /* ===== STYLE BARU UNTUK MODAL ===== */ - .modal-header-pastel { background: #FFD97D !important; color: black !important; @@ -73,57 +66,101 @@ } .modal-content { - border-radius: 15px; + border-radius: 20px; border: none; + box-shadow: 0 10px 30px rgba(0,0,0,0.2); } - .modal-body label { - font-weight: bold; + .modal-body label { font-weight: bold; } + + /* ===== PASANGAN MAPEL - KELAS ===== */ + .mengajar-row { + display: flex; + gap: 10px; + align-items: center; + background: #f8fafc; + border-radius: 10px; + padding: 10px 12px; + margin-bottom: 8px; + border: 1px solid #e2e8f0; } - .modal { - left: auto !important; - right: 0; - width: calc(100% - 250px); -} + .mengajar-row select { + flex: 1; + border-radius: 8px; + border: 1px solid #cbd5e1; + padding: 6px 10px; + font-size: 14px; + } -.modal-backdrop { - left: auto !important; - right: 0; - width: calc(100% - 250px); -} + .btn-hapus-row { + background: #fee2e2; + color: #ef4444; + border: none; + border-radius: 8px; + width: 32px; + height: 32px; + font-size: 16px; + cursor: pointer; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; + } -.modal-dialog { - margin-right: auto; - margin-left: auto; -} + .btn-hapus-row:hover { background: #fca5a5; } -.modal-content { - border-radius: 20px; - box-shadow: 0 10px 30px rgba(0,0,0,0.2); -} + .btn-tambah-row { + background: #e6f0ff; + color: #2b8ef3; + border: none; + border-radius: 8px; + padding: 7px 14px; + font-size: 13px; + font-weight: 600; + cursor: pointer; + margin-top: 4px; + transition: background 0.2s; + } + .btn-tambah-row:hover { background: #bfdbfe; } + .row-label { + font-size: 12px; + color: #64748b; + font-weight: 600; + min-width: 50px; + } + .alert-success-custom { + background: #dcfce7; + color: #166534; + border-radius: 10px; + padding: 12px 16px; + margin-bottom: 16px; + font-weight: 500; + }

DAFTAR GURU

+@if(session('success')) +
✅ {{ session('success') }}
+@endif +
-
- -
-
Tampilkan - - data -
@@ -162,28 +195,52 @@ No Nama Lengkap NIP + Mapel + Kelas Password Aksi - @forelse($gurus as $index => $guru) {{ $gurus->firstItem() + $index }} {{ $guru->nama }} {{ $guru->nip }} + + + @forelse($guru->mengajars as $m) +
{{ optional($m->mapel)->nama_mapel ?? '-' }}
+ @empty + - + @endforelse + + + + @forelse($guru->mengajars as $m) +
{{ optional($m->kelas)->tingkat }} {{ optional($m->kelas)->nama_kelas }}
+ @empty + - + @endforelse + + ******** - -
+ onsubmit="return confirm('Yakin hapus guru ini?')"> @csrf @method('DELETE')
-{{-- MODAL TAMBAH DATA --}} + +{{-- ============================================================ --}} +{{-- MODAL TAMBAH DATA --}} +{{-- ============================================================ --}}