perbaikan terakhir

pemfinalan semua
This commit is contained in:
Ryan Maulana 2026-05-21 10:51:28 +07:00
parent af235f8e06
commit a5b76a11a4
35 changed files with 29451 additions and 1129 deletions

View File

@ -0,0 +1,586 @@
@extends('layouts.app')
@section('content')
{{-- ============================================================
FILE: resources/views/admin/dashboard.blade.php
============================================================ --}}
<style>
body { background: #f0f4f8 !important; }
/* ── PAGE HEADER ── */
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
margin-bottom: 24px;
flex-wrap: wrap;
}
.page-header-left {
display: flex;
align-items: center;
gap: 14px;
}
.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;
}
/* ── CLOCK WIDGET ── */
.admin-clock {
display: flex;
align-items: center;
gap: 12px;
background: linear-gradient(135deg, #064e3b, #0d6e4f);
border-radius: 14px;
padding: 12px 20px;
box-shadow: 0 4px 16px rgba(6,78,59,0.25);
flex-shrink: 0;
}
.admin-clock-icon {
width: 36px;
height: 36px;
background: rgba(255,255,255,0.15);
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 15px;
flex-shrink: 0;
}
.admin-clock-info {
text-align: left;
}
.admin-clock-time {
font-size: 1.3rem;
font-weight: 800;
color: #ffffff;
letter-spacing: 0.04em;
line-height: 1;
margin-bottom: 3px;
}
.admin-clock-colon {
animation: adminBlink 1s step-end infinite;
display: inline-block;
}
@keyframes adminBlink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.admin-clock-date {
font-size: 0.65rem;
font-weight: 700;
color: rgba(255,255,255,0.7);
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* ── STATS ── */
.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 ── */
.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: 768px) {
.page-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.admin-clock {
width: 100%;
justify-content: flex-start;
border-radius: 12px;
padding: 10px 16px;
}
.admin-clock-time { font-size: 1.15rem; }
.admin-clock-date { font-size: 0.62rem; }
}
@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; }
.admin-clock-time { font-size: 1rem; }
}
</style>
<div class="container-fluid" style="padding: 20px 16px;">
{{-- PAGE HEADER + CLOCK --}}
<div class="page-header">
<div class="page-header-left">
<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>
{{-- CLOCK WIDGET --}}
<div class="admin-clock">
<div class="admin-clock-icon">
<i class="fas fa-clock"></i>
</div>
<div class="admin-clock-info">
<div class="admin-clock-time" id="admin-clock-time">00:00:00</div>
<div class="admin-clock-date" id="admin-clock-date">Memuat...</div>
</div>
</div>
</div>
{{-- STATS GRID --}}
<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>
{{-- BOTTOM GRID --}}
<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 () {
// ── CHART ──
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); });
// ── CLOCK ADMIN ──
function updateAdminClock() {
const now = new Date();
const days = ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'];
const months = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
const hari = days[now.getDay()];
const tgl = String(now.getDate()).padStart(2, '0');
const bln = months[now.getMonth()];
const thn = now.getFullYear();
const jam = String(now.getHours()).padStart(2, '0');
const menit = String(now.getMinutes()).padStart(2, '0');
const detik = String(now.getSeconds()).padStart(2, '0');
const timeEl = document.getElementById('admin-clock-time');
if (timeEl) {
timeEl.innerHTML =
`${jam}<span class="admin-clock-colon">:</span>${menit}<span class="admin-clock-colon">:</span>${detik}`;
}
const dateEl = document.getElementById('admin-clock-date');
if (dateEl) {
dateEl.textContent = `${hari}, ${tgl} ${bln} ${thn}`;
}
}
updateAdminClock();
setInterval(updateAdminClock, 1000);
});
</script>

View File

@ -0,0 +1,701 @@
@extends('layouts.app')
@section('content')
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap"
rel="stylesheet">
<div class="dash-wrap">
<!-- HERO HEADER -->
<div class="dash-hero">
<div class="hero-shapes">
<div class="hs hs1"></div>
<div class="hs hs2"></div>
<div class="hs hs3"></div>
</div>
<div class="hero-content">
<div class="hero-badge">
<span class="badge-dot"></span>
Live Dashboard
</div>
<h1 class="hero-title">Dashboard RT</h1>
<p class="hero-sub">Pantau aktivitas RT secara real-time</p>
</div>
{{-- CLOCK WIDGET --}}
<div class="rt-clock">
<div class="rt-clock-time" id="rt-clock-time">00:00:00</div>
<div class="rt-clock-date" id="rt-clock-date">Memuat...</div>
</div>
<div class="hero-deco">
<svg viewBox="0 0 140 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 70 Q45 15 80 55 Q105 78 130 35" stroke="rgba(255,255,255,0.25)" stroke-width="3"
fill="none" stroke-linecap="round" />
<circle cx="10" cy="70" r="5" fill="rgba(255,255,255,0.4)" />
<circle cx="80" cy="55" r="5" fill="rgba(255,255,255,0.4)" />
<circle cx="130" cy="35" r="5" fill="rgba(255,255,255,0.4)" />
<circle cx="10" cy="70" r="10" fill="rgba(255,255,255,0.08)" />
<circle cx="80" cy="55" r="10" fill="rgba(255,255,255,0.08)" />
<circle cx="130" cy="35" r="10" fill="rgba(255,255,255,0.08)" />
</svg>
</div>
</div>
<!-- STATS GRID -->
<div class="stats-grid">
{{-- PENGHUNI (RT login) --}}
<div class="stat-card" style="--delay:0.05s">
<div class="stat-icon-wrap c-green">
<i class="fas fa-users"></i>
</div>
<div class="stat-body">
<p class="stat-label">Penghuni RT Saya</p>
<h2 class="stat-val vc-green">{{ $totalPenghuni }}</h2>
<span class="stat-sub">Warga di wilayah RT ini</span>
</div>
<div class="stat-glow g-green"></div>
</div>
{{-- RUMAH (RT login) --}}
<div class="stat-card" style="--delay:0.1s">
<div class="stat-icon-wrap c-teal">
<i class="fas fa-home"></i>
</div>
<div class="stat-body">
<p class="stat-label">Rumah RT Saya</p>
<h2 class="stat-val vc-teal">{{ $totalRumah }}</h2>
<span class="stat-sub">
Terisi: {{ $rumahTerisi }} &nbsp;·&nbsp; Kosong: {{ $rumahKosong }}
</span>
<div class="prog-bar" style="margin-top:10px">
<div class="prog-fill pf-teal"
style="width: {{ $totalRumah > 0 ? ($rumahTerisi / $totalRumah * 100) : 0 }}%">
</div>
</div>
</div>
<div class="stat-glow g-teal"></div>
</div>
<div class="stat-card" style="--delay:0.15s">
<div class="stat-icon-wrap c-amber">
<i class="fas fa-money-bill-wave"></i>
</div>
<div class="stat-body">
<p class="stat-label">Iuran</p>
<h2 class="stat-val vc-amber">{{ $totalIuran }}</h2>
<span class="stat-sub">Total iuran bulanan</span>
</div>
<div class="stat-glow g-amber"></div>
</div>
<div class="stat-card" style="--delay:0.2s">
<div class="stat-icon-wrap c-rose">
<i class="fas fa-bullhorn"></i>
</div>
<div class="stat-body">
<p class="stat-label">Pengaduan</p>
<h2 class="stat-val vc-rose">{{ $totalPengaduan }}</h2>
<span class="stat-sub">Laporan masuk</span>
</div>
<div class="stat-glow g-rose"></div>
</div>
<div class="stat-card wide" style="--delay:0.25s">
<div class="stat-icon-wrap c-orange large">
<i class="fas fa-hourglass-half"></i>
</div>
<div class="stat-body">
<p class="stat-label">Menunggu RT</p>
<h2 class="stat-val vc-orange">{{ $menungguRT }}</h2>
<span class="stat-sub">Perlu penanganan segera</span>
<div class="prog-bar">
<div class="prog-fill pf-orange"
style="width: {{ min(($menungguRT / max($totalPengaduan, 1)) * 100, 100) }}%"></div>
</div>
</div>
<div class="stat-glow g-orange"></div>
</div>
<div class="stat-card wide" style="--delay:0.3s">
<div class="stat-icon-wrap c-sky large">
<i class="fas fa-paper-plane"></i>
</div>
<div class="stat-body">
<p class="stat-label">Ke Admin</p>
<h2 class="stat-val vc-sky">{{ $menungguAdmin }}</h2>
<span class="stat-sub">Sedang diproses admin</span>
<div class="prog-bar">
<div class="prog-fill pf-sky"
style="width: {{ min(($menungguAdmin / max($totalPengaduan, 1)) * 100, 100) }}%"></div>
</div>
</div>
<div class="stat-glow g-sky"></div>
</div>
</div>
<!-- CHART -->
<div class="chart-card">
<div class="chart-head">
<div>
<h5 class="chart-title"><i class="fas fa-chart-line"></i> Statistik Pengaduan</h5>
<p class="chart-sub">Tren 12 bulan terakhir</p>
</div>
<div class="chart-legend">
<span class="leg-item"><span class="leg-dot ld-blue"></span>Diajukan</span>
<span class="leg-item"><span class="leg-dot ld-pink"></span>Menunggu</span>
<span class="leg-item"><span class="leg-dot ld-green"></span>Selesai</span>
</div>
</div>
<div class="chart-body">
<canvas id="chartPengaduan"></canvas>
</div>
</div>
</div>
<style>
.pf-teal {
background: linear-gradient(90deg, #0d7377, #14a085);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.dash-wrap {
padding: 24px 24px 48px;
font-family: 'Plus Jakarta Sans', 'Segoe UI', sans-serif;
}
.dash-wrap .dash-hero {
border-radius: 22px !important;
-webkit-border-radius: 22px !important;
}
/* ── HERO ── */
.dash-hero {
position: relative;
background: linear-gradient(135deg, #064e3b 0%, #065f46 45%, #10b981 100%);
border-radius: 22px !important;
padding: 40px 44px;
margin-bottom: 24px;
overflow: hidden;
box-shadow: 0 16px 48px rgba(6, 78, 59, 0.35);
}
.hero-shapes {
position: absolute;
inset: 0;
pointer-events: none;
}
.hs {
position: absolute;
border-radius: 50%;
background: white;
opacity: 0.07;
}
.hs1 {
width: 280px;
height: 280px;
top: -80px;
right: -50px;
}
.hs2 {
width: 150px;
height: 150px;
bottom: -40px;
right: 200px;
}
.hs3 {
width: 90px;
height: 90px;
top: 20px;
right: 300px;
}
.hero-content {
position: relative;
z-index: 1;
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 7px;
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
padding: 5px 13px;
border-radius: 100px;
margin-bottom: 14px;
}
.badge-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: #a7f3d0;
animation: blink 1.8s ease infinite;
}
@keyframes blink {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(1.4); }
}
.hero-title {
font-size: 2.2rem;
font-weight: 800;
color: white;
letter-spacing: -0.03em;
line-height: 1.1;
margin-bottom: 7px;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}
.hero-sub {
color: rgba(255, 255, 255, 0.82);
font-size: 1rem;
font-weight: 500;
}
.hero-deco {
position: absolute;
right: 44px;
bottom: 20px;
width: 150px;
opacity: 0.55;
z-index: 1;
}
/* ── CLOCK RT ── */
.rt-clock {
position: absolute;
top: 50%;
right: 44px;
transform: translateY(-50%);
z-index: 2;
text-align: center;
background: rgba(255,255,255,0.12);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.25);
border-radius: 18px;
padding: 16px 26px;
min-width: 160px;
}
.rt-clock-time {
font-family: 'Plus Jakarta Sans', sans-serif;
font-size: 2rem;
font-weight: 800;
color: #ffffff;
letter-spacing: 0.04em;
line-height: 1;
margin-bottom: 6px;
}
.rt-clock-colon {
animation: rtBlink 1s step-end infinite;
display: inline-block;
}
@keyframes rtBlink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.rt-clock-date {
font-size: 0.68rem;
font-weight: 700;
color: rgba(255,255,255,0.75);
letter-spacing: 0.06em;
text-transform: uppercase;
}
/* ── STATS GRID ── */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 18px;
margin-bottom: 24px;
}
.stat-card {
background: #fff;
border-radius: 18px;
padding: 24px 22px 20px;
position: relative;
overflow: hidden;
border: 1px solid #e8ede9;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
animation: slideUp 0.45s ease both;
animation-delay: var(--delay, 0s);
transition: transform 0.25s ease, box-shadow 0.25s ease;
isolation: isolate;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.1);
}
.stat-card.wide {
grid-column: span 2;
display: flex;
align-items: center;
gap: 18px;
}
.stat-card.wide .stat-body {
flex: 1;
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Icon */
.stat-icon-wrap {
width: 52px;
height: 52px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
color: white;
flex-shrink: 0;
margin-bottom: 16px;
}
.stat-icon-wrap.large {
width: 60px;
height: 60px;
font-size: 1.45rem;
margin-bottom: 0;
}
.c-green { background: linear-gradient(135deg, #064e3b, #10b981); box-shadow: 0 6px 18px rgba(6,78,59,0.3); }
.c-teal { background: linear-gradient(135deg, #0d7377, #14a085); box-shadow: 0 6px 18px rgba(13,115,119,0.3); }
.c-amber { background: linear-gradient(135deg, #b45309, #d97706); box-shadow: 0 6px 18px rgba(217,119,6,0.3); }
.c-rose { background: linear-gradient(135deg, #be123c, #e11d48); box-shadow: 0 6px 18px rgba(225,29,72,0.3); }
.c-orange { background: linear-gradient(135deg, #c2410c, #ea580c); box-shadow: 0 6px 18px rgba(234,88,12,0.3); }
.c-sky { background: linear-gradient(135deg, #0369a1, #0284c7); box-shadow: 0 6px 18px rgba(2,132,199,0.3); }
.stat-icon-wrap, .stat-body { position: relative; z-index: 1; }
.stat-label {
font-size: 0.75rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: #94a3b8;
margin-bottom: 3px;
}
.stat-val {
font-size: 2.4rem;
font-weight: 800;
letter-spacing: -0.04em;
line-height: 1;
margin-bottom: 5px;
}
.stat-sub { font-size: 0.78rem; color: #94a3b8; font-weight: 500; }
.stat-val.vc-green { color: #064e3b; }
.stat-val.vc-teal { color: #0d7377; }
.stat-val.vc-amber { color: #b45309; }
.stat-val.vc-rose { color: #be123c; }
.stat-val.vc-orange { color: #c2410c; }
.stat-val.vc-sky { color: #0369a1; }
.prog-bar {
height: 4px;
background: #f1f5f1;
border-radius: 100px;
margin-top: 10px;
overflow: hidden;
}
.prog-fill {
height: 100%;
border-radius: 100px;
transition: width 1s ease;
}
.pf-orange { background: linear-gradient(90deg, #c2410c, #ea580c); }
.pf-sky { background: linear-gradient(90deg, #0369a1, #38bdf8); }
.stat-glow {
position: absolute;
width: 120px; height: 120px;
border-radius: 50%;
right: -30px; bottom: -40px;
opacity: 0.06;
pointer-events: none;
z-index: 0;
}
.g-green { background: #10b981; }
.g-teal { background: #14a085; }
.g-amber { background: #d97706; }
.g-rose { background: #e11d48; }
.g-orange { background: #ea580c; }
.g-sky { background: #38bdf8; }
/* ── CHART ── */
.chart-card {
background: #fff;
border-radius: 18px;
border: 1px solid #e8ede9;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
overflow: hidden;
animation: slideUp 0.45s 0.35s ease both;
}
.chart-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 24px 16px;
border-bottom: 1px solid #f0f4f1;
flex-wrap: wrap;
gap: 10px;
}
.chart-title {
font-size: 1rem;
font-weight: 700;
color: #064e3b;
display: flex;
align-items: center;
gap: 7px;
margin-bottom: 3px;
}
.chart-title i { color: #206d31; }
.chart-sub { font-size: 0.78rem; color: #94a3b8; }
.chart-legend { display: flex; gap: 16px; }
.leg-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.8rem;
font-weight: 600;
color: #64748b;
}
.leg-dot { width: 9px; height: 9px; border-radius: 50%; }
.ld-blue { background: #3b82f6; }
.ld-pink { background: #ec4899; }
.ld-green { background: #064e3b; }
.chart-body {
padding: 20px 24px 24px;
height: 320px;
}
/* ── RESPONSIVE ── */
@media (max-width: 1024px) {
.stats-grid { grid-template-columns: repeat(2, 1fr); }
.stat-card.wide { grid-column: span 2; }
.rt-clock {
right: 24px;
padding: 12px 18px;
min-width: 130px;
}
.rt-clock-time { font-size: 1.6rem; }
}
@media (max-width: 640px) {
.dash-wrap { padding: 14px 14px 40px; }
.dash-hero {
padding: 28px 22px 22px;
display: flex;
flex-direction: column;
}
.hero-title { font-size: 1.75rem; }
.hero-deco { display: none; }
/* Clock turun ke bawah konten hero, bentuk pill */
.rt-clock {
position: static;
transform: none;
display: inline-flex;
align-items: center;
gap: 10px;
margin-top: 18px;
padding: 10px 16px;
border-radius: 50px;
min-width: 0;
width: fit-content;
align-self: flex-start;
}
.rt-clock-time {
font-size: 1.15rem;
margin-bottom: 0;
line-height: 1;
}
.rt-clock-date {
font-size: 0.62rem;
text-align: left;
line-height: 1.4;
}
.stats-grid {
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.stat-card.wide { grid-column: span 2; }
.stat-val { font-size: 1.9rem; }
.chart-head {
flex-direction: column;
align-items: flex-start;
}
}
@media (max-width: 400px) {
.rt-clock { padding: 8px 12px; }
.rt-clock-time { font-size: 1rem; }
.rt-clock-date { font-size: 0.58rem; }
}
</style>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
// ── CHART ──
const ctx = document.getElementById('chartPengaduan');
const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nov', 'Des'];
const base = [
{{ $diajukan }}, {{ $menunggu }}, {{ $selesai }},
{{ $diajukan * 0.8 }}, {{ $menunggu * 1.2 }}, {{ $selesai * 0.9 }},
{{ $diajukan * 1.1 }}, {{ $menunggu * 0.7 }}, {{ $selesai * 1.3 }},
{{ $diajukan * 0.95 }}, {{ $menunggu * 1.1 }}, {{ $selesai * 1.0 }}
];
const mkGrad = (chartCtx, c1, c2) => {
const g = chartCtx.createLinearGradient(0, 0, 0, 260);
g.addColorStop(0, c1);
g.addColorStop(1, c2);
return g;
};
new Chart(ctx, {
type: 'line',
data: {
labels,
datasets: [
{
label: 'Diajukan',
data: base,
borderColor: '#3b82f6',
backgroundColor: (c) => mkGrad(c.chart.ctx, 'rgba(59,130,246,0.15)', 'rgba(59,130,246,0)'),
borderWidth: 2.5, fill: true, tension: 0.45,
pointBackgroundColor: '#3b82f6', pointBorderColor: '#fff',
pointBorderWidth: 2, pointRadius: 4, pointHoverRadius: 6
},
{
label: 'Menunggu',
data: base.map(d => d * 0.7),
borderColor: '#ec4899',
backgroundColor: (c) => mkGrad(c.chart.ctx, 'rgba(236,72,153,0.12)', 'rgba(236,72,153,0)'),
borderWidth: 2.5, fill: true, tension: 0.45,
pointBackgroundColor: '#206d31', pointBorderColor: '#fff',
pointBorderWidth: 2, pointRadius: 4, pointHoverRadius: 6
},
{
label: 'Selesai',
data: base.map(d => d * 1.2),
borderColor: '#064e3b',
backgroundColor: (c) => mkGrad(c.chart.ctx, 'rgba(6,78,59,0.15)', 'rgba(6,78,59,0)'),
borderWidth: 2.5, fill: true, tension: 0.45,
pointBackgroundColor: '#064e3b', pointBorderColor: '#fff',
pointBorderWidth: 2, pointRadius: 4, pointHoverRadius: 6
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: { intersect: false, mode: 'index' },
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: '#1a2e22',
titleColor: '#94a3b8',
bodyColor: '#f8fafc',
borderColor: 'rgba(255,255,255,0.08)',
borderWidth: 1,
padding: 11,
cornerRadius: 10,
boxPadding: 5
}
},
scales: {
x: {
grid: { color: 'rgba(0,0,0,0.04)' },
ticks: { font: { family: "'Plus Jakarta Sans'", size: 11, weight: '600' }, color: '#94a3b8' }
},
y: {
grid: { color: 'rgba(0,0,0,0.04)' },
ticks: { font: { family: "'Plus Jakarta Sans'", size: 11 }, color: '#94a3b8', stepSize: 1 },
beginAtZero: true
}
}
}
});
// ── CLOCK RT ──
function updateRtClock() {
const now = new Date();
const days = ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'];
const months = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
const hari = days[now.getDay()];
const tgl = String(now.getDate()).padStart(2,'0');
const bln = months[now.getMonth()];
const thn = now.getFullYear();
const jam = String(now.getHours()).padStart(2,'0');
const menit = String(now.getMinutes()).padStart(2,'0');
const detik = String(now.getSeconds()).padStart(2,'0');
const timeEl = document.getElementById('rt-clock-time');
if (timeEl) {
timeEl.innerHTML =
`${jam}<span class="rt-clock-colon">:</span>${menit}<span class="rt-clock-colon">:</span>${detik}`;
}
const dateEl = document.getElementById('rt-clock-date');
if (dateEl) {
dateEl.textContent = `${hari}, ${tgl} ${bln} ${thn}`;
}
}
updateRtClock();
setInterval(updateRtClock, 1000);
});
</script>
@endsection

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,375 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : 'belum' }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,375 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : 'belum' }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,375 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,379 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,379 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,379 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,379 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,379 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,379 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,383 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
{{-- JADI --}}
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@elseif($i->bukti_pembayaran)
{{-- Sudah upload bukti, sedang diproses tidak ada aksi --}}
<span style="font-size:12px; color:#9aaa9a; font-style:italic;">Sedang diproses</span>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,383 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
{{-- JADI --}}
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@elseif($i->bukti_pembayaran)
{{-- Sudah upload bukti, sedang diproses tidak ada aksi --}}
<span style="font-size:12px; color:#9aaa9a; font-style:italic;">Sedang diproses</span>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,385 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
{{-- JADI --}}
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@elseif($i->bukti_pembayaran)
{{-- Sudah upload bukti, sedang diproses tidak ada aksi --}}
<span style="font-size:12px; color:#9aaa9a; font-style:italic;">Sedang diproses</span>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

View File

@ -0,0 +1,384 @@
@extends('layouts.app')
@section('content')
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=DM+Mono:wght@400;500&display=swap');
* { box-sizing: border-box; }
.iv-wrap {
font-family: 'Plus Jakarta Sans', sans-serif;
background: #f0f4f0;
min-height: 100vh;
padding: 28px 24px 60px;
color: #1a1f1a;
}
.iv-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
.iv-header-left h2 { font-size:22px; font-weight:800; color:#0f1f0f; letter-spacing:-0.4px; }
.iv-header-left p { font-size:13px; color:#6b7c6b; margin-top:2px; }
.iv-header-badge { background:#1a3d1a; color:#7edd7e; font-size:12px; font-weight:700; padding:6px 14px; border-radius:50px; }
.iv-stats { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:24px; }
.iv-stat-card { background:#fff; border-radius:18px; padding:18px 20px; border:1px solid rgba(0,0,0,0.06); position:relative; overflow:hidden; transition:transform 0.2s,box-shadow 0.2s; }
.iv-stat-card:hover { transform:translateY(-3px); box-shadow:0 12px 32px rgba(0,0,0,0.09); }
.iv-stat-card::after { content:''; position:absolute; top:0; left:0; right:0; height:3px; border-radius:18px 18px 0 0; }
.iv-stat-card.green::after { background:linear-gradient(90deg,#22c55e,#16a34a); }
.iv-stat-card.amber::after { background:linear-gradient(90deg,#f59e0b,#d97706); }
.iv-stat-card.blue::after { background:linear-gradient(90deg,#3b82f6,#2563eb); }
.iv-stat-icon { width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; font-size:16px; margin-bottom:12px; }
.iv-stat-card.green .iv-stat-icon { background:#dcfce7; color:#16a34a; }
.iv-stat-card.amber .iv-stat-icon { background:#fef3c7; color:#d97706; }
.iv-stat-card.blue .iv-stat-icon { background:#dbeafe; color:#2563eb; }
.iv-stat-val { font-size:24px; font-weight:800; color:#0f1f0f; line-height:1; }
.iv-stat-lbl { font-size:12px; color:#7a8a7a; font-weight:500; margin-top:4px; }
.iv-progress-bar { width:100%; height:4px; background:#e8f0e8; border-radius:4px; overflow:hidden; margin-top:10px; }
.iv-progress-fill { height:100%; background:linear-gradient(90deg,#22c55e,#16a34a); border-radius:4px; }
.iv-main { display:grid; grid-template-columns:300px 1fr; gap:20px; align-items:start; }
@media(max-width:900px){ .iv-main { grid-template-columns:1fr; } }
.iv-qris-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-qris-top { background:linear-gradient(135deg,#0f2d0f 0%,#1a5c1a 50%,#22a022 100%); padding:20px; text-align:center; }
.iv-qris-top h6 { color:#fff; font-size:14px; font-weight:700; margin-bottom:4px; }
.iv-qris-top p { color:rgba(255,255,255,0.6); font-size:11px; }
.iv-qris-body { padding:20px; text-align:center; }
.iv-qris-img-wrap { background:#f8faf8; border-radius:16px; padding:12px; border:1.5px dashed #c8e6c8; margin-bottom:16px; }
.iv-qris-img { width:100%; border-radius:10px; object-fit:contain; max-height:240px; }
.iv-qris-footer { background:#f8faf8; border-top:1px solid #e8f0e8; padding:14px 20px; display:flex; align-items:center; gap:10px; }
.iv-qris-icon { width:36px; height:36px; background:#dcfce7; border-radius:10px; display:flex; align-items:center; justify-content:center; color:#16a34a; font-size:15px; flex-shrink:0; }
.iv-qris-footer span { font-size:12px; color:#5a6e5a; line-height:1.4; }
.iv-table-card { background:#fff; border-radius:22px; overflow:hidden; border:1px solid rgba(0,0,0,0.06); box-shadow:0 4px 20px rgba(0,0,0,0.05); }
.iv-table-head { padding:20px 24px 16px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid #f0f4f0; flex-wrap:wrap; gap:12px; }
.iv-table-head-left { display:flex; align-items:center; gap:12px; }
.iv-table-icon { width:40px; height:40px; background:linear-gradient(135deg,#dcfce7,#bbf7d0); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:17px; color:#15803d; }
.iv-table-head h5 { font-size:16px; font-weight:800; color:#0f1f0f; margin:0 0 2px; }
.iv-table-head p { font-size:12px; color:#7a8a7a; margin:0; }
.iv-filter-tabs { display:flex; gap:6px; }
.iv-tab { padding:6px 14px; border-radius:50px; font-size:12px; font-weight:600; cursor:pointer; border:none; transition:all 0.2s; font-family:'Plus Jakarta Sans',sans-serif; }
.iv-tab.active { background:#1a3d1a; color:#7edd7e; }
.iv-tab:not(.active) { background:#f0f4f0; color:#6b7c6b; }
.iv-table-wrap { overflow-x:auto; }
table.iv-table { width:100%; border-collapse:collapse; }
table.iv-table thead th { padding:12px 24px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.6px; color:#7a8a7a; background:#f8faf8; border-bottom:1px solid #eef2ee; }
table.iv-table tbody tr { border-bottom:1px solid #f4f7f4; transition:background 0.15s; }
table.iv-table tbody tr:hover { background:#f8fdf8; }
table.iv-table tbody tr:last-child { border-bottom:none; }
table.iv-table td { padding:16px 24px; font-size:14px; vertical-align:middle; }
.iv-month-cell { display:flex; align-items:center; gap:12px; }
.iv-month-icon { width:40px; height:40px; background:linear-gradient(135deg,#f0fdf4,#dcfce7); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:14px; color:#15803d; flex-shrink:0; }
.iv-month-name { font-weight:700; color:#1a2a1a; font-size:14px; }
.iv-month-year { font-size:11px; color:#9aaa9a; margin-top:1px; }
.iv-amount { font-family:'DM Mono',monospace; font-size:14px; font-weight:500; color:#1a5c1a; }
.iv-amount-small { font-size:11px; color:#9aaa9a; }
.iv-badge { display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:50px; font-size:11.5px; font-weight:700; }
.iv-badge-green { background:#dcfce7; color:#15803d; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
.iv-badge-blue { background:#dbeafe; color:#1d4ed8; }
.iv-badge-red { background:#fee2e2; color:#b91c1c; }
.iv-status-paid { display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:#15803d; }
.iv-status-dot { width:8px; height:8px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 3px rgba(34,197,94,0.2); }
.iv-btn-pay { display:inline-flex; align-items:center; gap:7px; padding:8px 18px; background:linear-gradient(135deg,#0f2d0f,#1a6c1a); color:#fff; font-size:12.5px; font-weight:700; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:10px; cursor:pointer; transition:all 0.2s; box-shadow:0 3px 12px rgba(22,163,74,0.3); text-decoration:none; }
.iv-btn-pay:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(22,163,74,0.4); color:#fff; }
.iv-btn-detail { display:inline-flex; align-items:center; gap:5px; padding:7px 14px; background:#f0f4f0; color:#4a5a4a; font-size:12px; font-weight:600; font-family:'Plus Jakarta Sans',sans-serif; border:none; border-radius:9px; cursor:pointer; transition:all 0.2s; }
.iv-btn-detail:hover { background:#e2eae2; }
.iv-empty { padding:60px 24px; text-align:center; }
.iv-empty-icon { width:72px; height:72px; background:#f0f4f0; border-radius:22px; display:flex; align-items:center; justify-content:center; font-size:28px; margin:0 auto 16px; }
.iv-empty h6 { font-size:16px; font-weight:700; color:#2a3a2a; margin-bottom:6px; }
.iv-empty p { font-size:13px; color:#7a8a7a; }
@keyframes fadeUp { from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
.fade-up { opacity:0; animation:fadeUp 0.45s ease forwards; }
.d1{animation-delay:0.05s} .d2{animation-delay:0.1s} .d3{animation-delay:0.15s} .d4{animation-delay:0.2s}
/* MODAL */
.iv-modal-header { background:linear-gradient(135deg,#0f2d0f,#1a6c1a); padding:20px 24px; display:flex; align-items:center; justify-content:space-between; }
.iv-modal-icon { width:42px; height:42px; background:rgba(255,255,255,0.15); border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:18px; }
.iv-modal-title { font-size:16px; font-weight:800; color:#fff; }
.iv-modal-sub { font-size:12px; color:rgba(255,255,255,0.6); margin-top:2px; }
.iv-modal-close { color:#fff; opacity:0.7; font-size:22px; background:none; border:none; cursor:pointer; line-height:1; padding:0; }
.iv-modal-close:hover { opacity:1; }
.iv-modal-body { padding:24px; }
.iv-modal-badge { text-align:center; margin-bottom:20px; }
.iv-modal-row { display:flex; align-items:center; justify-content:space-between; padding:12px 0; border-bottom:1px solid #f0f4f0; }
.iv-modal-row:last-child { border-bottom:none; }
.iv-modal-row-left { display:flex; align-items:center; gap:10px; color:#6b7c6b; font-size:13px; font-weight:500; }
.iv-modal-row-icon { width:32px; height:32px; background:#f0f4f0; border-radius:9px; display:flex; align-items:center; justify-content:center; }
.iv-modal-row-icon i { font-size:13px; color:#4a7a4a; }
.iv-modal-row-val { font-size:13px; font-weight:700; color:#1a2a1a; }
.iv-modal-keterangan { margin-top:14px; background:#f8faf8; border-radius:12px; padding:14px 16px; border:1px solid #e8f0e8; }
.iv-modal-keterangan-label { font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.5px; color:#9aaa9a; margin-bottom:6px; }
.iv-modal-keterangan-val { font-size:13px; color:#4a5a4a; line-height:1.55; }
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
</style>
<div class="iv-wrap">
{{-- HEADER --}}
<div class="iv-header fade-up d1">
<div class="iv-header-left">
<h2>💰 Data Iuran Saya</h2>
<p>Kelola pembayaran iuran bulanan Anda</p>
</div>
<span class="iv-header-badge">Tahun {{ date('Y') }}</span>
</div>
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
<div class="iv-stats fade-up d2">
<div class="iv-stat-card green">
<div class="iv-stat-icon"><i class="fas fa-check-circle"></i></div>
<div class="iv-stat-val">{{ $lunas }}</div>
<div class="iv-stat-lbl">Bulan Lunas</div>
<div class="iv-progress-bar">
<div class="iv-progress-fill" style="width:{{ $pct }}%"></div>
</div>
</div>
<div class="iv-stat-card amber">
<div class="iv-stat-icon"><i class="fas fa-clock"></i></div>
<div class="iv-stat-val">{{ $belum }}</div>
<div class="iv-stat-lbl">Belum Bayar</div>
</div>
<div class="iv-stat-card blue">
<div class="iv-stat-icon"><i class="fas fa-coins"></i></div>
<div class="iv-stat-val">Rp {{ number_format($total,0,',','.') }}</div>
<div class="iv-stat-lbl">Total Dibayar</div>
</div>
</div>
{{-- MAIN GRID --}}
<div class="iv-main">
{{-- QRIS --}}
<div class="iv-qris-card fade-up d3">
<div class="iv-qris-top">
<h6><i class="fas fa-qrcode me-2"></i> Bayar via QRIS</h6>
<p>Scan dengan e-wallet apapun</p>
</div>
<div class="iv-qris-body">
<div class="iv-qris-img-wrap">
<img src="{{ asset('qris/qris.jpeg') }}" class="iv-qris-img" alt="QRIS">
</div>
<div style="font-size:12px;color:#7a8a7a;line-height:1.6">
Scan menggunakan <strong style="color:#1a3d1a">GoPay, OVO, Dana,</strong> atau e-wallet lainnya
</div>
</div>
<div class="iv-qris-footer">
<div class="iv-qris-icon"><i class="fas fa-shield-alt"></i></div>
<span>Pembayaran aman & terenkripsi oleh sistem QRIS nasional</span>
</div>
</div>
{{-- TABLE --}}
<div class="iv-table-card fade-up d4">
<div class="iv-table-head">
<div class="iv-table-head-left">
<div class="iv-table-icon"><i class="fas fa-wallet"></i></div>
<div>
<h5>Riwayat Iuran</h5>
<p>{{ $iuran->count() }} tagihan tahun berjalan</p>
</div>
</div>
<div class="iv-filter-tabs">
<button class="iv-tab active" onclick="filterTab(this,'all')">Semua</button>
<button class="iv-tab" onclick="filterTab(this,'lunas')">Lunas</button>
<button class="iv-tab" onclick="filterTab(this,'belum')">Belum</button>
</div>
</div>
<div class="iv-table-wrap">
<table class="iv-table">
<thead>
<tr>
<th>Bulan</th>
<th>Jumlah</th>
<th>Jenis</th>
<th>Status</th>
<th style="text-align:right">Aksi</th>
</tr>
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
<div>
<div class="iv-month-name">{{ $i->bulan }}</div>
<div class="iv-month-year">{{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
</td>
<td>
<div class="iv-amount">Rp {{ number_format($i->jumlah,0,',','.') }}</div>
<div class="iv-amount-small">Bulanan</div>
</td>
<td>
<span class="iv-badge iv-badge-blue">{{ $i->jenis_iuran ?? '-' }}</span>
</td>
<td>
@if($i->status == 'lunas')
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
{{-- JADI --}}
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
data-toggle="modal"
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@elseif($i->bukti_pembayaran)
{{-- Sudah upload bukti, sedang diproses tidak ada aksi --}}
<span style="font-size:12px; color:#9aaa9a; font-style:italic;">Sedang diproses</span>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar
</a>
@endif
</td>
</tr>
@empty
<tr>
<td colspan="5">
<div class="iv-empty">
<div class="iv-empty-icon">💳</div>
<h6>Belum Ada Data Iuran</h6>
<p>Data iuran Anda akan muncul di sini</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
{{-- ── MODAL DETAIL ── --}}
@foreach($iuran->where('status','lunas') as $i)
<div class="modal fade" id="modalDetail{{ $i->id }}" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document" style="max-width:460px;">
<div class="modal-content" style="border-radius:20px;border:none;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,0.15);">
<div class="iv-modal-header">
<div style="display:flex;align-items:center;gap:12px;">
<div class="iv-modal-icon">🧾</div>
<div>
<div class="iv-modal-title">Detail Iuran</div>
<div class="iv-modal-sub">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
</div>
<button class="iv-modal-close" data-dismiss="modal">&times;</button>
</div>
<div class="iv-modal-body">
<div class="iv-modal-badge">
<span style="background:#dcfce7;color:#15803d;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:50px;display:inline-flex;align-items:center;gap:7px;">
<span style="width:8px;height:8px;border-radius:50%;background:#22c55e;display:inline-block;box-shadow:0 0 0 3px rgba(34,197,94,0.2);"></span>
Pembayaran Lunas
</span>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-alt"></i></div>
Bulan
</div>
<div class="iv-modal-row-val">{{ $i->bulan }} {{ $i->tahun ?? date('Y') }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-coins"></i></div>
Jumlah
</div>
<div class="iv-modal-row-val" style="color:#1a5c1a;font-family:'DM Mono',monospace;">
Rp {{ number_format($i->jumlah,0,',','.') }}
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-tag"></i></div>
Jenis Iuran
</div>
<div class="iv-modal-row-val">{{ $i->jenis_iuran ?? '-' }}</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-check-circle"></i></div>
Status
</div>
<div class="iv-modal-row-val">
<span class="iv-badge iv-badge-green">Lunas</span>
</div>
</div>
<div class="iv-modal-row">
<div class="iv-modal-row-left">
<div class="iv-modal-row-icon"><i class="fas fa-calendar-check"></i></div>
Tgl Bayar
</div>
<div class="iv-modal-row-val">
{{ $i->updated_at ? \Carbon\Carbon::parse($i->updated_at)->format('d M Y') : '-' }}
</div>
</div>
@if($i->keterangan)
<div class="iv-modal-keterangan">
<div class="iv-modal-keterangan-label">Keterangan</div>
<div class="iv-modal-keterangan-val">{{ $i->keterangan }}</div>
</div>
@endif
</div>
<div class="iv-modal-footer">
<button class="iv-modal-btn-close" data-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
@endforeach
<script>
function filterTab(btn, status) {
document.querySelectorAll('.iv-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('#iuranBody tr').forEach(row => {
row.style.display = (status === 'all' || row.dataset.status === status) ? '' : 'none';
});
}
</script>
@endsection

BIN
public/bukti/1779332761.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View File

@ -9,11 +9,20 @@
<style>
body { background: #f0f4f8 !important; }
/* ── PAGE HEADER ── */
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
margin-bottom: 24px;
flex-wrap: wrap;
}
.page-header-left {
display: flex;
align-items: center;
gap: 14px;
}
.page-icon {
@ -44,6 +53,63 @@
margin: 2px 0 0;
}
/* ── CLOCK WIDGET ── */
.admin-clock {
display: flex;
align-items: center;
gap: 12px;
background: linear-gradient(135deg, #064e3b, #0d6e4f);
border-radius: 14px;
padding: 12px 20px;
box-shadow: 0 4px 16px rgba(6,78,59,0.25);
flex-shrink: 0;
}
.admin-clock-icon {
width: 36px;
height: 36px;
background: rgba(255,255,255,0.15);
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 15px;
flex-shrink: 0;
}
.admin-clock-info {
text-align: left;
}
.admin-clock-time {
font-size: 1.3rem;
font-weight: 800;
color: #ffffff;
letter-spacing: 0.04em;
line-height: 1;
margin-bottom: 3px;
}
.admin-clock-colon {
animation: adminBlink 1s step-end infinite;
display: inline-block;
}
@keyframes adminBlink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.admin-clock-date {
font-size: 0.65rem;
font-weight: 700;
color: rgba(255,255,255,0.7);
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* ── STATS ── */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
@ -107,6 +173,7 @@
to { opacity: 1; transform: translateY(0); }
}
/* ── BOTTOM GRID ── */
.bottom-grid {
display: grid;
grid-template-columns: 1fr 300px;
@ -243,44 +310,45 @@
/* ── RESPONSIVE ── */
@media (max-width: 1024px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
.stats-grid { grid-template-columns: repeat(2, 1fr); }
.bottom-grid { grid-template-columns: 1fr; }
}
.bottom-grid {
grid-template-columns: 1fr;
@media (max-width: 768px) {
.page-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.admin-clock {
width: 100%;
justify-content: flex-start;
border-radius: 12px;
padding: 10px 16px;
}
.admin-clock-time { font-size: 1.15rem; }
.admin-clock-date { font-size: 0.62rem; }
}
@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;
}
.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;
}
.stats-grid { grid-template-columns: 1fr; }
.admin-clock-time { font-size: 1rem; }
}
</style>
<div class="container-fluid" style="padding: 20px 16px;">
{{-- PAGE HEADER + CLOCK --}}
<div class="page-header">
<div class="page-header-left">
<div class="page-icon">
<i class="fas fa-tachometer-alt"></i>
</div>
@ -290,6 +358,19 @@
</div>
</div>
{{-- CLOCK WIDGET --}}
<div class="admin-clock">
<div class="admin-clock-icon">
<i class="fas fa-clock"></i>
</div>
<div class="admin-clock-info">
<div class="admin-clock-time" id="admin-clock-time">00:00:00</div>
<div class="admin-clock-date" id="admin-clock-date">Memuat...</div>
</div>
</div>
</div>
{{-- STATS GRID --}}
<div class="stats-grid">
<div class="stat-card">
@ -334,6 +415,7 @@
</div>
{{-- BOTTOM GRID --}}
<div class="bottom-grid">
<div class="card-box">
@ -392,6 +474,8 @@
<script>
document.addEventListener("DOMContentLoaded", function () {
// ── CHART ──
const canvas = document.getElementById('chartAdmin');
const filter = document.getElementById('filterChart');
if (!canvas) return;
@ -410,10 +494,19 @@
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'}); }),
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()]
tahunan: [
new Date().getFullYear() - 3,
new Date().getFullYear() - 2,
new Date().getFullYear() - 1,
new Date().getFullYear()
]
};
let chart;
@ -442,7 +535,13 @@ function renderChart(type) {
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: { backgroundColor: '#111827', titleColor: '#f9fafb', bodyColor: '#d1d5db', padding: 10, cornerRadius: 8 }
tooltip: {
backgroundColor: '#111827',
titleColor: '#f9fafb',
bodyColor: '#d1d5db',
padding: 10,
cornerRadius: 8
}
},
scales: {
x: { grid: { color: '#f3f4f6' }, ticks: { color: '#6b7280', font: { size: 12 } } },
@ -454,5 +553,34 @@ function renderChart(type) {
renderChart('bulanan');
if (filter) filter.addEventListener('change', function () { renderChart(this.value); });
// ── CLOCK ADMIN ──
function updateAdminClock() {
const now = new Date();
const days = ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'];
const months = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
const hari = days[now.getDay()];
const tgl = String(now.getDate()).padStart(2, '0');
const bln = months[now.getMonth()];
const thn = now.getFullYear();
const jam = String(now.getHours()).padStart(2, '0');
const menit = String(now.getMinutes()).padStart(2, '0');
const detik = String(now.getSeconds()).padStart(2, '0');
const timeEl = document.getElementById('admin-clock-time');
if (timeEl) {
timeEl.innerHTML =
`${jam}<span class="admin-clock-colon">:</span>${menit}<span class="admin-clock-colon">:</span>${detik}`;
}
const dateEl = document.getElementById('admin-clock-date');
if (dateEl) {
dateEl.textContent = `${hari}, ${tgl} ${bln} ${thn}`;
}
}
updateAdminClock();
setInterval(updateAdminClock, 1000);
});
</script>

View File

@ -22,6 +22,13 @@
<h1 class="hero-title">Dashboard RT</h1>
<p class="hero-sub">Pantau aktivitas RT secara real-time</p>
</div>
{{-- CLOCK WIDGET --}}
<div class="rt-clock">
<div class="rt-clock-time" id="rt-clock-time">00:00:00</div>
<div class="rt-clock-date" id="rt-clock-date">Memuat...</div>
</div>
<div class="hero-deco">
<svg viewBox="0 0 140 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 70 Q45 15 80 55 Q105 78 130 35" stroke="rgba(255,255,255,0.25)" stroke-width="3"
@ -248,17 +255,8 @@
}
@keyframes blink {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.5;
transform: scale(1.4);
}
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(1.4); }
}
.hero-title {
@ -286,6 +284,47 @@
z-index: 1;
}
/* ── CLOCK RT ── */
.rt-clock {
position: absolute;
top: 50%;
right: 44px;
transform: translateY(-50%);
z-index: 2;
text-align: center;
background: rgba(255,255,255,0.12);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.25);
border-radius: 18px;
padding: 16px 26px;
min-width: 160px;
}
.rt-clock-time {
font-family: 'Plus Jakarta Sans', sans-serif;
font-size: 2rem;
font-weight: 800;
color: #ffffff;
letter-spacing: 0.04em;
line-height: 1;
margin-bottom: 6px;
}
.rt-clock-colon {
animation: rtBlink 1s step-end infinite;
display: inline-block;
}
@keyframes rtBlink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.rt-clock-date {
font-size: 0.68rem;
font-weight: 700;
color: rgba(255,255,255,0.75);
letter-spacing: 0.06em;
text-transform: uppercase;
}
/* ── STATS GRID ── */
.stats-grid {
display: grid;
@ -325,15 +364,8 @@
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Icon */
@ -357,44 +389,15 @@
margin-bottom: 0;
}
.c-green {
background: linear-gradient(135deg, #064e3b, #10b981);
box-shadow: 0 6px 18px rgba(6, 78, 59, 0.3);
}
.c-green { background: linear-gradient(135deg, #064e3b, #10b981); box-shadow: 0 6px 18px rgba(6,78,59,0.3); }
.c-teal { background: linear-gradient(135deg, #0d7377, #14a085); box-shadow: 0 6px 18px rgba(13,115,119,0.3); }
.c-amber { background: linear-gradient(135deg, #b45309, #d97706); box-shadow: 0 6px 18px rgba(217,119,6,0.3); }
.c-rose { background: linear-gradient(135deg, #be123c, #e11d48); box-shadow: 0 6px 18px rgba(225,29,72,0.3); }
.c-orange { background: linear-gradient(135deg, #c2410c, #ea580c); box-shadow: 0 6px 18px rgba(234,88,12,0.3); }
.c-sky { background: linear-gradient(135deg, #0369a1, #0284c7); box-shadow: 0 6px 18px rgba(2,132,199,0.3); }
.c-teal {
background: linear-gradient(135deg, #0d7377, #14a085);
box-shadow: 0 6px 18px rgba(13, 115, 119, 0.3);
}
.stat-icon-wrap, .stat-body { position: relative; z-index: 1; }
.c-amber {
background: linear-gradient(135deg, #b45309, #d97706);
box-shadow: 0 6px 18px rgba(217, 119, 6, 0.3);
}
.c-rose {
background: linear-gradient(135deg, #be123c, #e11d48);
box-shadow: 0 6px 18px rgba(225, 29, 72, 0.3);
}
.c-orange {
background: linear-gradient(135deg, #c2410c, #ea580c);
box-shadow: 0 6px 18px rgba(234, 88, 12, 0.3);
}
.c-sky {
background: linear-gradient(135deg, #0369a1, #0284c7);
box-shadow: 0 6px 18px rgba(2, 132, 199, 0.3);
}
/* Ensure content sits above glow */
.stat-icon-wrap,
.stat-body {
position: relative;
z-index: 1;
}
/* Text */
.stat-label {
font-size: 0.75rem;
font-weight: 700;
@ -412,37 +415,15 @@
margin-bottom: 5px;
}
.stat-sub {
font-size: 0.78rem;
color: #94a3b8;
font-weight: 500;
}
.stat-sub { font-size: 0.78rem; color: #94a3b8; font-weight: 500; }
.stat-val.vc-green {
color: #064e3b;
}
.stat-val.vc-green { color: #064e3b; }
.stat-val.vc-teal { color: #0d7377; }
.stat-val.vc-amber { color: #b45309; }
.stat-val.vc-rose { color: #be123c; }
.stat-val.vc-orange { color: #c2410c; }
.stat-val.vc-sky { color: #0369a1; }
.stat-val.vc-teal {
color: #0d7377;
}
.stat-val.vc-amber {
color: #b45309;
}
.stat-val.vc-rose {
color: #be123c;
}
.stat-val.vc-orange {
color: #c2410c;
}
.stat-val.vc-sky {
color: #0369a1;
}
/* Progress bar */
.prog-bar {
height: 4px;
background: #f1f5f1;
@ -457,50 +438,25 @@
transition: width 1s ease;
}
.pf-orange {
background: linear-gradient(90deg, #c2410c, #ea580c);
}
.pf-orange { background: linear-gradient(90deg, #c2410c, #ea580c); }
.pf-sky { background: linear-gradient(90deg, #0369a1, #38bdf8); }
.pf-sky {
background: linear-gradient(90deg, #0369a1, #38bdf8);
}
/* Glow blobs */
.stat-glow {
position: absolute;
width: 120px;
height: 120px;
width: 120px; height: 120px;
border-radius: 50%;
right: -30px;
bottom: -40px;
right: -30px; bottom: -40px;
opacity: 0.06;
pointer-events: none;
z-index: 0;
}
.g-green {
background: #10b981;
}
.g-teal {
background: #14a085;
}
.g-amber {
background: #d97706;
}
.g-rose {
background: #e11d48;
}
.g-orange {
background: #ea580c;
}
.g-sky {
background: #38bdf8;
}
.g-green { background: #10b981; }
.g-teal { background: #14a085; }
.g-amber { background: #d97706; }
.g-rose { background: #e11d48; }
.g-orange { background: #ea580c; }
.g-sky { background: #38bdf8; }
/* ── CHART ── */
.chart-card {
@ -532,19 +488,10 @@
margin-bottom: 3px;
}
.chart-title i {
color: #206d31;
}
.chart-title i { color: #206d31; }
.chart-sub { font-size: 0.78rem; color: #94a3b8; }
.chart-sub {
font-size: 0.78rem;
color: #94a3b8;
}
.chart-legend {
display: flex;
gap: 16px;
}
.chart-legend { display: flex; gap: 16px; }
.leg-item {
display: flex;
@ -555,23 +502,10 @@
color: #64748b;
}
.leg-dot {
width: 9px;
height: 9px;
border-radius: 50%;
}
.ld-blue {
background: #3b82f6;
}
.ld-pink {
background: #ec4899;
}
.ld-green {
background: #064e3b;
}
.leg-dot { width: 9px; height: 9px; border-radius: 50%; }
.ld-blue { background: #3b82f6; }
.ld-pink { background: #ec4899; }
.ld-green { background: #064e3b; }
.chart-body {
padding: 20px 24px 24px;
@ -580,55 +514,78 @@
/* ── RESPONSIVE ── */
@media (max-width: 1024px) {
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
.stat-card.wide {
grid-column: span 2;
.stats-grid { grid-template-columns: repeat(2, 1fr); }
.stat-card.wide { grid-column: span 2; }
.rt-clock {
right: 24px;
padding: 12px 18px;
min-width: 130px;
}
.rt-clock-time { font-size: 1.6rem; }
}
@media (max-width: 640px) {
.dash-wrap {
padding: 14px 14px 40px;
}
.dash-wrap { padding: 14px 14px 40px; }
.dash-hero {
padding: 28px 22px;
padding: 28px 22px 22px;
display: flex;
flex-direction: column;
}
.hero-title {
font-size: 1.75rem;
}
.hero-title { font-size: 1.75rem; }
.hero-deco { display: none; }
.hero-deco {
display: none;
/* Clock turun ke bawah konten hero, bentuk pill */
.rt-clock {
position: static;
transform: none;
display: inline-flex;
align-items: center;
gap: 10px;
margin-top: 18px;
padding: 10px 16px;
border-radius: 50px;
min-width: 0;
width: fit-content;
align-self: flex-start;
}
.rt-clock-time {
font-size: 1.15rem;
margin-bottom: 0;
line-height: 1;
}
.rt-clock-date {
font-size: 0.62rem;
text-align: left;
line-height: 1.4;
}
.stats-grid {
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.stat-card.wide {
grid-column: span 2;
}
.stat-val {
font-size: 1.9rem;
}
.stat-card.wide { grid-column: span 2; }
.stat-val { font-size: 1.9rem; }
.chart-head {
flex-direction: column;
align-items: flex-start;
}
}
@media (max-width: 400px) {
.rt-clock { padding: 8px 12px; }
.rt-clock-time { font-size: 1rem; }
.rt-clock-date { font-size: 0.58rem; }
}
</style>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
// ── CHART ──
const ctx = document.getElementById('chartPengaduan');
const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nov', 'Des'];
@ -710,6 +667,34 @@
}
}
});
// ── CLOCK RT ──
function updateRtClock() {
const now = new Date();
const days = ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'];
const months = ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'];
const hari = days[now.getDay()];
const tgl = String(now.getDate()).padStart(2,'0');
const bln = months[now.getMonth()];
const thn = now.getFullYear();
const jam = String(now.getHours()).padStart(2,'0');
const menit = String(now.getMinutes()).padStart(2,'0');
const detik = String(now.getSeconds()).padStart(2,'0');
const timeEl = document.getElementById('rt-clock-time');
if (timeEl) {
timeEl.innerHTML =
`${jam}<span class="rt-clock-colon">:</span>${menit}<span class="rt-clock-colon">:</span>${detik}`;
}
const dateEl = document.getElementById('rt-clock-date');
if (dateEl) {
dateEl.textContent = `${hari}, ${tgl} ${bln} ${thn}`;
}
}
updateRtClock();
setInterval(updateRtClock, 1000);
});
</script>

File diff suppressed because it is too large Load Diff

View File

@ -120,6 +120,7 @@
.iv-modal-footer { padding:16px 24px; background:#f8faf8; border-top:1px solid #eef2ee; text-align:right; }
.iv-modal-btn-close { padding:9px 22px; border-radius:10px; border:none; background:#1a3d1a; color:#7edd7e; font-size:13px; font-weight:700; cursor:pointer; font-family:'Plus Jakarta Sans',sans-serif; transition:opacity 0.2s; }
.iv-modal-btn-close:hover { opacity:0.85; }
.iv-badge-amber { background:#fef3c7; color:#a16207; }
</style>
<div class="iv-wrap">
@ -136,7 +137,7 @@
{{-- STATS --}}
@php
$lunas = $iuran->where('status','lunas')->count();
$belum = $iuran->where('status','!=','lunas')->count();
$belum = $iuran->filter(fn($x) => $x->status != 'lunas' && !$x->bukti_pembayaran)->count();
$total = $iuran->where('status','lunas')->sum('jumlah');
$pct = $iuran->count() > 0 ? round($lunas / $iuran->count() * 100) : 0;
@endphp
@ -214,7 +215,7 @@
</thead>
<tbody id="iuranBody">
@forelse($iuran as $i)
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : 'belum' }}">
<tr data-status="{{ $i->status == 'lunas' ? 'lunas' : ($i->bukti_pembayaran ? 'proses' : 'belum') }}">
<td>
<div class="iv-month-cell">
<div class="iv-month-icon"><i class="fas fa-calendar-alt"></i></div>
@ -236,10 +237,15 @@
<div class="iv-status-paid">
<div class="iv-status-dot"></div> Lunas
</div>
@elseif($i->status == 'rt')
<span class="iv-badge iv-badge-blue"> Menunggu Admin</span>
@elseif($i->bukti_pembayaran)
<span class="iv-badge iv-badge-amber"> Menunggu RT</span>
@else
<span class="iv-badge iv-badge-red"> Belum Bayar</span>
@endif
</td>
{{-- JADI --}}
<td style="text-align:right">
@if($i->status == 'lunas')
<button class="iv-btn-detail"
@ -247,6 +253,9 @@
data-target="#modalDetail{{ $i->id }}">
🧾 Detail
</button>
@elseif($i->bukti_pembayaran)
{{-- Sudah upload bukti, sedang diproses tidak ada aksi --}}
<span style="font-size:12px; color:#9aaa9a; font-style:italic;">Sedang diproses</span>
@else
<a href="{{ route('user.iuran.upload', $i->id) }}" class="iv-btn-pay">
<i class="fas fa-credit-card"></i> Bayar