MIF_E31230892/sim-pkpps/storage/framework/views/313421d53bce467b3badbcdb3a6...

777 lines
34 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php $__env->startSection('content'); ?>
<style>
/* ── Filter Periode ── */
.period-bar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.period-btn {
padding:6px 14px; border-radius:20px; border:1px solid #e2e8f0;
background:#fff; cursor:pointer; font-size:0.85rem; transition:all .2s;
}
.period-btn:hover, .period-btn.active {
background:var(--primary-color); color:#fff; border-color:var(--primary-color);
}
.custom-range { display:none; align-items:center; gap:8px; }
.custom-range.show { display:flex; }
.custom-range input[type=date] {
padding:5px 10px; border:1px solid #e2e8f0; border-radius:6px; font-size:0.85rem;
}
/* ── KPI Strip ── */
.kpi-strip {
display:grid;
grid-template-columns: repeat(5, 1fr);
gap:12px;
margin-bottom:18px;
}
.kpi-card {
background:#fff; border-radius:10px; padding:14px 16px;
box-shadow:0 2px 8px rgba(0,0,0,.06);
border-top:3px solid transparent;
}
.kpi-card.kpi-hadir { border-color:#10B981; }
.kpi-card.kpi-alpa { border-color:#EF4444; }
.kpi-card.kpi-avg { border-color:#3B82F6; }
.kpi-card.kpi-warning{ border-color:#F59E0B; }
.kpi-card.kpi-info { border-color:#6366F1; }
.kpi-label { font-size:0.78rem; color:#6B7280; margin-bottom:4px; }
.kpi-value { font-size:1.45rem; font-weight:700; color:var(--primary-dark); line-height:1.1; }
.kpi-context { font-size:0.75rem; color:#9CA3AF; margin-top:4px; }
.kpi-trend { font-size:0.78rem; margin-top:5px; display:flex; align-items:center; gap:4px; }
.kpi-trend.up { color:#10B981; }
.kpi-trend.down { color:#EF4444; }
.kpi-trend.neutral { color:#6B7280; }
/* ── Dua kolom ── */
.two-col { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:16px; }
.three-col { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:16px; }
@media(max-width:900px){
.kpi-strip { grid-template-columns:repeat(2,1fr); }
.two-col { grid-template-columns:1fr; }
.three-col { grid-template-columns:1fr; }
}
/* ── Cards ── */
.panel {
background:#fff; border-radius:10px; padding:16px;
box-shadow:0 2px 8px rgba(0,0,0,.06);
}
.panel-title {
font-size:.93rem; font-weight:600; margin:0 0 12px;
display:flex; align-items:center; gap:8px;
}
.panel-title a { font-size:.78rem; margin-left:auto; color:var(--primary-color); font-weight:400; }
/* ── List item kegiatan ── */
.kg-item {
display:flex; align-items:center; gap:10px;
padding:8px 0; border-bottom:1px solid #f1f5f9; font-size:.84rem;
}
.kg-item:last-child { border-bottom:none; }
.kg-name { flex:1; font-weight:500; }
.kg-context { font-size:.76rem; color:#6B7280; }
.kg-persen {
font-weight:700; font-size:.9rem; min-width:52px; text-align:right;
}
/* ── Anomali ── */
.alert-row {
display:flex; align-items:flex-start; gap:10px;
padding:10px 12px; border-radius:8px; margin-bottom:6px;
font-size:.85rem; border-left:4px solid transparent;
}
.alert-row:last-child { margin-bottom:0; }
.alert-row.a-danger { background:#FEF2F2; border-color:#EF4444; color:#991B1B; }
.alert-row.a-warning { background:#FFFBEB; border-color:#F59E0B; color:#92400E; }
.alert-row.a-info { background:#EFF6FF; border-color:#3B82F6; color:#1E40AF; }
.alert-row.a-success { background:#ECFDF5; border-color:#10B981; color:#065F46; }
.alert-text { flex:1; }
.alert-title { font-weight:600; font-size:.86rem; }
.alert-desc { font-size:.8rem; opacity:.85; margin-top:2px; }
/* ── Kelas chart legend ── */
.kelas-legend { display:flex; gap:16px; flex-wrap:wrap; margin-top:10px; font-size:.78rem; }
.kelas-legend-item { display:flex; align-items:center; gap:5px; color:#6B7280; }
.kelas-legend-dot { width:10px; height:10px; border-radius:50%; flex-shrink:0; }
/* ── Santri perlu perhatian ── */
.spp-item {
display:flex; align-items:center; gap:10px;
padding:7px 0; border-bottom:1px solid #f1f5f9; font-size:.84rem;
}
.spp-item:last-child { border-bottom:none; }
.spp-rank { width:22px; text-align:center; color:#9CA3AF; font-size:.78rem; }
.spp-name { flex:1; font-weight:500; }
.spp-pct { font-weight:700; color:#EF4444; }
.spp-ctx { font-size:.75rem; color:#9CA3AF; }
/* ── Trend chart ── */
.chart-wrap { background:#fff; border-radius:10px; padding:16px; box-shadow:0 2px 8px rgba(0,0,0,.06); margin-bottom:16px; }
.chart-wrap h4 { margin:0 0 10px; font-size:.93rem; color:var(--primary-dark); }
</style>
<div class="page-header">
<h2><i class="fas fa-chart-line"></i> Laporan Kegiatan</h2>
</div>
<div class="content-box" style="margin-bottom:16px;">
<form method="GET" id="periodForm" action="<?php echo e(route('admin.laporan-kegiatan.index')); ?>">
<div class="period-bar">
<span style="font-size:.85rem;color:var(--text-light);">
<i class="fas fa-calendar-alt"></i> Periode:
</span>
<?php $__currentLoopData = ['hari_ini'=>'Hari Ini','minggu_ini'=>'Minggu Ini','bulan_ini'=>'Bulan Ini','semester_ini'=>'Semester','custom'=>'Custom']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $key=>$label): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<button type="button"
class="period-btn <?php echo e($periode===$key?'active':''); ?>"
onclick="setPeriode('<?php echo e($key); ?>')"><?php echo e($label); ?></button>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<div class="custom-range <?php echo e($periode==='custom'?'show':''); ?>" id="customRange">
<input type="date" name="tanggal_dari"
value="<?php echo e(request('tanggal_dari', $startDate->format('Y-m-d'))); ?>">
<span></span>
<input type="date" name="tanggal_sampai"
value="<?php echo e(request('tanggal_sampai', $endDate->format('Y-m-d'))); ?>">
</div>
<input type="hidden" name="periode" id="periodeInput" value="<?php echo e($periode); ?>">
<button type="submit" class="btn btn-primary btn-sm">
<i class="fas fa-sync-alt"></i> Terapkan
</button>
</div>
</form>
<p style="margin:8px 0 0;font-size:.82rem;color:var(--text-light);">
<i class="fas fa-info-circle"></i> Data: <strong><?php echo e($periodeLabel); ?></strong>
</p>
</div>
<div class="kpi-strip">
<div class="kpi-card kpi-avg">
<div class="kpi-label">Rata-rata Kehadiran</div>
<div class="kpi-value"><?php echo e($kpi['avg_kehadiran']); ?>%</div>
<div class="kpi-context">
<?php echo e(number_format($kpi['total_hadir'])); ?> hadir dari
<?php echo e(number_format($kpi['total_absensi'])); ?> tercatat
</div>
<?php $diffAvg = $kpiComparison['avg_kehadiran']; ?>
<div class="kpi-trend <?php echo e($diffAvg > 0 ? 'up' : ($diffAvg < 0 ? 'down' : 'neutral')); ?>">
<i class="fas fa-arrow-<?php echo e($diffAvg >= 0 ? 'up' : 'down'); ?>"></i>
<?php echo e(abs($diffAvg)); ?>% vs periode sebelumnya
</div>
</div>
<div class="kpi-card kpi-hadir">
<div class="kpi-label">Hadir Efektif</div>
<div class="kpi-value"><?php echo e(number_format($kpi['total_hadir'])); ?></div>
<div class="kpi-context">
termasuk <?php echo e($kpi['total_terlambat']); ?> terlambat
— dari <?php echo e(number_format($kpi['total_absensi'])); ?> sesi tercatat
</div>
</div>
<div class="kpi-card kpi-alpa">
<div class="kpi-label">Total Alpa</div>
<div class="kpi-value"><?php echo e(number_format($kpi['total_alpa'])); ?></div>
<div class="kpi-context">
<?php $alpaRate = $kpi['total_absensi'] > 0 ? round($kpi['total_alpa']/$kpi['total_absensi']*100,1) : 0; ?>
<?php echo e($alpaRate); ?>% dari <?php echo e(number_format($kpi['total_absensi'])); ?> tercatat
</div>
</div>
<div class="kpi-card kpi-warning">
<div class="kpi-label">Santri Perlu Perhatian</div>
<div class="kpi-value"><?php echo e($kpi['santri_perlu_perhatian']); ?></div>
<div class="kpi-context">
dari <?php echo e($kpi['total_santri_aktif']); ?> santri aktif
(kehadiran &lt;70%)
</div>
<?php $diffSpp = $kpiComparison['santri_perlu_perhatian']; ?>
<div class="kpi-trend <?php echo e($diffSpp <= 0 ? 'up' : 'down'); ?>">
<i class="fas fa-arrow-<?php echo e($diffSpp <= 0 ? 'down' : 'up'); ?>"></i>
<?php echo e(abs($diffSpp)); ?> vs periode sebelumnya
</div>
</div>
<div class="kpi-card kpi-info">
<div class="kpi-label">Kehadiran Terbaik</div>
<div class="kpi-value" style="font-size:1rem;">
<?php echo e($kpi['kegiatan_terbaik']['nama']); ?>
</div>
<div class="kpi-context">
<?php echo e($kpi['kegiatan_terbaik']['persen']); ?>%
(<?php echo e($kpi['kegiatan_terbaik']['hadir']); ?> hadir dari <?php echo e($kpi['kegiatan_terbaik']['total']); ?> tercatat)
</div>
</div>
</div>
<?php
$buckets = $distribusiSantri['buckets'];
$totalDengan = $distribusiSantri['total'];
?>
<div class="chart-wrap" style="margin-bottom:16px;">
<div style="display:flex;align-items:flex-start;gap:24px;flex-wrap:wrap;">
<div style="position:relative;width:200px;height:200px;flex-shrink:0;">
<canvas id="distribusiChart"></canvas>
<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;pointer-events:none;">
<div style="font-size:1.6rem;font-weight:700;color:var(--primary-dark);line-height:1;">
<?php echo e($totalDengan); ?>
</div>
<div style="font-size:.72rem;color:#6B7280;margin-top:2px;">santri<br>tercatat</div>
</div>
</div>
<div style="flex:1;min-width:220px;">
<h4 style="margin:0 0 6px;font-size:.93rem;color:var(--primary-dark);">
<i class="fas fa-users"></i> Kondisi Kehadiran Santri
</h4>
<?php $__currentLoopData = $buckets; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $b): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;">
<div style="width:12px;height:12px;border-radius:50%;background:<?php echo e($b['color']); ?>;flex-shrink:0;"></div>
<div style="flex:1;min-width:0;">
<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:3px;">
<span style="font-size:.83rem;font-weight:600;color:var(--primary-dark);">
<?php echo e($b['label']); ?>
<?php if($b['label']==='Sangat Baik'): ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(≥95%)</span>
<?php elseif($b['label']==='Baik'): ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(8594%)</span>
<?php elseif($b['label']==='Cukup'): ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(7084%)</span>
<?php else: ?> <span style="font-weight:400;color:#9CA3AF;font-size:.75rem;">(&lt;70%)</span>
<?php endif; ?>
</span>
<span style="font-size:.83rem;font-weight:700;color:<?php echo e($b['color']); ?>;">
<?php echo e($b['count']); ?> santri
<span style="font-weight:400;color:#9CA3AF;">(<?php echo e($b['persen']); ?>%)</span>
</span>
</div>
<div style="background:#f1f5f9;border-radius:4px;height:6px;overflow:hidden;">
<div style="width:<?php echo e($b['persen']); ?>%;height:100%;background:<?php echo e($b['color']); ?>;border-radius:4px;"></div>
</div>
</div>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php $tanpaData = $kpi['total_santri_aktif'] - $totalDengan; ?>
<?php if($tanpaData > 0): ?>
<p style="margin:6px 0 0;font-size:.76rem;color:#9CA3AF;">
<i class="fas fa-info-circle"></i>
<?php echo e($tanpaData); ?> santri aktif belum punya data absensi di periode ini.
</p>
<?php endif; ?>
</div>
</div>
</div>
<div class="panel" style="margin-bottom:16px;">
<div class="panel-title" style="color:#EF4444;">
<i class="fas fa-bell"></i> Anomali & Perlu Tindak Lanjut
</div>
<?php if(!empty($patterns) && count($patterns) > 0): ?>
<?php $__currentLoopData = $patterns; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $p): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
<div class="alert-row a-<?php echo e($p['type']); ?>">
<?php if($p['type']==='danger'): ?>
<i class="fas fa-exclamation-circle" style="margin-top:2px;"></i>
<?php elseif($p['type']==='warning'): ?>
<i class="fas fa-exclamation-triangle" style="margin-top:2px;"></i>
<?php else: ?>
<i class="fas fa-info-circle" style="margin-top:2px;"></i>
<?php endif; ?>
<div class="alert-text">
<div class="alert-title"><?php echo e($p['title']); ?></div>
<div class="alert-desc"><?php echo e($p['description']); ?></div>
</div>
<?php if(!empty($p['action_url'])): ?>
<a href="<?php echo e($p['action_url']); ?>"
class="btn btn-sm btn-<?php echo e($p['type']==='danger'?'danger':($p['type']==='warning'?'warning':'info')); ?>"
style="white-space:nowrap;">
<?php echo e($p['action_text'] ?? 'Lihat'); ?>
</a>
<?php endif; ?>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
<?php else: ?>
<div class="alert-row a-success">
<i class="fas fa-check-circle"></i>
<div class="alert-text">
<div class="alert-title">Tidak ada anomali</div>
<div class="alert-desc">Pola kehadiran dalam kondisi normal.</div>
</div>
</div>
<?php endif; ?>
</div>
<?php
$trendLabels = $trendData['labels'] ?? [];
$trendDs = $trendData['datasets'] ?? [];
$avgLine = [];
foreach ($trendLabels as $i => $_) {
$sum=0; $cnt=0;
foreach ($trendDs as $ds) {
if (isset($ds['data'][$i]) && $ds['data'][$i] !== null) { $sum+=$ds['data'][$i]; $cnt++; }
}
$avgLine[] = $cnt > 0 ? round($sum/$cnt,1) : null;
}
?>
<div class="chart-wrap">
<h4><i class="fas fa-chart-line"></i> Trend Kehadiran Rata-rata</h4>
<p style="margin:0 0 10px;font-size:.8rem;color:#6B7280;">
Angka = % hadir efektif (Terlambat dihitung Hadir). Hover untuk detail.
</p>
<div style="position:relative;height:200px;">
<canvas id="trendChart"></canvas>
</div>
</div>
<div class="three-col">
<div class="panel">
<div class="panel-title" style="color:#10B981;">
<i class="fas fa-trophy"></i> Kehadiran Terbaik
</div>
<?php $__empty_1 = true; $__currentLoopData = $topKegiatan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<div class="kg-item">
<span style="color:#9CA3AF;font-size:.75rem;width:16px;flex-shrink:0;text-align:center;">
<?php echo e($i + 1); ?>
</span>
<div style="flex:1;min-width:0;">
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:6px;margin-bottom:2px;">
<div class="kg-name"
style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.84rem;font-weight:600;">
<?php echo e($kg['nama_kegiatan']); ?>
</div>
<span style="font-weight:700;color:#10B981;font-size:.88rem;flex-shrink:0;">
<?php echo e($kg['persen']); ?>%
</span>
</div>
<div style="background:#f1f5f9;border-radius:4px;height:6px;overflow:hidden;margin-bottom:4px;">
<div style="width:<?php echo e($kg['persen']); ?>%;height:100%;background:#10B981;border-radius:4px;transition:width .5s;"></div>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;">
<span class="kg-context">
<?php echo e($kg['nama_kategori'] ?? '-'); ?> · <?php echo e($kg['hari'] ?? '-'); ?>
</span>
<span style="font-size:.74rem;color:#10B981;">
<?php echo e($kg['hadir']); ?>/<?php echo e($kg['total']); ?> sesi
</span>
</div>
</div>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<p style="color:var(--text-light);font-size:.85rem;text-align:center;padding:16px 0;">
Belum ada data absensi di periode ini.
</p>
<?php endif; ?>
</div>
<div class="panel">
<div class="panel-title" style="color:#EF4444;">
<i class="fas fa-arrow-trend-down"></i> Kehadiran Terendah
</div>
<?php $__empty_1 = true; $__currentLoopData = $bottomKegiatan; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $kg): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<?php
$warna = $kg['persen'] < 70 ? '#EF4444' : '#F59E0B';
$bgBar = $kg['persen'] < 70 ? '#FEF2F2' : '#FFFBEB';
$kgId = $kg['id'];
?>
<div class="kg-item">
<span style="color:#9CA3AF;font-size:.75rem;width:16px;flex-shrink:0;text-align:center;">
<?php echo e($i + 1); ?>
</span>
<div style="flex:1;min-width:0;">
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:6px;margin-bottom:2px;">
<a href="<?php echo e(route('admin.riwayat-kegiatan.show', $kgId)); ?>"
style="text-decoration:none;color:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.84rem;font-weight:600;flex:1;min-width:0;">
<?php echo e($kg['nama_kegiatan']); ?>
</a>
<span style="font-weight:700;color:<?php echo e($warna); ?>;font-size:.88rem;flex-shrink:0;">
<?php echo e($kg['persen']); ?>%
</span>
</div>
<div style="background:<?php echo e($bgBar); ?>;border-radius:4px;height:6px;overflow:hidden;margin-bottom:4px;">
<div style="width:<?php echo e($kg['persen']); ?>%;height:100%;background:<?php echo e($warna); ?>;border-radius:4px;transition:width .5s;"></div>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;">
<span class="kg-context">
<?php echo e($kg['nama_kategori'] ?? '-'); ?> · <?php echo e($kg['hari'] ?? '-'); ?>
</span>
<span style="font-size:.74rem;color:<?php echo e($warna); ?>;">
<?php echo e($kg['hadir']); ?>/<?php echo e($kg['total']); ?> sesi
<?php if(($kg['alpa'] ?? 0) > 0): ?>
· <strong><?php echo e($kg['alpa']); ?>× alpa</strong>
<?php endif; ?>
</span>
</div>
</div>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<p style="color:var(--text-light);font-size:.85rem;text-align:center;padding:16px 0;">
Belum ada data absensi di periode ini.
</p>
<?php endif; ?>
</div>
<div class="panel">
<div class="panel-title" style="color:#F59E0B;">
<i class="fas fa-user-clock"></i> Santri Perlu Perhatian
<a href="<?php echo e(route('admin.laporan-kegiatan.santri-perlu-perhatian', request()->query())); ?>">
Lihat Semua →
</a>
</div>
<p style="font-size:.78rem;color:#6B7280;margin:0 0 10px;">
<?php echo e($kpi['santri_perlu_perhatian']); ?> dari <?php echo e($kpi['total_santri_aktif']); ?> santri aktif
dengan kehadiran &lt;70%
</p>
<?php $__empty_1 = true; $__currentLoopData = $santriPerluPerhatianList; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $i => $s): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
<div class="spp-item">
<span class="spp-rank"><?php echo e($i + 1); ?></span>
<div style="flex:1;min-width:0;">
<div style="display:flex;justify-content:space-between;align-items:baseline;gap:6px;margin-bottom:2px;">
<a href="<?php echo e(route('admin.riwayat-kegiatan.detail-santri', $s->id_santri)); ?>"
class="spp-name"
style="text-decoration:none;color:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;">
<?php echo e($s->nama_lengkap); ?>
</a>
<span class="spp-pct" style="flex-shrink:0;"><?php echo e($s->persen); ?>%</span>
</div>
<div style="background:#FEF2F2;border-radius:4px;height:6px;overflow:hidden;margin-bottom:3px;">
<div style="width:<?php echo e($s->persen); ?>%;height:100%;background:#EF4444;border-radius:4px;transition:width .5s;"></div>
</div>
<div class="spp-ctx">
<?php echo e($s->hadir); ?>/<?php echo e($s->total); ?> sesi · <?php echo e($s->alpa); ?>× alpa
</div>
</div>
</div>
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
<div style="padding:12px;background:#ECFDF5;border-radius:8px;color:#065F46;
font-size:.85rem;display:flex;align-items:center;gap:8px;margin-top:4px;">
<i class="fas fa-check-circle"></i> Semua santri kehadiran ≥70%. Alhamdulillah!
</div>
<?php endif; ?>
</div>
</div>
<?php
/* Flatten semua kelas dari semua kelompok untuk chart */
$chartKelasLabels = [];
$chartKelasData = [];
$chartKelasColors = [];
$chartKelasContext = []; // untuk tooltip: "hadir / total"
$chartKelasGroups = []; // label kelompok per kelas
foreach ($kelasRingkasan as $kelompok) {
foreach ($kelompok['kelas'] as $k) {
$chartKelasLabels[] = $k['nama_kelas'];
$chartKelasData[] = $k['persen'];
$chartKelasColors[] = $k['persen'] >= 85 ? '#10B981' : ($k['persen'] >= 70 ? '#F59E0B' : '#EF4444');
$chartKelasContext[] = $k['hadir'] . ' hadir dari ' . $k['total'] . ' tercatat';
$chartKelasGroups[] = $kelompok['nama_kelompok'];
}
}
$chartHeight = max(180, count($chartKelasLabels) * 34 + 40);
?>
<div class="chart-wrap" style="margin-bottom:16px;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;flex-wrap:wrap;gap:8px;">
<h4 style="margin:0;">
<i class="fas fa-school"></i> Kehadiran Per Kelas
</h4>
<a href="<?php echo e(route('admin.riwayat-kegiatan.index')); ?>"
style="font-size:.78rem;color:var(--primary-color);">
Detail di Riwayat Kegiatan →
</a>
</div>
<p style="margin:0 0 12px;font-size:.78rem;color:#6B7280;">
% hadir efektif — Terlambat dihitung Hadir. Hover bar untuk melihat angka lengkap.
</p>
<?php if(count($chartKelasLabels) > 0): ?>
<div style="position:relative;height:<?php echo e($chartHeight); ?>px;">
<canvas id="kelasChart"></canvas>
</div>
<div class="kelas-legend">
<div class="kelas-legend-item">
<div class="kelas-legend-dot" style="background:#10B981;"></div> ≥85% Baik
</div>
<div class="kelas-legend-item">
<div class="kelas-legend-dot" style="background:#F59E0B;"></div> 7084% Cukup
</div>
<div class="kelas-legend-item">
<div class="kelas-legend-dot" style="background:#EF4444;"></div> &lt;70% Perlu Perhatian
</div>
</div>
<?php else: ?>
<p style="color:var(--text-light);font-size:.85rem;text-align:center;padding:20px 0;">
Belum ada data kelas untuk periode ini.
</p>
<?php endif; ?>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<script>
function setPeriode(p) {
document.getElementById('periodeInput').value = p;
document.querySelectorAll('.period-btn').forEach(b => b.classList.remove('active'));
event.target.classList.add('active');
const cr = document.getElementById('customRange');
if (p === 'custom') { cr.classList.add('show'); }
else { cr.classList.remove('show'); document.getElementById('periodForm').submit(); }
}
// ── Distribusi Santri Donut Chart ──
const distribusiBuckets = <?php echo json_encode($buckets, 15, 512) ?>;
new Chart(document.getElementById('distribusiChart'), {
type: 'doughnut',
data: {
labels: distribusiBuckets.map(b => b.label),
datasets: [{
data: distribusiBuckets.map(b => b.count),
backgroundColor: distribusiBuckets.map(b => b.color),
borderWidth: 2,
borderColor: '#fff',
hoverOffset: 8,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '68%',
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (ctx) => {
const b = distribusiBuckets[ctx.dataIndex];
return [
` ${b.count} santri (${b.persen}%)`,
` dari <?php echo e($totalDengan); ?> santri tercatat`,
];
}
},
backgroundColor: 'rgba(17,24,39,.9)',
titleFont: { size: 13, weight: '600' },
bodyFont: { size: 12 },
padding: 10,
cornerRadius: 8,
}
}
}
});
const labels = <?php echo json_encode($trendLabels, 15, 512) ?>;
const avgLine = <?php echo json_encode($avgLine, 15, 512) ?>;
new Chart(document.getElementById('trendChart'), {
type: 'line',
data: {
labels,
datasets: [{
label: 'Rata-rata Kehadiran',
data: avgLine,
borderColor: '#10B981',
backgroundColor: 'rgba(16,185,129,.1)',
tension: 0.4, fill: true,
pointRadius: 4, pointHoverRadius: 6,
spanGaps: true,
}]
},
options: {
responsive: true, maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: ctx => {
const v = ctx.parsed.y;
return v !== null ? `${v}% kehadiran rata-rata` : 'Tidak ada data';
}
}
}
},
scales: {
y: {
min: 0, max: 100,
ticks: { callback: v => v + '%' },
grid: { color: '#f1f5f9' }
},
x: { grid: { display: false } }
}
}
});
// ── Horizontal Bar Chart: Kehadiran Per Kelas ──
<?php if(count($chartKelasLabels) > 0): ?>
const kelasLabels = <?php echo json_encode($chartKelasLabels, 15, 512) ?>;
const kelasData = <?php echo json_encode($chartKelasData, 15, 512) ?>;
const kelasColors = <?php echo json_encode($chartKelasColors, 15, 512) ?>;
const kelasContext = <?php echo json_encode($chartKelasContext, 15, 512) ?>;
const kelasGroups = <?php echo json_encode($chartKelasGroups, 15, 512) ?>;
new Chart(document.getElementById('kelasChart'), {
type: 'bar',
data: {
labels: kelasLabels,
datasets: [{
label: '% Kehadiran',
data: kelasData,
backgroundColor: kelasColors,
borderRadius: 5,
borderSkipped: false,
barThickness: 20,
}]
},
options: {
indexAxis: 'y', // horizontal
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
title: (items) => {
const i = items[0].dataIndex;
return `${kelasLabels[i]} — ${kelasGroups[i]}`;
},
label: (ctx) => {
const i = ctx.dataIndex;
return [
`Kehadiran: ${ctx.parsed.x}%`,
kelasContext[i],
];
},
labelColor: (ctx) => ({
borderColor: kelasColors[ctx.dataIndex],
backgroundColor: kelasColors[ctx.dataIndex],
borderRadius: 3,
}),
},
backgroundColor: 'rgba(17,24,39,.9)',
titleFont: { size: 13, weight: '600' },
bodyFont: { size: 12 },
padding: 10,
cornerRadius: 8,
}
},
scales: {
x: {
min: 0, max: 100,
ticks: { callback: v => v + '%', font: { size: 11 } },
grid: { color: '#f1f5f9' },
// Garis referensi 70% dan 85%
},
y: {
ticks: { font: { size: 11 } },
grid: { display: false },
}
},
// Plugin untuk garis referensi 70% dan 85%
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
title: (items) => {
const i = items[0].dataIndex;
return `${kelasLabels[i]} — ${kelasGroups[i]}`;
},
label: (ctx) => {
const i = ctx.dataIndex;
return [
`Kehadiran: ${ctx.parsed.x}%`,
kelasContext[i],
];
},
},
backgroundColor: 'rgba(17,24,39,.9)',
titleFont: { size: 13, weight: '600' },
bodyFont: { size: 12 },
padding: 10,
cornerRadius: 8,
},
annotation: undefined,
},
},
plugins: [{
// Plugin custom: garis vertikal referensi 70% dan 85%
id: 'refLines',
afterDraw(chart) {
const { ctx, chartArea: { top, bottom }, scales: { x } } = chart;
[{ v: 70, color: '#F59E0B', label: '70%' }, { v: 85, color: '#10B981', label: '85%' }].forEach(ref => {
const xPx = x.getPixelForValue(ref.v);
ctx.save();
ctx.beginPath();
ctx.setLineDash([4, 4]);
ctx.moveTo(xPx, top);
ctx.lineTo(xPx, bottom);
ctx.strokeStyle = ref.color;
ctx.lineWidth = 1.5;
ctx.globalAlpha = 0.6;
ctx.stroke();
ctx.globalAlpha = 1;
ctx.fillStyle = ref.color;
ctx.font = '10px sans-serif';
ctx.fillText(ref.label, xPx + 3, top + 10);
ctx.restore();
});
}
}]
});
<?php endif; ?>
</script>
<style>
@media print {
.period-bar, .btn, button { display:none !important; }
.panel, .chart-wrap { box-shadow:none !important; border:1px solid #e2e8f0; }
}
</style>
<?php $__env->stopSection(); ?>
<?php echo $__env->make('layouts.app', \Illuminate\Support\Arr::except(get_defined_vars(), ['__data', '__path']))->render(); ?><?php /**PATH C:\xampp\htdocs\TugasAkhir\sim-pkpps\resources\views/admin/kegiatan/laporan/index.blade.php ENDPATH**/ ?>