siswa fixed, mapel updated (undone)

This commit is contained in:
RetasyaSalsabila 2026-02-11 20:43:22 +07:00
parent 949e483f7e
commit e1f4801551
6 changed files with 446 additions and 7 deletions

View File

@ -0,0 +1,97 @@
<?php
// ============================================================
// FILE 1: app/Http/Controllers/Admin/MapelController.php
// ============================================================
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Mapel;
use App\Models\Kelas;
use Illuminate\Http\Request;
class MapelController extends Controller
{
public function index(Request $request)
{
$query = Mapel::query();
// SEARCH
if ($request->has('search')) {
$search = $request->search;
$query->where('nama_mapel', 'like', "%$search%")
->orWhere('id_mapel', 'like', "%$search%");
}
// FILTER BY KELAS (lewat table mengajars)
if ($request->has('filter_kelas') && $request->filter_kelas != '') {
$query->whereHas('mengajars', function($q) use ($request) {
$q->where('id_kelas', $request->filter_kelas);
});
}
// SHOW PER PAGE
$perPage = $request->get('perPage', 10);
$mapels = $query->paginate($perPage)->appends($request->all());
// Ambil semua kelas untuk dropdown filter
$kelass = Kelas::orderBy('tingkat')->orderBy('nama_kelas')->get();
return view('admin.mapel.index', compact('mapels', 'kelass'));
}
public function store(Request $request)
{
$validated = $request->validate([
'nama_mapel' => 'required|string|max:100',
], [
'nama_mapel.required' => 'Nama mata pelajaran wajib diisi',
]);
// Auto-generate id_mapel
$lastMapel = Mapel::orderBy('id_mapel', 'desc')->first();
if ($lastMapel) {
$lastNumber = (int) substr($lastMapel->id_mapel, 2); // Ambil angka setelah "MP"
$newNumber = $lastNumber + 1;
} else {
$newNumber = 1;
}
$newIdMapel = 'MP' . str_pad($newNumber, 3, '0', STR_PAD_LEFT); // MP001, MP002, dst
Mapel::create([
'id_mapel' => $newIdMapel,
'nama_mapel' => $validated['nama_mapel'],
]);
return redirect()->route('admin.mapel.index')
->with('success', 'Data mata pelajaran berhasil ditambahkan!');
}
public function update(Request $request, $id_mapel)
{
$mapel = Mapel::findOrFail($id_mapel);
$validated = $request->validate([
'nama_mapel' => 'required|string|max:100',
], [
'nama_mapel.required' => 'Nama mata pelajaran wajib diisi',
]);
$mapel->update($validated);
return redirect()->route('admin.mapel.index')
->with('success', 'Data mata pelajaran berhasil diupdate!');
}
public function destroy($id_mapel)
{
$mapel = Mapel::findOrFail($id_mapel);
$mapel->delete();
return redirect()->route('admin.mapel.index')
->with('success', 'Data mata pelajaran berhasil dihapus!');
}
}

View File

@ -1,3 +1,4 @@
<?php
namespace App\Http\Controllers\Admin;
@ -11,7 +12,7 @@ class SiswaController extends Controller
{
public function index(Request $request)
{
$query = Siswa::with('kelas'); // Eager load relasi kelas
$query = Siswa::with('kelas');
// SEARCH
if ($request->has('search')) {
@ -94,7 +95,6 @@ public function update(Request $request, $nisn)
$siswa->tanggal_lahir = $validated['tanggal_lahir'];
$siswa->id_kelas = $validated['id_kelas'];
// Update password hanya jika diisi
if ($request->filled('password')) {
$siswa->password = Hash::make($validated['password']);
}
@ -113,4 +113,4 @@ public function destroy($nisn)
return redirect()->route('admin.siswa.index')
->with('success', 'Data siswa berhasil dihapus!');
}
}
}

View File

@ -10,7 +10,6 @@ class Mapel extends Model
use HasFactory;
protected $table = 'mapels';
protected $primaryKey = 'id_mapel';
public $incrementing = false;
protected $keyType = 'string';
@ -19,4 +18,16 @@ class Mapel extends Model
'id_mapel',
'nama_mapel',
];
// Relasi ke Mengajar (mapel diajar di kelas mana aja lewat guru)
public function mengajars()
{
return $this->hasMany(Mengajar::class, 'id_mapel', 'id_mapel');
}
// Relasi many-to-many ke Kelas (lewat mengajars)
public function kelas()
{
return $this->belongsToMany(Kelas::class, 'mengajars', 'id_mapel', 'id_kelas');
}
}

View File

@ -9,8 +9,7 @@ class Mengajar extends Model
{
use HasFactory;
protected $table = 'mengajars';
protected $table = 'mengajars';
protected $primaryKey = 'id_mengajar';
protected $fillable = [
@ -18,4 +17,22 @@ class Mengajar extends Model
'id_mapel',
'id_kelas',
];
// Relasi ke Guru
public function guru()
{
return $this->belongsTo(Guru::class, 'nip', 'nip');
}
// Relasi ke Mapel
public function mapel()
{
return $this->belongsTo(Mapel::class, 'id_mapel', 'id_mapel');
}
// Relasi ke Kelas
public function kelas()
{
return $this->belongsTo(Kelas::class, 'id_kelas', 'id_kelas');
}
}

View File

@ -0,0 +1,313 @@
@extends('admin.layouts.app')
@section('title', 'Daftar Mata Pelajaran')
@section('content')
<style>
.page-title {
font-size: 30px;
font-weight: 800;
margin-bottom: 10px;
margin-top: -20px;
}
.custom-card {
background: white;
border-radius: 20px;
border: 2px solid #e5e5e5;
padding: 25px;
}
.btn-primary-custom {
background: #2b8ef3;
color: white;
border-radius: 10px;
padding: 8px 18px;
border: none;
display: inline-flex;
align-items: center;
gap: 8px;
font-size: 14px;
text-decoration: none;
}
.table-header {
background: #a5e6ba;
}
.search-box {
background: #a5e6ba;
border-radius: 30px;
padding: 6px 15px;
display: flex;
align-items: center;
gap: 8px;
}
.search-box input {
border: none;
outline: none;
background: transparent;
width: 150px;
}
.action-icon {
width: 20px;
cursor: pointer;
margin: 0 5px;
}
.per-page-select, .filter-select {
border-radius: 10px;
padding: 5px;
border: 1px solid #ccc;
}
.modal {
left: auto !important;
right: 0;
width: calc(100% - 250px);
}
.modal-backdrop {
left: auto !important;
right: 0;
width: calc(100% - 250px);
}
.modal-dialog {
margin-right: auto;
margin-left: auto;
}
.modal-content {
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.modal-header-pastel {
background: #FFD97D !important;
color: black !important;
border-bottom: none;
padding: 15px 20px;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
}
</style>
<h3 class="page-title">DAFTAR MATA PELAJARAN</h3>
<div class="custom-card">
<div class="d-flex justify-content-between align-items-center mb-3">
<button class="btn-primary-custom" data-bs-toggle="modal" data-bs-target="#modalTambah">
<img src="{{ asset('images/icon/main/add.png') }}" width="18">
Tambah Data
</button>
<form method="GET">
<div class="search-box">
<input type="text" name="search" placeholder="Cari" value="{{ request('search') }}">
<button style="border:none;background:none">
<img src="{{ asset('images/icon/main/search.png') }}" width="18">
</button>
</div>
</form>
</div>
<form method="GET" class="mb-2">
<span>Tampilkan</span>
<select name="perPage" onchange="this.form.submit()" class="per-page-select">
<option value="10" {{ request('perPage') == 10 ? 'selected' : '' }}>10</option>
<option value="25" {{ request('perPage') == 25 ? 'selected' : '' }}>25</option>
<option value="50" {{ request('perPage') == 50 ? 'selected' : '' }}>50</option>
</select>
<span>data</span>
<span class="ms-3">Filter Kelas</span>
<select name="filter_kelas" onchange="this.form.submit()" class="filter-select">
<option value="">Semua Kelas</option>
@foreach($kelass as $kelas)
<option value="{{ $kelas->id_kelas }}"
{{ request('filter_kelas') == $kelas->id_kelas ? 'selected' : '' }}>
{{ $kelas->tingkat }} - {{ $kelas->nama_kelas }}
</option>
@endforeach
</select>
<input type="hidden" name="search" value="{{ request('search') }}">
</form>
{{-- Alert Success --}}
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
<table class="table text-center align-middle">
<thead class="table-header">
<tr>
<th>No</th>
<th>ID Mapel</th>
<th>Nama Mata Pelajaran</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@forelse($mapels as $index => $mapel)
<tr>
<td>{{ $mapels->firstItem() + $index }}</td>
<td>{{ $mapel->id_mapel }}</td>
<td>{{ $mapel->nama_mapel }}</td>
<td>
<button onclick="openEditModal(
'{{ $mapel->id_mapel }}',
'{{ $mapel->nama_mapel }}'
)" style="border:none;background:none">
<img src="{{ asset('images/icon/main/edit.png') }}" class="action-icon">
</button>
<form action="{{ route('admin.mapel.destroy', $mapel->id_mapel) }}"
method="POST" class="d-inline"
onsubmit="return confirm('Yakin ingin menghapus mata pelajaran {{ $mapel->nama_mapel }}?')">
@csrf
@method('DELETE')
<button type="submit" style="border:none;background:none">
<img src="{{ asset('images/icon/main/del.png') }}" class="action-icon">
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="4">Belum ada data mata pelajaran</td>
</tr>
@endforelse
</tbody>
</table>
<div class="d-flex justify-content-end">
{{ $mapels->links() }}
</div>
</div>
{{-- MODAL TAMBAH --}}
<div class="modal fade" id="modalTambah">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header modal-header-pastel">
<h5 class="modal-title w-100">Tambah Mata Pelajaran</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form action="{{ route('admin.mapel.store') }}" method="POST">
@csrf
<div class="modal-body">
<div class="mb-3">
<label>Nama Mata Pelajaran <span class="text-danger">*</span></label>
<input type="text" name="nama_mapel" class="form-control @error('nama_mapel') is-invalid @enderror"
value="{{ old('nama_mapel') }}" placeholder="Contoh: Pemrograman Web" required>
@error('nama_mapel')
<small class="text-danger">{{ $message }}</small>
@enderror
<small class="text-muted">ID Mapel akan dibuat otomatis (MP001, MP002, ...)</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button class="btn btn-success">Simpan Data</button>
</div>
</form>
</div>
</div>
</div>
{{-- MODAL EDIT --}}
<div class="modal fade" id="modalEdit">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header modal-header-pastel">
<h5 class="modal-title w-100">Edit Mata Pelajaran</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form id="formEdit" method="POST">
@csrf
@method('PUT')
<div class="modal-body">
<div class="mb-3">
<label>ID Mapel</label>
<input type="text" id="editIdMapel" class="form-control bg-light" disabled>
<small class="text-muted">ID Mapel tidak dapat diubah</small>
</div>
<div class="mb-3">
<label>Nama Mata Pelajaran <span class="text-danger">*</span></label>
<input type="text" id="editNamaMapel" name="nama_mapel" class="form-control" required>
@error('nama_mapel')
<small class="text-danger">{{ $message }}</small>
@enderror
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button class="btn btn-success">Update</button>
</div>
</form>
</div>
</div>
</div>
<script>
function openEditModal(idMapel, namaMapel) {
document.getElementById('editIdMapel').value = idMapel;
document.getElementById('editNamaMapel').value = namaMapel;
document.getElementById('formEdit').action = "{{ url('admin/mapel') }}/" + idMapel;
new bootstrap.Modal(document.getElementById('modalEdit')).show();
}
</script>
@if ($errors->any())
<script>
document.addEventListener("DOMContentLoaded", function() {
@if(session('error_from') == 'edit')
var modal = new bootstrap.Modal(document.getElementById('modalEdit'));
@else
var modal = new bootstrap.Modal(document.getElementById('modalTambah'));
@endif
modal.show();
});
</script>
@endif
@endsection

View File

@ -9,11 +9,12 @@
use App\Http\Controllers\Admin\GuruController;
use App\Http\Controllers\Admin\KelasController;
use App\Http\Controllers\Admin\SiswaController;
use App\Http\Controllers\Admin\MapelController;
// use App\Http\Controllers\GuruController;
// use App\Http\Controllers\SiswaController;
// use App\Http\Controllers\KelasController;
use App\Http\Controllers\MapelController;
// use App\Http\Controllers\MapelController;
use App\Http\Controllers\ChallengeController;
use App\Http\Controllers\LeaderboardController;