TKK_E32230947/web/index.html

263 lines
9.8 KiB
HTML

<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard — Smart Donation Box</title>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<link rel="stylesheet" href="style.css">
<style>
.foto-section {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-top: 24px;
}
.foto-card {
background: var(--card-bg);
border: 1px solid var(--border-color);
border-radius: 16px;
overflow: hidden;
transition: background-color 0.3s ease;
}
.foto-card-header {
padding: 16px 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border-color);
}
.foto-card-header h3 {
font-size: 15px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.pulse-dot {
width: 8px;
height: 8px;
background: var(--primary-green);
border-radius: 50%;
animation: pulse 2s infinite;
display: inline-block;
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(1.3); }
}
.foto-container {
position: relative;
width: 100%;
aspect-ratio: 4/3;
background: #0a0f1a;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.foto-container img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
transition: opacity 0.4s ease;
}
.foto-placeholder {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
color: var(--text-muted);
}
.foto-placeholder i { font-size: 40px; opacity: 0.3; }
.foto-placeholder p { font-size: 13px; }
.foto-footer {
padding: 12px 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.foto-label {
font-size: 13px;
font-weight: 600;
color: var(--primary-green);
background: var(--primary-green-light);
padding: 4px 10px;
border-radius: 6px;
}
.foto-time {
font-size: 12px;
color: var(--text-muted);
}
.summary-grid-dash {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
margin-bottom: 0;
}
</style>
</head>
<body>
<script type="module">
if (localStorage.getItem('isLoggedIn') !== 'true') {
window.location.href = 'login.html';
}
window.logout = function() {
if (confirm('Apakah Anda yakin ingin keluar?')) {
localStorage.removeItem('isLoggedIn');
window.location.href = 'login.html';
}
}
import { initLayout } from './layout.js';
import { db, formatRp, formatWaktu, isToday } from './firebase-config.js';
import { ref, onValue } from "https://www.gstatic.com/firebasejs/12.10.0/firebase-database.js";
initLayout('dashboard');
document.getElementById('content-area').innerHTML = `
<div class="summary-grid-dash">
<div class="card stat-card">
<div class="stat-icon bg-green-light"><i class="fa-regular fa-calendar-check"></i></div>
<div class="stat-info">
<p>Donasi Hari Ini</p>
<h2 id="dash-donasi-hari-ini">Rp 0</h2>
</div>
</div>
<div class="card stat-card">
<div class="stat-icon bg-blue-light"><i class="fa-solid fa-wallet"></i></div>
<div class="stat-info">
<p>Total Donasi Terkumpul</p>
<h2 id="dash-total-donasi">Rp 0</h2>
</div>
</div>
</div>
<div class="foto-section">
<div class="foto-card">
<div class="foto-card-header">
<h3>
<span class="pulse-dot"></span>
Foto Deteksi Terakhir
</h3>
<span id="foto-badge-status" style="font-size:12px; color:var(--text-muted);">Menunggu...</span>
</div>
<div class="foto-container">
<div class="foto-placeholder" id="foto-placeholder">
<i class="fa-solid fa-camera"></i>
<p>Belum ada deteksi</p>
</div>
<img id="foto-deteksi" src="" alt="Foto Deteksi"
style="display:none;"
onerror="this.style.display='none'; document.getElementById('foto-placeholder').style.display='flex';">
</div>
<div class="foto-footer">
<span class="foto-label" id="foto-label-hasil">—</span>
<span class="foto-time" id="foto-waktu">—</span>
</div>
</div>
<div class="card">
<div class="card-header">
<h3>Transaksi Terakhir</h3>
<a href="log.html" style="font-size:13px; color:var(--primary-green); text-decoration:none; font-weight:500;">
Lihat Semua
</a>
</div>
<table class="styled-table" id="table-transaksi-terakhir">
<tr><td colspan="2" style="text-align:center; color:var(--text-muted); padding:32px;">
<i class="fa-solid fa-spinner fa-spin"></i> Memuat...
</td></tr>
</table>
</div>
</div>
`;
onValue(ref(db, 'smart_donation_box/summary'), (snap) => {
const d = snap.val() || {};
document.getElementById('dash-total-donasi').innerText = formatRp(d.total_donasi);
});
onValue(ref(db, 'smart_donation_box/donasi_log'), (snap) => {
const data = snap.val() || {};
// Filter: buang nominal 0
const keys = Object.keys(data)
.reverse()
.filter(key => (data[key].nominal || 0) > 0);
let donasiHariIni = 0;
let html = '';
if (keys.length === 0) {
html = `<tr><td colspan="2" style="text-align:center; color:var(--text-muted); padding:32px;">
Belum ada transaksi
</td></tr>`;
} else {
keys.forEach((key, i) => {
const item = data[key];
if (isToday(item.timestamp)) donasiHariIni += item.nominal;
if (i < 5) {
html += `
<tr>
<td>
<div style="display:flex; align-items:center; gap:12px;">
<div style="background:var(--primary-green-light);
color:var(--primary-green);
width:32px; height:32px; border-radius:50%;
display:flex; align-items:center; justify-content:center;
flex-shrink:0;">
<i class="fa-solid fa-arrow-down" style="font-size:12px;"></i>
</div>
<div>
<div style="font-weight:600; font-size:13px;">Donasi Masuk</div>
<div style="font-size:11px; color:var(--text-muted);">${formatWaktu(item.timestamp)}</div>
</div>
</div>
</td>
<td style="font-weight:600; text-align:right;">${formatRp(item.nominal)}</td>
</tr>
`;
}
});
}
document.getElementById('dash-donasi-hari-ini').innerText = formatRp(donasiHariIni);
document.getElementById('table-transaksi-terakhir').innerHTML = html;
});
onValue(ref(db, 'smart_donation_box/last_detection'), (snap) => {
const d = snap.val();
if (!d || !d.foto_url) return;
const img = document.getElementById('foto-deteksi');
const placeholder = document.getElementById('foto-placeholder');
const badge = document.getElementById('foto-badge-status');
const label = document.getElementById('foto-label-hasil');
const waktu = document.getElementById('foto-waktu');
badge.textContent = 'Update otomatis';
badge.style.color = 'var(--primary-green)';
label.textContent = d.label || '—';
waktu.textContent = formatWaktu(d.timestamp);
const isBase64 = d.foto_url.startsWith('data:image');
img.onload = () => {
img.style.display = 'block';
placeholder.style.display = 'none';
};
img.onerror = () => {
img.style.display = 'none';
placeholder.style.display = 'flex';
};
img.src = isBase64 ? d.foto_url : d.foto_url + '?t=' + d.timestamp;
});
</script>
</body>
</html>