dashboard admin guru
This commit is contained in:
parent
7b0cb0350f
commit
d06fafb7cc
|
|
@ -5,6 +5,7 @@
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Mengajar;
|
||||
use App\Models\Siswa;
|
||||
use App\Models\Tugas;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DashboardController extends Controller
|
||||
|
|
@ -15,25 +16,47 @@ public function index()
|
|||
|
||||
try {
|
||||
$totalKelas = Mengajar::where('id_guru', $guru->id_guru)
|
||||
->distinct('id_kelas')
|
||||
->count('id_kelas');
|
||||
->distinct('id_kelas')->count('id_kelas');
|
||||
|
||||
$totalMapel = Mengajar::where('id_guru', $guru->id_guru)
|
||||
->distinct('id_mapel')
|
||||
->count('id_mapel');
|
||||
->distinct('id_mapel')->count('id_mapel');
|
||||
|
||||
$kelasIds = Mengajar::where('id_guru', $guru->id_guru)
|
||||
->pluck('id_kelas')
|
||||
->unique();
|
||||
$kelasIds = Mengajar::where('id_guru', $guru->id_guru)
|
||||
->pluck('id_kelas')->unique();
|
||||
|
||||
$totalSiswa = Siswa::whereIn('id_kelas', $kelasIds)->count();
|
||||
|
||||
// Chart: pengumpulan tugas per tugas (6 tugas terbaru)
|
||||
$idMengajars = Mengajar::where('id_guru', $guru->id_guru)->pluck('id_mengajar');
|
||||
|
||||
$tugasList = Tugas::with(['mengajar.mapel', 'pengumpulanTugas'])
|
||||
->whereIn('id_mengajar', $idMengajars)
|
||||
->latest()->take(6)->get();
|
||||
|
||||
$chartLabels = [];
|
||||
$chartSudah = [];
|
||||
$chartBelum = [];
|
||||
|
||||
foreach ($tugasList as $tugas) {
|
||||
$namaMapel = optional($tugas->mengajar->mapel)->nama_mapel ?? 'Mapel';
|
||||
$chartLabels[] = strlen($namaMapel) > 14 ? substr($namaMapel, 0, 14) . '…' : $namaMapel;
|
||||
$sudah = $tugas->pengumpulanTugas->count();
|
||||
$chartSudah[] = $sudah;
|
||||
$chartBelum[] = max(0, $totalSiswa - $sudah);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$totalKelas = 0;
|
||||
$totalMapel = 0;
|
||||
$totalSiswa = 0;
|
||||
$totalKelas = 0;
|
||||
$totalMapel = 0;
|
||||
$totalSiswa = 0;
|
||||
$chartLabels = [];
|
||||
$chartSudah = [];
|
||||
$chartBelum = [];
|
||||
}
|
||||
|
||||
return view('guru.dashboard', compact('totalKelas', 'totalMapel', 'totalSiswa'));
|
||||
return view('guru.dashboard', compact(
|
||||
'totalKelas', 'totalMapel', 'totalSiswa',
|
||||
'chartLabels', 'chartSudah', 'chartBelum'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -956,7 +956,6 @@ function openTambahModal() {
|
|||
|
||||
data.soal.forEach(s => tambahSoal('editSoalContainer', s));
|
||||
|
||||
// Recalc EXP otomatis setiap kali angka EXP di modal edit berubah
|
||||
const expElEdit = document.getElementById('editExp');
|
||||
expElEdit.oninput = () => recalcExp('editSoalContainer');
|
||||
|
||||
|
|
|
|||
|
|
@ -4,118 +4,64 @@
|
|||
|
||||
@push('styles')
|
||||
<style>
|
||||
/* ── PAGE ── */
|
||||
.dash-header { margin-bottom: 28px; }
|
||||
.dash-title { font-size: 22px; font-weight: 800; color: #0f1f3d; margin-bottom: 2px; }
|
||||
.dash-sub { font-size: 13px; color: #94a3b8; }
|
||||
|
||||
/* ── STAT CARDS ── */
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-bottom: 28px; }
|
||||
/* STAT CARDS */
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-bottom: 24px; }
|
||||
|
||||
.stat-card {
|
||||
border-radius: 20px;
|
||||
padding: 24px 22px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
border-radius: 20px; padding: 24px 22px;
|
||||
position: relative; overflow: hidden;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
animation: fadeUp 0.4s ease both;
|
||||
}
|
||||
|
||||
.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; }
|
||||
.stat-card:nth-child(2) { background: linear-gradient(135deg, #e8fff3, #b8f5d4); animation-delay: 0.07s; }
|
||||
.stat-card:nth-child(3) { background: linear-gradient(135deg, #eef4ff, #c5d9ff); animation-delay: 0.14s; }
|
||||
.stat-card:nth-child(4) { background: linear-gradient(135deg, #ffeef4, #ffc5db); animation-delay: 0.21s; }
|
||||
|
||||
.stat-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 120px; height: 120px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.15;
|
||||
right: -30px; bottom: -30px;
|
||||
}
|
||||
|
||||
.stat-card::after { content: ''; position: absolute; width: 120px; height: 120px; border-radius: 50%; opacity: 0.15; right: -30px; bottom: -30px; }
|
||||
.stat-card:nth-child(1)::after { background: #f97316; }
|
||||
.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-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; 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); }
|
||||
.stat-card:nth-child(3) .stat-icon { background: rgba(43,142,243,0.15); }
|
||||
.stat-card:nth-child(4) .stat-icon { background: rgba(236,72,153,0.15); }
|
||||
|
||||
/* ── BOTTOM ROW ── */
|
||||
.dash-bottom { display: grid; grid-template-columns: 1fr 340px; gap: 20px; }
|
||||
/* BOTTOM */
|
||||
.dash-bottom { display: grid; grid-template-columns: 1fr 320px; gap: 20px; animation: fadeUp 0.4s ease 0.28s both; }
|
||||
|
||||
/* Card container */
|
||||
.dash-card {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
border: 1.5px solid #e8f0fb;
|
||||
padding: 24px;
|
||||
box-shadow: 0 4px 20px rgba(43,142,243,0.06);
|
||||
animation: fadeUp 0.4s ease 0.28s both;
|
||||
}
|
||||
|
||||
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; }
|
||||
.dash-card { background: white; border-radius: 20px; border: 1.5px solid #e8f0fb; padding: 24px; box-shadow: 0 4px 20px rgba(43,142,243,0.06); }
|
||||
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
|
||||
.card-title { font-size: 15px; font-weight: 700; color: #0f1f3d; }
|
||||
.card-badge { font-size: 11px; font-weight: 700; background: #e8f4ff; color: #2b8ef3; padding: 3px 10px; border-radius: 99px; }
|
||||
.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 */
|
||||
.chart-wrap { position: relative; height: 240px; }
|
||||
|
||||
/* Challenge list */
|
||||
.challenge-item {
|
||||
background: #f8faff;
|
||||
border-radius: 14px;
|
||||
padding: 14px 16px;
|
||||
margin-bottom: 10px;
|
||||
border-left: 4px solid #2b8ef3;
|
||||
transition: all 0.2s;
|
||||
cursor: default;
|
||||
}
|
||||
/* 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; }
|
||||
|
||||
.challenge-item:hover { background: #eef4ff; transform: translateX(3px); }
|
||||
|
||||
.ch-kelas { font-size: 12px; font-weight: 700; color: #2b8ef3; margin-bottom: 3px; }
|
||||
.challenge-item:nth-child(2) .ch-kelas { color: #16a34a; }
|
||||
.challenge-item:nth-child(3) .ch-kelas { color: #ea580c; }
|
||||
|
||||
.ch-judul { font-size: 13px; font-weight: 600; color: #0f1f3d; margin-bottom: 3px; }
|
||||
.ch-meta { font-size: 11px; color: #94a3b8; }
|
||||
|
||||
.btn-add-challenge {
|
||||
display: flex; align-items: center; justify-content: center; gap: 6px;
|
||||
width: 100%; padding: 11px;
|
||||
background: white; border: 2px dashed #dbeeff;
|
||||
border-radius: 12px; color: #2b8ef3; font-size: 13px; font-weight: 700;
|
||||
text-decoration: none; margin-top: 4px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-add-challenge { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; padding: 11px; background: white; border: 2px dashed #dbeeff; border-radius: 12px; color: #2b8ef3; font-size: 13px; font-weight: 700; text-decoration: none; margin-top: 4px; transition: all 0.2s; }
|
||||
.btn-add-challenge:hover { background: #e8f4ff; border-color: #2b8ef3; color: #2b8ef3; }
|
||||
|
||||
@keyframes fadeUp {
|
||||
|
|
@ -124,7 +70,7 @@
|
|||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.stat-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.stat-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
.dash-bottom { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
|
|
@ -134,7 +80,6 @@
|
|||
|
||||
@php
|
||||
use Carbon\Carbon;
|
||||
$greeting = Carbon::now()->hour < 12 ? 'Selamat Pagi' : (Carbon::now()->hour < 17 ? 'Selamat Siang' : 'Selamat Malam');
|
||||
@endphp
|
||||
|
||||
<div class="dash-header">
|
||||
|
|
@ -165,7 +110,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{-- BOTTOM: Chart + Challenge --}}
|
||||
{{-- BOTTOM --}}
|
||||
<div class="dash-bottom">
|
||||
|
||||
{{-- Bar Chart --}}
|
||||
|
|
@ -183,7 +128,7 @@
|
|||
<div class="dash-card">
|
||||
<div class="card-head">
|
||||
<div class="card-title">Challenge Terbaru</div>
|
||||
<a href="{{ route('admin.challenge.index') }}" class="card-badge" style="text-decoration:none">Lihat Semua →</a>
|
||||
<a href="{{ route('admin.challenge.index') }}" class="card-badge">Lihat Semua →</a>
|
||||
</div>
|
||||
|
||||
@forelse($latestChallenges as $ch)
|
||||
|
|
@ -221,16 +166,16 @@
|
|||
const values = @json($chartData->pluck('siswa_count'));
|
||||
|
||||
const colors = [
|
||||
'rgba(43,142,243,0.8)',
|
||||
'rgba(34,197,94,0.8)',
|
||||
'rgba(249,115,22,0.8)',
|
||||
'rgba(168,85,247,0.8)',
|
||||
'rgba(236,72,153,0.8)',
|
||||
'rgba(234,179,8,0.8)',
|
||||
'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');
|
||||
new Chart(ctx, {
|
||||
const kelasChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
|
|
@ -238,7 +183,7 @@
|
|||
label: 'Jumlah Siswa',
|
||||
data: values,
|
||||
backgroundColor: labels.map((_, i) => colors[i % colors.length]),
|
||||
borderRadius: 10,
|
||||
borderRadius: 8,
|
||||
borderSkipped: false,
|
||||
}]
|
||||
},
|
||||
|
|
@ -248,16 +193,14 @@
|
|||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: ctx => ` ${ctx.parsed.y} siswa`
|
||||
}
|
||||
callbacks: { label: ctx => ` ${ctx.parsed.y} siswa` }
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
grid: { color: '#f1f5f9' },
|
||||
ticks: { font: { family: 'Poppins', size: 11 }, color: '#94a3b8' }
|
||||
ticks: { font: { family: 'Poppins', size: 11 }, color: '#94a3b8', stepSize: 1 }
|
||||
},
|
||||
x: {
|
||||
grid: { display: false },
|
||||
|
|
@ -266,5 +209,10 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Fix resize saat sidebar toggle
|
||||
document.getElementById('sidebarToggleBtn')?.addEventListener('click', () => {
|
||||
setTimeout(() => kelasChart.resize(), 320);
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -5,70 +5,58 @@
|
|||
@push('styles')
|
||||
<style>
|
||||
.dash-header { margin-bottom: 28px; }
|
||||
.dash-title { font-size: 22px; font-weight: 800; color: #0f1f3d; margin-bottom: 2px; }
|
||||
.dash-sub { font-size: 13px; color: #94a3b8; }
|
||||
|
||||
/* STAT CARDS */
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-bottom: 28px; }
|
||||
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-bottom: 24px; }
|
||||
|
||||
.stat-card {
|
||||
border-radius: 20px; padding: 28px 24px;
|
||||
border-radius: 20px; padding: 24px 22px;
|
||||
position: relative; overflow: hidden;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
animation: fadeUp 0.4s ease both;
|
||||
}
|
||||
|
||||
.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, #eef4ff, #c5d9ff); animation-delay: 0s; }
|
||||
.stat-card:nth-child(2) { background: linear-gradient(135deg, #e8fff3, #b8f5d4); animation-delay: 0.07s; }
|
||||
.stat-card:nth-child(3) { background: linear-gradient(135deg, #fff7e6, #ffe4b2); animation-delay: 0.14s; }
|
||||
|
||||
.stat-card::after { content: ''; position: absolute; width: 120px; height: 120px; border-radius: 50%; opacity: 0.15; right: -30px; bottom: -30px; }
|
||||
.stat-card:nth-child(1)::after { background: #2b8ef3; }
|
||||
.stat-card:nth-child(2)::after { background: #22c55e; }
|
||||
.stat-card:nth-child(3)::after { background: #f97316; }
|
||||
|
||||
.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: #1d5fb8; }
|
||||
.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-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); }
|
||||
|
||||
/* INFO CARD */
|
||||
.info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; animation: fadeUp 0.4s ease 0.25s both; }
|
||||
/* BOTTOM GRID */
|
||||
.dash-bottom { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; animation: fadeUp 0.4s ease 0.2s both; }
|
||||
|
||||
.dash-card { background: white; border-radius: 20px; border: 1.5px solid #e8f0fb; padding: 24px; box-shadow: 0 4px 20px rgba(43,142,243,0.06); }
|
||||
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
|
||||
.card-title { font-size: 15px; font-weight: 700; color: #0f1f3d; }
|
||||
.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; color: #2b8ef3; }
|
||||
.card-badge:hover { background: #dbeeff; }
|
||||
|
||||
/* Chart */
|
||||
.chart-wrap { position: relative; height: 220px; }
|
||||
|
||||
/* Legend */
|
||||
.chart-legend { display: flex; gap: 16px; margin-top: 12px; }
|
||||
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #64748b; font-weight: 500; }
|
||||
.legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
|
||||
|
||||
/* Mapel list */
|
||||
.mapel-item { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 12px; margin-bottom: 8px; background: #f8faff; transition: background 0.2s; }
|
||||
.mapel-item { display: flex; align-items: center; gap: 12px; padding: 11px 14px; border-radius: 12px; margin-bottom: 8px; background: #f8faff; transition: background 0.2s; }
|
||||
.mapel-item:hover { background: #eef4ff; }
|
||||
.mapel-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
|
||||
.mapel-name { font-size: 13px; font-weight: 600; color: #1e293b; flex: 1; }
|
||||
.mapel-kelas { font-size: 11px; color: #94a3b8; }
|
||||
|
||||
/* Quick links */
|
||||
.quick-link {
|
||||
display: flex; align-items: center; gap: 14px;
|
||||
padding: 14px 16px; border-radius: 14px;
|
||||
background: #f8faff; border: 1.5px solid #e8f0fb;
|
||||
text-decoration: none; margin-bottom: 10px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.quick-link:hover { background: #eef4ff; border-color: #2b8ef3; transform: translateX(4px); }
|
||||
.ql-icon { width: 40px; height: 40px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
|
||||
.ql-title { font-size: 13px; font-weight: 700; color: #0f1f3d; margin-bottom: 1px; }
|
||||
.ql-desc { font-size: 11px; color: #94a3b8; }
|
||||
.ql-arrow { margin-left: auto; color: #94a3b8; font-size: 16px; }
|
||||
.mapel-kelas { font-size: 11px; color: #94a3b8; background: #f1f5f9; padding: 2px 8px; border-radius: 99px; }
|
||||
|
||||
@keyframes fadeUp {
|
||||
from { opacity: 0; transform: translateY(16px); }
|
||||
|
|
@ -76,8 +64,8 @@
|
|||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.stat-grid { grid-template-columns: 1fr 1fr; }
|
||||
.info-grid { grid-template-columns: 1fr; }
|
||||
.stat-grid { grid-template-columns: 1fr 1fr; }
|
||||
.dash-bottom { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
|
@ -87,17 +75,13 @@
|
|||
@php
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Mengajar;
|
||||
$guru = Auth::guard('guru')->user();
|
||||
$greeting = Carbon::now()->hour < 12 ? 'Selamat Pagi' : (Carbon::now()->hour < 17 ? 'Selamat Siang' : 'Selamat Malam');
|
||||
|
||||
// Ambil mengajar dengan relasi mapel & kelas
|
||||
$guru = Auth::guard('guru')->user();
|
||||
$mengajars = Mengajar::with(['mapel', 'kelas'])
|
||||
->where('id_guru', $guru->id_guru)
|
||||
->get();
|
||||
->where('id_guru', $guru->id_guru)->get();
|
||||
$dotColors = ['#2b8ef3','#22c55e','#f97316','#a855f7','#ec4899','#eab308'];
|
||||
@endphp
|
||||
|
||||
<div class="dash-header">
|
||||
<div class="dash-title">{{ $greeting }}, {{ $guru->nama ?? 'Guru' }} 👋</div>
|
||||
<div class="dash-sub">{{ Carbon::now()->isoFormat('dddd, D MMMM Y') }}</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -120,8 +104,37 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{-- INFO GRID --}}
|
||||
<div class="info-grid">
|
||||
{{-- BOTTOM --}}
|
||||
<div class="dash-bottom">
|
||||
|
||||
{{-- Stacked Bar Chart: Pengumpulan Tugas --}}
|
||||
<div class="dash-card">
|
||||
<div class="card-head">
|
||||
<div class="card-title">Status Pengumpulan Tugas</div>
|
||||
<a href="{{ route('guru.tugas.history') }}" class="card-badge">Lihat Semua →</a>
|
||||
</div>
|
||||
|
||||
@if(count($chartLabels) > 0)
|
||||
<div class="chart-wrap">
|
||||
<canvas id="tugasChart"></canvas>
|
||||
</div>
|
||||
<div class="chart-legend">
|
||||
<div class="legend-item">
|
||||
<div class="legend-dot" style="background:#2b8ef3"></div>
|
||||
Sudah Kumpul
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-dot" style="background:#e2e8f0"></div>
|
||||
Belum Kumpul
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div style="text-align:center;padding:40px 20px;color:#94a3b8;">
|
||||
<div style="font-size:36px;margin-bottom:8px">📋</div>
|
||||
<div style="font-size:13px">Belum ada tugas dibuat.</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- Daftar Mengajar --}}
|
||||
<div class="dash-card">
|
||||
|
|
@ -130,9 +143,7 @@
|
|||
<a href="{{ route('guru.mapel.index') }}" class="card-badge">Lihat Semua →</a>
|
||||
</div>
|
||||
|
||||
@php $dotColors = ['#2b8ef3','#22c55e','#f97316','#a855f7','#ec4899','#eab308']; @endphp
|
||||
|
||||
@forelse($mengajars->take(6) as $i => $m)
|
||||
@forelse($mengajars->take(7) as $i => $m)
|
||||
<div class="mapel-item">
|
||||
<div class="mapel-dot" style="background:{{ $dotColors[$i % count($dotColors)] }}"></div>
|
||||
<div class="mapel-name">{{ optional($m->mapel)->nama_mapel ?? '-' }}</div>
|
||||
|
|
@ -145,49 +156,58 @@
|
|||
@endforelse
|
||||
</div>
|
||||
|
||||
{{-- Quick Links --}}
|
||||
<div class="dash-card">
|
||||
<div class="card-head">
|
||||
<div class="card-title">Akses Cepat</div>
|
||||
</div>
|
||||
|
||||
<a href="{{ route('guru.mapel.index') }}" class="quick-link">
|
||||
<div class="ql-icon" style="background:#e8f4ff">📖</div>
|
||||
<div>
|
||||
<div class="ql-title">Upload Materi</div>
|
||||
<div class="ql-desc">Tambah modul belajar untuk siswa</div>
|
||||
</div>
|
||||
<span class="ql-arrow">›</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('guru.mapel.index') }}" class="quick-link">
|
||||
<div class="ql-icon" style="background:#eefaf3">📝</div>
|
||||
<div>
|
||||
<div class="ql-title">Buat Tugas</div>
|
||||
<div class="ql-desc">Buat dan kelola tugas kelas</div>
|
||||
</div>
|
||||
<span class="ql-arrow">›</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('guru.tugas.history') }}" class="quick-link">
|
||||
<div class="ql-icon" style="background:#fff7e6">📋</div>
|
||||
<div>
|
||||
<div class="ql-title">History Tugas</div>
|
||||
<div class="ql-desc">Lihat pengumpulan tugas siswa</div>
|
||||
</div>
|
||||
<span class="ql-arrow">›</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('guru.leaderboard.index') }}" class="quick-link">
|
||||
<div class="ql-icon" style="background:#f5eeff">🏆</div>
|
||||
<div>
|
||||
<div class="ql-title">Leaderboard</div>
|
||||
<div class="ql-desc">Pantau peringkat EXP kelas</div>
|
||||
</div>
|
||||
<span class="ql-arrow">›</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||
<script>
|
||||
@if(count($chartLabels) > 0)
|
||||
const tugasCtx = document.getElementById('tugasChart').getContext('2d');
|
||||
const tugasChart = new Chart(tugasCtx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: @json($chartLabels),
|
||||
datasets: [
|
||||
{
|
||||
label: 'Sudah Kumpul',
|
||||
data: @json($chartSudah),
|
||||
backgroundColor: 'rgba(43,142,243,0.85)',
|
||||
borderRadius: { topLeft: 6, topRight: 6, bottomLeft: 0, bottomRight: 0 },
|
||||
borderSkipped: false,
|
||||
},
|
||||
{
|
||||
label: 'Belum Kumpul',
|
||||
data: @json($chartBelum),
|
||||
backgroundColor: 'rgba(226,232,240,0.9)',
|
||||
borderRadius: { topLeft: 6, topRight: 6, bottomLeft: 0, bottomRight: 0 },
|
||||
borderSkipped: false,
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: ctx => ` ${ctx.dataset.label}: ${ctx.parsed.y} siswa`
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: { stacked: true, grid: { display: false }, ticks: { font: { family: 'Poppins', size: 11 }, color: '#64748b' } },
|
||||
y: { stacked: true, beginAtZero: true, grid: { color: '#f1f5f9' }, ticks: { font: { family: 'Poppins', size: 11 }, color: '#94a3b8', stepSize: 1 } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Resize chart saat sidebar toggle
|
||||
document.getElementById('sidebarToggleBtn')?.addEventListener('click', () => {
|
||||
setTimeout(() => tugasChart.resize(), 320);
|
||||
});
|
||||
@endif
|
||||
</script>
|
||||
@endpush
|
||||
Loading…
Reference in New Issue