239 lines
9.6 KiB
PHP
239 lines
9.6 KiB
PHP
@extends('guru.layouts.app')
|
|
|
|
@section('title', 'Dashboard Guru')
|
|
|
|
@push('styles')
|
|
<style>
|
|
.dash-header { margin-bottom: 28px; }
|
|
.dash-sub { font-size: 13px; color: #94a3b8; }
|
|
|
|
/* STAT CARDS */
|
|
.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-bottom: 24px; }
|
|
|
|
.stat-card {
|
|
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; 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); }
|
|
|
|
.stat-link {
|
|
display: inline-block;
|
|
margin-top: 12px;
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
padding: 4px 12px;
|
|
border-radius: 99px;
|
|
text-decoration: none;
|
|
transition: opacity 0.2s;
|
|
}
|
|
.stat-link:hover { opacity: 0.75; }
|
|
.stat-card:nth-child(1) .stat-link { background: rgba(43,142,243,0.15); color: #1d5fb8; }
|
|
.stat-card:nth-child(2) .stat-link { background: rgba(34,197,94,0.15); color: #15803d; }
|
|
.stat-card:nth-child(3) .stat-link { background: rgba(249,115,22,0.15); color: #c2651a; }
|
|
|
|
/* 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; }
|
|
|
|
/* 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: 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; background: #f1f5f9; padding: 2px 8px; border-radius: 99px; }
|
|
|
|
@keyframes fadeUp {
|
|
from { opacity: 0; transform: translateY(16px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
.stat-grid { grid-template-columns: 1fr 1fr; }
|
|
.dash-bottom { grid-template-columns: 1fr; }
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
|
|
@php
|
|
use Carbon\Carbon;
|
|
use App\Models\Mengajar;
|
|
$guru = Auth::guard('guru')->user();
|
|
$mengajars = Mengajar::with(['mapel', 'kelas'])
|
|
->where('id_guru', $guru->id_guru)->get();
|
|
$dotColors = ['#2b8ef3','#22c55e','#f97316','#a855f7','#ec4899','#eab308'];
|
|
@endphp
|
|
|
|
<div class="dash-header">
|
|
<div class="dash-sub">{{ Carbon::now()->isoFormat('dddd, D MMMM Y') }}</div>
|
|
</div>
|
|
|
|
{{-- STAT CARDS --}}
|
|
<div class="stat-grid">
|
|
<div class="stat-card">
|
|
<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">
|
|
<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">
|
|
<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>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 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="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
|
|
</div>
|
|
|
|
{{-- Daftar Mengajar --}}
|
|
<div class="dash-card">
|
|
<div class="card-head">
|
|
<div class="card-title">Mata Pelajaran & Kelas</div>
|
|
<a href="{{ route('guru.mapel.index') }}" class="card-badge">Lihat Semua →</a>
|
|
</div>
|
|
|
|
@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>
|
|
<div class="mapel-kelas">{{ optional($m->kelas)->nama_kelas ?? '-' }}</div>
|
|
</div>
|
|
@empty
|
|
<div style="text-align:center;padding:20px;color:#94a3b8;font-size:13px;">
|
|
Belum ada data mengajar.
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
|
|
</div>
|
|
|
|
@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 |