project-ta/.history/resources/views/admin/dashboard.blade_20260510224...

459 lines
12 KiB
PHP

@extends('layouts.app')
@section('content')
{{-- ============================================================
FILE: resources/views/admin/dashboard.blade.php
============================================================ --}}
<style>
body { background: #f0f4f8 !important; }
.page-header {
display: flex;
align-items: center;
gap: 14px;
margin-bottom: 24px;
}
.page-icon {
width: 46px;
height: 46px;
background: linear-gradient(135deg, #064e3b, #0d6e4f);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
color: #fff;
box-shadow: 0 4px 14px rgba(6,78,59,0.3);
}
.page-title {
font-size: 22px;
font-weight: 800;
color: #111827;
margin: 0;
line-height: 1.2;
}
.page-subtitle {
font-size: 13px;
color: #6b7280;
margin: 2px 0 0;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 20px;
}
.stat-card {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 16px;
padding: 20px 22px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
animation: fadeUp 0.35s ease;
transition: all 0.2s ease;
}
.stat-card:hover {
transform: translateY(-3px);
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
}
.stat-card-left .stat-label {
font-size: 12.5px;
color: #6b7280;
font-weight: 500;
margin-bottom: 4px;
}
.stat-card-left .stat-value {
font-size: 26px;
font-weight: 800;
color: #111827;
margin: 0;
line-height: 1.1;
}
.stat-icon-wrap {
width: 46px;
height: 46px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
color: #fff;
}
.icon-blue { background: linear-gradient(135deg, #3b82f6, #2563eb); }
.icon-green { background: linear-gradient(135deg, #064e3b, #0d6e4f); }
.icon-yellow { background: linear-gradient(135deg, #f59e0b, #d97706); }
.icon-red { background: linear-gradient(135deg, #ef4444, #dc2626); }
@keyframes fadeUp {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
.bottom-grid {
display: grid;
grid-template-columns: 1fr 300px;
gap: 16px;
}
.card-box {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 16px;
padding: 22px 24px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
animation: fadeUp 0.4s ease;
}
.chart-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.chart-title {
font-size: 15px;
font-weight: 700;
color: #111827;
margin: 0;
display: flex;
align-items: center;
gap: 8px;
}
.chart-filter {
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 6px 12px;
font-size: 12.5px;
font-weight: 600;
color: #374151;
background: #f9fafb;
outline: none;
cursor: pointer;
transition: all 0.15s;
}
.chart-filter:focus {
border-color: #064e3b;
box-shadow: 0 0 0 3px rgba(6,78,59,0.1);
}
.info-card {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
}
.info-title {
font-size: 15px;
font-weight: 700;
color: #111827;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 6px;
}
.info-desc {
font-size: 13px;
color: #6b7280;
line-height: 1.6;
margin-bottom: 20px;
}
.info-divider {
border: none;
border-top: 1px solid #f3f4f6;
margin: 16px 0;
}
.info-list {
list-style: none;
padding: 0;
margin: 0 0 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.info-list li {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
color: #374151;
font-weight: 500;
}
.info-check {
width: 20px;
height: 20px;
background: #d1fae5;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #064e3b;
font-size: 10px;
flex-shrink: 0;
}
.btn-laporan {
background: linear-gradient(135deg, #064e3b, #0d6e4f);
border: none;
color: #ffffff;
width: 100%;
padding: 11px;
border-radius: 10px;
font-size: 13.5px;
font-weight: 700;
cursor: pointer;
text-align: center;
text-decoration: none;
display: block;
transition: all 0.15s ease;
box-shadow: 0 3px 10px rgba(6,78,59,0.3);
}
.btn-laporan:hover {
opacity: 0.9;
color: #fff;
transform: translateY(-1px);
}
/* ── RESPONSIVE ── */
@media (max-width: 1024px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.bottom-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 640px) {
.stats-grid {
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.stat-card {
padding: 14px 16px;
}
.stat-card-left .stat-value {
font-size: 20px;
}
.page-title {
font-size: 18px;
}
.chart-header {
flex-wrap: wrap;
gap: 10px;
}
}
@media (max-width: 400px) {
.stats-grid {
grid-template-columns: 1fr;
}
}
</style>
<div class="container-fluid" style="padding: 20px 16px;">
<div class="page-header">
<div class="page-icon">
<i class="fas fa-tachometer-alt"></i>
</div>
<div>
<h1 class="page-title">Dashboard Admin</h1>
<p class="page-subtitle">Ringkasan data dan statistik sistem</p>
</div>
</div>
{{-- <div class="stats-grid">
<div class="stat-card">
<div class="stat-card-left">
<p class="stat-label">Penghuni</p>
<p class="stat-value">{{ $totalPenghuni }}</p>
</div>
<div class="stat-icon-wrap icon-blue">
<i class="fas fa-users"></i>
</div>
</div>
<div class="stat-card">
<div class="stat-card-left">
<p class="stat-label">Rumah</p>
<p class="stat-value">{{ $totalRumah }}</p>
</div>
<div class="stat-icon-wrap icon-green">
<i class="fas fa-home"></i>
</div>
</div>
<div class="stat-card">
<div class="stat-card-left">
<p class="stat-label">Pengaduan</p>
<p class="stat-value">{{ $totalPengaduan }}</p>
</div>
<div class="stat-icon-wrap icon-yellow">
<i class="fas fa-clipboard-list"></i>
</div>
</div>
<div class="stat-card">
<div class="stat-card-left">
<p class="stat-label">Administrasi Iuran</p>
<p class="stat-value" style="font-size:18px;">Rp {{ number_format($totalIuran, 0, ',', '.') }}</p>
</div>
<div class="stat-icon-wrap icon-red">
<i class="fas fa-money-bill-wave"></i>
</div>
</div>
</div>
<div class="bottom-grid">
<div class="card-box">
<div class="chart-header">
<p class="chart-title">
<i class="fas fa-chart-line" style="color:#064e3b;"></i>
Statistik Pengaduan
</p>
<select id="filterChart" class="chart-filter">
<option value="harian">Harian</option>
<option value="mingguan">Mingguan</option>
<option value="bulanan" selected>Bulanan</option>
<option value="tahunan">Tahunan</option>
</select>
</div>
<div style="height: 300px; position: relative;">
<canvas id="chartAdmin"></canvas>
</div>
</div>
<div class="card-box">
<div class="info-card">
<div>
<p class="info-title">
<i class="fas fa-info-circle" style="color:#064e3b;"></i>
Informasi
</p>
<p class="info-desc">
Sistem membantu pengelolaan penghuni, rumah, dan pengaduan secara efisien.
</p>
<hr class="info-divider">
<ul class="info-list">
<li><span class="info-check"><i class="fas fa-check"></i></span> Data Penghuni</li>
<li><span class="info-check"><i class="fas fa-check"></i></span> Data Rumah</li>
<li><span class="info-check"><i class="fas fa-check"></i></span> Pengaduan Warga</li>
<li><span class="info-check"><i class="fas fa-check"></i></span> Administrasi Iuran</li>
<li><span class="info-check"><i class="fas fa-check"></i></span> Laporan Bulanan</li>
</ul>
</div>
<a href="{{ route('laporan.index') }}" class="btn-laporan">
<i class="fas fa-file-alt" style="margin-right:6px;"></i> Lihat Laporan
</a>
</div>
</div> --}}
</div>
</div>
@endsection
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
const canvas = document.getElementById('chartAdmin');
const filter = document.getElementById('filterChart');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let dataSets = {
harian: @json($chartHarian),
mingguan: @json($chartMingguan),
bulanan: @json($chartBulanan),
tahunan: @json($chartTahunan)
};
if (!dataSets.harian.length) dataSets.harian = [1,2,3,2,4,3,5];
if (!dataSets.mingguan.length) dataSets.mingguan = [5,10,7,12];
if (!dataSets.bulanan.length) dataSets.bulanan = [0,0,0,7,0,0,0,0,0,0,0,0];
if (!dataSets.tahunan.length) dataSets.tahunan = [50,70,40,90];
const labelsSets = {
harian: [...Array(7).keys()].map(i => { let d = new Date(); d.setDate(d.getDate()-(6-i)); return d.toLocaleDateString('id-ID',{weekday:'short'}); }),
mingguan: ['Minggu 1','Minggu 2','Minggu 3','Minggu 4'],
bulanan: ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'],
tahunan: [new Date().getFullYear()-3, new Date().getFullYear()-2, new Date().getFullYear()-1, new Date().getFullYear()]
};
let chart;
function renderChart(type) {
if (chart) chart.destroy();
chart = new Chart(ctx, {
type: 'line',
data: {
labels: labelsSets[type],
datasets: [{
label: 'Jumlah Pengaduan',
data: dataSets[type],
borderColor: '#064e3b',
backgroundColor: 'rgba(6,78,59,0.08)',
fill: true,
tension: 0.4,
pointRadius: 5,
pointBackgroundColor: '#064e3b',
pointBorderColor: '#ffffff',
pointBorderWidth: 2,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: { backgroundColor: '#111827', titleColor: '#f9fafb', bodyColor: '#d1d5db', padding: 10, cornerRadius: 8 }
},
scales: {
x: { grid: { color: '#f3f4f6' }, ticks: { color: '#6b7280', font: { size: 12 } } },
y: { beginAtZero: true, grid: { color: '#f3f4f6' }, ticks: { color: '#6b7280', font: { size: 12 }, stepSize: 1 } }
}
}
});
}
renderChart('bulanan');
if (filter) filter.addEventListener('change', function () { renderChart(this.value); });
});
</script>