333 lines
21 KiB
PHP
333 lines
21 KiB
PHP
<?php
|
|
require_once __DIR__ . '/db/config.php';
|
|
@date_default_timezone_set('Asia/Jakarta');
|
|
|
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Sistem manajemen percetakan Kenanga Kreasindo untuk order, SPK, produksi, invoice, dan tracking customer.';
|
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|
$projectName = $_SERVER['PROJECT_NAME'] ?? 'Kenanga Kreasindo Printing';
|
|
|
|
function e(string $value): string { return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); }
|
|
function rupiah(float $value): string { return 'Rp ' . number_format($value, 0, ',', '.'); }
|
|
function nextNumber(PDO $pdo, string $prefix, string $column): string {
|
|
$stmt = $pdo->prepare("SELECT COUNT(*) AS total FROM print_orders WHERE $column LIKE :prefix");
|
|
$stmt->execute([':prefix' => $prefix . '%']);
|
|
$count = (int)($stmt->fetch()['total'] ?? 0) + 1;
|
|
return $prefix . str_pad((string)$count, 5, '0', STR_PAD_LEFT);
|
|
}
|
|
function statusBadge(string $status): string {
|
|
return match ($status) {
|
|
'Order diterima' => 'secondary',
|
|
'SPK dibuat' => 'info',
|
|
'Produksi berjalan' => 'primary',
|
|
'QC / Finishing' => 'warning',
|
|
'Barang selesai' => 'success',
|
|
'Invoice / Tagihan' => 'dark',
|
|
default => 'secondary',
|
|
};
|
|
}
|
|
function ensureSchema(PDO $pdo): void {
|
|
$pdo->exec("CREATE TABLE IF NOT EXISTS print_orders (
|
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
|
order_no VARCHAR(40) NOT NULL UNIQUE,
|
|
spk_no VARCHAR(40) NOT NULL UNIQUE,
|
|
invoice_no VARCHAR(40) NOT NULL UNIQUE,
|
|
customer_name VARCHAR(140) NOT NULL,
|
|
customer_phone VARCHAR(40) NOT NULL,
|
|
customer_email VARCHAR(160) NULL,
|
|
project_name VARCHAR(180) NOT NULL,
|
|
category VARCHAR(100) NOT NULL,
|
|
quantity INT UNSIGNED NOT NULL DEFAULT 1,
|
|
size_info VARCHAR(120) NULL,
|
|
material VARCHAR(160) NULL,
|
|
finishing VARCHAR(180) NULL,
|
|
deadline DATE NULL,
|
|
operator_name VARCHAR(120) NULL,
|
|
cs_name VARCHAR(120) NULL,
|
|
status VARCHAR(40) NOT NULL DEFAULT 'Order diterima',
|
|
progress_note TEXT NULL,
|
|
unit_price DECIMAL(14,2) NOT NULL DEFAULT 0,
|
|
discount DECIMAL(14,2) NOT NULL DEFAULT 0,
|
|
paid_amount DECIMAL(14,2) NOT NULL DEFAULT 0,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
INDEX idx_phone (customer_phone),
|
|
INDEX idx_status (status)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
|
|
}
|
|
|
|
$pdo = db();
|
|
ensureSchema($pdo);
|
|
$errors = [];
|
|
$notice = '';
|
|
$createdId = 0;
|
|
$statuses = ['Order diterima', 'SPK dibuat', 'Produksi berjalan', 'QC / Finishing', 'Barang selesai', 'Invoice / Tagihan'];
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
if ($action === 'create_order') {
|
|
$customerName = trim((string)($_POST['customer_name'] ?? ''));
|
|
$customerPhone = preg_replace('/[^0-9+]/', '', (string)($_POST['customer_phone'] ?? ''));
|
|
$customerEmail = trim((string)($_POST['customer_email'] ?? ''));
|
|
$project = trim((string)($_POST['project_name'] ?? ''));
|
|
$category = trim((string)($_POST['category'] ?? ''));
|
|
$qty = max(1, (int)($_POST['quantity'] ?? 1));
|
|
$deadline = trim((string)($_POST['deadline'] ?? '')) ?: null;
|
|
$unitPrice = max(0, (float)($_POST['unit_price'] ?? 0));
|
|
$discount = max(0, (float)($_POST['discount'] ?? 0));
|
|
$paid = max(0, (float)($_POST['paid_amount'] ?? 0));
|
|
|
|
foreach ([
|
|
'Nama customer' => $customerName,
|
|
'Nomor telepon' => $customerPhone,
|
|
'Nama pekerjaan' => $project,
|
|
'Kategori' => $category,
|
|
] as $label => $value) {
|
|
if ($value === '') { $errors[] = $label . ' wajib diisi.'; }
|
|
}
|
|
if ($customerEmail !== '' && !filter_var($customerEmail, FILTER_VALIDATE_EMAIL)) { $errors[] = 'Format email customer tidak valid.'; }
|
|
|
|
if (!$errors) {
|
|
$year = date('y');
|
|
$month = date('m');
|
|
$orderNo = nextNumber($pdo, 'ORD-' . date('Y') . '-', 'order_no');
|
|
$invoiceNo = nextNumber($pdo, 'VI-' . $year . '-', 'invoice_no');
|
|
$spkPrefix = str_pad((string)(((int)$pdo->query('SELECT COUNT(*) FROM print_orders')->fetchColumn()) + 1), 2, '0', STR_PAD_LEFT) . '-SPK-' . $month . '-' . date('Y');
|
|
$spkNo = $spkPrefix;
|
|
|
|
$stmt = $pdo->prepare('INSERT INTO print_orders (order_no, spk_no, invoice_no, customer_name, customer_phone, customer_email, project_name, category, quantity, size_info, material, finishing, deadline, operator_name, cs_name, status, progress_note, unit_price, discount, paid_amount) VALUES (:order_no, :spk_no, :invoice_no, :customer_name, :customer_phone, :customer_email, :project_name, :category, :quantity, :size_info, :material, :finishing, :deadline, :operator_name, :cs_name, :status, :progress_note, :unit_price, :discount, :paid_amount)');
|
|
$stmt->execute([
|
|
':order_no' => $orderNo,
|
|
':spk_no' => $spkNo,
|
|
':invoice_no' => $invoiceNo,
|
|
':customer_name' => $customerName,
|
|
':customer_phone' => $customerPhone,
|
|
':customer_email' => $customerEmail ?: null,
|
|
':project_name' => $project,
|
|
':category' => $category,
|
|
':quantity' => $qty,
|
|
':size_info' => trim((string)($_POST['size_info'] ?? '')) ?: null,
|
|
':material' => trim((string)($_POST['material'] ?? '')) ?: null,
|
|
':finishing' => trim((string)($_POST['finishing'] ?? '')) ?: null,
|
|
':deadline' => $deadline,
|
|
':operator_name' => trim((string)($_POST['operator_name'] ?? '')) ?: null,
|
|
':cs_name' => trim((string)($_POST['cs_name'] ?? '')) ?: null,
|
|
':status' => 'SPK dibuat',
|
|
':progress_note' => trim((string)($_POST['progress_note'] ?? 'Order diterima dan SPK siap dicetak.')),
|
|
':unit_price' => $unitPrice,
|
|
':discount' => $discount,
|
|
':paid_amount' => $paid,
|
|
]);
|
|
$createdId = (int)$pdo->lastInsertId();
|
|
$notice = 'Order berhasil dibuat. SPK dan Invoice sudah otomatis tersedia.';
|
|
}
|
|
} elseif ($action === 'update_status') {
|
|
$id = (int)($_POST['id'] ?? 0);
|
|
$status = (string)($_POST['status'] ?? '');
|
|
$note = trim((string)($_POST['progress_note'] ?? ''));
|
|
if ($id > 0 && in_array($status, $statuses, true)) {
|
|
$stmt = $pdo->prepare('UPDATE print_orders SET status = :status, progress_note = :note WHERE id = :id');
|
|
$stmt->execute([':status' => $status, ':note' => $note, ':id' => $id]);
|
|
$notice = 'Status produksi berhasil diperbarui.';
|
|
}
|
|
}
|
|
}
|
|
|
|
$trackResult = null;
|
|
if (isset($_GET['track_order'], $_GET['track_phone'])) {
|
|
$trackOrder = trim((string)$_GET['track_order']);
|
|
$trackPhone = preg_replace('/[^0-9+]/', '', (string)$_GET['track_phone']);
|
|
$stmt = $pdo->prepare('SELECT * FROM print_orders WHERE order_no = :order_no AND customer_phone = :phone LIMIT 1');
|
|
$stmt->execute([':order_no' => $trackOrder, ':phone' => $trackPhone]);
|
|
$trackResult = $stmt->fetch() ?: false;
|
|
}
|
|
|
|
$orders = $pdo->query('SELECT * FROM print_orders ORDER BY created_at DESC LIMIT 25')->fetchAll();
|
|
$totalOrders = (int)$pdo->query('SELECT COUNT(*) FROM print_orders')->fetchColumn();
|
|
$activeOrders = (int)$pdo->query("SELECT COUNT(*) FROM print_orders WHERE status NOT IN ('Barang selesai','Invoice / Tagihan')")->fetchColumn();
|
|
$finishedOrders = (int)$pdo->query("SELECT COUNT(*) FROM print_orders WHERE status = 'Barang selesai'")->fetchColumn();
|
|
$finance = $pdo->query('SELECT COALESCE(SUM(quantity * unit_price - discount),0) AS billed, COALESCE(SUM(paid_amount),0) AS paid FROM print_orders')->fetch();
|
|
$receivable = max(0, (float)$finance['billed'] - (float)$finance['paid']);
|
|
?>
|
|
<!doctype html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title><?= e($projectName) ?> — Order, SPK, Produksi & Invoice</title>
|
|
<meta name="description" content="<?= e($projectDescription) ?>">
|
|
<meta property="og:title" content="<?= e($projectName) ?>">
|
|
<meta property="og:description" content="<?= e($projectDescription) ?>">
|
|
<meta property="twitter:title" content="<?= e($projectName) ?>">
|
|
<meta property="twitter:description" content="<?= e($projectDescription) ?>">
|
|
<?php if ($projectImageUrl): ?>
|
|
<meta property="og:image" content="<?= e($projectImageUrl) ?>">
|
|
<meta property="twitter:image" content="<?= e($projectImageUrl) ?>">
|
|
<?php endif; ?>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?= time() ?>">
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg kk-navbar sticky-top">
|
|
<div class="container-fluid px-3 px-lg-4">
|
|
<a class="navbar-brand d-flex align-items-center gap-2" href="#top" aria-label="Kenanga Kreasindo Home">
|
|
<span class="brand-mark">K</span><span>Kenanga Kreasindo</span>
|
|
</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navMenu" aria-controls="navMenu" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
|
|
<div class="collapse navbar-collapse" id="navMenu">
|
|
<div class="navbar-nav ms-auto gap-lg-2">
|
|
<a class="nav-link" href="#order">Order</a>
|
|
<a class="nav-link" href="#produksi">Produksi</a>
|
|
<a class="nav-link" href="#tracking">Tracking Customer</a>
|
|
<a class="nav-link" href="#laporan">Keuangan</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<main id="top" class="container-fluid px-3 px-lg-4 py-4">
|
|
<?php if ($notice || $errors): ?>
|
|
<div class="toast-container position-fixed top-0 end-0 p-3">
|
|
<div class="toast show" role="status" aria-live="polite" aria-atomic="true">
|
|
<div class="toast-header"><strong class="me-auto"><?= $errors ? 'Validasi belum lengkap' : 'Berhasil' ?></strong><button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button></div>
|
|
<div class="toast-body"><?= $errors ? e(implode(' ', $errors)) : e($notice) ?></div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<section class="hero panel mb-4" aria-labelledby="heroTitle">
|
|
<div class="row g-4 align-items-center">
|
|
<div class="col-lg-7">
|
|
<p class="eyebrow mb-2">Sistem Percetakan</p>
|
|
<h1 id="heroTitle">Order masuk, SPK, produksi, invoice, dan tracking customer dalam satu alur.</h1>
|
|
<p class="hero-copy mb-4">MVP awal untuk Percetakan Kenanga Kreasindo: admin membuat order, sistem menerbitkan SPK dan invoice, produksi memperbarui status, customer mengecek progres memakai nomor order + telepon.</p>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<a href="#order" class="btn btn-dark btn-lg">Buat Order & SPK</a>
|
|
<a href="#tracking" class="btn btn-outline-dark btn-lg">Cek Status Customer</a>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-5">
|
|
<div class="company-card">
|
|
<div class="small text-muted">Percetakan</div>
|
|
<h2 class="h4 mb-3">Kenanga Kreasindo</h2>
|
|
<div class="meta-row"><span>Alamat</span><strong>Perum BCL Jln Kenanga Raya</strong></div>
|
|
<div class="meta-row"><span>Email</span><strong>kenangakreasindo@gmail.com</strong></div>
|
|
<div class="meta-row"><span>Runtime</span><strong>PHP <?= e(PHP_VERSION) ?></strong></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="laporan" class="row g-3 mb-4" aria-label="Ringkasan laporan">
|
|
<div class="col-6 col-lg-3"><div class="stat-card"><span>Total Order</span><strong><?= $totalOrders ?></strong></div></div>
|
|
<div class="col-6 col-lg-3"><div class="stat-card"><span>Produksi Aktif</span><strong><?= $activeOrders ?></strong></div></div>
|
|
<div class="col-6 col-lg-3"><div class="stat-card"><span>Barang Selesai</span><strong><?= $finishedOrders ?></strong></div></div>
|
|
<div class="col-6 col-lg-3"><div class="stat-card"><span>Piutang</span><strong><?= e(rupiah($receivable)) ?></strong></div></div>
|
|
</section>
|
|
|
|
<div class="row g-4">
|
|
<section id="order" class="col-xl-5" aria-labelledby="orderTitle">
|
|
<div class="panel h-100">
|
|
<div class="section-heading">
|
|
<p class="eyebrow">Penerimaan Order</p>
|
|
<h2 id="orderTitle">Buat order + SPK</h2>
|
|
</div>
|
|
<form method="post" class="kk-form" novalidate>
|
|
<input type="hidden" name="action" value="create_order">
|
|
<div class="row g-3">
|
|
<div class="col-md-6"><label class="form-label">Nama Customer *</label><input class="form-control" name="customer_name" required></div>
|
|
<div class="col-md-6"><label class="form-label">Telepon *</label><input class="form-control" name="customer_phone" required placeholder="08..."></div>
|
|
<div class="col-12"><label class="form-label">Email</label><input class="form-control" name="customer_email" type="email" placeholder="opsional"></div>
|
|
<div class="col-md-8"><label class="form-label">Nama Pekerjaan *</label><input class="form-control" name="project_name" required placeholder="Contoh: Banner Grand Opening"></div>
|
|
<div class="col-md-4"><label class="form-label">Kategori *</label><select class="form-select" name="category" required><option value="Digital Printing">Digital Printing</option><option value="Offset">Offset</option><option value="Merchandise">Merchandise</option><option value="Apparel">Apparel</option><option value="Lainnya">Lainnya</option></select></div>
|
|
<div class="col-md-4"><label class="form-label">Qty *</label><input class="form-control" name="quantity" type="number" min="1" value="1" required></div>
|
|
<div class="col-md-4"><label class="form-label">Ukuran</label><input class="form-control" name="size_info" placeholder="A3 / 3x1 m"></div>
|
|
<div class="col-md-4"><label class="form-label">Deadline</label><input class="form-control" name="deadline" type="date"></div>
|
|
<div class="col-md-6"><label class="form-label">Bahan</label><input class="form-control" name="material" placeholder="Flexi 280 / Art carton"></div>
|
|
<div class="col-md-6"><label class="form-label">Finishing</label><input class="form-control" name="finishing" placeholder="Laminasi, potong, mata ayam"></div>
|
|
<div class="col-md-6"><label class="form-label">CS</label><input class="form-control" name="cs_name" placeholder="Nama CS"></div>
|
|
<div class="col-md-6"><label class="form-label">Operator</label><input class="form-control" name="operator_name" placeholder="Nama operator"></div>
|
|
<div class="col-md-4"><label class="form-label">Harga / Unit</label><input class="form-control money-input" name="unit_price" type="number" min="0" value="0"></div>
|
|
<div class="col-md-4"><label class="form-label">Diskon</label><input class="form-control money-input" name="discount" type="number" min="0" value="0"></div>
|
|
<div class="col-md-4"><label class="form-label">Terbayar</label><input class="form-control money-input" name="paid_amount" type="number" min="0" value="0"></div>
|
|
<div class="col-12"><label class="form-label">Detail Pesanan / Catatan SPK</label><textarea class="form-control" name="progress_note" rows="3" placeholder="Instruksi file, warna, referensi, catatan operator..."></textarea></div>
|
|
</div>
|
|
<div class="d-flex justify-content-between align-items-center mt-4">
|
|
<small class="text-muted">* wajib diisi. Nomor order, SPK, dan invoice otomatis.</small>
|
|
<button class="btn btn-dark" type="submit">Simpan Order</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="produksi" class="col-xl-7" aria-labelledby="productionTitle">
|
|
<div class="panel h-100">
|
|
<div class="section-heading d-flex justify-content-between align-items-start gap-3">
|
|
<div><p class="eyebrow">Produksi & Monitoring</p><h2 id="productionTitle">Daftar order terbaru</h2></div>
|
|
<?php if ($createdId): ?><a class="btn btn-outline-dark btn-sm" href="order_detail.php?id=<?= $createdId ?>">Lihat order baru</a><?php endif; ?>
|
|
</div>
|
|
<?php if (!$orders): ?>
|
|
<div class="empty-state"><strong>Belum ada order.</strong><span>Buat order pertama untuk menghasilkan SPK, tracking, dan invoice.</span></div>
|
|
<?php else: ?>
|
|
<div class="table-responsive">
|
|
<table class="table align-middle kk-table">
|
|
<thead><tr><th>Order</th><th>Customer</th><th>Pekerjaan</th><th>Status</th><th>Tagihan</th><th>Aksi</th></tr></thead>
|
|
<tbody>
|
|
<?php foreach ($orders as $order): $amount = ((float)$order['quantity'] * (float)$order['unit_price']) - (float)$order['discount']; ?>
|
|
<tr>
|
|
<td><strong><?= e($order['order_no']) ?></strong><div class="small text-muted"><?= e(date('d M Y', strtotime($order['created_at']))) ?></div></td>
|
|
<td><?= e($order['customer_name']) ?><div class="small text-muted"><?= e($order['customer_phone']) ?></div></td>
|
|
<td><?= e($order['project_name']) ?><div class="small text-muted"><?= e($order['category']) ?> · <?= (int)$order['quantity'] ?> pcs</div></td>
|
|
<td><span class="badge text-bg-<?= e(statusBadge($order['status'])) ?>"><?= e($order['status']) ?></span></td>
|
|
<td><?= e(rupiah(max(0, $amount))) ?><div class="small text-muted">Bayar <?= e(rupiah((float)$order['paid_amount'])) ?></div></td>
|
|
<td><div class="btn-group btn-group-sm"><a class="btn btn-outline-dark" href="order_detail.php?id=<?= (int)$order['id'] ?>">Detail</a><a class="btn btn-outline-dark" href="spk.php?id=<?= (int)$order['id'] ?>">SPK</a><a class="btn btn-outline-dark" href="invoice.php?id=<?= (int)$order['id'] ?>">Invoice</a></div></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<section id="tracking" class="panel mt-4" aria-labelledby="trackingTitle">
|
|
<div class="row g-4 align-items-start">
|
|
<div class="col-lg-5">
|
|
<div class="section-heading"><p class="eyebrow">Customer Portal</p><h2 id="trackingTitle">Cek progres order</h2></div>
|
|
<p class="text-muted">Customer tidak perlu login. Masukkan nomor order dan telepon yang tercatat di order.</p>
|
|
<form method="get" class="row g-2">
|
|
<div class="col-md-6"><label class="form-label">Nomor Order</label><input class="form-control" name="track_order" value="<?= e((string)($_GET['track_order'] ?? '')) ?>" placeholder="ORD-2026-00001" required></div>
|
|
<div class="col-md-6"><label class="form-label">Telepon</label><input class="form-control" name="track_phone" value="<?= e((string)($_GET['track_phone'] ?? '')) ?>" placeholder="08..." required></div>
|
|
<div class="col-12"><button class="btn btn-dark" type="submit">Cek Status</button></div>
|
|
</form>
|
|
</div>
|
|
<div class="col-lg-7">
|
|
<?php if ($trackResult === null): ?>
|
|
<div class="empty-state"><strong>Hasil tracking muncul di sini.</strong><span>Gunakan nomor order dari admin/Kasir.</span></div>
|
|
<?php elseif ($trackResult === false): ?>
|
|
<div class="alert alert-warning mb-0">Order tidak ditemukan. Pastikan nomor order dan telepon sudah benar.</div>
|
|
<?php else: ?>
|
|
<div class="tracking-card">
|
|
<div class="d-flex justify-content-between gap-3 flex-wrap"><div><span class="small text-muted">Order</span><h3><?= e($trackResult['order_no']) ?></h3></div><span class="badge text-bg-<?= e(statusBadge($trackResult['status'])) ?> align-self-start"><?= e($trackResult['status']) ?></span></div>
|
|
<p class="mb-2"><strong><?= e($trackResult['project_name']) ?></strong> — <?= e($trackResult['category']) ?>, <?= (int)$trackResult['quantity'] ?> pcs</p>
|
|
<p class="text-muted mb-3"><?= nl2br(e((string)$trackResult['progress_note'])) ?></p>
|
|
<ol class="progress-steps">
|
|
<?php $current = array_search($trackResult['status'], $statuses, true); foreach ($statuses as $i => $s): ?>
|
|
<li class="<?= $i <= (int)$current ? 'done' : '' ?>"><span><?= e($s) ?></span></li>
|
|
<?php endforeach; ?>
|
|
</ol>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer class="container-fluid px-3 px-lg-4 pb-4">
|
|
<div class="footer-line">© <?= date('Y') ?> Kenanga Kreasindo · Perum BCL Jln Kenanga Raya · kenangakreasindo@gmail.com</div>
|
|
</footer>
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="assets/js/main.js?v=<?= time() ?>"></script>
|
|
</body>
|
|
</html>
|