This commit is contained in:
RetasyaSalsabila 2026-04-09 21:12:24 +07:00
parent be6db46930
commit 3dfee40774
73 changed files with 941 additions and 325 deletions

View File

@ -16,12 +16,10 @@ public function index()
{
$guru = Auth::guard('guru')->user();
// 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
->groupBy('id_mapel');
return view('guru.mapel.index', compact('mengajars'));
}
@ -43,16 +41,15 @@ public function storeMateri(Request $request)
'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');
$file = $request->file('lampiran_materi');
$filename = 'materi_' . $guru->id_guru . '_' . time() . '.' . $file->getClientOriginalExtension();
$path = $file->storeAs('materi', $filename, 'public');
$path = $file->storeAs('materi', $filename, 'public');
}
Materi::create([
@ -74,24 +71,33 @@ 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',
'id_mengajar' => 'required|exists:mengajars,id_mengajar',
'judul_tugas' => 'required|string|max:200',
'keterangan' => 'nullable|string',
'deadline' => 'required|date|after:now',
'lampiran_tugas' => 'nullable|file|max:10240', // semua tipe file, maks 10MB
], [
'deadline.after' => 'Deadline harus lebih dari waktu sekarang.',
'deadline.after' => 'Deadline harus lebih dari waktu sekarang.',
'lampiran_tugas.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_tugas')) {
$file = $request->file('lampiran_tugas');
$filename = 'tugas_' . $guru->id_guru . '_' . time() . '.' . $file->getClientOriginalExtension();
$path = $file->storeAs('tugas', $filename, 'public');
}
Tugas::create([
'id_mengajar' => $request->id_mengajar,
'judul_tugas' => $request->judul_tugas,
'keterangan' => $request->keterangan,
'deadline' => $request->deadline,
'lampiran' => $path,
]);
return redirect()->route('guru.mapel.index')
@ -105,7 +111,6 @@ public function historyMateri()
{
$guru = Auth::guard('guru')->user();
// Ambil id_mengajar milik guru ini
$idMengajars = Mengajar::where('id_guru', $guru->id_guru)
->pluck('id_mengajar');
@ -130,7 +135,6 @@ public function destroyMateri($id)
->where('id_materi', $id)
->firstOrFail();
// Hapus file jika ada
if ($materi->lampiran_materi && \Storage::disk('public')->exists($materi->lampiran_materi)) {
\Storage::disk('public')->delete($materi->lampiran_materi);
}
@ -193,6 +197,11 @@ public function destroyTugas($id)
->where('id_tugas', $id)
->firstOrFail();
// Hapus file lampiran jika ada
if ($tugas->lampiran && \Storage::disk('public')->exists($tugas->lampiran)) {
\Storage::disk('public')->delete($tugas->lampiran);
}
$tugas->delete();
return redirect()->route('guru.tugas.history')

View File

@ -17,6 +17,7 @@ class Tugas extends Model
'judul_tugas',
'keterangan',
'deadline',
'lampiran',
];
protected $casts = [

View File

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('tugas', function (Blueprint $table) {
$table->string('lampiran')->nullable()->after('deadline');
});
}
public function down(): void
{
Schema::table('tugas', function (Blueprint $table) {
$table->dropColumn('lampiran');
});
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,203 @@
@extends('guru.layouts.app')
@section('title', 'History Materi')
@push('styles')
<style>
.page-title {
font-size: 28px;
font-weight: 800;
margin-bottom: 6px;
margin-top: -20px;
}
.back-link {
display: inline-flex;
align-items: center;
gap: 8px;
color: #2b8ef3;
font-weight: 600;
font-size: 14px;
text-decoration: none;
margin-bottom: 20px;
}
.back-link:hover { text-decoration: underline; }
.custom-card {
background: white;
border-radius: 20px;
border: 2px solid #e5e5e5;
padding: 25px;
}
.table-header { background: #a5e6ba; }
.mapel-badge {
display: inline-block;
background: #e6f0ff;
color: #1d4ed8;
font-size: 12px;
font-weight: 600;
padding: 3px 10px;
border-radius: 99px;
}
.kelas-badge {
display: inline-block;
background: #f0fdf4;
color: #166534;
font-size: 12px;
font-weight: 600;
padding: 3px 10px;
border-radius: 99px;
}
.file-icon { font-size: 20px; }
.btn-hapus {
background: #fee2e2;
color: #ef4444;
border: none;
border-radius: 8px;
padding: 5px 12px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
}
.btn-hapus:hover { background: #fca5a5; }
.btn-unduh {
background: #e6f0ff;
color: #2b8ef3;
border: none;
border-radius: 8px;
padding: 5px 12px;
font-size: 13px;
font-weight: 600;
text-decoration: none;
transition: background 0.2s;
display: inline-block;
}
.btn-unduh:hover { background: #bfdbfe; color: #1d4ed8; }
.alert-success-custom {
background: #dcfce7;
color: #166534;
border-radius: 10px;
padding: 12px 16px;
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
}
.empty-state {
text-align: center;
padding: 50px 20px;
color: #94a3b8;
}
</style>
@endpush
@section('content')
<a href="{{ route('guru.mapel.index') }}" class="back-link"> Kembali ke Mata Pelajaran</a>
<h3 class="page-title"><img src="{{ asset('images/icon/gurud/file.png') }}" class="topbar-waving" alt="Waving">History Materi</h3>
<p style="color:#64748b;font-size:14px;margin-bottom:20px">
Semua materi yang pernah Anda upload.
</p>
@if(session('success'))
<div class="alert-success-custom"><img src="{{ asset('images/icon/gurud/v.png') }}" class="topbar-waving" alt="Waving">{{ session('success') }}</div>
@endif
<div class="custom-card">
@if($materiList->isEmpty())
<div class="empty-state">
<div style="font-size:48px;margin-bottom:12px">📭</div>
<p>Belum ada materi yang diupload.</p>
</div>
@else
<table class="table align-middle">
<thead class="table-header text-center">
<tr>
<th>No</th>
<th>Judul Materi</th>
<th>Mata Pelajaran</th>
<th>Kelas</th>
<th>Tanggal Upload</th>
<th>File</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($materiList as $i => $materi)
<tr>
<td class="text-center">{{ $materiList->firstItem() + $i }}</td>
<td>
<div style="font-weight:600;color:#1e293b">{{ $materi->judul_materi }}</div>
@if($materi->deskripsi)
<div style="font-size:12px;color:#94a3b8;margin-top:2px">
{{ Str::limit($materi->deskripsi, 60) }}
</div>
@endif
</td>
<td class="text-center">
<span class="mapel-badge">
{{ optional(optional($materi->mengajar)->mapel)->nama_mapel ?? '-' }}
</span>
</td>
<td class="text-center">
<span class="kelas-badge">
{{ optional(optional($materi->mengajar)->kelas)->tingkat }}
{{ optional(optional($materi->mengajar)->kelas)->nama_kelas ?? '-' }}
</span>
</td>
<td class="text-center" style="font-size:13px;color:#64748b">
{{ \Carbon\Carbon::parse($materi->tanggal_upload)->format('d M Y, H:i') }}
</td>
<td class="text-center">
@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
<a href="{{ asset('storage/' . $materi->lampiran_materi) }}"
target="_blank" class="btn-unduh">
{{ $icon }} Unduh
</a>
@else
<span style="font-size:12px;color:#94a3b8">Tidak ada file</span>
@endif
</td>
<td class="text-center">
<form action="{{ route('guru.materi.destroy', $materi->id_materi) }}"
method="POST"
onsubmit="return confirm('Yakin hapus materi ini?')">
@csrf
@method('DELETE')
<button type="submit" class="btn-hapus">🗑️ Hapus</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="d-flex justify-content-end mt-3">
{{ $materiList->links() }}
</div>
@endif
</div>
@endsection

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 939 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -54,12 +54,22 @@
.action-icon { width: 20px; cursor: pointer; margin: 0 4px; }
/* Icon kecil inline (di dalam teks / badge / label) */
.inline-icon {
width: 16px;
height: 16px;
vertical-align: middle;
display: inline-block;
}
.deadline-badge {
font-size: 11px;
font-weight: 700;
padding: 3px 8px;
border-radius: 99px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.deadline-aktif { background: #dcfce7; color: #16a34a; }
@ -93,6 +103,9 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
/* ── MODAL SHARED ─────────────────────────────────── */
@ -110,7 +123,13 @@
border-radius: 16px 16px 0 0;
padding: 18px 24px;
}
.modal-header-yellow .modal-title { font-weight: 800; font-size: 18px; }
.modal-header-yellow .modal-title {
font-weight: 800;
font-size: 18px;
display: flex;
align-items: center;
gap: 8px;
}
.modal-header-yellow .btn-close { filter: none; }
/* Header ungu (Edit — tetap seperti semula) */
@ -344,6 +363,9 @@
.soal-scroll-area::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
.section-divider {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
font-weight: 700;
color: #667eea;
@ -374,20 +396,23 @@
<h3 class="page-title">DAFTAR CHALLENGE</h3>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="inline-icon" alt="Berhasil">
{{ session('success') }}
</div>
@endif
<div class="custom-card">
<div class="d-flex justify-content-between align-items-center mb-3">
<button class="btn-primary-custom" onclick="openTambahModal()">
<img src="{{ asset('images/icon/main/add.png') }}" width="18" alt="Tambah"> Tambah Challenge
<img src="{{ asset('images/icon/main/add.png') }}" class="inline-icon" alt="Tambah Challenge"> Tambah Challenge
</button>
<form method="GET">
<div class="search-box">
<input type="text" name="search" placeholder="Cari challenge..."
value="{{ request('search') }}">
<button style="border:none;background:none" type="submit">
<img src="{{ asset('images/icon/main/search.png') }}" width="18" alt="Cari">
<img src="{{ asset('images/icon/main/search.png') }}" class="inline-icon" alt="Cari">
</button>
</div>
</form>
@ -425,7 +450,11 @@
<td style="font-weight:700;color:#667eea">{{ $ch->exp }} EXP</td>
<td>
<span class="deadline-badge {{ $isLewat ? 'deadline-lewat' : 'deadline-aktif' }}">
{{ $isLewat ? '⏰ Lewat' : '✅ Aktif' }}
@if($isLewat)
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="inline-icon" alt="Lewat"> Lewat
@else
<img src="{{ asset('images/icon/gurud/v.png') }}" class="inline-icon" alt="Aktif"> Aktif
@endif
</span>
<div style="font-size:11px;color:#64748b;margin-top:3px">
{{ \Carbon\Carbon::parse($ch->tenggat_waktu)->format('d M Y, H:i') }}
@ -434,18 +463,18 @@
<td>
<button onclick="openEditModal({{ $ch->id_challenge }})"
style="border:none;background:none">
<img src="{{ asset('images/icon/main/edit.png') }}" class="action-icon" alt="Edit">
<img src="{{ asset('images/icon/main/edit.png') }}" class="action-icon" alt="Edit Challenge">
</button>
<a href="{{ route('admin.challenge.show', $ch->id_challenge) }}"
style="border:none;background:none;display:inline">
<img src="{{ asset('images/icon/main/search.png') }}" class="action-icon" alt="Detail">
<img src="{{ asset('images/icon/main/search.png') }}" class="action-icon" alt="Lihat Detail">
</a>
<form action="{{ route('admin.challenge.destroy', $ch->id_challenge) }}"
method="POST" class="d-inline"
onsubmit="return confirm('Yakin hapus challenge ini?')">
@csrf @method('DELETE')
<button type="submit" style="border:none;background:none">
<img src="{{ asset('images/icon/main/del.png') }}" class="action-icon" alt="Hapus">
<img src="{{ asset('images/icon/main/del.png') }}" class="action-icon" alt="Hapus Challenge">
</button>
</form>
</td>
@ -471,7 +500,9 @@
{{-- Header kuning --}}
<div class="modal-header modal-header-yellow">
<h5 class="modal-title">🏆 Tambah Challenge Baru</h5>
<h5 class="modal-title">
<img src="{{ asset('images/icon/gurud/piala.png') }}" class="inline-icon" alt="Piala"> Tambah Challenge Baru
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
@ -493,7 +524,9 @@
{{-- ─── STEP 1: Info Challenge ─── --}}
<div class="step-panel active" id="tambah-step-1">
<div class="section-divider">📋 Informasi Challenge</div>
<div class="section-divider">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="inline-icon" alt="Informasi"> Informasi Challenge
</div>
<div class="row g-3 mb-2">
<div class="col-8">
<label>Judul Challenge <span class="text-danger">*</span></label>
@ -529,7 +562,9 @@
</div>
</div>
<div class="section-divider">🏫 Target Kelas</div>
<div class="section-divider">
<img src="{{ asset('images/icon/gurud/school.png') }}" class="inline-icon" alt="Kelas"> Target Kelas
</div>
<div class="kelas-checkbox-grid mb-1">
@foreach($kelas as $k)
<label class="kelas-check-item">
@ -544,7 +579,9 @@
{{-- ─── STEP 2: Soal ─── --}}
<div class="step-panel" id="tambah-step-2">
<div class="section-divider" style="flex-shrink:0">📝 Daftar Soal</div>
<div class="section-divider" style="flex-shrink:0">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="inline-icon" alt="Soal"> Daftar Soal
</div>
<div id="soalContainer" class="soal-scroll-area"></div>
<div style="flex-shrink:0;padding-top:8px">
<button type="button" class="btn-tambah-soal" onclick="tambahSoal('soalContainer')">
@ -569,7 +606,7 @@
{{-- Submit (step 2, hidden awalnya) --}}
<button type="submit" class="btn-green" id="tambah-btn-submit" style="display:none">
💾 Simpan Challenge
<img src="{{ asset('images/icon/gurud/save.png') }}" class="inline-icon" alt="Simpan"> Simpan Challenge
</button>
</div>
@ -586,7 +623,9 @@
<div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-fixed">
<div class="modal-content">
<div class="modal-header modal-header-yellow">
<h5 class="modal-title">✏️ Edit Challenge</h5>
<h5 class="modal-title">
<img src="{{ asset('images/icon/gurud/pencil.png') }}" class="inline-icon" alt="Edit"> Edit Challenge
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
@ -608,7 +647,9 @@
{{-- ─── STEP 1: Info Challenge ─── --}}
<div class="step-panel active" id="edit-step-1">
<div class="section-divider">📋 Informasi Challenge</div>
<div class="section-divider">
<img src="{{ asset('images/icon/gurud/buku2.png') }}" class="inline-icon" alt="Informasi"> Informasi Challenge
</div>
<div class="row g-3 mb-2">
<div class="col-8">
<label>Judul Challenge <span class="text-danger">*</span></label>
@ -641,7 +682,9 @@
</div>
</div>
<div class="section-divider">🏫 Target Kelas</div>
<div class="section-divider">
<img src="{{ asset('images/icon/gurud/school.png') }}" class="inline-icon" alt="Kelas"> Target Kelas
</div>
<div class="kelas-checkbox-grid mb-1" id="editKelasContainer">
@foreach($kelas as $k)
<label class="kelas-check-item">
@ -657,7 +700,9 @@
{{-- ─── STEP 2: Soal ─── --}}
<div class="step-panel" id="edit-step-2">
<div class="section-divider" style="flex-shrink:0">📝 Daftar Soal</div>
<div class="section-divider" style="flex-shrink:0">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="inline-icon" alt="Soal"> Daftar Soal
</div>
<div id="editSoalContainer" class="soal-scroll-area"></div>
<div style="flex-shrink:0;padding-top:8px">
<button type="button" class="btn-tambah-soal" onclick="tambahSoal('editSoalContainer')">
@ -677,7 +722,7 @@
Berikutnya
</button>
<button type="submit" class="btn-green" id="edit-btn-submit" style="display:none">
💾 Update Challenge
<img src="{{ asset('images/icon/gurud/save.png') }}" class="inline-icon" alt="Simpan"> Update Challenge
</button>
</div>
@ -868,7 +913,6 @@ function tambahSoal(containerId, data = null) {
`<option value="${o}" ${data && data.jawaban_benar === o ? 'selected' : ''}>${o}</option>`
).join('')}
</select>
{{-- Hidden nilainya diisi recalcExp() --}}
<input type="hidden" name="exp_per_soal[]" value="0">
<span style="margin-left:auto;background:#f0fdf4;color:#16a34a;font-size:12px;font-weight:700;
padding:4px 12px;border-radius:99px;white-space:nowrap">
@ -879,7 +923,7 @@ function tambahSoal(containerId, data = null) {
container.appendChild(card);
renumberSoal(containerId);
recalcExp(containerId); // update semua kartu setelah soal baru ditambah
recalcExp(containerId);
// Scroll ke soal baru
const scrollArea = container.closest('.soal-scroll-area') || container;
@ -894,7 +938,7 @@ function hapusSoal(btn, containerId) {
}
btn.closest('.soal-card').remove();
renumberSoal(containerId);
recalcExp(containerId); // update ulang setelah soal dihapus
recalcExp(containerId);
}
function renumberSoal(containerId) {
@ -908,18 +952,13 @@ function renumberSoal(containerId) {
OPEN MODAL TAMBAH
══════════════════════════════════════════════════ */
function openTambahModal() {
// Reset state
soalCountTambah = 0;
document.getElementById('soalContainer').innerHTML = '';
document.getElementById('formTambah').reset();
// Paksa step 1
tambahGoStep1();
// Default 1 soal
tambahSoal('soalContainer');
// Recalc EXP otomatis setiap kali angka EXP di step-1 berubah
const expElTambah = document.getElementById('tambah-exp');
expElTambah.oninput = () => recalcExp('soalContainer');
@ -933,7 +972,6 @@ function openTambahModal() {
soalCountEdit = 0;
document.getElementById('editSoalContainer').innerHTML = '';
// Reset ke step 1
editGoStep1();
const res = await fetch(`/admin/challenge/${idChallenge}/edit-data`);
@ -959,7 +997,6 @@ function openTambahModal() {
const expElEdit = document.getElementById('editExp');
expElEdit.oninput = () => recalcExp('editSoalContainer');
// Recalc sekali saat modal dibuka
recalcExp('editSoalContainer');
new bootstrap.Modal(document.getElementById('modalEdit')).show();

View File

@ -26,7 +26,15 @@
border-left: 5px solid #667eea;
}
.info-title { font-size: 22px; font-weight: 800; color: #1e293b; margin: 0 0 12px; }
.info-title {
font-size: 22px;
font-weight: 800;
color: #1e293b;
margin: 0 0 12px;
display: flex;
align-items: center;
gap: 8px;
}
.meta-chip {
display: inline-flex;
@ -43,6 +51,14 @@
.meta-chip.green { background: #dcfce7; color: #16a34a; }
.meta-chip.red { background: #fee2e2; color: #dc2626; }
/* Icon kecil inline (di dalam teks / badge / label) */
.inline-icon {
width: 16px;
height: 16px;
vertical-align: middle;
display: inline-block;
}
.kelas-chip {
display: inline-block;
background: #e6f0ff;
@ -127,7 +143,9 @@
padding: 3px 10px;
border-radius: 99px;
margin-top: 10px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.custom-card {
@ -138,7 +156,15 @@
margin-bottom: 20px;
}
.section-title { font-size: 16px; font-weight: 700; color: #1e293b; margin-bottom: 14px; }
.section-title {
font-size: 16px;
font-weight: 700;
color: #1e293b;
margin-bottom: 14px;
display: flex;
align-items: center;
gap: 6px;
}
</style>
<a href="{{ route('admin.challenge.index') }}" class="back-link"> Kembali ke Daftar Challenge</a>
@ -149,15 +175,25 @@
{{-- INFO --}}
<div class="info-card">
<h2 class="info-title">🏆 {{ $challenge->judul_challenge }}</h2>
<h2 class="info-title">
<img src="{{ asset('images/icon/gurud/piala.png') }}" class="inline-icon" alt="Piala">
{{ $challenge->judul_challenge }}
</h2>
<div class="d-flex flex-wrap gap-2 mb-3">
<span class="meta-chip purple"> {{ $challenge->exp }} EXP</span>
<span class="meta-chip purple">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="inline-icon" alt="EXP">
{{ $challenge->exp }} EXP
</span>
<span class="meta-chip {{ $isLewat ? 'red' : 'green' }}">
{{ \Carbon\Carbon::parse($challenge->tenggat_waktu)->format('d M Y, H:i') }}
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="inline-icon" alt="Tenggat">
{{ \Carbon\Carbon::parse($challenge->tenggat_waktu)->format('d M Y, H:i') }}
{{ $isLewat ? 'Sudah lewat' : 'Masih aktif' }}
</span>
<span class="meta-chip">📝 {{ $challenge->soal->count() }} soal</span>
<span class="meta-chip">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="inline-icon" alt="Soal">
{{ $challenge->soal->count() }} soal
</span>
</div>
<div class="mb-2">
@ -175,7 +211,10 @@
{{-- DAFTAR SOAL --}}
<div class="custom-card">
<p class="section-title">📝 Daftar Soal Challenge</p>
<p class="section-title">
<img src="{{ asset('images/icon/gurud/buku2.png') }}" class="inline-icon" alt="Daftar Soal">
Daftar Soal Challenge
</p>
@forelse($challenge->soal as $i => $soal)
<div class="soal-card">
@ -189,13 +228,18 @@
<span class="opsi-label">{{ $opsi }}</span>
<span>{{ $soal->$key }}</span>
@if($soal->jawaban_benar === $opsi)
<span style="margin-left:auto;font-size:16px"></span>
<span style="margin-left:auto;display:inline-flex;align-items:center">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="inline-icon" alt="Jawaban Benar">
</span>
@endif
</div>
@endforeach
</div>
<span class="exp-badge"> {{ $soal->exp_per_soal }} EXP per soal</span>
<span class="exp-badge">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="inline-icon" alt="EXP">
{{ $soal->exp_per_soal }} EXP per soal
</span>
</div>
@empty
<p class="text-muted text-center py-3">Belum ada soal.</p>

View File

@ -15,6 +15,8 @@
position: relative; overflow: hidden;
transition: transform 0.2s ease, box-shadow 0.2s ease;
animation: fadeUp 0.4s ease both;
text-decoration: none;
display: block;
}
.stat-card:hover { transform: translateY(-4px); box-shadow: 0 16px 40px rgba(0,0,0,0.12); }
.stat-card:nth-child(1) { background: linear-gradient(135deg, #fff7e6, #ffe4b2); animation-delay: 0s; }
@ -26,12 +28,27 @@
.stat-card:nth-child(2)::after { background: #22c55e; }
.stat-card:nth-child(3)::after { background: #2b8ef3; }
.stat-card:nth-child(4)::after { background: #ec4899; }
.stat-label { font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; margin-bottom: 10px; }
.stat-card:nth-child(1) .stat-label { color: #c2651a; }
.stat-card:nth-child(2) .stat-label { color: #15803d; }
.stat-card:nth-child(3) .stat-label { color: #1d5fb8; }
.stat-card:nth-child(4) .stat-label { color: #be185d; }
.stat-num { font-size: 42px; font-weight: 800; line-height: 1; color: #0f1f3d; }
.stat-num { font-size: 42px; font-weight: 800; line-height: 1; color: #0f1f3d; margin-bottom: 12px; }
.stat-link {
font-size: 11px; font-weight: 700;
display: inline-flex; align-items: center; gap: 4px;
opacity: 0.6;
transition: opacity 0.2s;
}
.stat-card:hover .stat-link { opacity: 1; }
.stat-card:nth-child(1) .stat-link { color: #c2651a; }
.stat-card:nth-child(2) .stat-link { color: #15803d; }
.stat-card:nth-child(3) .stat-link { color: #1d5fb8; }
.stat-card:nth-child(4) .stat-link { color: #be185d; }
.stat-icon { position: absolute; top: 20px; right: 20px; width: 42px; height: 42px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 20px; opacity: 0.7; }
.stat-card:nth-child(1) .stat-icon { background: rgba(249,115,22,0.15); }
.stat-card:nth-child(2) .stat-icon { background: rgba(34,197,94,0.15); }
@ -47,10 +64,8 @@
.card-badge { font-size: 11px; font-weight: 700; background: #e8f4ff; color: #2b8ef3; padding: 3px 10px; border-radius: 99px; text-decoration: none; }
.card-badge:hover { background: #dbeeff; }
/* Chart — tinggi responsif */
.chart-wrap { position: relative; height: 220px; }
/* Challenge */
.challenge-item { background: #f8faff; border-radius: 14px; padding: 14px 16px; margin-bottom: 10px; border-left: 4px solid #2b8ef3; transition: all 0.2s; }
.challenge-item:nth-child(2) { border-left-color: #22c55e; }
.challenge-item:nth-child(3) { border-left-color: #f97316; }
@ -78,9 +93,7 @@
@section('content')
@php
use Carbon\Carbon;
@endphp
@php use Carbon\Carbon; @endphp
<div class="dash-header">
<div class="dash-sub">{{ Carbon::now()->isoFormat('dddd, D MMMM Y') }}</div>
@ -88,32 +101,35 @@
{{-- STAT CARDS --}}
<div class="stat-grid">
<div class="stat-card">
<div class="stat-icon">👨‍🏫</div>
<a href="{{ route('admin.guru.index') }}" class="stat-card">
<div class="stat-icon"><img src="{{ asset('images/icon/gurud/guru.png') }}" class="topbar-waving" alt="Waving"></div>
<div class="stat-label">Total Guru</div>
<div class="stat-num">{{ $totalGuru }}</div>
</div>
<div class="stat-card">
<div class="stat-icon">🏫</div>
<div class="stat-link">Lihat Data </div>
</a>
<a href="{{ route('admin.kelas.index') }}" class="stat-card">
<div class="stat-icon"><img src="{{ asset('images/icon/gurud/school.png') }}" class="topbar-waving" alt="Waving"></div>
<div class="stat-label">Total Kelas</div>
<div class="stat-num">{{ $totalKelas }}</div>
</div>
<div class="stat-card">
<div class="stat-icon">👨‍🎓</div>
<div class="stat-link">Lihat Data </div>
</a>
<a href="{{ route('admin.siswa.index') }}" class="stat-card">
<div class="stat-icon"><img src="{{ asset('images/icon/gurud/siswa.png') }}" class="topbar-waving" alt="Waving"></div>
<div class="stat-label">Total Siswa</div>
<div class="stat-num">{{ $totalSiswa }}</div>
</div>
<div class="stat-card">
<div class="stat-icon">📚</div>
<div class="stat-link">Lihat Data </div>
</a>
<a href="{{ route('admin.mapel.index') }}" class="stat-card">
<div class="stat-icon"><img src="{{ asset('images/icon/gurud/stacked.png') }}" class="topbar-waving" alt="Waving"></div>
<div class="stat-label">Total Mapel</div>
<div class="stat-num">{{ $totalMapel }}</div>
</div>
<div class="stat-link">Lihat Data </div>
</a>
</div>
{{-- BOTTOM --}}
<div class="dash-bottom">
{{-- Bar Chart --}}
<div class="dash-card">
<div class="card-head">
<div class="card-title">Total Siswa Berdasarkan Kelas</div>
@ -124,7 +140,6 @@
</div>
</div>
{{-- Challenge Terbaru --}}
<div class="dash-card">
<div class="card-head">
<div class="card-title">Challenge Terbaru</div>
@ -164,21 +179,16 @@
<script>
const labels = @json($chartData->pluck('nama_kelas'));
const values = @json($chartData->pluck('siswa_count'));
const colors = [
'rgba(43,142,243,0.85)',
'rgba(34,197,94,0.85)',
'rgba(249,115,22,0.85)',
'rgba(168,85,247,0.85)',
'rgba(236,72,153,0.85)',
'rgba(234,179,8,0.85)',
'rgba(43,142,243,0.85)', 'rgba(34,197,94,0.85)', 'rgba(249,115,22,0.85)',
'rgba(168,85,247,0.85)', 'rgba(236,72,153,0.85)', 'rgba(234,179,8,0.85)',
];
const ctx = document.getElementById('kelasChart').getContext('2d');
const kelasChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
labels,
datasets: [{
label: 'Jumlah Siswa',
data: values,
@ -192,25 +202,15 @@
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: { label: ctx => ` ${ctx.parsed.y} siswa` }
}
tooltip: { callbacks: { label: ctx => ` ${ctx.parsed.y} siswa` } }
},
scales: {
y: {
beginAtZero: true,
grid: { color: '#f1f5f9' },
ticks: { font: { family: 'Poppins', size: 11 }, color: '#94a3b8', stepSize: 1 }
},
x: {
grid: { display: false },
ticks: { font: { family: 'Poppins', size: 11 }, color: '#64748b' }
}
y: { beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { font: { family: 'Poppins', size: 11 }, color: '#94a3b8', stepSize: 1 } },
x: { grid: { display: false }, ticks: { font: { family: 'Poppins', size: 11 }, color: '#64748b' } }
}
}
});
// Fix resize saat sidebar toggle
document.getElementById('sidebarToggleBtn')?.addEventListener('click', () => {
setTimeout(() => kelasChart.resize(), 320);
});

View File

@ -51,7 +51,14 @@
width: 150px;
}
.action-icon { width: 20px; cursor: pointer; margin: 0 5px; }
.action-icon {
width: 20px;
height: 20px;
cursor: pointer;
margin: 0 5px;
display: inline-block;
vertical-align: middle;
}
.per-page-select {
border-radius: 10px;
@ -140,13 +147,19 @@
padding: 12px 16px;
margin-bottom: 16px;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
}
</style>
<h3 class="page-title">DAFTAR GURU</h3>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" width="18" height="18" alt="Berhasil">
{{ session('success') }}
</div>
@endif
<div class="custom-card">
@ -154,15 +167,15 @@
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="d-flex gap-2">
<button class="btn-primary-custom" data-bs-toggle="modal" data-bs-target="#modalTambah">
<img src="{{ asset('images/icon/main/add.png') }}" width="18">
<img src="{{ asset('images/icon/main/add.png') }}" width="18" height="18" alt="Tambah">
Tambah Data
</button>
<button class="btn-primary-custom">
<img src="{{ asset('images/icon/main/download.png') }}" width="18">
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download">
Download PDF
</button>
<button class="btn-primary-custom">
<img src="{{ asset('images/icon/main/download.png') }}" width="18">
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download">
Download Excel
</button>
</div>
@ -171,7 +184,7 @@
<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">
<img src="{{ asset('images/icon/main/search.png') }}" width="18" height="18" alt="Cari">
</button>
</div>
</form>
@ -234,7 +247,7 @@
'{{ addslashes($guru->nama) }}',
{{ $guru->mengajars->map(fn($m) => ['id_mapel' => $m->id_mapel, 'id_kelas' => $m->id_kelas])->toJson() }}
)" style="border:none;background:none">
<img src="{{ asset('images/icon/main/edit.png') }}" class="action-icon">
<img src="{{ asset('images/icon/main/edit.png') }}" class="action-icon" alt="Edit guru">
</button>
{{-- TOMBOL HAPUS --}}
@ -244,7 +257,7 @@
@csrf
@method('DELETE')
<button type="submit" style="border:none;background:none">
<img src="{{ asset('images/icon/main/del.png') }}" class="action-icon">
<img src="{{ asset('images/icon/main/del.png') }}" class="action-icon" alt="Hapus guru">
</button>
</form>
</td>
@ -422,13 +435,11 @@
<script>
const KELAS_BY_MAPEL_URL = "{{ route('admin.guru.kelasByMapel') }}";
// ===== SAAT MAPEL DIPILIH → fetch kelas otomatis =====
async function onMapelChange(selectMapel) {
const idMapel = selectMapel.value;
const row = selectMapel.closest('.mengajar-row');
const selectKelas = row.querySelector('.select-kelas');
// Reset kelas
selectKelas.innerHTML = '<option value="">-- Memuat kelas... --</option>';
selectKelas.disabled = true;
@ -454,7 +465,6 @@
selectKelas.appendChild(opt);
});
// Jika hanya 1 kelas, langsung pilih otomatis
if (data.length === 1) {
selectKelas.value = data[0].id_kelas;
}
@ -466,7 +476,6 @@
}
}
// ===== TAMBAH BARIS BARU =====
async function tambahRow(containerId, selectedMapel = null, selectedKelas = null) {
const template = document.getElementById('rowTemplate');
const clone = template.content.cloneNode(true);
@ -482,7 +491,6 @@
if (selectedMapel) {
selectMapel.value = selectedMapel;
// Fetch kelas untuk mapel yang sudah dipilih
try {
const res = await fetch(`${KELAS_BY_MAPEL_URL}?id_mapel=${selectedMapel}`);
const data = await res.json();
@ -504,7 +512,6 @@
}
}
// ===== HAPUS BARIS =====
function hapusRow(btn) {
const container = btn.closest('[id$="Rows"]');
const rows = container.querySelectorAll('.mengajar-row');
@ -515,7 +522,6 @@ function hapusRow(btn) {
btn.closest('.mengajar-row').remove();
}
// ===== BUKA MODAL EDIT =====
async function openEditModal(idGuru, nip, nama, mengajars) {
document.getElementById('formEdit').action = "{{ url('admin/guru') }}/" + idGuru;
document.getElementById('editNip').value = nip;

View File

@ -14,7 +14,7 @@
body { font-family: 'Poppins', sans-serif; background-color: #f5f9ff; margin: 0; height: 100vh; overflow: hidden; }
.admin-wrapper { display: flex; height: 100vh; overflow: hidden; }
/* ── SIDEBAR (scrollable internally for admin) ── */
/* ── SIDEBAR ── */
.sidebar {
width: 260px; flex-shrink: 0;
background: #ffffff;
@ -27,12 +27,12 @@
}
.sidebar.collapsed { width: 0; padding: 0; border-right: none; }
.sidebar-logo { text-align: center; margin-bottom: 36px; white-space: nowrap; flex-shrink: 0; }
.sidebar-logo img { width: 90px; }
.sidebar-logo img { width: 90px; height: auto; }
.sidebar-menu { display: flex; flex-direction: column; white-space: nowrap; }
.sidebar-link { display: flex; align-items: center; gap: 12px; padding: 11px 18px; margin-bottom: 4px; border-radius: 12px; color: #64748b; text-decoration: none; font-weight: 500; font-size: 14px; transition: all 0.2s ease; }
.sidebar-link:hover { background: #e6f0ff; color: #1d4ed8; }
.sidebar-link.active { background: #e6f0ff; color: #1d4ed8; }
.sidebar-icon { width: 20px; height: 20px; flex-shrink: 0; }
.sidebar-icon { width: 20px; height: 20px; flex-shrink: 0; object-fit: contain; }
.sidebar-section { font-size: 10px; font-weight: 700; color: #94a3b8; letter-spacing: 1px; text-transform: uppercase; padding: 4px 18px; margin: 8px 0 4px; white-space: nowrap; }
.sidebar-logout { margin-top: auto; padding-top: 16px; border-top: 1px solid #f1f5f9; flex-shrink: 0; }
.sidebar-logout button { width: 100%; border: none; background: transparent; color: #ef4444; font-weight: 600; font-size: 14px; padding: 10px 18px; text-align: left; border-radius: 12px; cursor: pointer; display: flex; align-items: center; gap: 12px; transition: background 0.2s; }
@ -45,13 +45,16 @@
.toggle-arrow { width: 12px; height: 12px; fill: none; stroke: white; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.3s ease; }
.sidebar-toggle-btn.collapsed .toggle-arrow { transform: rotate(180deg); }
/* ── MAIN (scrollable) ── */
/* ── MAIN ── */
.main { flex: 1; display: flex; flex-direction: column; min-width: 0; height: 100vh; overflow: hidden; }
.topbar { background: #2b8ef3; margin: 20px 20px 0; padding: 16px 24px; border-radius: 16px; color: white; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 8px 24px rgba(43,142,243,0.25); flex-shrink: 0; }
.topbar-left { font-weight: 600; font-size: 16px; display: flex; align-items: center; gap: 10px; }
.topbar-right { display: flex; align-items: center; gap: 14px; }
/* ── WAVING HAND — ukuran seragam di semua halaman ── */
.topbar-waving { width: 24px; height: 24px; object-fit: contain; vertical-align: middle; flex-shrink: 0; }
.content { padding: 20px 28px 28px; flex: 1; overflow-y: auto; }
/* ── NOTIF BELL ── */
@ -92,38 +95,19 @@
transition: all 0.2s cubic-bezier(0.34,1.56,0.64,1);
overflow: hidden;
}
.notif-dropdown.show { opacity: 1; pointer-events: all; transform: translateY(0) scale(1); }
.notif-dropdown.show {
opacity: 1; pointer-events: all;
transform: translateY(0) scale(1);
}
.notif-head {
padding: 16px 18px 12px;
border-bottom: 1px solid #f1f5f9;
display: flex; align-items: center; justify-content: space-between;
}
.notif-head { padding: 16px 18px 12px; border-bottom: 1px solid #f1f5f9; display: flex; align-items: center; justify-content: space-between; }
.notif-head-title { font-size: 14px; font-weight: 700; color: #0f1f3d; }
.notif-head-count { font-size: 11px; color: #94a3b8; }
.notif-list { max-height: 340px; overflow-y: auto; }
.notif-item {
display: flex; align-items: flex-start; gap: 12px;
padding: 13px 18px;
border-bottom: 1px solid #f8fafc;
transition: background 0.15s; cursor: default;
}
.notif-item { display: flex; align-items: flex-start; gap: 12px; padding: 13px 18px; border-bottom: 1px solid #f8fafc; transition: background 0.15s; cursor: default; }
.notif-item:hover { background: #f8faff; }
.notif-item:last-child { border-bottom: none; }
.notif-icon-wrap {
width: 36px; height: 36px; border-radius: 12px;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0; font-size: 16px;
}
.notif-icon-wrap { width: 36px; height: 36px; border-radius: 12px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 16px; }
.notif-icon-materi { background: #e8f4ff; }
.notif-icon-tugas { background: #fff7e6; }
.notif-icon-pengumpulan { background: #eefaf3; }
@ -135,11 +119,12 @@
.notif-time { font-size: 10px; color: #94a3b8; white-space: nowrap; margin-top: 2px; }
.notif-empty { padding: 32px 18px; text-align: center; }
.notif-empty-icon { font-size: 36px; margin-bottom: 8px; }
.notif-empty-icon { margin-bottom: 8px; }
.notif-empty-icon img { width: 36px; height: 36px; object-fit: contain; }
.notif-empty-text { font-size: 13px; color: #94a3b8; }
/* ── TOPBAR AVATAR ── */
.topbar-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; border: 2px solid rgba(255,255,255,0.5); cursor: pointer; transition: all 0.2s; display: block; }
.topbar-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; border: 2px solid rgba(255,255,255,0.5); cursor: pointer; transition: all 0.2s; display: block; flex-shrink: 0; }
.topbar-avatar:hover { border-color: white; transform: scale(1.05); }
.topbar-avatar-icon { width: 36px; height: 36px; border-radius: 50%; background: rgba(255,255,255,0.2); border: 2px solid rgba(255,255,255,0.4); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.2s; flex-shrink: 0; }
.topbar-avatar-icon:hover { background: rgba(255,255,255,0.35); }
@ -188,34 +173,43 @@
</div>
<nav class="sidebar-menu">
<a href="{{ route('admin.dashboard') }}" class="sidebar-link {{ request()->routeIs('admin.dashboard') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/home.png') }}" class="sidebar-icon" alt=""><span>Dashboard</span>
<img src="{{ asset('images/icon/sidebar/home.png') }}" class="sidebar-icon" alt="Dashboard">
<span>Dashboard</span>
</a>
<div class="sidebar-section">Data Master</div>
<a href="{{ route('admin.guru.index') }}" class="sidebar-link {{ request()->routeIs('admin.guru.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/guru.png') }}" class="sidebar-icon" alt=""><span>Daftar Guru</span>
<img src="{{ asset('images/icon/sidebar/guru.png') }}" class="sidebar-icon" alt="Daftar Guru">
<span>Daftar Guru</span>
</a>
<a href="{{ route('admin.kelas.index') }}" class="sidebar-link {{ request()->routeIs('admin.kelas.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/kelas.png') }}" class="sidebar-icon" alt=""><span>Daftar Kelas</span>
<img src="{{ asset('images/icon/sidebar/kelas.png') }}" class="sidebar-icon" alt="Daftar Kelas">
<span>Daftar Kelas</span>
</a>
<a href="{{ route('admin.siswa.index') }}" class="sidebar-link {{ request()->routeIs('admin.siswa.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/siswa.png') }}" class="sidebar-icon" alt=""><span>Daftar Siswa</span>
<img src="{{ asset('images/icon/sidebar/siswa.png') }}" class="sidebar-icon" alt="Daftar Siswa">
<span>Daftar Siswa</span>
</a>
<a href="{{ route('admin.mapel.index') }}" class="sidebar-link {{ request()->routeIs('admin.mapel.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/mapel.png') }}" class="sidebar-icon" alt=""><span>Mata Pelajaran</span>
<img src="{{ asset('images/icon/sidebar/mapel.png') }}" class="sidebar-icon" alt="Mata Pelajaran">
<span>Mata Pelajaran</span>
</a>
<div class="sidebar-section">Konten Guru</div>
<a href="{{ route('admin.materi.history') }}" class="sidebar-link {{ request()->routeIs('admin.materi.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/mapel.png') }}" class="sidebar-icon" alt=""><span>History Materi</span>
<img src="{{ asset('images/icon/sidebar/mapel.png') }}" class="sidebar-icon" alt="History Materi">
<span>History Materi</span>
</a>
<a href="{{ route('admin.tugas.history') }}" class="sidebar-link {{ request()->routeIs('admin.tugas.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/guru.png') }}" class="sidebar-icon" alt=""><span>History Tugas</span>
<img src="{{ asset('images/icon/sidebar/guru.png') }}" class="sidebar-icon" alt="History Tugas">
<span>History Tugas</span>
</a>
<div class="sidebar-section">Gamifikasi</div>
<a href="{{ route('admin.challenge.index') }}" class="sidebar-link {{ request()->routeIs('admin.challenge.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/challenge.png') }}" class="sidebar-icon" alt=""><span>Challenge</span>
<img src="{{ asset('images/icon/sidebar/challenge.png') }}" class="sidebar-icon" alt="Challenge">
<span>Challenge</span>
</a>
<a href="{{ route('admin.leaderboard.index') }}" class="sidebar-link {{ request()->routeIs('admin.leaderboard.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/lb.png') }}" class="sidebar-icon" alt=""><span>Leaderboard</span>
<img src="{{ asset('images/icon/sidebar/lb.png') }}" class="sidebar-icon" alt="Leaderboard">
<span>Leaderboard</span>
</a>
</nav>
<form action="{{ route('admin.logout') }}" method="POST" class="sidebar-logout">
@ -234,13 +228,14 @@
<div class="main">
<header class="topbar">
<div class="topbar-left">
👋 Hai, <span id="topbar-username">{{ Auth::guard('admin')->user()->username ?? 'Admin' }}</span>
<img src="{{ asset('images/icon/gurud/wavinghand.png') }}" class="topbar-waving" alt="Waving hand">
Hai, <span id="topbar-username">{{ Auth::guard('admin')->user()->username ?? 'Admin' }}</span>
</div>
<div class="topbar-right">
{{-- NOTIF BELL --}}
<div class="notif-wrap" id="notifWrap">
<button class="notif-btn" id="notifBtn" onclick="toggleNotif(event)">
<button class="notif-btn" id="notifBtn" onclick="toggleNotif(event)" aria-label="Notifikasi">
<svg viewBox="0 0 24 24"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
</button>
<div class="notif-badge" id="notifBadge"></div>
@ -251,7 +246,9 @@
</div>
<div class="notif-list" id="notifList">
<div class="notif-empty">
<div class="notif-empty-icon">🔔</div>
<div class="notif-empty-icon">
<img src="{{ asset('images/icon/gurud/bell.png') }}" class="topbar-waving" alt="Notifikasi kosong">
</div>
<div class="notif-empty-text">Memuat notifikasi...</div>
</div>
</div>
@ -260,9 +257,13 @@
@php $admin = Auth::guard('admin')->user(); @endphp
@if($admin->foto_profil)
<img src="{{ Storage::url($admin->foto_profil) }}" class="topbar-avatar" id="topbar-foto" onclick="openProfileModal()" alt="Profil">
<img src="{{ Storage::url($admin->foto_profil) }}"
class="topbar-avatar"
id="topbar-foto"
onclick="openProfileModal()"
alt="Foto profil {{ $admin->username }}">
@else
<div class="topbar-avatar-icon" id="topbar-foto-icon" onclick="openProfileModal()">
<div class="topbar-avatar-icon" id="topbar-foto-icon" onclick="openProfileModal()" role="button" aria-label="Edit profil">
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>
</div>
@endif
@ -278,7 +279,7 @@
{{-- PROFILE MODAL --}}
<div class="profile-modal-overlay" id="profileModalOverlay" onclick="closeOnOverlay(event)">
<div class="profile-modal">
<button class="modal-close" onclick="closeProfileModal()">
<button class="modal-close" onclick="closeProfileModal()" aria-label="Tutup modal">
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
<div class="modal-title">Edit Profil</div>
@ -289,10 +290,10 @@
<div class="foto-upload-area">
<div class="foto-circle">
@if($admin->foto_profil)
<img src="{{ Storage::url($admin->foto_profil) }}" id="modal-foto-preview" alt="">
<img src="{{ Storage::url($admin->foto_profil) }}" id="modal-foto-preview" alt="Foto profil saat ini">
@else
<svg id="modal-foto-icon" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>
<img src="" id="modal-foto-preview" alt="" style="display:none">
<img src="" id="modal-foto-preview" alt="Preview foto profil" style="display:none">
@endif
</div>
<div class="foto-info">
@ -429,7 +430,7 @@ function closeOnOverlay(e) { if (e.target === document.getElementById('profileMo
if (data.foto_url) {
const tf = document.getElementById('topbar-foto'); const ti = document.getElementById('topbar-foto-icon');
if (tf) { tf.src = data.foto_url + '?t=' + Date.now(); }
else if (ti) { const img = document.createElement('img'); img.src = data.foto_url + '?t=' + Date.now(); img.className = 'topbar-avatar'; img.id = 'topbar-foto'; img.onclick = openProfileModal; img.alt = 'Profil'; ti.replaceWith(img); }
else if (ti) { const img = document.createElement('img'); img.src = data.foto_url + '?t=' + Date.now(); img.className = 'topbar-avatar'; img.id = 'topbar-foto'; img.onclick = openProfileModal; img.alt = 'Foto profil ' + (data.username ?? ''); ti.replaceWith(img); }
const mp = document.getElementById('modal-foto-preview'); const mi = document.getElementById('modal-foto-icon');
if (mp) { mp.src = data.foto_url; mp.style.display = 'block'; } if (mi) mi.style.display = 'none';
}

View File

@ -71,7 +71,7 @@
.podium-name { font-size: 13px; font-weight: 700; color: #1e293b; text-align: center; max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.podium-kelas { font-size: 11px; color: #94a3b8; }
.podium-exp { font-size: 12px; color: #64748b; }
.podium-exp { font-size: 12px; color: #64748b; display: flex; align-items: center; gap: 4px; }
.podium-bar { border-radius: 12px 12px 0 0; width: 80px; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 800; color: white; }
.rank-1 .podium-bar { height: 80px; background: linear-gradient(135deg,#f59e0b,#d97706); }
@ -80,7 +80,7 @@
/* Tabel */
.custom-card { background: white; border-radius: 20px; border: 2px solid #e5e5e5; padding: 22px; }
.section-title { font-size: 15px; font-weight: 700; color: #1e293b; margin-bottom: 16px; }
.section-title { font-size: 15px; font-weight: 700; color: #1e293b; margin-bottom: 16px; display: flex; align-items: center; gap: 6px; }
.lb-row { display: flex; align-items: center; gap: 14px; padding: 11px 14px; border-radius: 12px; margin-bottom: 6px; transition: background 0.15s; }
.lb-row:hover { background: #f8fafc; }
@ -99,16 +99,23 @@
.lb-nama { flex: 1; font-size: 14px; font-weight: 600; color: #1e293b; }
.lb-nisn { font-size: 12px; color: #94a3b8; }
.lb-kelas { font-size: 12px; color: #64748b; background: #f1f5f9; padding: 2px 8px; border-radius: 99px; }
.lb-exp { font-size: 14px; font-weight: 700; color: #2b8ef3; }
.lb-exp { font-size: 14px; font-weight: 700; color: #2b8ef3; display: flex; align-items: center; gap: 4px; }
.semester-badge { display: inline-block; background: #e0f2fe; color: #0369a1; font-size: 12px; font-weight: 700; padding: 4px 12px; border-radius: 99px; margin-bottom: 20px; }
.empty-state { text-align: center; padding: 40px 20px; color: #94a3b8; }
/* Icon sizes */
.icon-title { width: 28px; height: 28px; vertical-align: middle; margin-right: 6px; }
.icon-sm { width: 16px; height: 16px; vertical-align: middle; }
.icon-crown { width: 24px; height: 24px; }
.icon-rank { width: 20px; height: 20px; }
.icon-empty { width: 56px; height: 56px; }
</style>
@endpush
@section('content')
<h3 class="page-title">🏅 Leaderboard</h3>
<h3 class="page-title">LEADERBOARD</h3>
<p class="page-subtitle">Peringkat siswa berdasarkan total EXP yang dikumpulkan.</p>
{{-- Filter --}}
@ -151,7 +158,9 @@
@if($leaderboard->isEmpty())
<div class="empty-state">
<div style="font-size:52px;margin-bottom:12px">📊</div>
<div style="margin-bottom:12px">
<img src="{{ asset('images/icon/gurud/lb.png') }}" class="icon-empty topbar-waving" alt="Leaderboard kosong">
</div>
<p style="font-size:15px;font-weight:600;color:#475569">Belum ada data leaderboard.</p>
<p style="font-size:13px">Belum ada siswa yang menyelesaikan challenge pada periode ini.</p>
</div>
@ -171,19 +180,27 @@
<div class="podium-avatar">{{ strtoupper(substr($second['nama'],0,1)) }}</div>
<div class="podium-name">{{ $second['nama'] }}</div>
<div class="podium-kelas">{{ $second['nama_kelas'] }}</div>
<div class="podium-exp"> {{ number_format($second['exp']) }}</div>
<div class="podium-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-sm topbar-waving" alt="EXP">
{{ number_format($second['exp']) }}
</div>
<div class="podium-bar">2</div>
</div>
@endif
<div class="podium-item rank-1">
<div class="podium-avatar">
<span class="podium-crown">👑</span>
<span class="podium-crown">
<img src="{{ asset('images/icon/gurud/crown.png') }}" class="icon-crown topbar-waving" alt="Mahkota juara 1">
</span>
{{ strtoupper(substr($first['nama'],0,1)) }}
</div>
<div class="podium-name">{{ $first['nama'] }}</div>
<div class="podium-kelas">{{ $first['nama_kelas'] }}</div>
<div class="podium-exp"> {{ number_format($first['exp']) }}</div>
<div class="podium-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-sm topbar-waving" alt="EXP">
{{ number_format($first['exp']) }}
</div>
<div class="podium-bar">1</div>
</div>
@ -192,7 +209,10 @@
<div class="podium-avatar">{{ strtoupper(substr($third['nama'],0,1)) }}</div>
<div class="podium-name">{{ $third['nama'] }}</div>
<div class="podium-kelas">{{ $third['nama_kelas'] }}</div>
<div class="podium-exp"> {{ number_format($third['exp']) }}</div>
<div class="podium-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-sm topbar-waving" alt="EXP">
{{ number_format($third['exp']) }}
</div>
<div class="podium-bar">3</div>
</div>
@endif
@ -201,7 +221,10 @@
{{-- Tabel --}}
<div class="custom-card">
<p class="section-title">📋 Semua Peringkat ({{ $leaderboard->count() }} siswa)</p>
<p class="section-title">
<img src="{{ asset('images/icon/gurud/buku2.png') }}" class="icon-sm topbar-waving" alt="Daftar peringkat">
Semua Peringkat ({{ $leaderboard->count() }} siswa)
</p>
@foreach($leaderboard as $item)
@php
@ -209,10 +232,14 @@
@endphp
<div class="lb-row">
<div class="lb-rank {{ $rankClass }}">
@if($item['ranking']===1) 🥇
@elseif($item['ranking']===2) 🥈
@elseif($item['ranking']===3) 🥉
@else {{ $item['ranking'] }}
@if($item['ranking']===1)
<img src="{{ asset('images/icon/gurud/1.png') }}" class="icon-rank topbar-waving" alt="Peringkat 1">
@elseif($item['ranking']===2)
<img src="{{ asset('images/icon/gurud/2.png') }}" class="icon-rank topbar-waving" alt="Peringkat 2">
@elseif($item['ranking']===3)
<img src="{{ asset('images/icon/gurud/3.png') }}" class="icon-rank topbar-waving" alt="Peringkat 3">
@else
{{ $item['ranking'] }}
@endif
</div>
<div style="flex:1">
@ -220,7 +247,10 @@
<div class="lb-nisn">{{ $item['nisn'] }}</div>
</div>
<span class="lb-kelas">{{ $item['nama_kelas'] }}</span>
<div class="lb-exp"> {{ number_format($item['exp']) }}</div>
<div class="lb-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-sm topbar-waving" alt="EXP">
{{ number_format($item['exp']) }}
</div>
</div>
@endforeach
</div>

View File

@ -84,7 +84,9 @@
font-size: 13px;
font-weight: 600;
text-decoration: none;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
transition: background 0.2s;
}
@ -99,6 +101,9 @@
font-size: 13px;
font-weight: 600;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 4px;
transition: background 0.2s;
}
@ -112,6 +117,9 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 6px;
}
.empty-state {
@ -119,12 +127,19 @@
padding: 50px 20px;
color: #94a3b8;
}
/* Icon sizes */
.icon-sm { width: 16px; height: 16px; vertical-align: middle; }
.icon-empty { width: 56px; height: 56px; }
</style>
<h3 class="page-title">HISTORY MATERI</h3>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-sm topbar-waving" alt="Berhasil">
{{ session('success') }}
</div>
@endif
<div class="custom-card">
@ -132,7 +147,7 @@
{{-- FILTER & SEARCH --}}
<form method="GET" action="{{ route('admin.materi.history') }}" class="d-flex flex-wrap gap-2 align-items-center mb-4">
<select name="id_guru" class="filter-select" onchange="this.form.submit()">
<option value="">👨‍🏫 Semua Guru</option>
<option value="">Semua Guru</option>
@foreach($gurus as $guru)
<option value="{{ $guru->id_guru }}" {{ request('id_guru') == $guru->id_guru ? 'selected' : '' }}>
{{ $guru->nama }}
@ -144,7 +159,7 @@
<input type="text" name="search" placeholder="Cari judul materi..."
value="{{ request('search') }}">
<button style="border:none;background:none" type="submit">
<img src="{{ asset('images/icon/main/search.png') }}" width="18">
<img src="{{ asset('images/icon/main/search.png') }}" class="icon-sm" alt="Cari">
</button>
</div>
@ -160,7 +175,9 @@
@if($materiList->isEmpty())
<div class="empty-state">
<div style="font-size:48px;margin-bottom:12px">📭</div>
<div style="margin-bottom:12px">
<img src="{{ asset('images/icon/gurud/mailbox.png') }}" class="icon-empty topbar-waving" alt="Tidak ada materi">
</div>
<p>Tidak ada materi ditemukan.</p>
</div>
@else
@ -215,18 +232,26 @@
<td class="text-center">
@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 => '📎',
$ext = strtolower(pathinfo($materi->lampiran_materi, PATHINFO_EXTENSION));
$iconSrc = match(true) {
in_array($ext, ['pdf']) => asset('images/icon/gurud/buku2.png'),
in_array($ext, ['doc','docx']) => asset('images/icon/gurud/buku1.png'),
in_array($ext, ['ppt','pptx']) => asset('images/icon/gurud/lb.png'),
in_array($ext, ['jpg','jpeg','png']) => asset('images/icon/gurud/image.png'),
default => asset('images/icon/gurud/link.png'),
};
$iconAlt = match(true) {
in_array($ext, ['pdf']) => 'File PDF',
in_array($ext, ['doc','docx']) => 'File Word',
in_array($ext, ['ppt','pptx']) => 'File PowerPoint',
in_array($ext, ['jpg','jpeg','png']) => 'File Gambar',
default => 'File Lampiran',
};
@endphp
<a href="{{ asset('storage/' . $materi->lampiran_materi) }}"
target="_blank" class="btn-unduh">
{{ $icon }} Unduh
<img src="{{ $iconSrc }}" class="icon-sm topbar-waving" alt="{{ $iconAlt }}">
Unduh
</a>
@else
<span style="font-size:12px;color:#94a3b8">Tidak ada</span>
@ -238,7 +263,10 @@
onsubmit="return confirm('Yakin hapus materi ini?')">
@csrf
@method('DELETE')
<button type="submit" class="btn-hapus">🗑️ Hapus</button>
<button type="submit" class="btn-hapus">
<img src="{{ asset('images/icon/gurud/bin.png') }}" class="icon-sm topbar-waving" alt="Hapus">
Hapus
</button>
</form>
</td>
</tr>

View File

@ -116,6 +116,9 @@
font-weight: 700;
color: #1e293b;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 6px;
}
.table-header { background: #a5e6ba; }
@ -125,7 +128,9 @@
font-weight: 700;
padding: 4px 10px;
border-radius: 99px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.status-dikumpulkan { background: #dcfce7; color: #16a34a; }
@ -139,7 +144,9 @@
font-weight: 700;
padding: 3px 10px;
border-radius: 99px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.btn-unduh {
@ -151,7 +158,9 @@
font-size: 13px;
font-weight: 600;
text-decoration: none;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
transition: background 0.2s;
}
@ -163,7 +172,6 @@
color: #94a3b8;
}
/* Search di tabel pengumpulan */
.table-search {
border: 1px solid #cbd5e1;
border-radius: 10px;
@ -174,6 +182,11 @@
}
.table-search:focus { border-color: #2b8ef3; }
/* Icon sizes */
.icon-sm { width: 16px; height: 16px; vertical-align: middle; }
.icon-meta { width: 15px; height: 15px; vertical-align: middle; }
.icon-empty { width: 56px; height: 56px; }
</style>
@php
@ -191,17 +204,21 @@
<div class="info-meta">
<span class="meta-chip yellow">
👨‍🏫 {{ optional(optional($tugas->mengajar)->guru)->nama ?? '-' }}
<img src="{{ asset('images/icon/gurud/guru.png') }}" class="icon-meta topbar-waving" alt="Guru">
{{ optional(optional($tugas->mengajar)->guru)->nama ?? '-' }}
</span>
<span class="meta-chip">
📚 {{ optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-' }}
<img src="{{ asset('images/icon/gurud/stacked.png') }}" class="icon-meta topbar-waving" alt="Mata Pelajaran">
{{ optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-' }}
</span>
<span class="meta-chip">
🏫 {{ optional(optional($tugas->mengajar)->kelas)->tingkat }}
{{ optional(optional($tugas->mengajar)->kelas)->nama_kelas ?? '-' }}
<img src="{{ asset('images/icon/gurud/school.png') }}" class="icon-meta topbar-waving" alt="Kelas">
{{ optional(optional($tugas->mengajar)->kelas)->tingkat }}
{{ optional(optional($tugas->mengajar)->kelas)->nama_kelas ?? '-' }}
</span>
<span class="meta-chip {{ $isLewat ? 'red' : 'green' }}">
{{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }}
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="icon-meta topbar-waving" alt="Deadline">
{{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }}
{{ $isLewat ? 'Sudah lewat' : 'Masih aktif' }}
</span>
</div>
@ -232,15 +249,20 @@
{{-- DAFTAR PENGUMPULAN --}}
<div class="custom-card">
<div class="d-flex justify-content-between align-items-center mb-3">
<p class="section-title mb-0">📥 Daftar Pengumpulan Siswa</p>
<p class="section-title mb-0">
<img src="{{ asset('images/icon/gurud/pengumpulan.png') }}" class="icon-sm topbar-waving" alt="Pengumpulan">
Daftar Pengumpulan Siswa
</p>
<input type="text" class="table-search" id="searchSiswa"
placeholder="🔍 Cari nama / NISN..."
placeholder="Cari nama / NISN..."
onkeyup="filterTable()">
</div>
@if($tugas->pengumpulanTugas->isEmpty())
<div class="empty-state">
<div style="font-size:40px;margin-bottom:10px">📭</div>
<div style="margin-bottom:10px">
<img src="{{ asset('images/icon/gurud/mailbox.png') }}" class="icon-empty topbar-waving" alt="Belum ada pengumpulan">
</div>
<p>Belum ada siswa yang mengumpulkan tugas ini.</p>
</div>
@else
@ -275,15 +297,24 @@
</td>
<td class="text-center">
<span class="status-badge status-{{ $kumpul->status }}">
@if($kumpul->status === 'dikumpulkan') Tepat Waktu
@elseif($kumpul->status === 'terlambat') Terlambat
@else Belum
@if($kumpul->status === 'dikumpulkan')
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-sm topbar-waving" alt="Tepat waktu">
Tepat Waktu
@elseif($kumpul->status === 'terlambat')
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="icon-sm topbar-waving" alt="Terlambat">
Terlambat
@else
<img src="{{ asset('images/icon/gurud/x.png') }}" class="icon-sm topbar-waving" alt="Belum dikumpulkan">
Belum
@endif
</span>
</td>
<td class="text-center">
@if($kumpul->exp > 0)
<span class="exp-badge"> {{ $kumpul->exp }} EXP</span>
<span class="exp-badge">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-sm topbar-waving" alt="EXP">
{{ $kumpul->exp }} EXP
</span>
@else
<span style="font-size:12px;color:#94a3b8">Belum dinilai</span>
@endif
@ -291,17 +322,24 @@
<td class="text-center">
@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 => '📎',
$ext = strtolower(pathinfo($kumpul->lampiran_tugas, PATHINFO_EXTENSION));
$iconSrc = match(true) {
in_array($ext, ['pdf']) => asset('images/icon/gurud/buku2.png'),
in_array($ext, ['doc','docx']) => asset('images/icon/gurud/buku1.png'),
in_array($ext, ['jpg','jpeg','png']) => asset('images/icon/gurud/image.png'),
default => asset('images/icon/gurud/link.png'),
};
$iconAlt = match(true) {
in_array($ext, ['pdf']) => 'File PDF',
in_array($ext, ['doc','docx']) => 'File Word',
in_array($ext, ['jpg','jpeg','png']) => 'File Gambar',
default => 'File Lampiran',
};
@endphp
<a href="{{ asset('storage/' . $kumpul->lampiran_tugas) }}"
target="_blank" class="btn-unduh">
{{ $icon }} Unduh
<img src="{{ $iconSrc }}" class="icon-sm topbar-waving" alt="{{ $iconAlt }}">
Unduh
</a>
@else
<span style="font-size:12px;color:#94a3b8">-</span>

View File

@ -80,7 +80,9 @@
font-weight: 600;
padding: 3px 10px;
border-radius: 99px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.deadline-lewat { background: #fee2e2; color: #ef4444; }
@ -101,7 +103,9 @@
font-size: 13px;
font-weight: 600;
text-decoration: none;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
transition: background 0.2s;
}
@ -116,6 +120,9 @@
font-size: 13px;
font-weight: 600;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 4px;
transition: background 0.2s;
}
@ -129,6 +136,9 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 6px;
}
.empty-state {
@ -136,12 +146,19 @@
padding: 50px 20px;
color: #94a3b8;
}
/* Icon sizes */
.icon-sm { width: 16px; height: 16px; vertical-align: middle; }
.icon-empty { width: 56px; height: 56px; }
</style>
<h3 class="page-title">HISTORY TUGAS</h3>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-sm topbar-waving" alt="Berhasil">
{{ session('success') }}
</div>
@endif
<div class="custom-card">
@ -149,7 +166,7 @@
{{-- FILTER & SEARCH --}}
<form method="GET" action="{{ route('admin.tugas.history') }}" class="d-flex flex-wrap gap-2 align-items-center mb-4">
<select name="id_guru" class="filter-select" onchange="this.form.submit()">
<option value="">👨‍🏫 Semua Guru</option>
<option value="">Semua Guru</option>
@foreach($gurus as $guru)
<option value="{{ $guru->id_guru }}" {{ request('id_guru') == $guru->id_guru ? 'selected' : '' }}>
{{ $guru->nama }}
@ -161,7 +178,7 @@
<input type="text" name="search" placeholder="Cari judul tugas..."
value="{{ request('search') }}">
<button style="border:none;background:none" type="submit">
<img src="{{ asset('images/icon/main/search.png') }}" width="18">
<img src="{{ asset('images/icon/main/search.png') }}" class="icon-sm" alt="Cari">
</button>
</div>
@ -177,7 +194,9 @@
@if($tugasList->isEmpty())
<div class="empty-state">
<div style="font-size:48px;margin-bottom:12px">📭</div>
<div style="margin-bottom:12px">
<img src="{{ asset('images/icon/gurud/mailbox.png') }}" class="icon-empty topbar-waving" alt="Tidak ada tugas">
</div>
<p>Tidak ada tugas ditemukan.</p>
</div>
@else
@ -198,7 +217,7 @@
<tbody>
@foreach($tugasList as $i => $tugas)
@php
$isLewat = \Carbon\Carbon::parse($tugas->deadline)->isPast();
$isLewat = \Carbon\Carbon::parse($tugas->deadline)->isPast();
$jumlahKumpul = $tugas->pengumpulanTugas->count();
@endphp
<tr>
@ -229,7 +248,13 @@
</td>
<td class="text-center">
<span class="deadline-badge {{ $isLewat ? 'deadline-lewat' : 'deadline-aktif' }}">
{{ $isLewat ? '⏰ Lewat' : '✅ Aktif' }}
@if($isLewat)
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="icon-sm topbar-waving" alt="Deadline lewat">
Lewat
@else
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-sm topbar-waving" alt="Deadline aktif">
Aktif
@endif
</span>
<div style="font-size:11px;color:#64748b;margin-top:3px">
{{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }}
@ -241,14 +266,18 @@
</td>
<td class="text-center">
<div class="d-flex gap-1 justify-content-center">
<a href="{{ route('admin.tugas.detail', $tugas->id_tugas) }}"
class="btn-detail">👁️ Detail</a>
<a href="{{ route('admin.tugas.detail', $tugas->id_tugas) }}" class="btn-detail">
<img src="{{ asset('images/icon/gurud/eye.png') }}" class="icon-sm topbar-waving" alt="Lihat detail">
Detail
</a>
<form action="{{ route('admin.tugas.destroy', $tugas->id_tugas) }}"
method="POST"
onsubmit="return confirm('Yakin hapus tugas ini? Semua pengumpulan ikut terhapus.')">
@csrf
@method('DELETE')
<button type="submit" class="btn-hapus">🗑️</button>
<button type="submit" class="btn-hapus">
<img src="{{ asset('images/icon/gurud/bin.png') }}" class="icon-sm topbar-waving" alt="Hapus tugas">
</button>
</form>
</div>
</td>

View File

@ -29,7 +29,7 @@
.stat-card:nth-child(2) .stat-label { color: #15803d; }
.stat-card:nth-child(3) .stat-label { color: #c2651a; }
.stat-num { font-size: 42px; font-weight: 800; line-height: 1; color: #0f1f3d; }
.stat-icon { position: absolute; top: 20px; right: 20px; width: 42px; height: 42px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 20px; opacity: 0.7; }
.stat-icon { position: absolute; top: 20px; right: 20px; width: 42px; height: 42px; border-radius: 12px; display: flex; align-items: center; justify-content: center; opacity: 0.7; }
.stat-card:nth-child(1) .stat-icon { background: rgba(43,142,243,0.15); }
.stat-card:nth-child(2) .stat-icon { background: rgba(34,197,94,0.15); }
.stat-card:nth-child(3) .stat-icon { background: rgba(249,115,22,0.15); }
@ -103,19 +103,25 @@
{{-- STAT CARDS --}}
<div class="stat-grid">
<div class="stat-card">
<div class="stat-icon">🏫</div>
<div class="stat-icon">
<img src="{{ asset('images/icon/gurud/school.png') }}" class="icon-sm" alt="Ikon kelas">
</div>
<div class="stat-label">Kelas Diampu</div>
<div class="stat-num">{{ $totalKelas }}</div>
<a href="{{ route('guru.kelas.index') }}" class="stat-link">Lihat Data </a>
</div>
<div class="stat-card">
<div class="stat-icon">📚</div>
<div class="stat-icon">
<img src="{{ asset('images/icon/gurud/stacked.png') }}" class="icon-sm" alt="Ikon mata pelajaran">
</div>
<div class="stat-label">Mata Pelajaran</div>
<div class="stat-num">{{ $totalMapel }}</div>
<a href="{{ route('guru.mapel.index') }}" class="stat-link">Lihat Data </a>
</div>
<div class="stat-card">
<div class="stat-icon">👨‍🎓</div>
<div class="stat-icon">
<img src="{{ asset('images/icon/gurud/siswa.png') }}" class="icon-sm" alt="Ikon siswa">
</div>
<div class="stat-label">Siswa Diajar</div>
<div class="stat-num">{{ $totalSiswa }}</div>
<a href="{{ route('guru.siswa.index') }}" class="stat-link">Lihat Data </a>
@ -148,7 +154,9 @@
</div>
@else
<div style="text-align:center;padding:40px 20px;color:#94a3b8;">
<div style="font-size:36px;margin-bottom:8px">📋</div>
<div style="margin-bottom:8px">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="icon-sm" alt="Belum ada tugas">
</div>
<div style="font-size:13px">Belum ada tugas dibuat.</div>
</div>
@endif

View File

@ -61,15 +61,11 @@
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="badge-info">
📖 Mode Hanya Lihat (Read Only)
</div>
<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">
<img src="{{ asset('images/icon/main/search.png') }}" width="18" height="18" alt="Cari kelas">
</button>
</div>
</form>
@ -123,4 +119,4 @@
</div>
@endsection
@endsection

View File

@ -37,6 +37,11 @@
.topbar-right { display: flex; align-items: center; gap: 14px; }
.content { padding: 20px 28px 28px; flex: 1; overflow-y: auto; }
/* Shared icon utility classes */
.icon-inline { width: 18px; height: 18px; vertical-align: middle; }
.icon-sm { width: 32px; height: 32px; }
.icon-lg { width: 48px; height: 48px; }
/* NOTIF */
.notif-wrap { position: relative; }
.notif-btn { width: 36px; height: 36px; border-radius: 50%; background: rgba(255,255,255,0.2); border: 2px solid rgba(255,255,255,0.4); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.2s; flex-shrink: 0; }
@ -105,21 +110,23 @@
<body>
<div class="wrapper">
<aside class="sidebar" id="mainSidebar">
<div class="sidebar-logo"><img src="{{ asset('images/logo/logosmk.png') }}" alt="Logo"></div>
<div class="sidebar-logo">
<img src="{{ asset('images/logo/logosmk.png') }}" alt="Logo SMK">
</div>
<a href="{{ route('guru.dashboard') }}" class="sidebar-link {{ request()->routeIs('guru.dashboard') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/home.png') }}" class="sidebar-icon"><span>Dashboard</span>
<img src="{{ asset('images/icon/sidebar/home.png') }}" class="sidebar-icon" alt="Dashboard"><span>Dashboard</span>
</a>
<a href="{{ route('guru.kelas.index') }}" class="sidebar-link {{ request()->routeIs('guru.kelas.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/kelas.png') }}" class="sidebar-icon"><span>Daftar Kelas</span>
<img src="{{ asset('images/icon/sidebar/kelas.png') }}" class="sidebar-icon" alt="Daftar Kelas"><span>Daftar Kelas</span>
</a>
<a href="{{ route('guru.siswa.index') }}" class="sidebar-link {{ request()->routeIs('guru.siswa.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/siswa.png') }}" class="sidebar-icon"><span>Daftar Siswa</span>
<img src="{{ asset('images/icon/sidebar/siswa.png') }}" class="sidebar-icon" alt="Daftar Siswa"><span>Daftar Siswa</span>
</a>
<a href="{{ route('guru.mapel.index') }}" class="sidebar-link {{ request()->routeIs('guru.mapel.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/mapel.png') }}" class="sidebar-icon"><span>Mata Pelajaran</span>
<img src="{{ asset('images/icon/sidebar/mapel.png') }}" class="sidebar-icon" alt="Mata Pelajaran"><span>Mata Pelajaran</span>
</a>
<a href="{{ route('guru.leaderboard.index') }}" class="sidebar-link {{ request()->routeIs('guru.leaderboard.*') ? 'active' : '' }}">
<img src="{{ asset('images/icon/sidebar/lb.png') }}" class="sidebar-icon"><span>Leaderboard</span>
<img src="{{ asset('images/icon/sidebar/lb.png') }}" class="sidebar-icon" alt="Leaderboard"><span>Leaderboard</span>
</a>
<form action="{{ route('guru.logout') }}" method="POST" class="sidebar-logout">
@csrf
@ -137,7 +144,7 @@
<div class="main">
<header class="topbar">
<div class="topbar-left">
<img src="{{ asset('images/icon/main/hi.png') }}" class="topbar-waving" alt="Waving">
<img src="{{ asset('images/icon/gurud/wavinghand.png') }}" class="topbar-waving" alt="Ikon salam">
Selamat datang, {{ Auth::guard('guru')->user()->nama ?? 'Guru' }}
</div>
<div class="topbar-right">
@ -152,14 +159,17 @@
<span class="notif-head-count" id="notifCount">7 hari terakhir</span>
</div>
<div class="notif-list" id="notifList">
<div class="notif-empty"><div class="notif-empty-icon">🔔</div><div class="notif-empty-text">Memuat notifikasi...</div></div>
<div class="notif-empty">
<div class="notif-empty-icon"><img src="{{ asset('images/icon/gurud/notif.png') }}" alt="Notifikasi kosong" class="icon-sm"></div>
<div class="notif-empty-text">Memuat notifikasi...</div>
</div>
</div>
</div>
</div>
@php $guru = Auth::guard('guru')->user(); @endphp
@if($guru->foto_profil)
<img src="{{ Storage::url($guru->foto_profil) }}" class="topbar-avatar" id="topbar-foto" onclick="openProfileModal()" alt="Profil">
<img src="{{ Storage::url($guru->foto_profil) }}" class="topbar-avatar" id="topbar-foto" onclick="openProfileModal()" alt="Foto profil {{ $guru->nama }}">
@else
<div class="topbar-avatar-icon" id="topbar-foto-icon" onclick="openProfileModal()">
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>
@ -182,7 +192,7 @@
@csrf
<div class="foto-upload-area">
<div class="foto-circle">
@if($guru->foto_profil) <img src="{{ Storage::url($guru->foto_profil) }}" id="modal-foto-preview" alt="">
@if($guru->foto_profil) <img src="{{ Storage::url($guru->foto_profil) }}" id="modal-foto-preview" alt="Foto profil saat ini">
@else <svg id="modal-foto-icon" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg>
<img src="" id="modal-foto-preview" alt="" style="display:none"> @endif
</div>
@ -219,8 +229,8 @@ function updateToggle(c) { toggleBtn.style.left = c ? '0px' : SIDEBAR_W+'px'; c
if (data.count > 0) badge.textContent = data.count > 99 ? '99+' : data.count;
count.textContent = `${data.count} notifikasi`;
list.innerHTML = data.notifications.length === 0
? `<div class="notif-empty"><div class="notif-empty-icon">🔔</div><div class="notif-empty-text">Tidak ada notifikasi baru</div></div>`
: data.notifications.map(n => `<div class="notif-item"><div class="notif-icon-wrap notif-icon-pengumpulan"></div><div class="notif-body"><div class="notif-title">${n.title}</div><div class="notif-message">${n.message}</div><div class="notif-time">${n.time}</div></div></div>`).join('');
? `<div class="notif-empty"><div class="notif-empty-icon"><img src="{{ asset('images/icon/gurud/bell.png') }}" alt="Tidak ada notifikasi" class="icon-sm"></div><div class="notif-empty-text">Tidak ada notifikasi baru</div></div>`
: data.notifications.map(n => `<div class="notif-item"><div class="notif-icon-wrap notif-icon-pengumpulan"><img src="{{ asset('images/icon/gurud/v.png') }}" alt="Tugas dikumpulkan" class="icon-inline"></div><div class="notif-body"><div class="notif-title">${n.title}</div><div class="notif-message">${n.message}</div><div class="notif-time">${n.time}</div></div></div>`).join('');
} catch(e) {}
}
function toggleNotif(e) { e.stopPropagation(); document.getElementById('notifDropdown').classList.toggle('show'); }
@ -239,7 +249,7 @@ function closeOnOverlay(e) { if (e.target===document.getElementById('profileModa
const res=await fetch('{{ route("guru.profile.update") }}',{method:'POST',headers:{'X-CSRF-TOKEN':document.querySelector('meta[name="csrf-token"]').content},body:fd});
const data=await res.json();
if(data.success){
if(data.foto_url){const tf=document.getElementById('topbar-foto');const ti=document.getElementById('topbar-foto-icon');if(tf){tf.src=data.foto_url+'?t='+Date.now();}else if(ti){const img=document.createElement('img');img.src=data.foto_url+'?t='+Date.now();img.className='topbar-avatar';img.id='topbar-foto';img.onclick=openProfileModal;img.alt='Profil';ti.replaceWith(img);}const mp=document.getElementById('modal-foto-preview');const mi=document.getElementById('modal-foto-icon');if(mp){mp.src=data.foto_url;mp.style.display='block';}if(mi)mi.style.display='none';}
if(data.foto_url){const tf=document.getElementById('topbar-foto');const ti=document.getElementById('topbar-foto-icon');if(tf){tf.src=data.foto_url+'?t='+Date.now();}else if(ti){const img=document.createElement('img');img.src=data.foto_url+'?t='+Date.now();img.className='topbar-avatar';img.id='topbar-foto';img.onclick=openProfileModal;img.alt='Foto profil {{ $guru->nama }}';ti.replaceWith(img);}const mp=document.getElementById('modal-foto-preview');const mi=document.getElementById('modal-foto-icon');if(mp){mp.src=data.foto_url;mp.style.display='block';}if(mi)mi.style.display='none';}
toast.className='modal-toast success'; toast.textContent='✓ '+data.message;
this.querySelector('[name="password"]').value=''; this.querySelector('[name="password_confirmation"]').value='';
} else { const err=data.errors?Object.values(data.errors).flat().join(' · '):'Terjadi kesalahan.'; toast.className='modal-toast error'; toast.textContent=err; }

View File

@ -60,7 +60,7 @@
.rank-3 .podium-avatar { background: linear-gradient(135deg,#f97316,#ea580c); }
.podium-name { font-size: 13px; font-weight: 700; color: #1e293b; text-align: center; max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.podium-exp { font-size: 12px; color: #64748b; }
.podium-exp { font-size: 12px; color: #64748b; display: flex; align-items: center; gap: 4px; }
.podium-bar { border-radius: 12px 12px 0 0; width: 80px; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 800; color: white; }
.rank-1 .podium-bar { height: 80px; background: linear-gradient(135deg,#f59e0b,#d97706); }
@ -68,7 +68,7 @@
.rank-3 .podium-bar { height: 44px; background: linear-gradient(135deg,#f97316,#ea580c); }
.custom-card { background: white; border-radius: 20px; border: 2px solid #e5e5e5; padding: 22px; }
.section-title { font-size: 15px; font-weight: 700; color: #1e293b; margin-bottom: 16px; }
.section-title { font-size: 15px; font-weight: 700; color: #1e293b; margin-bottom: 16px; display: flex; align-items: center; gap: 6px; }
.lb-row { display: flex; align-items: center; gap: 14px; padding: 11px 14px; border-radius: 12px; margin-bottom: 6px; transition: background 0.15s; }
.lb-row:hover { background: #f8fafc; }
@ -86,7 +86,7 @@
.lb-nama { flex: 1; font-size: 14px; font-weight: 600; color: #1e293b; }
.lb-nisn { font-size: 12px; color: #94a3b8; }
.lb-exp { font-size: 14px; font-weight: 700; color: #2b8ef3; }
.lb-exp { font-size: 14px; font-weight: 700; color: #2b8ef3; display: flex; align-items: center; gap: 4px; }
.semester-badge { display: inline-block; background: #e0f2fe; color: #0369a1; font-size: 12px; font-weight: 700; padding: 4px 12px; border-radius: 99px; margin-bottom: 20px; }
.empty-state { text-align: center; padding: 40px 20px; color: #94a3b8; }
@ -100,18 +100,23 @@
color: #c2410c;
font-size: 14px;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
</style>
@endpush
@section('content')
<h3 class="page-title">🏅 Leaderboard</h3>
<h3 class="page-title">LEADERBOARD</h3>
<p class="page-subtitle">Peringkat siswa di kelas yang Anda ajar.</p>
@if($kelasList->isEmpty())
<div class="no-kelas-box">
⚠️ Anda belum mengajar kelas manapun. Hubungi admin untuk mengatur jadwal mengajar.
<img src="{{ asset('images/icon/gurud/alert.png') }}" class="icon-inline" alt="Peringatan">
Anda belum mengajar kelas manapun. Hubungi admin untuk mengatur jadwal mengajar.
</div>
@else
@ -155,7 +160,9 @@
@if($leaderboard->isEmpty())
<div class="empty-state">
<div style="font-size:52px;margin-bottom:12px">📊</div>
<div style="margin-bottom:12px">
<img src="{{ asset('images/icon/gurud/lb.png') }}" class="icon-lg" alt="Leaderboard kosong">
</div>
<p style="font-size:15px;font-weight:600;color:#475569">Belum ada data leaderboard.</p>
<p style="font-size:13px">Belum ada siswa yang menyelesaikan challenge pada periode ini.</p>
</div>
@ -174,18 +181,26 @@
<div class="podium-item rank-2">
<div class="podium-avatar">{{ strtoupper(substr($second['nama'],0,1)) }}</div>
<div class="podium-name">{{ $second['nama'] }}</div>
<div class="podium-exp"> {{ number_format($second['exp']) }}</div>
<div class="podium-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-inline" alt="EXP">
{{ number_format($second['exp']) }}
</div>
<div class="podium-bar">2</div>
</div>
@endif
<div class="podium-item rank-1">
<div class="podium-avatar">
<span class="podium-crown">👑</span>
<span class="podium-crown">
<img src="{{ asset('images/icon/gurud/crown.png') }}" style="width:22px;height:22px" alt="Mahkota juara 1">
</span>
{{ strtoupper(substr($first['nama'],0,1)) }}
</div>
<div class="podium-name">{{ $first['nama'] }}</div>
<div class="podium-exp"> {{ number_format($first['exp']) }}</div>
<div class="podium-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-inline" alt="EXP">
{{ number_format($first['exp']) }}
</div>
<div class="podium-bar">1</div>
</div>
@ -193,7 +208,10 @@
<div class="podium-item rank-3">
<div class="podium-avatar">{{ strtoupper(substr($third['nama'],0,1)) }}</div>
<div class="podium-name">{{ $third['nama'] }}</div>
<div class="podium-exp"> {{ number_format($third['exp']) }}</div>
<div class="podium-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-inline" alt="EXP">
{{ number_format($third['exp']) }}
</div>
<div class="podium-bar">3</div>
</div>
@endif
@ -202,23 +220,33 @@
{{-- Tabel --}}
<div class="custom-card">
<p class="section-title">📋 Semua Peringkat ({{ $leaderboard->count() }} siswa)</p>
<p class="section-title">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="icon-inline" alt="Daftar peringkat">
Semua Peringkat ({{ $leaderboard->count() }} siswa)
</p>
@foreach($leaderboard as $item)
@php $rankClass = match($item['ranking']) { 1=>'gold', 2=>'silver', 3=>'bronze', default=>'' }; @endphp
<div class="lb-row">
<div class="lb-rank {{ $rankClass }}">
@if($item['ranking']===1) 🥇
@elseif($item['ranking']===2) 🥈
@elseif($item['ranking']===3) 🥉
@else {{ $item['ranking'] }}
@if($item['ranking']===1)
<img src="{{ asset('images/icon/gurud/1.png') }}" style="width:20px;height:20px" alt="Peringkat 1">
@elseif($item['ranking']===2)
<img src="{{ asset('images/icon/gurud/2.png') }}" style="width:20px;height:20px" alt="Peringkat 2">
@elseif($item['ranking']===3)
<img src="{{ asset('images/icon/gurud/3.png') }}" style="width:20px;height:20px" alt="Peringkat 3">
@else
{{ $item['ranking'] }}
@endif
</div>
<div style="flex:1">
<div class="lb-nama">{{ $item['nama'] }}</div>
<div class="lb-nisn">{{ $item['nisn'] }}</div>
</div>
<div class="lb-exp"> {{ number_format($item['exp']) }}</div>
<div class="lb-exp">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-inline" alt="EXP">
{{ number_format($item['exp']) }}
</div>
</div>
@endforeach
</div>

View File

@ -29,7 +29,9 @@
font-size: 13px;
cursor: pointer;
text-decoration: none;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 6px;
}
.btn-materi {
@ -132,6 +134,8 @@
color: white;
}
.btn-history-tugas:hover { background: #0d9488; color: white; }
.alert-success-custom {
background: #dcfce7;
color: #166534;
border-radius: 10px;
@ -139,6 +143,9 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.alert-error-custom {
@ -149,7 +156,12 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.upload-icon { width: 40px; height: 40px; margin: 0 auto 6px; }
</style>
@endpush
@ -158,11 +170,17 @@
<h3 class="page-title">MATA PELAJARAN YANG ANDA AJAR</h3>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-inline" alt="Berhasil">
{{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="alert-error-custom"> {{ session('error') }}</div>
<div class="alert-error-custom">
<img src="{{ asset('images/icon/gurud/x.png') }}" class="icon-inline" alt="Gagal">
{{ session('error') }}
</div>
@endif
<div class="custom-card">
@ -181,7 +199,6 @@
@php
$mapel = $rows->first()->mapel;
$kelasList = $rows->map(fn($m) => $m->kelas)->filter();
// Ambil id_mengajar pertama sebagai default (bisa dipilih per kelas di modal)
$mengajarOptions = $rows->map(fn($m) => [
'id_mengajar' => $m->id_mengajar,
'kelas' => optional($m->kelas)->tingkat . ' ' . optional($m->kelas)->nama_kelas,
@ -208,7 +225,8 @@
'{{ addslashes(optional($mapel)->nama_mapel) }}',
{{ $mengajarOptions->toJson() }}
)">
📄 Upload Materi
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="icon-inline" alt="Upload materi">
Upload Materi
</button>
<button class="action-btn btn-tugas"
@ -216,17 +234,20 @@
'{{ addslashes(optional($mapel)->nama_mapel) }}',
{{ $mengajarOptions->toJson() }}
)">
📋 Buat Tugas
<img src="{{ asset('images/icon/gurud/buku2.png') }}" class="icon-inline" alt="Buat tugas">
Buat Tugas
</button>
<a href="{{ route('guru.materi.history', ['id_mapel' => $idMapel]) }}"
class="action-btn btn-history-materi">
🗂️ History Materi
<img src="{{ asset('images/icon/gurud/file.png') }}" class="icon-inline" alt="History materi">
History Materi
</a>
<a href="{{ route('guru.tugas.history', ['id_mapel' => $idMapel]) }}"
class="action-btn btn-history-tugas">
📑 History Tugas
<img src="{{ asset('images/icon/gurud/history.png') }}" class="icon-inline" alt="History tugas">
History Tugas
</a>
</div>
</td>
@ -251,7 +272,10 @@ class="action-btn btn-history-tugas">
<div class="modal-content">
<div class="modal-header modal-header-blue">
<h5 class="modal-title">📄 Upload Materi <span id="materiMapelLabel"></span></h5>
<h5 class="modal-title d-flex align-items-center gap-2">
<img src="{{ asset('images/icon/gurud/add-file.png') }}" class="icon-inline" alt="Upload file">
Upload Materi <span id="materiMapelLabel"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
@ -259,7 +283,6 @@ class="action-btn btn-history-tugas">
@csrf
<div class="modal-body">
{{-- Pilih Kelas (jika guru ajar mapel ini di lebih dari 1 kelas) --}}
<div class="mb-3">
<label>Kelas Tujuan <span class="text-danger">*</span></label>
<select name="id_mengajar" id="materiMengajar" class="form-control" required>
@ -286,7 +309,7 @@ class="action-btn btn-history-tugas">
<input type="file" name="lampiran_materi" id="materiFile"
accept=".pdf,.doc,.docx,.ppt,.pptx,.jpg,.jpeg,.png"
onchange="previewFile(this, 'materiPreview', 'materiFileName')">
<div style="font-size:32px">☁️</div>
<img src="{{ asset('images/icon/gurud/cloud.png') }}" class="upload-icon" alt="Upload ke cloud">
<p style="margin:6px 0 0;font-size:14px;color:#64748b">
<strong>Klik</strong> atau drag file ke sini
</p>
@ -316,15 +339,17 @@ class="action-btn btn-history-tugas">
<div class="modal-content">
<div class="modal-header modal-header-orange">
<h5 class="modal-title">📋 Buat Tugas <span id="tugasMapelLabel"></span></h5>
<h5 class="modal-title d-flex align-items-center gap-2">
<img src="{{ asset('images/icon/gurud/buku1.png') }}" class="icon-inline" alt="Buat tugas">
Buat Tugas <span id="tugasMapelLabel"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form action="{{ route('guru.tugas.store') }}" method="POST">
<form action="{{ route('guru.tugas.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="modal-body">
{{-- Pilih Kelas --}}
<div class="mb-3">
<label>Kelas Tujuan <span class="text-danger">*</span></label>
<select name="id_mengajar" id="tugasMengajar" class="form-control" required>
@ -352,6 +377,21 @@ class="action-btn btn-history-tugas">
<small class="text-muted">Pastikan deadline lebih dari waktu sekarang.</small>
</div>
<div class="mb-3">
<label>Lampiran Tugas <small class="text-muted fw-normal">(Semua tipe file maks 10MB, opsional)</small></label>
<div class="upload-area" id="tugasUploadArea">
<input type="file" name="lampiran_tugas" id="tugasFile"
onchange="previewFile(this, 'tugasPreview', 'tugasFileName')">
<img src="{{ asset('images/icon/gurud/link.png') }}" class="upload-icon" alt="Lampirkan file">
<p style="margin:6px 0 0;font-size:14px;color:#64748b">
<strong>Klik</strong> atau drag file ke sini
</p>
</div>
<div class="file-preview" id="tugasPreview">
📎 <span id="tugasFileName">-</span>
</div>
</div>
</div>
<div class="modal-footer">
@ -381,13 +421,13 @@ function openMateriModal(namaMapel, mengajars) {
select.appendChild(opt);
});
// Jika hanya 1 kelas, langsung pilih otomatis
if (mengajars.length === 1) select.value = mengajars[0].id_mengajar;
// Reset form
document.querySelector('#modalMateri input[name="judul_materi"]').value = '';
document.querySelector('#modalMateri textarea[name="deskripsi"]').value = '';
document.getElementById('materiPreview').classList.remove('show');
document.getElementById('materiFile').value = '';
new bootstrap.Modal(document.getElementById('modalMateri')).show();
}
@ -412,6 +452,8 @@ function openTugasModal(namaMapel, mengajars) {
document.querySelector('#modalTugas input[name="judul_tugas"]').value = '';
document.querySelector('#modalTugas textarea[name="keterangan"]').value = '';
document.querySelector('#modalTugas input[name="deadline"]').value = '';
document.getElementById('tugasPreview').classList.remove('show');
document.getElementById('tugasFile').value = '';
new bootstrap.Modal(document.getElementById('modalTugas')).show();
}
@ -421,8 +463,16 @@ function previewFile(input, previewId, nameId) {
const preview = document.getElementById(previewId);
const nameEl = document.getElementById(nameId);
if (input.files && input.files[0]) {
nameEl.textContent = input.files[0].name +
' (' + (input.files[0].size / 1024 / 1024).toFixed(2) + ' MB)';
const file = input.files[0];
if (file.size > 10 * 1024 * 1024) {
alert('❌ Ukuran file melebihi 10MB. Silakan pilih file yang lebih kecil.');
input.value = '';
preview.classList.remove('show');
return;
}
nameEl.textContent = file.name + ' (' + (file.size / 1024 / 1024).toFixed(2) + ' MB)';
preview.classList.add('show');
}
}

View File

@ -9,6 +9,9 @@
font-weight: 800;
margin-bottom: 6px;
margin-top: -20px;
display: flex;
align-items: center;
gap: 8px;
}
.back-link {
@ -53,8 +56,6 @@
border-radius: 99px;
}
.file-icon { font-size: 20px; }
.btn-hapus {
background: #fee2e2;
color: #ef4444;
@ -65,6 +66,9 @@
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
display: inline-flex;
align-items: center;
gap: 5px;
}
.btn-hapus:hover { background: #fca5a5; }
@ -79,7 +83,9 @@
font-weight: 600;
text-decoration: none;
transition: background 0.2s;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 5px;
}
.btn-unduh:hover { background: #bfdbfe; color: #1d4ed8; }
@ -92,6 +98,9 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.empty-state {
@ -106,19 +115,27 @@
<a href="{{ route('guru.mapel.index') }}" class="back-link"> Kembali ke Mata Pelajaran</a>
<h3 class="page-title">🗂️ History Materi</h3>
<h3 class="page-title">
<img src="{{ asset('images/icon/gurud/file.png') }}" class="icon-inline" alt="Ikon file">
History Materi
</h3>
<p style="color:#64748b;font-size:14px;margin-bottom:20px">
Semua materi yang pernah Anda upload.
</p>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-inline" alt="Berhasil">
{{ session('success') }}
</div>
@endif
<div class="custom-card">
@if($materiList->isEmpty())
<div class="empty-state">
<div style="font-size:48px;margin-bottom:12px">📭</div>
<div style="margin-bottom:12px">
<img src="{{ asset('images/icon/gurud/mailbox.png') }}" class="icon-lg" alt="Belum ada materi">
</div>
<p>Belum ada materi yang diupload.</p>
</div>
@else
@ -164,17 +181,24 @@
@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 => '📎',
$iconSrc = match(true) {
in_array($ext, ['pdf']) => asset('images/icon/gurud/file2.png'),
in_array($ext, ['doc','docx']) => asset('images/icon/gurud/buku1.png'),
in_array($ext, ['ppt','pptx']) => asset('images/icon/gurud/lb.png'),
in_array($ext, ['jpg','jpeg','png']) => asset('images/icon/gurud/image.png'),
default => asset('images/icon/gurud/link.png'),
};
$iconAlt = match(true) {
in_array($ext, ['pdf']) => 'File PDF',
in_array($ext, ['doc','docx']) => 'File Word',
in_array($ext, ['ppt','pptx']) => 'File PowerPoint',
in_array($ext, ['jpg','jpeg','png']) => 'File gambar',
default => 'File lampiran',
};
@endphp
<a href="{{ asset('storage/' . $materi->lampiran_materi) }}"
target="_blank" class="btn-unduh">
{{ $icon }} Unduh
<img src="{{ $iconSrc }}" class="icon-inline" alt="{{ $iconAlt }}"> Unduh
</a>
@else
<span style="font-size:12px;color:#94a3b8">Tidak ada file</span>
@ -186,7 +210,10 @@
onsubmit="return confirm('Yakin hapus materi ini?')">
@csrf
@method('DELETE')
<button type="submit" class="btn-hapus">🗑️ Hapus</button>
<button type="submit" class="btn-hapus">
<img src="{{ asset('images/icon/gurud/bin.png') }}" class="icon-inline" alt="Hapus">
Hapus
</button>
</form>
</td>
</tr>

View File

@ -46,7 +46,7 @@
<div class="mb-3">
<label class="form-label fw-bold">Nama Lengkap <span class="text-danger">*</span></label>
<input type="text" name="nama" class="form-control @error('nama') is-invalid @enderror"
<input type="text" name="nama" class="form-control @error('nama') is-invalid @enderror"
value="{{ old('nama', $guru->nama) }}" required>
@error('nama')
<small class="text-danger">{{ $message }}</small>
@ -55,7 +55,7 @@
<div class="mb-3">
<label class="form-label fw-bold">Password Baru</label>
<input type="password" name="password" class="form-control @error('password') is-invalid @enderror"
<input type="password" name="password" class="form-control @error('password') is-invalid @enderror"
placeholder="Kosongkan jika tidak ingin mengubah">
@error('password')
<small class="text-danger">{{ $message }}</small>
@ -64,14 +64,15 @@
<div class="mb-3">
<label class="form-label fw-bold">Konfirmasi Password Baru</label>
<input type="password" name="password_confirmation" class="form-control"
<input type="password" name="password_confirmation" class="form-control"
placeholder="Ulangi password baru">
<small class="text-muted">Isi hanya jika ingin mengubah password</small>
</div>
<div class="d-flex justify-content-end mt-4">
<button type="submit" class="btn btn-primary px-4">
💾 Simpan Perubahan
<button type="submit" class="btn btn-primary px-4 d-flex align-items-center gap-2">
<img src="{{ asset('images/icon/gurud/save.png') }}" class="icon-inline" alt="Simpan">
Simpan Perubahan
</button>
</div>

View File

@ -61,15 +61,11 @@
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="badge-info">
📖 Mode Hanya Lihat (Read Only)
</div>
<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">
<img src="{{ asset('images/icon/main/search.png') }}" width="18" height="18" alt="Cari siswa">
</button>
</div>
</form>
@ -92,7 +88,7 @@
<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 }}"
<option value="{{ $kelas->id_kelas }}"
{{ request('filter_kelas') == $kelas->id_kelas ? 'selected' : '' }}>
{{ $kelas->tingkat }} - {{ $kelas->nama_kelas }}
</option>

View File

@ -9,6 +9,9 @@
font-weight: 800;
margin-bottom: 6px;
margin-top: -20px;
display: flex;
align-items: center;
gap: 8px;
}
.back-link {
@ -86,6 +89,9 @@
font-weight: 700;
color: #1e293b;
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
}
.table-header { background: #a5e6ba; }
@ -95,7 +101,9 @@
font-weight: 700;
padding: 3px 10px;
border-radius: 99px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.status-dikumpulkan { background: #dcfce7; color: #16a34a; }
@ -111,7 +119,9 @@
font-size: 13px;
font-weight: 600;
text-decoration: none;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 5px;
transition: background 0.2s;
}
@ -171,14 +181,17 @@
<div class="info-meta">
<span class="meta-chip">
📚 {{ optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-' }}
<img src="{{ asset('images/icon/gurud/stacked.png') }}" class="icon-inline" alt="Mata pelajaran">
{{ optional(optional($tugas->mengajar)->mapel)->nama_mapel ?? '-' }}
</span>
<span class="meta-chip">
🏫 {{ optional(optional($tugas->mengajar)->kelas)->tingkat }}
{{ optional(optional($tugas->mengajar)->kelas)->nama_kelas ?? '-' }}
<img src="{{ asset('images/icon/gurud/school.png') }}" class="icon-inline" alt="Kelas">
{{ optional(optional($tugas->mengajar)->kelas)->tingkat }}
{{ optional(optional($tugas->mengajar)->kelas)->nama_kelas ?? '-' }}
</span>
<span class="meta-chip {{ $isLewat ? 'red' : 'green' }}">
Deadline: {{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }}
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="icon-inline" alt="Deadline">
Deadline: {{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }}
{{ $isLewat ? 'Sudah lewat' : 'Masih aktif' }}
</span>
</div>
@ -208,11 +221,16 @@
{{-- DAFTAR PENGUMPULAN --}}
<div class="custom-card">
<p class="section-title">📥 Daftar Pengumpulan Siswa</p>
<p class="section-title">
<img src="{{ asset('images/icon/gurud/pengumpulan.png') }}" class="icon-inline" alt="Pengumpulan tugas">
Daftar Pengumpulan Siswa
</p>
@if($tugas->pengumpulanTugas->isEmpty())
<div class="empty-state">
<div style="font-size:40px;margin-bottom:10px">📭</div>
<div style="margin-bottom:10px">
<img src="{{ asset('images/icon/gurud/mailbox.png') }}" class="icon-lg" alt="Belum ada pengumpulan">
</div>
<p>Belum ada siswa yang mengumpulkan tugas ini.</p>
</div>
@else
@ -243,17 +261,22 @@
</td>
<td class="text-center">
<span class="status-badge status-{{ $kumpul->status }}">
@if($kumpul->status === 'dikumpulkan') Tepat Waktu
@elseif($kumpul->status === 'terlambat') Terlambat
@else Belum
@if($kumpul->status === 'dikumpulkan')
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-inline" alt="Tepat waktu"> Tepat Waktu
@elseif($kumpul->status === 'terlambat')
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="icon-inline" alt="Terlambat"> Terlambat
@else
<img src="{{ asset('images/icon/gurud/x.png') }}" class="icon-inline" alt="Belum dikumpulkan"> Belum
@endif
</span>
</td>
<td class="text-center">
@if($kumpul->exp > 0)
<span style="background:#fef9c3;color:#b45309;font-size:12px;
font-weight:700;padding:3px 10px;border-radius:99px">
{{ $kumpul->exp }} EXP
font-weight:700;padding:3px 10px;border-radius:99px;
display:inline-flex;align-items:center;gap:4px">
<img src="{{ asset('images/icon/gurud/star.png') }}" class="icon-inline" alt="EXP">
{{ $kumpul->exp }} EXP
</span>
@else
<span style="font-size:12px;color:#94a3b8">Belum dinilai</span>
@ -263,7 +286,7 @@
@if($kumpul->lampiran_tugas)
<a href="{{ asset('storage/' . $kumpul->lampiran_tugas) }}"
target="_blank" class="btn-unduh">
📎 Unduh
<img src="{{ asset('images/icon/gurud/link.png') }}" class="icon-inline" alt="Unduh file"> Unduh
</a>
@else
<span style="font-size:12px;color:#94a3b8">-</span>

View File

@ -9,6 +9,9 @@
font-weight: 800;
margin-bottom: 6px;
margin-top: -20px;
display: flex;
align-items: center;
gap: 8px;
}
.back-link {
@ -58,7 +61,9 @@
font-weight: 600;
padding: 3px 10px;
border-radius: 99px;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 4px;
}
.deadline-lewat { background: #fee2e2; color: #ef4444; }
@ -79,7 +84,9 @@
font-size: 13px;
font-weight: 600;
text-decoration: none;
display: inline-block;
display: inline-flex;
align-items: center;
gap: 5px;
transition: background 0.2s;
}
@ -95,6 +102,9 @@
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
display: inline-flex;
align-items: center;
gap: 5px;
}
.btn-hapus:hover { background: #fca5a5; }
@ -107,6 +117,9 @@
margin-bottom: 16px;
font-weight: 500;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
}
.empty-state {
@ -121,19 +134,27 @@
<a href="{{ route('guru.mapel.index') }}" class="back-link"> Kembali ke Mata Pelajaran</a>
<h3 class="page-title">📑 History Tugas</h3>
<h3 class="page-title">
<img src="{{ asset('images/icon/gurud/history.png') }}" class="icon-inline" alt="Ikon history">
History Tugas
</h3>
<p style="color:#64748b;font-size:14px;margin-bottom:20px">
Semua tugas yang pernah Anda buat.
</p>
@if(session('success'))
<div class="alert-success-custom"> {{ session('success') }}</div>
<div class="alert-success-custom">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-inline" alt="Berhasil">
{{ session('success') }}
</div>
@endif
<div class="custom-card">
@if($tugasList->isEmpty())
<div class="empty-state">
<div style="font-size:48px;margin-bottom:12px">📭</div>
<div style="margin-bottom:12px">
<img src="{{ asset('images/icon/gurud/mailbox.png') }}" class="icon-lg" alt="Belum ada tugas">
</div>
<p>Belum ada tugas yang dibuat.</p>
</div>
@else
@ -177,9 +198,15 @@
</span>
</td>
<td class="text-center">
<span class="deadline-badge {{ $isLewat ? 'deadline-lewat' : 'deadline-aktif' }}">
{{ $isLewat ? '⏰ Lewat' : '✅ Aktif' }}
</span>
@if($isLewat)
<span class="deadline-badge deadline-lewat">
<img src="{{ asset('images/icon/gurud/alarm.png') }}" class="icon-inline" alt="Deadline lewat"> Lewat
</span>
@else
<span class="deadline-badge deadline-aktif">
<img src="{{ asset('images/icon/gurud/v.png') }}" class="icon-inline" alt="Deadline aktif"> Aktif
</span>
@endif
<div style="font-size:12px;color:#64748b;margin-top:4px">
{{ \Carbon\Carbon::parse($tugas->deadline)->format('d M Y, H:i') }}
</div>
@ -192,14 +219,16 @@
<div class="d-flex gap-1 justify-content-center">
<a href="{{ route('guru.tugas.detail', $tugas->id_tugas) }}"
class="btn-detail">
👁️ Detail
<img src="{{ asset('images/icon/gurud/detail.png') }}" class="icon-inline" alt="Detail tugas"> Detail
</a>
<form action="{{ route('guru.tugas.destroy', $tugas->id_tugas) }}"
method="POST"
onsubmit="return confirm('Yakin hapus tugas ini? Semua pengumpulan juga akan terhapus.')">
@csrf
@method('DELETE')
<button type="submit" class="btn-hapus">🗑️</button>
<button type="submit" class="btn-hapus">
<img src="{{ asset('images/icon/gurud/bin.png') }}" class="icon-inline" alt="Hapus tugas">
</button>
</form>
</div>
</td>