Initial commit for combined ProjectKP

This commit is contained in:
raditarahman5-cloud
2026-06-28 15:14:51 +07:00
commit ac6c3473d4
203 changed files with 41848 additions and 0 deletions
@@ -0,0 +1,913 @@
@extends('admin.layouts.app')
@section('content')
<style>
/* ══════════════════════════════════════════════
DISNAKER KALBAR ADMIN DASHBOARD
Professional Government Dashboard UI
══════════════════════════════════════════════ */
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap');
*, *::before, *::after { box-sizing: border-box; }
.d-wrap {
padding: 2rem 2.5rem 3rem;
max-width: 1440px;
margin: 0 auto;
font-family: 'Plus Jakarta Sans', sans-serif;
}
/* ── Page Header ─────────────────────────────── */
.page-header {
display: flex;
justify-content: space-between;
align-items: flex-end;
margin-bottom: 1.75rem;
}
.page-header-left h2 {
font-size: 22px;
font-weight: 700;
color: #0D215C;
letter-spacing: -0.3px;
line-height: 1;
}
.page-header-left .subtitle {
font-size: 12.5px;
color: #94a3b8;
font-weight: 500;
margin-top: 5px;
display: flex;
align-items: center;
gap: 6px;
}
.status-dot {
width: 7px; height: 7px;
border-radius: 50%;
background: #22c55e;
display: inline-block;
box-shadow: 0 0 0 3px rgba(34,197,94,0.2);
animation: pulse-dot 2s infinite;
}
@keyframes pulse-dot {
0%,100% { box-shadow: 0 0 0 3px rgba(34,197,94,0.2); }
50% { box-shadow: 0 0 0 6px rgba(34,197,94,0.08); }
}
.page-header-right {
display: flex;
align-items: center;
gap: 10px;
}
.hdr-chip {
font-size: 11px;
font-weight: 600;
padding: 7px 18px;
border-radius: 50px;
letter-spacing: 0.4px;
display: flex;
align-items: center;
gap: 6px;
}
.hdr-chip.navy { background: #0D215C; color: #fff; box-shadow: 0 4px 14px rgba(13,33,92,0.22); }
.hdr-chip.light { background: #fff; color: #64748b; border: 1px solid #e2e8f0; }
.hdr-chip svg { flex-shrink: 0; }
/* ── Stat Cards ──────────────────────────────── */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 18px;
margin-bottom: 1.75rem;
}
.s-card {
background: #fff;
border-radius: 20px;
padding: 1.5rem 1.6rem 1.4rem;
border: 1px solid #edf1f7;
position: relative;
overflow: hidden;
cursor: default;
transition: transform 0.22s cubic-bezier(.4,0,.2,1),
box-shadow 0.22s cubic-bezier(.4,0,.2,1);
}
.s-card:hover {
transform: translateY(-5px);
box-shadow: 0 16px 40px rgba(13,33,92,0.12);
}
.s-card::after {
content: '';
position: absolute;
bottom: 0; left: 0; right: 0;
height: 4px;
border-radius: 0 0 20px 20px;
opacity: 0.9;
}
.s-card.c-blue::after { background: linear-gradient(90deg,#3b82f6,#6366f1); }
.s-card.c-green::after { background: linear-gradient(90deg,#22c55e,#10b981); }
.s-card.c-yellow::after { background: linear-gradient(90deg,#f59e0b,#f97316); }
.s-card.c-red::after { background: linear-gradient(90deg,#64748b,#475569); }
.s-card::before {
content: '';
position: absolute;
top: -20px; right: -20px;
width: 100px; height: 100px;
border-radius: 50%;
opacity: 0.04;
}
.s-card.c-blue::before { background: #3b82f6; }
.s-card.c-green::before { background: #22c55e; }
.s-card.c-yellow::before { background: #f59e0b; }
.s-card.c-red::before { background: #64748b; }
.s-icon {
width: 44px; height: 44px;
border-radius: 12px;
display: flex; align-items: center; justify-content: center;
margin-bottom: 16px;
}
.s-icon.c-blue { background: #eff6ff; color: #3b82f6; }
.s-icon.c-green { background: #f0fdf4; color: #16a34a; }
.s-icon.c-yellow { background: #fffbeb; color: #d97706; }
.s-icon.c-red { background: #f8fafc; color: #475569; }
.s-icon svg { width: 20px; height: 20px; }
.s-num {
font-size: 36px;
font-weight: 700;
color: #0f172a;
letter-spacing: -2px;
line-height: 1;
}
.s-label {
font-size: 12px;
font-weight: 500;
color: #94a3b8;
margin-top: 5px;
letter-spacing: 0.3px;
}
.s-trend {
font-size: 11.5px;
font-weight: 500;
margin-top: 12px;
display: flex;
align-items: center;
gap: 4px;
color: #94a3b8;
}
.s-trend.up { color: #16a34a; }
.s-trend.down { color: #94a3b8; }
.s-trend.flat { color: #94a3b8; }
.s-trend svg { width: 13px; height: 13px; }
/* ── Main Content Grid ───────────────────────── */
.content-grid {
display: grid;
grid-template-columns: 1fr 360px;
gap: 20px;
align-items: start;
}
/* ── Generic Card ────────────────────────────── */
.g-card {
background: #fff;
border-radius: 20px;
padding: 1.5rem 1.6rem;
border: 1px solid #edf1f7;
box-shadow: 0 2px 12px rgba(13,33,92,0.04);
}
.g-card-title {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.2rem;
}
.g-card-title h3 {
font-size: 14px;
font-weight: 700;
color: #0D215C;
letter-spacing: -0.1px;
}
.g-card-title a {
font-size: 12px;
font-weight: 500;
color: #3b82f6;
text-decoration: none;
display: flex;
align-items: center;
gap: 4px;
transition: gap 0.18s;
}
.g-card-title a:hover { gap: 8px; }
/* ── Divider ─────────────────────────────────── */
.act-divider {
height: 1px;
background: #f1f5f9;
margin: 0 0 12px 0;
}
/* ── Filter Tabs ─────────────────────────────── */
.ftabs {
display: flex;
gap: 6px;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.ftab {
padding: 5px 15px;
border-radius: 50px;
font-size: 11px;
font-weight: 600;
cursor: pointer;
border: 1.5px solid transparent;
transition: all 0.15s;
user-select: none;
letter-spacing: 0.3px;
}
.ftab.on { background: #0D215C; color: #fff; border-color: #0D215C; }
.ftab.off { background: #f8fafc; color: #94a3b8; border-color: #e2e8f0; }
.ftab.off:hover { background: #eff6ff; color: #3b82f6; border-color: #bfdbfe; }
/* ── Activity Rows ───────────────────────────── */
.act-item {
display: flex;
align-items: center;
gap: 13px;
padding: 10px 10px;
border-radius: 12px;
cursor: pointer;
transition: background 0.15s, box-shadow 0.15s, transform 0.15s;
}
.act-item:hover {
background: #f8fafc;
box-shadow: 0 4px 16px rgba(13,33,92,0.06);
transform: translateX(2px);
}
.act-item:active { transform: scale(0.99); }
.act-ava {
width: 38px; height: 38px;
border-radius: 10px;
display: flex; align-items: center; justify-content: center;
font-size: 12px;
font-weight: 700;
color: #fff;
flex-shrink: 0;
}
.av-1 { background: linear-gradient(135deg,#3b82f6,#6366f1); }
.av-2 { background: linear-gradient(135deg,#14b8a6,#06b6d4); }
.av-3 { background: linear-gradient(135deg,#a855f7,#ec4899); }
.av-4 { background: linear-gradient(135deg,#f97316,#f59e0b); }
.av-5 { background: linear-gradient(135deg,#22c55e,#10b981); }
.act-body { flex: 1; min-width: 0; }
.act-name {
font-size: 13px;
font-weight: 600;
color: #1e293b;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.act-meta {
font-size: 11px;
color: #94a3b8;
font-weight: 400;
margin-top: 2px;
}
.pill {
font-size: 10px;
font-weight: 600;
padding: 4px 12px;
border-radius: 50px;
letter-spacing: 0.3px;
white-space: nowrap;
flex-shrink: 0;
}
.pill-ok { background: #dcfce7; color: #15803d; }
.pill-run { background: #dbeafe; color: #1d4ed8; }
.pill-del { background: #fee2e2; color: #b91c1c; }
.pill-pnd { background: #fef9c3; color: #92400e; }
.empty-box {
padding: 3.5rem 1rem;
text-align: center;
color: #cbd5e1;
}
.empty-box .ei {
width: 48px; height: 48px;
margin: 0 auto 12px;
display: flex; align-items: center; justify-content: center;
background: #f1f5f9;
border-radius: 14px;
color: #94a3b8;
}
.empty-box .ei svg { width: 22px; height: 22px; }
.empty-box p { font-size: 13px; font-weight: 500; color: #94a3b8; }
/* ── Modal ────────────────────────────────────── */
.modal-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(13,33,92,0.28);
backdrop-filter: blur(4px);
z-index: 999;
align-items: center;
justify-content: center;
animation: fadeIn 0.2s ease;
}
.modal-overlay.show { display: flex; }
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.modal-box {
background: #fff;
border-radius: 22px;
padding: 2rem;
width: 460px;
max-width: 95vw;
box-shadow: 0 30px 80px rgba(13,33,92,0.18);
animation: slideUp 0.25s cubic-bezier(.4,0,.2,1);
}
@keyframes slideUp {
from { opacity:0; transform:translateY(20px); }
to { opacity:1; transform:translateY(0); }
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 1.2rem;
}
.modal-header h4 {
font-size: 15px;
font-weight: 700;
color: #0D215C;
line-height: 1.4;
max-width: 85%;
}
.modal-close {
width: 30px; height: 30px;
border-radius: 50%;
background: #f1f5f9;
border: none;
cursor: pointer;
display: flex; align-items: center; justify-content: center;
color: #64748b;
transition: all 0.15s;
}
.modal-close:hover { background: #fee2e2; color: #ef4444; }
.modal-close svg { width: 14px; height: 14px; }
.modal-field {
display: flex;
gap: 10px;
padding: 10px 0;
border-bottom: 1px solid #f1f5f9;
font-size: 13px;
}
.modal-field:last-child { border-bottom: none; }
.modal-field .mf-label {
width: 120px;
flex-shrink: 0;
color: #94a3b8;
font-weight: 500;
font-size: 11.5px;
letter-spacing: 0.3px;
padding-top: 1px;
}
.modal-field .mf-value {
color: #1e293b;
font-weight: 500;
font-size: 13px;
}
/* ── Sidebar ─────────────────────────────────── */
.sidebar-col { display: flex; flex-direction: column; gap: 18px; }
/* Bar Chart */
.chart-bars {
display: flex;
align-items: flex-end;
gap: 8px;
height: 88px;
margin: 4px 0 8px;
}
.bar-wrap {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
gap: 6px;
cursor: pointer;
}
.bar-body {
width: 100%;
border-radius: 6px 6px 0 0;
background: #e0e7ff;
margin-top: auto;
transition: all 0.3s cubic-bezier(.4,0,.2,1);
position: relative;
}
.bar-wrap:hover .bar-body {
filter: brightness(0.9);
transform: scaleY(1.04);
transform-origin: bottom;
}
.bar-body::after {
content: attr(data-val);
position: absolute;
top: -28px;
left: 50%;
transform: translateX(-50%);
background: #0D215C;
color: #fff;
font-size: 10px;
font-weight: 600;
padding: 3px 8px;
border-radius: 6px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s;
}
.bar-wrap:hover .bar-body::after { opacity: 1; }
.bar-body.today { background: linear-gradient(180deg,#3b82f6 0%,#0D215C 100%); }
.bar-body.active { background: #93c5fd; }
.bar-lbl {
font-size: 10px;
font-weight: 500;
color: #94a3b8;
text-align: center;
}
.bar-lbl.today-lbl { color: #3b82f6; font-weight: 600; }
.chart-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 10px;
border-top: 1px solid #f1f5f9;
font-size: 12px;
color: #64748b;
font-weight: 400;
}
.chart-footer span { color: #94a3b8; }
.chart-footer strong { color: #0D215C; font-weight: 700; }
/* Progress */
.prog-item { margin-bottom: 14px; }
.prog-item:last-child { margin-bottom: 0; }
.prog-head { display: flex; justify-content: space-between; margin-bottom: 7px; }
.prog-head span { font-size: 12.5px; font-weight: 500; color: #334155; }
.prog-head strong { font-size: 12.5px; font-weight: 700; color: #0D215C; }
.prog-track { height: 8px; background: #f1f5f9; border-radius: 50px; overflow: hidden; }
.prog-fill { height: 100%; border-radius: 50px; transition: width 1.2s cubic-bezier(.4,0,.2,1); }
/* Top Users */
.usr-row {
display: flex;
align-items: center;
gap: 11px;
padding: 8px 10px;
border-radius: 12px;
transition: background 0.15s, box-shadow 0.15s;
cursor: default;
}
.usr-row:hover {
background: #f8fafc;
box-shadow: 0 2px 10px rgba(13,33,92,0.05);
}
.usr-rank {
width: 24px; height: 24px;
border-radius: 7px;
font-size: 11px;
font-weight: 700;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
.rank-1 { background: #fef9c3; color: #b45309; }
.rank-2 { background: #f1f5f9; color: #64748b; }
.rank-3 { background: #fff7ed; color: #c2410c; }
.rank-n { background: #f8fafc; color: #94a3b8; }
.usr-ava {
width: 32px; height: 32px;
border-radius: 9px;
background: linear-gradient(135deg,#0D215C,#2563eb);
color: #fff;
font-size: 10px;
font-weight: 700;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
}
.usr-name { flex: 1; font-size: 12.5px; font-weight: 500; color: #334155; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.usr-count {
font-size: 11px;
font-weight: 600;
color: #3b82f6;
background: #eff6ff;
padding: 3px 11px;
border-radius: 50px;
flex-shrink: 0;
}
/* ── Animations ──────────────────────────────── */
@keyframes fadeUp {
from { opacity:0; transform:translateY(16px); }
to { opacity:1; transform:translateY(0); }
}
.s-card { animation: fadeUp 0.4s ease both; }
.s-card:nth-child(1) { animation-delay:.06s; }
.s-card:nth-child(2) { animation-delay:.12s; }
.s-card:nth-child(3) { animation-delay:.18s; }
.s-card:nth-child(4) { animation-delay:.24s; }
.content-grid { animation: fadeUp 0.4s .28s ease both; }
/* ── Responsive ──────────────────────────────── */
@media (max-width:1100px) { .content-grid { grid-template-columns:1fr; } }
@media (max-width:768px) {
.stats-grid { grid-template-columns:repeat(2,1fr); gap: 12px; }
.d-wrap { padding: 1rem 0.5rem; }
.page-header { flex-direction:column; align-items:flex-start; gap:12px; }
.page-header-right { flex-wrap: wrap; gap: 8px; }
.g-card { padding: 1.2rem; }
.act-item { gap: 10px; padding: 8px; }
.hdr-chip { padding: 6px 12px; }
}
@media (max-width:480px) {
.stats-grid { grid-template-columns:1fr; }
.d-wrap { padding: 0.8rem 0; }
.g-card { padding: 1rem; border-radius: 16px; }
.act-meta { font-size: 10px; }
.s-card { padding: 1.2rem; }
.act-item { flex-direction: column; align-items: flex-start; gap: 8px; }
.act-item .pill { align-self: flex-start; }
}
</style>
{{-- ═══════ MODAL (Detail Kegiatan) ═══════ --}}
<div class="modal-overlay" id="detailModal">
<div class="modal-box">
<div class="modal-header">
<h4 id="mdl-title"></h4>
<button class="modal-close" onclick="closeModal()">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" 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>
<div id="mdl-body"></div>
</div>
</div>
<div class="d-wrap">
{{-- ── PAGE HEADER ── --}}
<div class="page-header">
<div class="page-header-left">
<h2>Dashboard Admin</h2>
<div class="subtitle">
<span class="status-dot"></span>
{{ \Carbon\Carbon::now()->timezone('Asia/Jakarta')->locale('id')->translatedFormat('l, d F Y') }}
&nbsp;·&nbsp; Sistem Online
</div>
</div>
<div class="page-header-right">
<span class="hdr-chip light">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
{{ \Carbon\Carbon::now()->timezone('Asia/Jakarta')->format('H:i') }} WIB
</span>
<span class="hdr-chip navy">
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
Disnaker Kalbar
</span>
</div>
</div>
{{-- ── STAT CARDS ── --}}
<div class="stats-grid">
<div class="s-card c-blue">
<div class="s-icon c-blue">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2"/>
<rect x="9" y="3" width="6" height="4" rx="1"/>
<line x1="9" y1="12" x2="15" y2="12"/>
<line x1="9" y1="16" x2="13" y2="16"/>
</svg>
</div>
<div class="s-num">{{ $stats['total'] ?? 0 }}</div>
<div class="s-label">Total Kegiatan</div>
<div class="s-trend up">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
12% bulan ini
</div>
</div>
<div class="s-card c-green">
<div class="s-icon c-green">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
<polyline points="22 4 12 14.01 9 11.01"/>
</svg>
</div>
<div class="s-num">{{ $stats['selesai'] ?? 0 }}</div>
<div class="s-label">Kegiatan Selesai</div>
<div class="s-trend up">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg>
8% dari kemarin
</div>
</div>
<div class="s-card c-yellow">
<div class="s-icon c-yellow">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="2" x2="12" y2="6"/>
<line x1="12" y1="18" x2="12" y2="22"/>
<line x1="4.93" y1="4.93" x2="7.76" y2="7.76"/>
<line x1="16.24" y1="16.24" x2="19.07" y2="19.07"/>
<line x1="2" y1="12" x2="6" y2="12"/>
<line x1="18" y1="12" x2="22" y2="12"/>
<line x1="4.93" y1="19.07" x2="7.76" y2="16.24"/>
<line x1="16.24" y1="7.76" x2="19.07" y2="4.93"/>
</svg>
</div>
<div class="s-num">{{ $stats['proses'] ?? 0 }}</div>
<div class="s-label">Sedang Berjalan</div>
<div class="s-trend flat">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>
Sama seperti kemarin
</div>
</div>
<div class="s-card c-red">
<div class="s-icon c-red">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
</div>
<div class="s-num">{{ $stats['users'] ?? 0 }}</div>
<div class="s-label">Pengguna Aktif</div>
<div class="s-trend down">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
3% minggu ini
</div>
</div>
</div>
{{-- ── MAIN GRID ── --}}
<div class="content-grid">
{{-- LEFT: Kegiatan Terbaru --}}
<div class="g-card">
<div class="g-card-title">
<h3>5 Kegiatan Terbaru</h3>
<a href="{{ route('admin.kegiatan.index') }}">Lihat Semua &rarr;</a>
</div>
<div class="ftabs">
<div class="ftab on" onclick="filterAct(this,'semua')">Semua</div>
<div class="ftab off" onclick="filterAct(this,'selesai')">Selesai</div>
<div class="ftab off" onclick="filterAct(this,'on_progres')">Berjalan</div>
<div class="ftab off" onclick="filterAct(this,'terlambat')">Terlambat</div>
<div class="ftab off" onclick="filterAct(this,'dibatalkan')">Dibatalkan</div>
</div>
<div class="act-divider"></div>
<div id="act-list">
@php
$avClasses = ['av-1','av-2','av-3','av-4','av-5'];
$pillMap = [
'selesai' => ['pill-ok', 'Selesai'],
'telah_ditinjau' => ['pill-ok', 'Ditinjau'],
'on_progres' => ['pill-run', 'Berjalan'],
'terlambat' => ['pill-del', 'Terlambat'],
'dibatalkan' => ['pill-del', 'Dibatalkan'],
'review' => ['pill-pnd', 'Review'],
'pending' => ['pill-pnd', 'Pending'],
];
@endphp
@forelse($activities ?? [] as $idx => $item)
@php
$st = strtolower($item->status ?? 'pending');
$pc = $pillMap[$st] ?? ['pill-pnd', ucfirst($st)];
$ac = $avClasses[$idx % 5];
$tgl = \Carbon\Carbon::parse($item->tanggal)->locale('id')->translatedFormat('d M Y');
$usr = e($item->user->name ?? 'Sistem');
$nm = e($item->nama_kegiatan);
@endphp
<div class="act-item"
data-status="{{ $st }}"
onclick="openModal(
'{{ addslashes($nm) }}',
'{{ addslashes($usr) }}',
'{{ $tgl }}',
'{{ $st }}',
'{{ addslashes(str_replace(["\r", "\n"], ["", "\\n"], $item->keterangan ?? '-')) }}',
'{{ addslashes(str_replace(["\r", "\n"], ["", "\\n"], $item->status_note ?? '')) }}',
'{{ addslashes($item->lokasi ?? '-') }}',
'{{ $item->lampiran ? rtrim(env('BACKEND_API_URL', 'http://127.0.0.1:8000'), '/api') . '/storage/' . $item->lampiran : '' }}'
)">
<div class="act-ava {{ $ac }}">{{ strtoupper(substr($item->user->name ?? 'U', 0, 2)) }}</div>
<div class="act-body">
<div class="act-name">{{ $nm }}</div>
<div class="act-meta">{{ $usr }} &bull; {{ $tgl }}</div>
</div>
<span class="pill {{ $pc[0] }}">{{ $pc[1] }}</span>
</div>
@empty
<div class="empty-box">
<div class="ei">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>
</div>
<p>Belum ada aktivitas kegiatan yang tercatat.</p>
</div>
@endforelse
</div>
</div>
{{-- RIGHT: Sidebar --}}
<div class="sidebar-col">
{{-- Weekly Chart --}}
<div class="g-card">
<div class="g-card-title" style="margin-bottom:.8rem">
<h3>Aktivitas Minggu Ini</h3>
@php $wTotal = array_sum($weeklyData ?? [0,0,0,0,0,0,0]); @endphp
<span class="pill pill-run">{{ $wTotal }} kegiatan</span>
</div>
@php
$days = ['Sen','Sel','Rab','Kam','Jum','Sab','Min'];
$wData = $weeklyData ?? [0,0,0,0,0,0,0];
$maxBar = max($wData) ?: 1;
$todayDI = (int)\Carbon\Carbon::now()->dayOfWeekIso - 1;
@endphp
<div class="chart-bars">
@foreach($days as $i => $d)
@php $pct = round(($wData[$i] / $maxBar) * 100); $isToday = $i === $todayDI; @endphp
<div class="bar-wrap">
<div class="bar-body {{ $isToday ? 'today' : ($wData[$i] > 0 ? 'active' : '') }}"
style="height:{{ max($pct, 8) }}%"
data-val="{{ $wData[$i] }} kegiatan">
</div>
<span class="bar-lbl {{ $isToday ? 'today-lbl' : '' }}">{{ $d }}</span>
</div>
@endforeach
</div>
<div class="chart-footer">
<span>Total minggu ini</span>
<strong>{{ $wTotal }} kegiatan</strong>
</div>
</div>
{{-- Division Progress --}}
<div class="g-card">
<div class="g-card-title" style="margin-bottom:.8rem">
<h3>Progres Divisi</h3>
</div>
{{-- FIX: Gunakan $divisionProgress dari controller, fallback jika tidak ada --}}
@php
$divs = $divisionProgress ?? [
['name' => 'Operasional', 'pct' => 78, 'clr' => 'linear-gradient(90deg,#3b82f6,#6366f1)'],
['name' => 'Keuangan', 'pct' => 64, 'clr' => 'linear-gradient(90deg,#22c55e,#10b981)'],
['name' => 'SDM', 'pct' => 91, 'clr' => 'linear-gradient(90deg,#f97316,#f59e0b)'],
['name' => 'IT', 'pct' => 55, 'clr' => 'linear-gradient(90deg,#a855f7,#ec4899)'],
];
@endphp
@foreach($divs as $dv)
<div class="prog-item">
<div class="prog-head">
<span>{{ $dv['name'] }}</span>
<strong>{{ $dv['pct'] ?? 0 }}%</strong>
</div>
<div class="prog-track">
<div class="prog-fill" style="width:{{ $dv['pct'] ?? 0 }}%;background:{{ $dv['clr'] ?? '#3b82f6' }}"></div>
</div>
</div>
@endforeach
</div>
{{-- Top Kontributor --}}
@if(!empty($topUsers) && count($topUsers))
<div class="g-card">
<div class="g-card-title" style="margin-bottom:.8rem">
<h3>Top Kontributor</h3>
</div>
@foreach($topUsers as $ri => $u)
@php
$rankCls = match($ri) { 0 => 'rank-1', 1 => 'rank-2', 2 => 'rank-3', default => 'rank-n' };
$medal = match($ri) {
0 => '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="#b45309" stroke="none"><circle cx="12" cy="8" r="6"/><path d="M15.477 12.89L17 22l-5-3-5 3 1.523-9.11"/></svg>',
1 => '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="#64748b" stroke="none"><circle cx="12" cy="8" r="6"/><path d="M15.477 12.89L17 22l-5-3-5 3 1.523-9.11"/></svg>',
2 => '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="#c2410c" stroke="none"><circle cx="12" cy="8" r="6"/><path d="M15.477 12.89L17 22l-5-3-5 3 1.523-9.11"/></svg>',
default => $ri + 1
};
@endphp
<div class="usr-row">
<div class="usr-rank {{ $rankCls }}">{!! $medal !!}</div>
<div class="usr-ava">{{ strtoupper(substr($u->name, 0, 2)) }}</div>
<span class="usr-name">{{ $u->name }}</span>
{{-- FIX: Ganti kegiatan_count activities_count (sesuai withCount('activities')) --}}
<span class="usr-count">{{ $u->activities_count ?? 0 }} Lap.</span>
</div>
@endforeach
</div>
@endif
</div>{{-- /sidebar --}}
</div>{{-- /content-grid --}}
</div>{{-- /d-wrap --}}
<script>
/* ── Filter Tabs ─────────────────── */
function filterAct(el, status) {
document.querySelectorAll('.ftab').forEach(t => {
t.classList.remove('on');
t.classList.add('off');
});
el.classList.add('on');
el.classList.remove('off');
document.querySelectorAll('#act-list .act-item').forEach(row => {
row.style.display = (status === 'semua' || row.dataset.status === status) ? 'flex' : 'none';
});
}
/* ── Modal ───────────────────────── */
const pillLabels = {
selesai: '<span class="pill pill-ok">Selesai</span>',
on_progres: '<span class="pill pill-run">Berjalan</span>',
terlambat: '<span class="pill pill-del">Terlambat</span>',
dibatalkan: '<span class="pill pill-del">Dibatalkan</span>',
review: '<span class="pill pill-pnd">Review</span>',
pending: '<span class="pill pill-pnd">Pending</span>'
};
function openModal(nama, user, tgl, status, ket, statusNote, lokasi, lampiranUrl) {
document.getElementById('mdl-title').textContent = nama;
let lampiranHtml = '';
if (lampiranUrl) {
lampiranHtml = `
<div class="modal-field" style="margin-top: 15px; grid-column: span 2;">
<span class="mf-label">Lampiran Foto/Dokumen</span>
<div style="margin-top: 8px;">
<img src="${lampiranUrl}" alt="Lampiran" style="max-width: 100%; max-height: 400px; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);">
</div>
</div>`;
}
document.getElementById('mdl-body').innerHTML = `
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px;">
<div class="modal-field">
<span class="mf-label">Pegawai Ditugaskan</span>
<span class="mf-value">${user}</span>
</div>
<div class="modal-field">
<span class="mf-label">Tanggal</span>
<span class="mf-value">${tgl}</span>
</div>
<div class="modal-field">
<span class="mf-label">Lokasi Tugas</span>
<span class="mf-value">${lokasi}</span>
</div>
<div class="modal-field">
<span class="mf-label">Status</span>
<span class="mf-value">${pillLabels[status] || status}</span>
</div>
<div class="modal-field" style="grid-column: span 2;">
<span class="mf-label">Deskripsi Laporan (Keterangan)</span>
<span class="mf-value" style="white-space: pre-wrap; line-height: 1.5;">${ket || '—'}</span>
</div>
${statusNote ? `
<div class="modal-field" style="grid-column: span 2; background: #eff6ff; padding: 12px; border-radius: 8px;">
<span class="mf-label" style="color: #2563eb; margin-bottom: 4px; display: block;">Catatan Status (Node Petugas)</span>
<span class="mf-value" style="white-space: pre-wrap; line-height: 1.5; color: #1e3a8a;">${statusNote}</span>
</div>
` : ''}
${lampiranHtml}
</div>
`;
document.getElementById('detailModal').classList.add('show');
}
function closeModal() {
document.getElementById('detailModal').classList.remove('show');
}
document.getElementById('detailModal').addEventListener('click', function(e) {
if (e.target === this) closeModal();
});
document.addEventListener('keydown', e => {
if (e.key === 'Escape') closeModal();
});
</script>
@endsection