TKK_E32230607/smart-drop-point/public/index.php

356 lines
7.9 KiB
PHP

<?php
require_once __DIR__ . "/../config/db.php";
include __DIR__ . "/../partials/header.php";
include __DIR__ . "/../partials/sidebar.php";
// stats
$stats = [
"total_resi" => 0,
"resi_valid" => 0,
"resi_invalid" => 0,
"log_today" => 0,
"log_ok" => 0,
"log_fail" => 0
];
$r = $conn->query("SELECT COUNT(*) c, SUM(status='valid') v, SUM(status='invalid') i FROM resi");
if ($r && $row = $r->fetch_assoc()) {
$stats["total_resi"] = (int)($row["c"] ?? 0);
$stats["resi_valid"] = (int)($row["v"] ?? 0);
$stats["resi_invalid"] = (int)($row["i"] ?? 0);
}
$today = date("Y-m-d");
$r2 = $conn->query("
SELECT
COUNT(*) c,
SUM(status='berhasil') ok,
SUM(status='gagal') fail
FROM log_akses
WHERE DATE(created_at)='{$today}'
");
if ($r2 && $row2 = $r2->fetch_assoc()) {
$stats["log_today"] = (int)($row2["c"] ?? 0);
$stats["log_ok"] = (int)($row2["ok"] ?? 0);
$stats["log_fail"] = (int)($row2["fail"] ?? 0);
}
// latest logs
$latest = $conn->query("
SELECT
id,
nomor_resi,
status,
pesan,
created_at,
foto_path
FROM log_akses
ORDER BY created_at DESC
LIMIT 8
");
?>
<div class="row g-3">
<div class="col-12">
<div class="card-glass p-4">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
<div>
<h3 class="mb-1">Dashboard</h3>
<div class="text-muted">
Ringkasan sistem monitoring paket & autentikasi resi.
</div>
</div>
<div class="d-flex gap-2">
<a class="btn btn-accent px-3 py-2 text-white"
href="/smart-drop-point/public/resi_add.php">
<i class="bi bi-plus-circle me-2"></i>
Tambah Resi
</a>
<a class="btn btn-danger px-3 py-2"
href="/smart-drop-point/public/manual_open.php"
onclick="return confirm('Yakin ingin membuka pintu secara manual?')">
🔓 Buka Pintu
</a>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card-glass p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted">Total Resi Terdaftar</div>
<div class="fs-3 fw-bold">
<?= $stats["total_resi"] ?>
</div>
</div>
<div class="badge badge-soft p-2">
<i class="bi bi-upc-scan fs-4"></i>
</div>
</div>
<div class="mt-2 small text-muted">
Valid: <?= $stats["resi_valid"] ?>
Invalid: <?= $stats["resi_invalid"] ?>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card-glass p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted">Total Scan Hari Ini</div>
<div class="fs-3 fw-bold">
<?= $stats["log_today"] ?>
</div>
</div>
<div class="badge badge-soft p-2">
<i class="bi bi-clock-history fs-4"></i>
</div>
</div>
<div class="mt-2 small text-muted">
Berhasil: <?= $stats["log_ok"] ?>
Gagal: <?= $stats["log_fail"] ?>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card-glass p-3">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="text-muted">Status Server</div>
<div class="fs-4 fw-bold">
<i class="bi bi-check-circle-fill me-2" style="color:#22c55e"></i>
Online
</div>
</div>
<div class="badge badge-soft p-2">
<i class="bi bi-hdd-network fs-4"></i>
</div>
</div>
<div class="mt-2 small text-muted">
Mode: Localhost (XAMPP)
</div>
</div>
</div>
<div class="col-12">
<div class="card-glass p-3">
<div class="d-flex justify-content-between align-items-center mb-2">
<div class="fw-semibold">
Log Terbaru
</div>
<a class="text-decoration-none"
href="/smart-drop-point/public/log.php">
Lihat semua
<i class="bi bi-arrow-right"></i>
</a>
</div>
<div class="table-responsive">
<table class="table table-dark table-hover align-middle mb-0">
<thead>
<tr>
<th>Waktu</th>
<th>Nomor Resi</th>
<th>Status</th>
<th>Pesan</th>
<th>Foto</th>
</tr>
</thead>
<tbody>
<?php if ($latest && $latest->num_rows > 0): ?>
<?php while ($x = $latest->fetch_assoc()): ?>
<tr>
<td class="text-muted">
<?= htmlspecialchars($x["created_at"]) ?>
</td>
<td class="fw-semibold">
<?= htmlspecialchars($x["nomor_resi"] ?? "-") ?>
</td>
<td>
<?php if ($x["status"] === "berhasil"): ?>
<span class="badge text-bg-success">
Berhasil
</span>
<?php else: ?>
<span class="badge text-bg-danger">
Gagal
</span>
<?php endif; ?>
</td>
<td class="text-muted">
<?= htmlspecialchars($x["pesan"] ?? "-") ?>
</td>
<td>
<?php if (!empty($x["foto_path"])): ?>
<a href="#"
data-foto-modal="1"
data-src="<?= htmlspecialchars($x["foto_path"]) ?>"
data-caption="<?= htmlspecialchars(($x["nomor_resi"] ?? "-") . " • " . $x["created_at"]) ?>">
<img
src="<?= htmlspecialchars($x["foto_path"]) ?>"
alt="foto"
style="width:52px;height:52px;object-fit:cover;border-radius:10px;border:1px solid rgba(255,255,255,.2);cursor:pointer;"
>
</a>
<?php else: ?>
<span class="text-muted">-</span>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
<?php else: ?>
<tr>
<td colspan="5" class="text-muted">
Belum ada log.
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="modal fade" id="fotoModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content bg-dark text-light">
<div class="modal-header border-secondary">
<h5 class="modal-title">Bukti Foto</h5>
<button type="button"
class="btn-close btn-close-white"
data-bs-dismiss="modal">
</button>
</div>
<div class="modal-body text-center">
<img id="fotoModalImg"
src=""
alt="foto"
style="max-width:100%;height:auto;border-radius:12px;">
<div class="mt-2 text-muted small"
id="fotoModalCaption">
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener("click", function (e) {
const a = e.target.closest("[data-foto-modal='1']");
if (!a) return;
e.preventDefault();
const src = a.getAttribute("data-src");
const caption = a.getAttribute("data-caption") || "";
document.getElementById("fotoModalImg").src = src;
document.getElementById("fotoModalCaption").textContent = caption;
const modal = new bootstrap.Modal(
document.getElementById("fotoModal")
);
modal.show();
});
document
.getElementById("fotoModal")
.addEventListener("hidden.bs.modal", function () {
document.getElementById("fotoModalImg").src = "";
document.getElementById("fotoModalCaption").textContent = "";
});
</script>
<?php include __DIR__ . "/../partials/footer.php"; ?>