<!DOCTYPE html>

<html lang="id">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Pangsit Mie Tetangga - POS & Finance</title>

</head>

<body>

    <!-- <!DOCTYPE html>

<html lang="id">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Pangsit Mie Tetangga - POS & Finance</title>


<!-- Tailwind -->

<script src="https://cdn.tailwindcss.com"></script>


<!-- Lucide Icons -->

<script src="https://unpkg.com/lucide@latest"></script>


<!-- html2canvas -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>


<script>

tailwind.config = {

        theme: {

                extend: {

                        colors: {

                                brand: {

                                        50: '#fff8ef',

                                        100: '#ffedd8',

                                        200: '#ffd5ad',

                                        300: '#ffb978',

                                        400: '#ff9745',

                                        500: '#f47c20',

                                        600: '#dc6410',

                                        700: '#b94c0d',

                                        800: '#963d10',

                                        900: '#77350f'

                                }

                        },

                        boxShadow: {

                                soft: '0 4px 20px rgba(30,41,59,.06)',

                                card: '0 2px 12px rgba(30,41,59,.05)'

                        }

                }

        }

}

</script>


<style>

* {

        box-sizing: border-box;

}


body {

        margin: 0;

        background: #faf9f7;

        color: #172033;

        font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

}


button, input, select, textarea {

        font: inherit;

}


button {

        -webkit-tap-highlight-color: transparent;

}


.sidebar {

        width: 270px;

        transition: .25s ease;

}


.main-area {

        margin-left: 270px;

        transition: .25s ease;

}


@media(max-width: 1024px) {

        .sidebar {

                transform: translateX(-100%);

                position: fixed;

                z-index: 100;

                height: 100vh;

        }


        .sidebar.open {

                transform: translateX(0);

        }


        .main-area {

                margin-left: 0;

        }

}


@media(max-width: 640px) {

        .desktop-only {

                display: none !important;

        }


        .mobile-bottom-nav {

                display: flex;

        }


        .main-content {

                padding-bottom: 95px !important;

        }

}


@media(min-width: 641px) {

        .mobile-bottom-nav {

                display: none;

        }

}


.card {

        background: white;

        border: 1px solid #ece9e4;

        border-radius: 14px;

        box-shadow: 0 2px 12px rgba(30,41,59,.035);

}


.stat-card {

        transition: .2s ease;

}


.stat-card:hover {

        transform: translateY(-2px);

        box-shadow: 0 8px 25px rgba(30,41,59,.07);

}


.food-icon {

        width: 46px;

        height: 46px;

        border-radius: 50%;

        display: flex;

        align-items: center;

        justify-content: center;

}


.food-icon.orange { background: #fff0dd; color: #e66d16; }

.food-icon.green { background: #e5f8e8; color: #159447; }

.food-icon.red { background: #ffe7e7; color: #dc3f3f; }

.food-icon.purple { background: #f1e8ff; color: #7137c9; }

.food-icon.blue { background: #e8f1ff; color: #2563c7; }


.menu-card { transition: .18s ease; }

.menu-card:hover {

        transform: translateY(-2px);

        box-shadow: 0 10px 28px rgba(30,41,59,.08);

}


.menu-img {

        height: 145px;

        width: 100%;

        object-fit: cover;

}


.qty-control {

        display: flex;

        align-items: center;

        gap: 8px;

}


.qty-btn {

        width: 32px;

        height: 32px;

        border-radius: 9px;

        display: flex;

        align-items: center;

        justify-content: center;

        background: #fff3e5;

        color: #d7630c;

        transition: .15s;

}


.qty-btn:hover { background: #ffe1c0; }


.floating-cart { animation: slideUp .25s ease; }


@keyframes slideUp {

        from { transform: translateY(20px); opacity: 0; }

        to { transform: translateY(0); opacity: 1; }

}


.modal-backdrop {

        background: rgba(15,23,42,.42);

        backdrop-filter: blur(3px);

}


.tab-active {

        background: #fff0dc;

        color: #c9570a;

}


.scrollbar-hide::-webkit-scrollbar { display: none; }

.scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; }


.receipt {

        width: 320px;

        background: white;

        padding: 22px;

        color: #111827;

        font-family: Arial, sans-serif;

}


.receipt-line {

        border-top: 1px dashed #aaa;

        margin: 12px 0;

}


@media(max-width: 640px) {

        .modal-container {

                width: 100%;

                max-height: 94vh;

                border-radius: 22px 22px 0 0;

                align-self: flex-end;

        }

}


.toast { animation: toastIn .25s ease; }


@keyframes toastIn {

        from { transform: translateY(10px); opacity: 0; }

        to { transform: translateY(0); opacity: 1; }

}

</style>

</head>


<body>


<div id="app">


        <!-- MOBILE OVERLAY -->

        <div id="sidebarOverlay" class="fixed inset-0 bg-black/30 z-[90] hidden lg:hidden" onclick="toggleSidebar()"></div>


        <!-- SIDEBAR -->

        <aside id="sidebar" class="sidebar fixed left-0 top-0 bottom-0 bg-white border-r border-stone-200 flex flex-col z-[100]">


                <div class="px-6 py-5 border-b border-stone-100">

                        <div class="flex items-center gap-3">

                                <div class="w-14 h-14 rounded-2xl bg-brand-50 flex items-center justify-center">

                                        <i data-lucide="soup" class="w-9 h-9 text-brand-600"></i>

                                </div>

                                <div>

                                        <div class="font-extrabold text-xl leading-tight text-stone-900">Pangsit Mie</div>

                                        <div class="font-semibold italic text-brand-600 text-xl leading-tight">Tetangga</div>

                                </div>

                        </div>

                </div>


                <div class="flex-1 overflow-y-auto px-4 py-5">


                        <div class="mb-7">

                                <div class="text-[11px] font-semibold uppercase tracking-wider text-slate-400 px-3 mb-2">Utama</div>

                                <button onclick="navigate('dashboard')" data-nav="dashboard" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium">

                                        <i data-lucide="layout-dashboard" class="w-5 h-5"></i>

                                        Dashboard

                                </button>

                        </div>


                        <div class="mb-7">

                                <div class="text-[11px] font-semibold uppercase tracking-wider text-slate-400 px-3 mb-2">POS & Transaksi</div>

                                <button onclick="navigate('pos')" data-nav="pos" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="soup" class="w-5 h-5"></i>

                                        Kasir (POS)

                                </button>

                                <button onclick="navigate('history')" data-nav="history" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="receipt-text" class="w-5 h-5"></i>

                                        Riwayat Transaksi

                                </button>

                                <button onclick="navigate('reports')" data-nav="reports" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="chart-column" class="w-5 h-5"></i>

                                        Laporan

                                </button>

                        </div>


                        <div class="mb-7">

                                <div class="text-[11px] font-semibold uppercase tracking-wider text-slate-400 px-3 mb-2">Keuangan</div>

                                <button onclick="navigate('accounts')" data-nav="accounts" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="wallet-cards" class="w-5 h-5"></i>

                                        Rekening & Saldo

                                </button>

                                <button onclick="navigate('transactions')" data-nav="transactions" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="arrow-right-left" class="w-5 h-5"></i>

                                        Transaksi

                                </button>

                                <button onclick="navigate('finance')" data-nav="finance" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="chart-no-axes-combined" class="w-5 h-5"></i>

                                        Laporan Keuangan

                                </button>

                        </div>


                        <div class="mb-7">

                                <div class="text-[11px] font-semibold uppercase tracking-wider text-slate-400 px-3 mb-2">Manajemen</div>

                                <button onclick="navigate('menus')" data-nav="menus" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="utensils" class="w-5 h-5"></i>

                                        Menu

                                </button>

                                <button onclick="navigate('users')" data-nav="users" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="user-round" class="w-5 h-5"></i>

                                        Akun

                                </button>

                                <button onclick="navigate('brand')" data-nav="brand" class="nav-item w-full flex items-center gap-3 px-3 py-3 rounded-xl text-sm font-medium text-slate-600 hover:bg-stone-50">

                                        <i data-lucide="store" class="w-5 h-5"></i>

                                        Profil Brand

                                </button>

                                                </div>


                </div>


                <div class="p-4 border-t border-stone-100">

                        <div class="rounded-xl border border-stone-200 p-3 flex items-center gap-3">

                                <div class="w-10 h-10 rounded-full bg-brand-100 text-brand-700 flex items-center justify-center">

                                        <i data-lucide="user-round" class="w-5 h-5"></i>

                                </div>

                                <div class="flex-1 min-w-0">

                                        <div class="font-semibold text-sm truncate" id="currentUserRoleName">Admin Owner</div>

                                        <div class="text-xs text-slate-500" id="currentUserRoleTag">Owner</div>

                                </div>

                                <i data-lucide="shield-check" class="w-4 h-4 text-emerald-600"></i>

                        </div>

<button onclick="logoutUser()" class="w-full mt-3 flex items-center justify-center gap-2 px-3 py-2.5 rounded-xl border border-red-200 text-red-600 bg-red-50 hover:bg-red-100 text-sm font-semibold transition">

<i data-lucide="log-out" class="w-4 h-4"></i>

Logout / Keluar

</button>

                </div>


        </aside>


        <!-- MAIN AREA -->

        <main class="main-area min-h-screen">


                <header class="h-[74px] bg-white border-b border-stone-200 flex items-center px-5 lg:px-7 sticky top-0 z-40">

                        <button onclick="toggleSidebar()" class="lg:hidden mr-4 p-2 rounded-lg hover:bg-stone-100">

                                <i data-lucide="menu" class="w-6 h-6"></i>

                        </button>


                        <div class="flex-1"></div>


                        <div class="flex items-center gap-3 sm:gap-4">


                                <div class="flex items-center gap-3">

                                        <div class="w-10 h-10 rounded-full bg-brand-50 text-brand-600 flex items-center justify-center">

                                                <i data-lucide="store" class="w-5 h-5"></i>

                                        </div>

                                        <div class="hidden sm:block">

                                                <div class="text-sm font-semibold">Pangsit Mie Tetangga</div>

                                                <div class="flex items-center gap-1 text-xs text-emerald-600">

                                                        <span class="w-2 h-2 bg-emerald-500 rounded-full"></span>

                                                        Online

                                                </div>

                                        </div>

                                </div>

                        </div>

                </header>


                <div id="content" class="main-content p-5 lg:p-7"></div>


        </main>


        <!-- MOBILE BOTTOM NAV -->

        <nav class="mobile-bottom-nav fixed bottom-0 left-0 right-0 bg-white border-t border-stone-200 z-[80] px-2 py-2 justify-around">

                <button onclick="navigate('dashboard')" class="flex flex-col items-center gap-1 p-2 text-slate-500">

                        <i data-lucide="layout-dashboard" class="w-5 h-5"></i>

                        <span class="text-[10px]">Home</span>

                </button>

                <button onclick="navigate('pos')" class="flex flex-col items-center gap-1 p-2 text-slate-500">

                        <i data-lucide="soup" class="w-5 h-5"></i>

                        <span class="text-[10px]">Kasir</span>

                </button>

                <button onclick="navigate('transactions')" class="flex flex-col items-center gap-1 p-2 text-slate-500">

                        <i data-lucide="arrow-right-left" class="w-5 h-5"></i>

                        <span class="text-[10px]">Transaksi</span>

                </button>

                <button onclick="navigate('history')" class="flex flex-col items-center gap-1 p-2 text-slate-500">

                        <i data-lucide="receipt-text" class="w-5 h-5"></i>

                        <span class="text-[10px]">Riwayat</span>

                </button>

        </nav>


</div>


<div id="modalRoot"></div>

<div id="toastContainer" class="fixed right-4 bottom-5 z-[300] space-y-2"></div>


<script>


/* =========================================================

      DATABASE DEMO

========================================================= */


const defaultMenus = [

        { id: 1, name: "Pangsit Mie Original", category: "Makanan", price: 16000, image: "https://images.unsplash.com/photo-1569718212165-3a8278d5f624?auto=format&fit=crop&w=600&q=80" },

        { id: 2, name: "Pangsit Kuah", category: "Makanan", price: 12000, image: "https://images.unsplash.com/photo-1585032226651-759b368d7246?auto=format&fit=crop&w=600&q=80" },

        { id: 3, name: "Dimsum", category: "Makanan", price: 11000, image: "https://images.unsplash.com/photo-1496116218417-1a781b1c416c?auto=format&fit=crop&w=600&q=80" },

        { id: 4, name: "Es Jeruk", category: "Minuman", price: 10000, image: "https://images.unsplash.com/photo-1621263764928-df1444c5e859?auto=format&fit=crop&w=600&q=80" },

        { id: 5, name: "Teh Manis", category: "Minuman", price: 8000, image: "https://images.unsplash.com/photo-1556679343-c7306c1976bc?auto=format&fit=crop&w=600&q=80" },

        { id: 6, name: "Es Teh Lemon", category: "Minuman", price: 10000, image: "https://images.unsplash.com/photo-1556679343-c7306c1976bc?auto=format&fit=crop&w=600&q=80" },

        { id: 7, name: "Extra Pangsit", category: "Extra", price: 5000, image: "https://images.unsplash.com/photo-1496116218417-1a781b1c416c?auto=format&fit=crop&w=600&q=80" },

        { id: 8, name: "Extra Bakso", category: "Extra", price: 5000, image: "https://images.unsplash.com/photo-1569718212165-3a8278d5f624?auto=format&fit=crop&w=600&q=80" }

];


const defaultAccounts = [

        { id: 1, name: "Cash (Tunai)", type: "Cash", balance: 320000 },

        { id: 2, name: "BCA", type: "Bank", balance: 250000 },

        { id: 3, name: "BRI", type: "Bank", balance: 150000 },

        { id: 4, name: "QRIS", type: "Digital", balance: 100000 },

        { id: 5, name: "ShopeePay", type: "Digital", balance: 50000 }

];


const defaultUsers = [

        { id: 1, name: "Admin Owner", username: "owner", password: "owner123", role: "Owner" },

        { id: 2, name: "Kasir Toko", username: "kasir", password: "kasir123", role: "Kasir" }

];


const defaultTransactions = [

        { id: 1001, type: "Pemasukan", amount: 500000, account: "BCA", note: "Modal tambahan", date: "2026-09-28T10:24:00", status: "Berhasil" },

        { id: 1002, type: "Penjualan", amount: 85000, account: "QRIS", note: "Pangsit Mie x2, Es Jeruk x1", date: "2026-09-28T09:45:00", status: "Berhasil", items: [{ name: "Pangsit Mie Original", qty: 2, price: 16000 }, { name: "Es Jeruk", qty: 1, price: 10000 }] },

        { id: 1003, type: "Pengeluaran Usaha", amount: 275000, account: "Cash (Tunai)", note: "Bahan baku", date: "2026-09-28T08:30:00", status: "Berhasil" },

        { id: 1004, type: "Pengeluaran Pribadi", amount: 100000, account: "Cash (Tunai)", note: "Bensin", date: "2026-09-28T07:15:00", status: "Berhasil" }

];


let menus = JSON.parse(localStorage.getItem("pmt_menus")) || defaultMenus;

let accounts = JSON.parse(localStorage.getItem("pmt_accounts")) || defaultAccounts;

let transactions = JSON.parse(localStorage.getItem("pmt_transactions")) || defaultTransactions;

let users = JSON.parse(localStorage.getItem("pmt_users")) || defaultUsers;


let cart = [];

let currentPage = "dashboard";

let currentPOSCategory = "Semua";

let currentUserRole = localStorage.getItem("pmt_current_role") || "Owner";

let currentUserName = localStorage.getItem("pmt_current_name") || (currentUserRole === "Owner" ? "Admin Owner" : "Kasir Toko");

let currentUserId = Number(localStorage.getItem("pmt_current_user_id")) || users.find(user => user.name === currentUserName && user.role === currentUserRole)?.id || null;


/* =========================================================

SESSION / LOGIN

========================================================= */

function isLoggedIn() {

        return localStorage.getItem("pmt_logged_in") === "1";

}

function updateCurrentUserUI() {

        const name = document.getElementById("currentUserRoleName");

        const role = document.getElementById("currentUserRoleTag");

                if (name) name.textContent = currentUserName;

        if (role) role.textContent = currentUserRole;

}

function loginAs(event) {

        event.preventDefault();

        const username = document.getElementById("loginUsername").value.trim().toLowerCase();

        const password = document.getElementById("loginPassword").value;

        const user = users.find(item => item.username.toLowerCase() === username && item.password === password);

        if (!user) {

                showToast("Username atau password salah.", "error");

                return;

        }

        currentUserId = user.id;

        currentUserRole = user.role;

        currentUserName = user.name;

        localStorage.setItem("pmt_logged_in", "1");

        localStorage.setItem("pmt_current_user_id", String(user.id));

        localStorage.setItem("pmt_current_role", currentUserRole);

        localStorage.setItem("pmt_current_name", currentUserName);

        document.getElementById("loginRoot")?.remove();

        render();

        showToast(`Masuk sebagai ${currentUserName}`);

}

function logoutUser() {

        if (!confirm("Yakin ingin keluar dari aplikasi?")) return;

        localStorage.removeItem("pmt_logged_in");

        localStorage.removeItem("pmt_current_user_id");

        localStorage.removeItem("pmt_current_role");

        localStorage.removeItem("pmt_current_name");

        currentUserId = null;

        currentUserRole = "Owner";

        currentUserName = "Admin Owner";

        document.getElementById("modalRoot").innerHTML = "";

        showLoginScreen();

}

function showLoginScreen() {

        let root = document.getElementById("loginRoot");

        if (!root) {

                root = document.createElement("div");

                root.id = "loginRoot";

                root.className = "fixed inset-0 z-[500] bg-slate-950/95 flex items-center justify-center p-4";

                document.body.appendChild(root);

        }

        root.innerHTML = `

                <div class="w-full max-w-md bg-white rounded-3xl shadow-2xl overflow-hidden">

                        <div class="p-7 bg-gradient-to-br from-brand-50 to-white border-b border-stone-100">

                                <div class="w-14 h-14 rounded-2xl bg-brand-500 text-white flex items-center justify-center mb-4">${icon("soup",28)}</div>

                                <h1 class="text-2xl font-extrabold text-slate-900">Pangsit Mie Tetangga</h1>

                                <p class="text-sm text-slate-500 mt-1">Masuk dengan username dan password.</p>

                        </div>

                        <form onsubmit="loginAs(event)" class="p-6 space-y-4">

                                <div>

                                        <label for="loginUsername" class="block text-sm font-semibold mb-1">Username</label>

                                        <input id="loginUsername" required autocomplete="username" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>

                                <div>

                                        <label for="loginPassword" class="block text-sm font-semibold mb-1">Password</label>

                                        <input id="loginPassword" type="password" required autocomplete="current-password" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>

                                <button type="submit" class="w-full bg-brand-500 hover:bg-brand-600 text-white py-3 rounded-xl font-bold">Masuk</button>

                                <p class="text-[11px] text-slate-400 text-center">Akun bawaan demo: owner / owner123 · kasir / kasir123. Data akun tersimpan lokal dan bukan untuk autentikasi produksi.</p>

                        </form>

                </div>`;

        lucide.createIcons();

}



/* =========================================================

      UTILITIES & APPS SCRIPT SYNC LOGIC

========================================================= */


let sharedSaveInFlight = false;

let sharedSavePending = false;

let sharedSyncFailed = false;

let sharedUpdatedAt = "";


function persistLocalData() {

        localStorage.setItem("pmt_menus", JSON.stringify(menus));

        localStorage.setItem("pmt_accounts", JSON.stringify(accounts));

        localStorage.setItem("pmt_transactions", JSON.stringify(transactions));

        localStorage.setItem("pmt_users", JSON.stringify(users));

}


function sharedDataSnapshot() {

        return {

                menus: menus,

                accounts: accounts,

                transactions: transactions,

                users: users

        };

}


function saveData() {

        persistLocalData();

        if (!window.google || !google.script || !google.script.run) return;

        sharedSavePending = true;

        flushSharedSave();

}


function flushSharedSave() {

        if (sharedSaveInFlight || !sharedSavePending || !google.script?.run) return;

        sharedSaveInFlight = true;

        sharedSavePending = false;

        google.script.run

                .withSuccessHandler(result => {

                        sharedSaveInFlight = false;

                        sharedSyncFailed = false;

                        sharedUpdatedAt = result?.updatedAt || sharedUpdatedAt;

                        if (sharedSavePending) flushSharedSave();

                })

                .withFailureHandler(error => {

                        sharedSaveInFlight = false;

                        sharedSyncFailed = true;

                        showToast(`Gagal menyimpan sinkronisasi: ${error?.message || "Periksa koneksi"}`, "error");

                })

                .saveSharedData(sharedDataSnapshot());

}


function applySharedData(data) {

        if (Array.isArray(data.menus)) menus = data.menus;

        if (Array.isArray(data.accounts)) accounts = data.accounts;

        if (Array.isArray(data.transactions)) transactions = data.transactions;

        if (Array.isArray(data.users)) users = data.users;

        sharedUpdatedAt = data.updatedAt || "";

        persistLocalData();

}


function startApp() {

        const finish = () => {

                if (isLoggedIn()) render();

                else { render(); showLoginScreen(); }

        };

        if (!window.google || !google.script || !google.script.run) {

                finish();

                return;

        }

        google.script.run

                .withSuccessHandler(data => {

                        if (data?.initialized) applySharedData(data);

                        else saveData();

                        finish();

                        window.setInterval(refreshSharedData, 15000);

                })

                .withFailureHandler(error => {

                        finish();

                        showToast(`Data server belum dapat dimuat: ${error?.message || "Periksa konfigurasi Apps Script"}`, "error");

                })

                .getSharedData();

}


function refreshSharedData() {

        if (sharedSaveInFlight || sharedSavePending || sharedSyncFailed || !google.script?.run) return;

        google.script.run

                .withSuccessHandler(data => {

                        if (!data?.initialized || !data.updatedAt || data.updatedAt === sharedUpdatedAt) return;

                        applySharedData(data);

                        render();

                        showToast("Data diperbarui dari perangkat lain.", "info");

                })

                .withFailureHandler(() => {})

                .getSharedData();

}


function rupiah(value) {

        value = Number(value) || 0;

        return "Rp " + value.toLocaleString("id-ID");

}


function numberFormat(value) {

        value = Number(value) || 0;

        return value.toLocaleString("id-ID");

}


function escapeHTML(str) {

        return String(str ?? "")

                .replaceAll("&", "&amp;")

                .replaceAll("<", "&lt;")

                .replaceAll(">", "&gt;")

                .replaceAll('"', "&quot;")

                .replaceAll("'", "&#039;");

}


function formatDate(date) {

        return new Date(date).toLocaleDateString("id-ID", { day: "2-digit", month: "short", year: "numeric" });

}


function formatDateTime(date) {

        return new Date(date).toLocaleString("id-ID", { day: "2-digit", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit" });

}


function getTotalBalance() {

        return accounts.reduce((sum, account) => sum + Number(account.balance || 0), 0);

}


function getTransactions(type = null) {

        if (!type) return transactions;

        return transactions.filter(t => t.type === type);

}


function totalTransaction(type) {

        return getTransactions(type).reduce((sum, t) => sum + Number(t.amount || 0), 0);

}


function showToast(message, type = "success") {

        const container = document.getElementById("toastContainer");

        const color = type === "success" ? "emerald" : type === "error" ? "red" : "amber";

        const div = document.createElement("div");

        div.className = `toast bg-white border border-${color}-200 shadow-xl rounded-xl px-4 py-3 flex items-center gap-3`;

        div.innerHTML = `

                <div class="w-8 h-8 rounded-full bg-${color}-50 text-${color}-600 flex items-center justify-center">

                        <i data-lucide="${type === "success" ? "check" : type === "error" ? "x" : "info"}" class="w-4 h-4"></i>

                </div>

                <div class="text-sm font-medium text-slate-700">${escapeHTML(message)}</div>

        `;

        container.appendChild(div);

        lucide.createIcons();

        setTimeout(() => div.remove(), 3200);

}


/* =========================================================

      APPS SCRIPT SYNC FUNCTIONALITY

========================================================= */


/* Data is persisted through google.script.run in saveData(). */

/*

async function syncToAppSheet(action, transactionData) {

        if (appSheetConfig.appScriptUrl) {

                const row = {

                        ID: String(transactionData.id),

                        Type: transactionData.type || "",

                        Amount: Number(transactionData.amount || 0),

                        Account: transactionData.account || "",

                        Note: transactionData.note || "",

                        Customer: transactionData.customer || "",

                        WhatsApp: transactionData.whatsapp || "",

                        Date: transactionData.date || new Date().toISOString(),

                        Status: transactionData.status || "Berhasil"

                };

                try {

                        const response = await fetch(appSheetConfig.appScriptUrl, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify({ action: action, row: row }) });

                        const result = await response.json();

                        if (response.ok && result.success) return { success: true };

                        return { success: false, message: result.message || result.response || "Apps Script gagal." };

                } catch (err) { return { success: false, message: err.message }; }

        }

        if (!appSheetConfig.appId || !appSheetConfig.accessKey) return { success: false, message: "Isi Apps Script URL atau App ID + Access Key AppSheet." };

        const endpoint = `https://api.appsheet.com/api/v2/apps/${encodeURIComponent(appSheetConfig.appId)}/tables/${encodeURIComponent(appSheetConfig.tableName || "Transactions")}/Action`;

        const rowPayload = { ID: String(transactionData.id), Type: transactionData.type || "", Amount: Number(transactionData.amount || 0), Account: transactionData.account || "", Note: transactionData.note || "", Customer: transactionData.customer || "", WhatsApp: transactionData.whatsapp || "", Date: transactionData.date || new Date().toISOString(), Status: transactionData.status || "Berhasil" };

        try {

                const response = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", "ApplicationAccessKey": appSheetConfig.accessKey }, body: JSON.stringify({ Action: action, Properties: { Locale: "id-ID", Timezone: "Asia/Jakarta" }, Rows: [rowPayload] }) });

                if (response.ok) return { success: true };

                return { success: false, message: await response.text() };

        } catch (err) { return { success: false, message: err.message }; }

}


async function triggerSyncWithFeedback(action, data, successLabel) {

        if (appSheetConfig.autoSync && (appSheetConfig.appScriptUrl || (appSheetConfig.appId && appSheetConfig.accessKey))) {

                showToast("Mengirim sync ke AppSheet...", "info");

                const res = await syncToAppSheet(action, data);

                if (res.success) {

                        showToast(`[AppSheet] ${successLabel} berhasil disinkronkan!`, "success");

                } else {

                        showToast(`Gagal Sync AppSheet: ${res.message || "Periksa API Key"}`, "error");

                }

        }

}


function openAppSheetModal() {

        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-center justify-center p-4">

                <div class="bg-white rounded-2xl w-full max-w-lg overflow-hidden shadow-2xl">

                        <div class="p-5 border-b border-stone-100 flex items-center justify-between bg-stone-50">

                                <div class="flex items-center gap-3">

                                        <div class="w-10 h-10 rounded-xl bg-brand-100 text-brand-700 flex items-center justify-center font-bold">

                                                <i data-lucide="cloud" class="w-5 h-5"></i>

                                        </div>

                                        <div>

                                                <h2 class="text-lg font-bold text-slate-900">Pengaturan Sync AppSheet</h2>

                                                <p class="text-xs text-slate-500">Hubungkan data transaksi ke spreadsheet AppSheet Anda</p>

                                        </div>

                                </div>

                                <button onclick="closeModal()" class="p-2 rounded-xl hover:bg-stone-200 text-stone-500">

                                        ${icon("x", 20)}

                                </button>

                        </div>


                        <form onsubmit="saveAppSheetConfig(event)" class="p-5 space-y-4">

                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-600 mb-1">Apps Script Web App URL (disarankan)</label>

                                        <input id="cfgAppScriptUrl" value="${escapeHTML(appSheetConfig.appScriptUrl || "")}" placeholder="https://script.google.com/macros/s/.../exec" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm font-mono focus:ring-2 focus:ring-brand-200 outline-none">

                                        <span class="text-[11px] text-slate-400">Frontend → Apps Script → AppSheet. API key tidak perlu disimpan di browser.</span>

                                </div>

                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-600 mb-1">

                                                App ID AppSheet (fallback langsung)

                                        </label>

                                        <input id="cfgAppId" value="${escapeHTML(appSheetConfig.appId)}" placeholder="Contoh: 1a2b3c4d-5e6f-7g8h-9i0j-1234567890ab" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm font-mono focus:ring-2 focus:ring-brand-200 outline-none">

                                        <span class="text-[11px] text-slate-400">Dapatkan di AppSheet -> Users -> Integrations -> API Access</span>

                                </div>


                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-600 mb-1">

                                                Application Access Key / API Key

                                        </label>


                                        <input id="cfgAccessKey" type="password" value="${escapeHTML(appSheetConfig.accessKey)}" placeholder="V2-xxxx-xxxx-xxxx" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm font-mono focus:ring-2 focus:ring-brand-200 outline-none">

                                </div>


                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-600 mb-1">

                                                Nama Tabel Target

                                        </label>

                                        <input id="cfgTableName" value="${escapeHTML(appSheetConfig.tableName || "Transactions")}" placeholder="Transactions" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm focus:ring-2 focus:ring-brand-200 outline-none">

                                </div>


                                <div class="flex items-center justify-between p-3 bg-brand-50 rounded-xl">

                                        <div>

                                                <div class="text-sm font-semibold text-brand-900">Otomatis Sync (Auto-Sync)</div>

                                                <div class="text-xs text-brand-700">Kirim data ke AppSheet saat buat, edit, & hapus.</div>

                                        </div>

                                        <label class="relative inline-flex items-center cursor-pointer">

                                                <input id="cfgAutoSync" type="checkbox" ${appSheetConfig.autoSync ? "checked" : ""} class="sr-only peer">

                                                <div class="w-11 h-6 bg-stone-300 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-stone-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-brand-600"></div>

                                        </label>

                                </div>


                                <div class="pt-2 flex flex-col sm:flex-row gap-2">

                                        <button type="submit" class="flex-1 bg-brand-500 hover:bg-brand-600 text-white font-bold py-3 rounded-xl text-sm transition">

                                                Simpan Pengaturan

                                        </button>

                                        <button type="button" onclick="testSyncAllToAppSheet()" class="px-4 py-3 border border-brand-200 text-brand-700 bg-brand-50 hover:bg-brand-100 font-semibold rounded-xl text-sm flex items-center justify-center gap-2">

                                                ${icon("refresh-cw", 16)}

                                                Sync Semua Data

                                        </button>

                                </div>

                        </form>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function saveAppSheetConfig(event) {

        event.preventDefault();

        appSheetConfig.appScriptUrl = document.getElementById("cfgAppScriptUrl")?.value.trim() || "";

        appSheetConfig.appId = document.getElementById("cfgAppId").value.trim();

        appSheetConfig.accessKey = document.getElementById("cfgAccessKey").value.trim();

        appSheetConfig.tableName = document.getElementById("cfgTableName").value.trim() || "Transactions";

        appSheetConfig.autoSync = document.getElementById("cfgAutoSync").checked;


        saveData();

        closeModal();

        showToast("Pengaturan AppSheet berhasil disimpan!");

}


async function testSyncAllToAppSheet() {

        if (!appSheetConfig.appScriptUrl && (!appSheetConfig.appId || !appSheetConfig.accessKey)) {

                showToast("Isi Apps Script URL atau App ID & API Access Key terlebih dahulu!", "error");

                return;

        }


        showToast("Mengirim seluruh data ke AppSheet...", "info");

        let successCount = 0;

        for (const t of transactions) {

                const res = await syncToAppSheet("Add", t);

                if (res.success) successCount++;

        }


        showToast(`Proses selesai! ${successCount} dari ${transactions.length} transaksi tersinkron.`, "success");

}


*/


/* =========================================================

      NAVIGATION & RENDER LOGIC

========================================================= */


function toggleSidebar() {

        const sidebar = document.getElementById("sidebar");

        const overlay = document.getElementById("sidebarOverlay");

        sidebar.classList.toggle("open");

        overlay.classList.toggle("hidden", !sidebar.classList.contains("open"));

}


function navigate(page) {

        if (page === "users" && currentUserRole !== "Owner") {

                showToast("Hanya Owner yang dapat mengelola akun.", "error");

                page = "dashboard";

        }

        currentPage = page;

        if (window.innerWidth < 1024 && document.getElementById("sidebar").classList.contains("open")) {

                toggleSidebar();

        }

        render();

}


function updateNav() {

        document.querySelectorAll(".nav-item").forEach(btn => {

                btn.classList.remove("bg-brand-50", "text-brand-700");

                btn.classList.add("text-slate-600");

        });


        const active = document.querySelector(`[data-nav="${currentPage}"]`);

        if (active) {

                active.classList.remove("text-slate-600");

                active.classList.add("bg-brand-50", "text-brand-700");

        }

}


function icon(name, size = "18") {

        return `<i data-lucide="${name}" style="width:${size}px;height:${size}px"></i>`;

}


/* =========================================================

      DASHBOARD PAGE

========================================================= */


function dashboardPage() {

        const sales = totalTransaction("Penjualan");

        const income = totalTransaction("Pemasukan");

        const businessExpense = totalTransaction("Pengeluaran Usaha");

        const personalExpense = totalTransaction("Pengeluaran Pribadi");


        return `

        <div class="max-w-[1500px] mx-auto">

                <div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4 mb-6">

                        <div>

                                <div class="flex items-center gap-2">

                                        <h1 class="text-2xl lg:text-[27px] font-bold text-slate-900">

                                                Selamat datang, ${escapeHTML(currentUserName)}

                                        </h1>

                                </div>

                                <p class="text-slate-500 mt-1">Kelola bisnis kuliner Anda dengan mudah dan efisien.</p>

                        </div>


                        <div class="flex items-center gap-3">

                                <button onclick="openTransactionModal('Pemasukan')" class="bg-brand-500 hover:bg-brand-600 text-white px-4 py-3 rounded-xl flex items-center justify-center gap-2 font-semibold shadow-sm">

                                        ${icon("plus",17)}

                                        Tambah Transaksi

                                </button>

                        </div>

                </div>


                <div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 mb-5">

                        ${statCard("Penjualan Hari Ini", rupiah(sales), "soup", "orange", "+12%", "dari kemarin")}

                        ${statCard("Pemasukan Lain", rupiah(income), "coins", "green", "+100%", "dari kemarin")}

                        ${statCard("Pengeluaran Usaha", rupiah(businessExpense), "shopping-basket", "red", "-8%", "dari kemarin")}

                        ${statCard("Pengeluaran Pribadi", rupiah(personalExpense), "wallet", "purple", "-5%", "dari kemarin")}

                </div>


                <div class="card bg-gradient-to-r from-[#fff8ef] to-[#fff0db] border-brand-200 p-5 lg:p-6 mb-5">

                        <div class="flex flex-col lg:flex-row lg:items-center gap-5">

                                <div class="flex items-center gap-4">

                                        <div class="w-14 h-14 rounded-full bg-brand-500 text-white flex items-center justify-center shadow-sm">

                                                ${icon("wallet",26)}

                                        </div>

                                        <div>

                                                <div class="text-sm text-brand-800 font-semibold">Saldo Bersih Total</div>

                                                <div class="text-2xl lg:text-3xl font-extrabold text-slate-950">${rupiah(getTotalBalance())}</div>

                                        </div>

                                </div>

                                <div class="hidden lg:block h-12 w-px bg-brand-200"></div>

                                <div>

                                        <div class="text-xs text-slate-500">Total Saldo Rekening Terhubung</div>

                                        <div class="font-bold text-lg">${rupiah(getTotalBalance())}</div>

                                </div>

                                <div class="lg:ml-auto">

                                        <button onclick="navigate('accounts')" class="flex items-center gap-2 text-sm font-semibold text-brand-700">

                                                Lihat Rekening ${icon("chevron-right",16)}

                                        </button>

                                </div>

                        </div>

                </div>


                <div class="grid grid-cols-1 xl:grid-cols-[1fr_330px] gap-5">

                        <div class="space-y-5">

                                <div class="card p-5">

                                        <div class="flex items-center justify-between mb-4">

                                                <div class="flex items-center gap-2">

                                                        ${icon("soup",19)}

                                                        <h2 class="font-bold text-lg">Penjualan Menu Terlaris</h2>

                                                </div>

                                                <button onclick="navigate('reports')" class="text-sm text-brand-600 font-semibold">Lihat Semua</button>

                                        </div>

                                        ${renderBestSeller()}

                                </div>


                                <div class="card p-5">

                                        <div class="flex items-center justify-between mb-4">

                                                <h2 class="font-bold text-lg">Transaksi Terbaru</h2>

                                                <button onclick="navigate('history')" class="text-sm text-brand-600 font-semibold">Lihat Semua</button>

                                        </div>

                                        ${renderRecentTransactions()}

                                </div>

                        </div>


                        <div class="space-y-5">

                                <div class="card p-5">

                                        <h2 class="font-bold text-lg mb-4">Tambah Transaksi Cepat</h2>

                                        ${quickTransaction("Pemasukan", "Modal, transfer, dll", "coins", "green")}

                                        ${quickTransaction("Penjualan", "Transaksi kasir", "soup", "orange")}

                                        ${quickTransaction("Pengeluaran Usaha", "Bahan baku, listrik, gas", "shopping-basket", "red")}

                                        ${quickTransaction("Pengeluaran Pribadi", "Prive, bensin, dll", "wallet", "purple")}

                                </div>


                                <div class="card p-5">

                                        <div class="flex items-center justify-between mb-3">

                                                <h2 class="font-bold">Rekening & Saldo</h2>

                                                <button onclick="navigate('accounts')" class="text-xs text-brand-600 font-semibold">Lihat Semua</button>

                                        </div>

                                        ${accounts.slice(0,5).map(accountRow).join("")}

                                </div>

                        </div>

                </div>

        </div>

        `;

}


function statCard(title, amount, iconName, color, trend, subtitle) {

        return `

        <div class="card stat-card p-5">

                <div class="flex items-center gap-3">

                        <div class="food-icon ${color}">${icon(iconName,23)}</div>

                        <div class="min-w-0">

                                <div class="text-xs sm:text-sm text-slate-500">${title}</div>

                                <div class="font-extrabold text-xl mt-1 truncate">${amount}</div>

                        </div>

                </div>

                <div class="mt-4 text-xs">

                        <span class="${trend.includes('-') ? 'text-red-500' : 'text-emerald-600'} font-semibold">${trend}</span>

                        <span class="text-slate-400">${subtitle}</span>

                </div>

        </div>

        `;

}


function quickTransaction(type, description, iconName, color) {

        const colors = {

                green: "bg-emerald-50 border-emerald-100 text-emerald-700",

                orange: "bg-brand-50 border-brand-100 text-brand-700",

                red: "bg-red-50 border-red-100 text-red-700",

                purple: "bg-purple-50 border-purple-100 text-purple-700"

        };


        return `

        <button onclick="openTransactionModal('${type}')" class="w-full flex items-center gap-3 p-3 rounded-xl border ${colors[color]} mb-3 text-left hover:shadow-sm transition">

                <div class="w-10 h-10 rounded-full bg-white/70 flex items-center justify-center">${icon(iconName,20)}</div>

                <div class="flex-1">

                        <div class="font-semibold text-sm">${type}</div>

                        <div class="text-xs opacity-70">${description}</div>

                </div>

                ${icon("chevron-right",17)}

        </button>

        `;

}


function accountRow(account) {

        let iconName = account.type === "Bank" ? "landmark" : account.type === "Digital" ? "qr-code" : "wallet-cards";

        return `

        <div class="flex items-center gap-3 py-3 border-b border-stone-100 last:border-0">

                <div class="w-9 h-9 rounded-full bg-slate-50 flex items-center justify-center text-slate-600">${icon(iconName,17)}</div>

                <div class="flex-1 text-sm">${escapeHTML(account.name)}</div>

                <div class="text-sm font-semibold">${rupiah(account.balance)}</div>

        </div>

        `;

}


function calculateBestSeller() {

        const result = {};

        transactions.filter(t => t.type === "Penjualan").forEach(t => {

                (t.items || []).forEach(item => {

                        if (!result[item.name]) {

                                result[item.name] = { name: item.name, qty: 0, total: 0 };

                        }

                        result[item.name].qty += Number(item.qty);

                        result[item.name].total += Number(item.qty) * Number(item.price);

                });

        });

        return Object.values(result).sort((a,b) => b.qty - a.qty);

}


function renderBestSeller() {

        let data = calculateBestSeller();

        if (!data.length) {

                data = menus.slice(0,5).map((m,i) => ({

                        name: m.name,

                        qty: [28,18,12,10,8][i] || 3,

                        total: m.price * ([28,18,12,10,8][i] || 3)

                }));

        }


        return data.slice(0,5).map((item,index) => {

                const menu = menus.find(m => m.name === item.name);

                return `

                <div class="flex items-center gap-3 py-3 border-b border-stone-100 last:border-0">

                        <img src="${menu?.image || ''}" class="w-12 h-12 rounded-xl object-cover bg-stone-100" onerror="this.style.display='none'">

                        <div class="flex-1">

                                <div class="font-semibold text-sm">${escapeHTML(item.name)}</div>

                                <div class="text-xs text-slate-500">${item.qty} terjual</div>

                        </div>

                        ${index === 0 ? `<span class="hidden sm:block text-xs text-brand-600 font-semibold">Best Seller</span>` : ""}

                        <div class="font-bold text-sm">${rupiah(item.total)}</div>

                </div>

                `;

        }).join("");

}


function transactionIcon(type) {

        const map = {

                "Pemasukan": ["coins","green"],

                "Penjualan": ["soup","orange"],

                "Pengeluaran Usaha": ["shopping-basket","red"],

                "Pengeluaran Pribadi": ["wallet","purple"]

        };

        return map[type] || ["receipt","blue"];

}


function renderRecentTransactions() {

        return transactions.slice().sort((a,b) => new Date(b.date) - new Date(a.date)).slice(0,5).map(t => {

                const [iconName,color] = transactionIcon(t.type);

                const positive = t.type === "Pemasukan" || t.type === "Penjualan";

                return `

                <div class="flex items-center gap-3 py-3 border-b border-stone-100 last:border-0">

                        <div class="food-icon ${color}" style="width:38px;height:38px">${icon(iconName,18)}</div>

                        <div class="flex-1 min-w-0">

                                <div class="text-sm font-semibold truncate">

                                        ${escapeHTML(t.type)}

                                        <span class="font-normal text-slate-500">- ${escapeHTML(t.note)}</span>

                                </div>

                                <div class="text-xs text-slate-400">${formatDateTime(t.date)}</div>

                        </div>

                        <div class="text-right">

                                <div class="font-semibold text-sm ${positive ? 'text-emerald-600' : 'text-red-500'}">

                                        ${positive ? '+' : '-'} ${rupiah(t.amount)}

                                </div>

                                <div class="text-[10px] text-emerald-600">Berhasil</div>

                        </div>

                </div>

                `;

        }).join("");

}


/* =========================================================

      POS PAGE

========================================================= */


function posPage() {

        const filtered = currentPOSCategory === "Semua" ? menus : menus.filter(m => m.category === currentPOSCategory);

        const cartCount = cart.reduce((sum,item) => sum + item.qty, 0);

        const cartTotal = cart.reduce((sum,item) => sum + item.qty * item.price, 0);


        return `

        <div class="max-w-[1500px] mx-auto">

                <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5">

                        <div>

                                <h1 class="text-2xl font-bold">Kasir (POS)</h1>

                                <p class="text-sm text-slate-500 mt-1">Pilih menu untuk membuat pesanan baru.</p>

                        </div>

                        <div class="relative">

                                <div class="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400">${icon("search",17)}</div>

                                <input id="menuSearch" oninput="searchPOS()" placeholder="Cari menu..." class="pl-9 pr-4 py-3 w-full sm:w-64 border border-stone-200 rounded-xl outline-none focus:ring-2 focus:ring-brand-200 text-sm">

                        </div>

                </div>


                <div class="flex gap-2 overflow-x-auto scrollbar-hide mb-5">

                        ${["Semua","Makanan","Minuman","Extra"].map(cat => `

                                <button onclick="setPOSCategory('${cat}')" class="px-5 py-2.5 rounded-xl text-sm font-semibold whitespace-nowrap ${currentPOSCategory === cat ? 'tab-active' : 'bg-white border border-stone-200 text-slate-500'}">

                                        ${cat}

                                </button>

                        `).join("")}

                </div>


                <div id="posMenuGrid" class="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-4">

                        ${filtered.map(menuCard).join("")}

                </div>


                ${cartCount > 0 ? `

                <button onclick="openCart()" class="floating-cart fixed bottom-5 left-4 right-4 sm:left-auto sm:right-6 sm:w-[370px] z-[70] bg-slate-900 text-white rounded-2xl shadow-2xl p-4 flex items-center gap-3">

                        <div class="w-11 h-11 rounded-xl bg-brand-500 flex items-center justify-center">${icon("shopping-bag",21)}</div>

                        <div class="flex-1 text-left">

                                <div class="font-bold">${cartCount} item</div>

                                <div class="text-xs text-slate-300">Tap untuk checkout</div>

                        </div>

                        <div class="font-bold">${rupiah(cartTotal)}</div>

                        ${icon("chevron-right",18)}

                </button>

                ` : ""}

        </div>

        `;

}


function menuCard(menu) {

        const item = cart.find(c => c.id === menu.id);

        const qty = item?.qty || 0;


        return `

        <div class="menu-card card overflow-hidden" data-menu-name="${escapeHTML(menu.name.toLowerCase())}">

                <div class="relative">

                        <img src="${menu.image}" class="menu-img" onerror="this.src='https://placehold.co/600x400/fff0dd/dc6410?text=Menu'">

                        <span class="absolute top-2 left-2 bg-white/90 backdrop-blur text-xs font-semibold px-2.5 py-1 rounded-full">${menu.category}</span>

                </div>

                <div class="p-4">

                        <div class="font-bold text-sm min-h-[40px]">${escapeHTML(menu.name)}</div>

                        <div class="text-brand-600 font-extrabold mt-1">${rupiah(menu.price)}</div>

                        <div class="mt-3">

                                ${qty === 0 ? `

                                        <button onclick="addToCart(${menu.id})" class="w-full bg-brand-50 hover:bg-brand-100 text-brand-700 py-2.5 rounded-xl text-sm font-bold flex items-center justify-center gap-2">

                                                ${icon("plus",16)} Tambah

                                        </button>

                                ` : `

                                        <div class="flex items-center justify-between bg-brand-50 rounded-xl p-1">

                                                <button onclick="changeQty(${menu.id}, -1)" class="qty-btn">${icon("minus",15)}</button>

                                                <span class="font-bold">${qty}</span>

                                                <button onclick="changeQty(${menu.id}, 1)" class="qty-btn">${icon("plus",15)}</button>

                                        </div>

                                `}

                        </div>

                </div>

        </div>

        `;

}


function setPOSCategory(category) {

        currentPOSCategory = category;

        render();

}


function searchPOS() {

        const keyword = document.getElementById("menuSearch")?.value.toLowerCase() || "";

        document.querySelectorAll("#posMenuGrid > div").forEach(card => {

                const name = card.dataset.menuName || "";

                card.style.display = name.includes(keyword) ? "" : "none";

        });

}


function addToCart(id) {

        const menu = menus.find(m => m.id === id);

        if (!menu) return;

        const existing = cart.find(item => item.id === id);

        if (existing) {

                existing.qty++;

        } else {

                cart.push({ ...menu, qty: 1 });

        }

        render();

}


function changeQty(id, amount) {

        const item = cart.find(i => i.id === id);

        if (!item) return;

        item.qty += amount;

        if (item.qty <= 0) {

                cart = cart.filter(i => i.id !== id);

        }

        render();

}


function openCart() {

        const total = cart.reduce((sum,item) => sum + item.qty * item.price, 0);

        const count = cart.reduce((sum,item) => sum + item.qty, 0);


        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center">

                <div class="modal-container bg-white w-full sm:max-w-lg max-h-[92vh] overflow-y-auto rounded-t-3xl sm:rounded-2xl">

                        <div class="p-5 border-b border-stone-100 flex items-center justify-between">

                                <div>

                                        <h2 class="text-xl font-bold">Pesanan Aktif</h2>

                                        <p class="text-sm text-slate-500">${count} item dipilih</p>

                                </div>

                                <button onclick="closeModal()" class="p-2 rounded-xl hover:bg-stone-100">${icon("x",20)}</button>

                        </div>


                        <div class="p-5">

                                ${cart.map(cartRow).join("")}

                                <div class="border-t border-dashed border-stone-300 mt-4 pt-4">

                                        <div class="flex justify-between text-sm">

                                                <span class="text-slate-500">Total</span>

                                                <span class="text-2xl font-extrabold">${rupiah(total)}</span>

                                        </div>

                                </div>

                                <button onclick="openCheckout()" class="w-full mt-5 bg-brand-500 hover:bg-brand-600 text-white py-3.5 rounded-xl font-bold">

                                        Lanjut Checkout

                                </button>

                        </div>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function cartRow(item) {

        return `

        <div class="flex items-center gap-3 py-3 border-b border-stone-100">

                <img src="${item.image}" class="w-14 h-14 rounded-xl object-cover">

                <div class="flex-1">

                        <div class="font-semibold text-sm">${escapeHTML(item.name)}</div>

                        <div class="text-xs text-slate-500">${rupiah(item.price)}</div>

                </div>

                <div class="qty-control">

                        <button onclick="changeQtyInModal(${item.id},-1)" class="qty-btn">${icon("minus",14)}</button>

                        <span class="font-bold w-5 text-center">${item.qty}</span>

                        <button onclick="changeQtyInModal(${item.id},1)" class="qty-btn">${icon("plus",14)}</button>

                </div>

        </div>

        `;

}


function changeQtyInModal(id, amount) {

        changeQty(id, amount);

        openCart();

}


function openCheckout() {

        const total = cart.reduce((sum,item) => sum + item.qty * item.price, 0);


        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center">

                <div class="modal-container bg-white w-full sm:max-w-lg max-h-[94vh] overflow-y-auto rounded-t-3xl sm:rounded-2xl">

                        <div class="p-5 border-b border-stone-100 flex items-center gap-3">

                                <button onclick="openCart()" class="p-2 rounded-xl hover:bg-stone-100">${icon("arrow-left",19)}</button>

                                <div>

                                        <h2 class="text-xl font-bold">Checkout</h2>

                                        <p class="text-sm text-slate-500">Selesaikan pembayaran</p>

                                </div>

                        </div>


                        <form onsubmit="completeSale(event)" class="p-5 space-y-4">

                                <div>

                                        <label class="block text-sm font-semibold mb-1">Nama Pelanggan</label>

                                        <input id="customerName" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200" placeholder="Contoh: Budi">

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Nomor WhatsApp</label>

                                        <input id="customerWA" type="tel" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200" placeholder="08xxxxxxxxxx">

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Pembayaran ke Rekening</label>

                                        <select id="paymentAccount" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200">

                                                ${accounts.map(a => `<option value="${escapeHTML(a.name)}">${escapeHTML(a.name)}</option>`).join("")}

                                        </select>

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Uang Diterima</label>

                                        <div class="relative">

                                                <span class="absolute left-4 top-1/2 -translate-y-1/2 text-slate-400 font-semibold">Rp</span>

                                                <input id="checkoutAmountReceived" required inputmode="numeric" oninput="formatAmountInput(this); updateCheckoutChange()" class="w-full border border-stone-200 rounded-xl pl-12 pr-4 py-3 text-lg font-bold outline-none focus:ring-2 focus:ring-brand-200" placeholder="0">

                                        </div>

                                </div>


                                <div class="bg-brand-50 rounded-2xl p-4">

                                        <div class="flex justify-between items-center">

                                                <span class="text-sm font-medium">Total Pembayaran</span>

                                                <span class="font-extrabold text-xl text-brand-700">${rupiah(total)}</span>

                                        </div>

                                        <div class="flex justify-between items-center mt-3 pt-3 border-t border-brand-100">

                                                <span class="text-sm font-medium">Kembalian</span>

                                                <span id="checkoutChange" class="font-bold text-sm text-slate-500">Masukkan uang diterima</span>

                                        </div>

                                </div>


                                <button class="w-full bg-brand-500 hover:bg-brand-600 text-white py-3.5 rounded-xl font-bold transition">

                                        Selesaikan Pembayaran

                                </button>

                        </form>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function updateCheckoutChange() {

        const total = cart.reduce((sum, item) => sum + item.qty * item.price, 0);

        const input = document.getElementById("checkoutAmountReceived");

        const display = document.getElementById("checkoutChange");

        if (!input || !display) return;


        const received = Number(input.value.replace(/\./g, "")) || 0;

        if (!received) {

                display.textContent = "Masukkan uang diterima";

                display.className = "font-bold text-sm text-slate-500";

        } else if (received < total) {

                display.textContent = `Kurang ${rupiah(total - received)}`;

                display.className = "font-bold text-sm text-red-600";

        } else {

                display.textContent = rupiah(received - total);

                display.className = "font-bold text-sm text-emerald-700";

        }

}


function completeSale(event) {

        event.preventDefault();

        if (!cart.length) {

                showToast("Keranjang masih kosong", "error");

                return;

        }


        const customer = document.getElementById("customerName").value.trim();

        const wa = document.getElementById("customerWA").value.trim();

        const account = document.getElementById("paymentAccount").value;

        const total = cart.reduce((sum,item) => sum + item.qty * item.price, 0);

        const received = Number(document.getElementById("checkoutAmountReceived").value.replace(/\./g, "")) || 0;

        if (received < total) {

                showToast("Uang diterima kurang dari total pembayaran", "error");

                return;

        }

        const change = received - total;

        const itemText = cart.map(item => `${item.name} x${item.qty}`).join(", ");


        const transaction = {

                id: Date.now(),

                type: "Penjualan",

                amount: total,

                amountReceived: received,

                change,

                account,

                note: `Pemasukan dari penjualan "${itemText}"`,

                customer,

                whatsapp: wa,

                items: cart.map(item => ({ name: item.name, qty: item.qty, price: item.price })),

                date: new Date().toISOString(),

                status: "Berhasil"

        };


        transactions.unshift(transaction);


        const acc = accounts.find(a => a.name === account);

        if (acc) {

                acc.balance = Number(acc.balance) + total;

        }


        saveData();

        cart = [];

        closeModal();

        showToast("Transaksi penjualan berhasil disimpan");

        render();


        setTimeout(() => { openReceipt(transaction); }, 250);

}


/* =========================================================

      TRANSACTION MODAL (ADD & EDIT KHUSUS OWNER)

========================================================= */


function openTransactionModal(type = "Pemasukan") {

        if (currentUserRole !== "Owner") { showToast("Akses transaksi manual hanya untuk Owner.", "error"); return; }

        const types = [

                { name: "Pemasukan", icon: "coins", color: "green" },

                { name: "Pengeluaran Usaha", icon: "shopping-basket", color: "red" },

                { name: "Pengeluaran Pribadi", icon: "wallet", color: "purple" }

        ];


        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center">

                <div class="modal-container bg-white w-full sm:max-w-xl max-h-[94vh] overflow-y-auto rounded-t-3xl sm:rounded-2xl">

                        <div class="p-5 border-b border-stone-100 flex items-center justify-between">

                                <div>

                                        <h2 class="text-xl font-bold">Tambah Transaksi</h2>

                                        <p class="text-sm text-slate-500">Catat arus kas bisnis</p>

                                </div>

                                <button onclick="closeModal()" class="p-2 rounded-xl hover:bg-stone-100">${icon("x",20)}</button>

                        </div>


                        <form onsubmit="saveManualTransaction(event)" class="p-5 space-y-4">

                                <div>

                                        <label class="block text-sm font-semibold mb-2">Jenis Transaksi</label>

                                        <div class="grid sm:grid-cols-3 gap-2">

                                                ${types.map(t => `

                                                        <button type="button" onclick="selectTransactionType('${t.name}')" id="type-${t.name.replaceAll(' ','-')}" class="transaction-type-btn p-3 rounded-xl border text-left ${t.name === type ? 'border-brand-300 bg-brand-50' : 'border-stone-200'}">

                                                                <div class="flex items-center gap-2">

                                                                        <div class="food-icon ${t.color}" style="width:32px;height:32px">${icon(t.icon,15)}</div>

                                                                        <span class="font-semibold text-xs">${t.name}</span>

                                                                </div>

                                                        </button>

                                                `).join("")}

                                        </div>

                                        <input type="hidden" id="transactionType" value="${type}">

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Nominal</label>

                                        <div class="relative">

                                                <span class="absolute left-4 top-1/2 -translate-y-1/2 text-slate-400 font-semibold">Rp</span>

                                                <input id="transactionAmount" required inputmode="numeric" oninput="formatAmountInput(this)" class="w-full border border-stone-200 rounded-xl pl-12 pr-4 py-3 text-lg font-bold outline-none focus:ring-2 focus:ring-brand-200" placeholder="0">

                                        </div>

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Sumber Saldo / Rekening</label>

                                        <select id="transactionAccount" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200">

                                                ${accounts.map(a => `<option value="${escapeHTML(a.name)}">${escapeHTML(a.name)}</option>`).join("")}

                                        </select>

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Keterangan</label>

                                        <textarea id="transactionNote" required rows="2" class="w-full border border-stone-200 rounded-xl px-4 py-3 resize-none outline-none focus:ring-2 focus:ring-brand-200" placeholder="Modal tambahan, beli bahan baku, bensin..."></textarea>

                                </div>


                                <button type="submit" class="w-full bg-brand-500 hover:bg-brand-600 text-white py-3.5 rounded-xl font-bold transition">

                                        Simpan Transaksi

                                </button>

                        </form>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function selectTransactionType(type) {

        document.getElementById("transactionType").value = type;

        document.querySelectorAll(".transaction-type-btn").forEach(btn => {

                btn.classList.remove("border-brand-300", "bg-brand-50");

                btn.classList.add("border-stone-200");

        });

        const selected = document.getElementById("type-" + type.replaceAll(" ", "-"));

        if (selected) {

                selected.classList.remove("border-stone-200");

                selected.classList.add("border-brand-300", "bg-brand-50");

        }

}


function formatAmountInput(input) {

        let value = input.value.replace(/\D/g,"");

        if (!value) { input.value = ""; return; }

        input.value = Number(value).toLocaleString("id-ID");

}


function saveManualTransaction(event) {

        event.preventDefault();

        const type = document.getElementById("transactionType").value;

        const amountText = document.getElementById("transactionAmount").value;

        const amount = Number(amountText.replace(/\./g,""));

        const accountName = document.getElementById("transactionAccount").value;

        const note = document.getElementById("transactionNote").value.trim();


        if (!amount || amount <= 0) { showToast("Nominal belum diisi", "error"); return; }

        if (!note) { showToast("Keterangan wajib diisi", "error"); return; }


        const transaction = {

                id: Date.now(),

                type,

                amount,

                account: accountName,

                note,

                date: new Date().toISOString(),

                status: "Berhasil"

        };


        transactions.unshift(transaction);


        const account = accounts.find(a => a.name === accountName);

        if (account) {

                if (type === "Pemasukan") {

                        account.balance = Number(account.balance) + amount;

                } else {

                        account.balance = Number(account.balance) - amount;

                }

        }


        saveData();

        closeModal();

        showToast(`${type} berhasil disimpan`);

        render();

}


/* =========================================================

      FITUR EDIT RIWAYAT TRANSAKSI (KHUSUS OWNER)

========================================================= */


function openEditTransactionModal(id) {

        if (currentUserRole !== "Owner") {

                showToast("Hanya akun Owner yang dapat mengedit transaksi!", "error");

                return;

        }


        const t = transactions.find(item => item.id === id);

        if (!t) {

                showToast("Transaksi tidak ditemukan", "error");

                return;

        }


        const isoDateStr = new Date(t.date).toISOString().slice(0, 16);


        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center">

                <div class="modal-container bg-white w-full sm:max-w-xl max-h-[94vh] overflow-y-auto rounded-t-3xl sm:rounded-2xl">

                        <div class="p-5 border-b border-stone-100 flex items-center justify-between bg-amber-50/50">

                                <div class="flex items-center gap-2">

                                        <div class="w-9 h-9 rounded-xl bg-amber-100 text-amber-800 flex items-center justify-center font-bold">

                                                ${icon("pencil", 18)}

                                        </div>

                                        <div>

                                                <h2 class="text-lg font-bold text-slate-900">Edit Riwayat Transaksi (Owner)</h2>

                                                <p class="text-xs text-slate-500">ID Transaksi: #${t.id}</p>

                                        </div>

                                </div>

                                <button onclick="closeModal()" class="p-2 rounded-xl hover:bg-stone-100">${icon("x",20)}</button>

                        </div>


                        <form onsubmit="updateTransaction(event, ${t.id})" class="p-5 space-y-4">

                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-1">Jenis Transaksi</label>

                                        <select id="editType" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm font-semibold outline-none focus:ring-2 focus:ring-brand-200">

                                                <option value="Penjualan" ${t.type === "Penjualan" ? "selected" : ""}>Penjualan</option>

                                                <option value="Pemasukan" ${t.type === "Pemasukan" ? "selected" : ""}>Pemasukan</option>

                                                <option value="Pengeluaran Usaha" ${t.type === "Pengeluaran Usaha" ? "selected" : ""}>Pengeluaran Usaha</option>

                                                <option value="Pengeluaran Pribadi" ${t.type === "Pengeluaran Pribadi" ? "selected" : ""}>Pengeluaran Pribadi</option>

                                        </select>

                                </div>


                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-1">Nominal (Rp)</label>

                                        <input id="editAmount" required inputmode="numeric" oninput="formatAmountInput(this)" value="${numberFormat(t.amount)}" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-lg font-bold outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-1">Rekening / Sumber Saldo</label>

                                        <select id="editAccount" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm outline-none focus:ring-2 focus:ring-brand-200">

                                                ${accounts.map(a => `<option value="${escapeHTML(a.name)}" ${a.name === t.account ? "selected" : ""}>${escapeHTML(a.name)}</option>`).join("")}

                                        </select>

                                </div>


                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-1">Waktu / Tanggal Transaksi</label>

                                        <input id="editDate" type="datetime-local" value="${isoDateStr}" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <div>

                                        <label class="block text-xs font-semibold uppercase tracking-wider text-slate-500 mb-1">Catatan / Keterangan</label>

                                        <textarea id="editNote" required rows="3" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 text-sm outline-none focus:ring-2 focus:ring-brand-200 resize-none">${escapeHTML(t.note)}</textarea>

                                </div>


                                <div class="bg-amber-50 border border-amber-200 rounded-xl p-3 text-xs text-amber-800 flex items-start gap-2">

                                        ${icon("info", 16)}

                                        <span>Mengedit transaksi akan otomatis memperbarui saldo pada rekening yang bersangkutan.</span>

                                </div>


                                <div class="pt-2 flex gap-3">

                                        <button type="button" onclick="closeModal()" class="flex-1 border border-stone-200 hover:bg-stone-50 py-3 rounded-xl font-semibold text-sm">

                                                Batal

                                        </button>

                                        <button type="submit" class="flex-1 bg-brand-500 hover:bg-brand-600 text-white py-3 rounded-xl font-bold text-sm transition">

                                                Simpan Perubahan

                                        </button>

                                </div>

                        </form>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function updateTransaction(event, id) {

        event.preventDefault();


        const index = transactions.findIndex(t => t.id === id);

        if (index === -1) return;


        const oldTrans = transactions[index];


        const newType = document.getElementById("editType").value;

        const newAmount = Number(document.getElementById("editAmount").value.replace(/\./g, ""));

        const newAccountName = document.getElementById("editAccount").value;

        const newDate = document.getElementById("editDate").value ? new Date(document.getElementById("editDate").value).toISOString() : oldTrans.date;

        const newNote = document.getElementById("editNote").value.trim();


        if (!newAmount || newAmount <= 0) {

                showToast("Nominal transaksi harus lebih dari 0", "error");

                return;

        }


        // 1. REVERT OLD TRANSACTION IMPACT ON ACCOUNT BALANCE

        const oldAcc = accounts.find(a => a.name === oldTrans.account);

        if (oldAcc) {

                if (oldTrans.type === "Pemasukan" || oldTrans.type === "Penjualan") {

                        oldAcc.balance -= Number(oldTrans.amount);

                } else {

                        oldAcc.balance += Number(oldTrans.amount);

                }

        }


        // 2. APPLY NEW TRANSACTION IMPACT ON ACCOUNT BALANCE

        const newAcc = accounts.find(a => a.name === newAccountName);

        if (newAcc) {

                if (newType === "Pemasukan" || newType === "Penjualan") {

                        newAcc.balance += newAmount;

                } else {

                        newAcc.balance -= newAmount;

                }

        }


        // 3. UPDATE TRANSACTION OBJECT

        const updatedTransaction = {

                ...oldTrans,

                type: newType,

                amount: newAmount,

                account: newAccountName,

                date: newDate,

                note: newNote

        };


        transactions[index] = updatedTransaction;


        saveData();

        closeModal();

        showToast("Transaksi berhasil diperbarui & saldo telah disesuaikan!");

        render();

}


/* =========================================================

      HISTORY PAGE

========================================================= */


function historyPage() {

        return `

        <div class="max-w-[1500px] mx-auto">

                <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5">

                        <div>

                                <h1 class="text-2xl font-bold">Riwayat Transaksi</h1>

                                <p class="text-sm text-slate-500">Semua transaksi bisnis terdaftar.</p>

                        </div>


                        <div class="flex items-center gap-2">

                                <button onclick="openTransactionModal()" class="bg-brand-500 text-white px-4 py-3 rounded-xl font-semibold flex items-center justify-center gap-2 text-sm">

                                        ${icon("plus",17)}

                                        Tambah Transaksi

                                </button>

                        </div>

                </div>


                <div class="card overflow-hidden">

                        <div class="p-4 border-b border-stone-100 flex flex-col md:flex-row gap-3">

                                <input id="historySearch" oninput="filterHistory()" placeholder="Cari transaksi..." class="flex-1 border border-stone-200 rounded-xl px-4 py-2.5 text-sm outline-none focus:ring-2 focus:ring-brand-200">

                                <select id="historyType" onchange="filterHistory()" class="border border-stone-200 rounded-xl px-4 py-2.5 text-sm outline-none focus:ring-2 focus:ring-brand-200">

                                        <option value="">Semua Jenis</option>

                                        <option>Penjualan</option>

                                        <option>Pemasukan</option>

                                        <option>Pengeluaran Usaha</option>

                                        <option>Pengeluaran Pribadi</option>

                                </select>

                        </div>


                        <div id="historyTable">

                                ${historyRows(transactions)}

                        </div>

                </div>

        </div>

        `;

}


function historyRows(data) {

        if (!data.length) {

                return `

                <div class="p-12 text-center text-slate-400">

                        ${icon("receipt",35)}

                        <div class="mt-3 text-sm">Belum ada transaksi.</div>

                </div>

                `;

        }


        return `

        <div class="overflow-x-auto">

                <table class="w-full text-sm">

                        <thead class="bg-stone-50 text-slate-500 border-b border-stone-100">

                                <tr>

                                        <th class="text-left px-5 py-3 font-semibold">Transaksi</th>

                                        <th class="text-left px-5 py-3 font-semibold">Rekening</th>

                                        <th class="text-right px-5 py-3 font-semibold">Nominal</th>

                                        <th class="text-left px-5 py-3 font-semibold">Waktu</th>

                                        <th class="text-right px-5 py-3 font-semibold">Aksi (Owner)</th>

                                </tr>

                        </thead>

                        <tbody>

                                ${data.map(t => {

                                        const positive = t.type === "Pemasukan" || t.type === "Penjualan";

                                        const [ic,col] = transactionIcon(t.type);


                                        return `

                                        <tr class="border-t border-stone-100 hover:bg-stone-50/80 transition">

                                                <td class="px-5 py-4">

                                                        <div class="flex items-center gap-3">

                                                                <div class="food-icon ${col}" style="width:38px;height:38px">

                                                                        ${icon(ic,18)}

                                                                </div>

                                                                <div>

                                                                        <div class="font-semibold text-slate-900">${escapeHTML(t.type)}</div>

                                                                        <div class="text-xs text-slate-500 max-w-[320px] truncate">${escapeHTML(t.note)}</div>

                                                                </div>

                                                        </div>

                                                </td>

                                                <td class="px-5 py-4 text-slate-600 font-medium">${escapeHTML(t.account || "-")}</td>

                                                <td class="px-5 py-4 text-right font-bold ${positive ? 'text-emerald-600' : 'text-red-500'}">

                                                        ${positive ? "+" : "-"} ${rupiah(t.amount)}

                                                </td>

                                                <td class="px-5 py-4 text-slate-500 whitespace-nowrap text-xs">${formatDateTime(t.date)}</td>

                                                <td class="px-5 py-4 text-right">

                                                        <div class="flex items-center justify-end gap-1">

                                                                <button onclick="openEditTransactionModal(${t.id})" title="Edit Transaksi (Owner)" class="p-2 rounded-lg text-amber-600 hover:bg-amber-50 transition">

                                                                        ${icon("pencil",16)}

                                                                </button>

                                                                <button onclick="deleteTransaction(${t.id})" title="Hapus Transaksi" class="p-2 rounded-lg text-red-500 hover:bg-red-50 transition">

                                                                        ${icon("trash-2",16)}

                                                                </button>

                                                        </div>

                                                </td>

                                        </tr>

                                        `;

                                }).join("")}

                        </tbody>

                </table>

        </div>

        `;

}


function filterHistory() {

        const keyword = document.getElementById("historySearch")?.value.toLowerCase() || "";

        const type = document.getElementById("historyType")?.value || "";


        const filtered = transactions.filter(t => {

                const text = `${t.type} ${t.note} ${t.account}`.toLowerCase();

                return text.includes(keyword) && (!type || t.type === type);

        });


        document.getElementById("historyTable").innerHTML = historyRows(filtered);

        lucide.createIcons();

}


function deleteTransaction(id) {

        if (!confirm("Hapus transaksi ini? Saldo rekening akan otomatis disesuaikan.")) return;


        const index = transactions.findIndex(t => t.id === id);

        if (index === -1) return;


        const t = transactions[index];

        const account = accounts.find(a => a.name === t.account);


        if (account) {

                if (t.type === "Pemasukan" || t.type === "Penjualan") {

                        account.balance -= Number(t.amount);

                } else {

                        account.balance += Number(t.amount);

                }

        }


        transactions.splice(index,1);

        saveData();


        showToast("Transaksi berhasil dihapus");

        render();

}


/* =========================================================

      OTHER PAGES (ACCOUNTS, MENUS, REPORTS, FINANCE, USERS, BRAND)

========================================================= */


function accountsPage() {

        return `

        <div class="max-w-[1200px] mx-auto">

                <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5">

                        <div>

                                <h1 class="text-2xl font-bold">Rekening & Saldo</h1>

                                <p class="text-sm text-slate-500 mt-1">Kelola sumber saldo usaha.</p>

                        </div>

                        <button onclick="openAccountModal()" class="bg-brand-500 text-white px-4 py-3 rounded-xl font-semibold flex items-center justify-center gap-2">

                                ${icon("plus",17)} Tambah Rekening

                        </button>

                </div>


                <div class="card bg-gradient-to-r from-[#fff7eb] to-[#ffecd3] p-6 mb-5">

                        <div class="text-sm text-brand-800">Total Saldo Tergabung</div>

                        <div class="text-3xl font-extrabold mt-1">${rupiah(getTotalBalance())}</div>

                </div>


                <div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">

                        ${accounts.map(account => `

                        <div class="card p-5">

                                <div class="flex items-center justify-between">

                                        <div class="food-icon blue">

                                                ${icon(account.type === "Bank" ? "landmark" : account.type === "Digital" ? "qr-code" : "wallet", 21)}

                                        </div>

                                        <div class="flex gap-1">

                                                <button onclick="openAccountModal(${account.id})" class="p-2 rounded-lg hover:bg-stone-100">${icon("pencil",15)}</button>

                                                <button onclick="deleteAccount(${account.id})" class="p-2 rounded-lg hover:bg-red-50 text-red-500">${icon("trash-2",15)}</button>

                                        </div>

                                </div>

                                <div class="mt-5">

                                        <div class="text-xs text-slate-500 uppercase tracking-wider font-semibold">${escapeHTML(account.type)}</div>

                                        <div class="font-bold text-lg text-slate-900">${escapeHTML(account.name)}</div>

                                        <div class="text-2xl font-extrabold mt-2 text-brand-700">${rupiah(account.balance)}</div>

                                </div>

                        </div>

                        `).join("")}

                </div>

        </div>

        `;

}


function openAccountModal(id = null) {

        const account = accounts.find(a => a.id === id);

        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center">

                <div class="modal-container bg-white w-full sm:max-w-md rounded-t-3xl sm:rounded-2xl">

                        <div class="p-5 border-b border-stone-100 flex justify-between items-center">

                                <h2 class="text-xl font-bold">${account ? "Edit Rekening" : "Tambah Rekening"}</h2>

                                <button onclick="closeModal()">${icon("x",20)}</button>

                        </div>


                        <form onsubmit="saveAccount(event, ${id || "null"})" class="p-5 space-y-4">

                                <div>

                                        <label class="block text-sm font-semibold mb-1">Nama Rekening</label>

                                        <input id="accountName" required value="${escapeHTML(account?.name || "")}" placeholder="Contoh: BCA / Kas" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Tipe Rekening</label>

                                        <select id="accountType" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                                ${["Cash","Bank","Digital"].map(type => `

                                                        <option ${account?.type === type ? "selected" : ""}>${type}</option>

                                                `).join("")}

                                        </select>

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Saldo Awal (Rp)</label>

                                        <input id="accountBalance" required inputmode="numeric" oninput="formatAmountInput(this)" value="${account ? numberFormat(account.balance) : ""}" placeholder="0" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <button class="w-full bg-brand-500 hover:bg-brand-600 text-white py-3.5 rounded-xl font-bold transition">

                                        Simpan Rekening

                                </button>

                        </form>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function saveAccount(event, id) {

        event.preventDefault();

        const name = document.getElementById("accountName").value.trim();

        const type = document.getElementById("accountType").value;

        const balance = Number(document.getElementById("accountBalance").value.replace(/\./g,""));


        if (id) {

                const account = accounts.find(a => a.id === id);

                account.name = name;

                account.type = type;

                account.balance = balance;

        } else {

                accounts.push({ id: Date.now(), name, type, balance });

        }


        saveData();

        closeModal();

        showToast("Rekening berhasil disimpan");

        render();

}


function deleteAccount(id) {

        if (accounts.length <= 1) { showToast("Minimal harus ada satu rekening!", "error"); return; }

        if (!confirm("Hapus rekening ini?")) return;


        accounts = accounts.filter(a => a.id !== id);

        saveData();

        showToast("Rekening berhasil dihapus");

        render();

}


function menusPage() {

        return `

        <div class="max-w-[1400px] mx-auto">

                <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5">

                        <div>

                                <h1 class="text-2xl font-bold">Manajemen Menu</h1>

                                <p class="text-sm text-slate-500">Kelola menu makanan, minuman, dan harga.</p>

                        </div>

                        <button onclick="openMenuModal()" class="bg-brand-500 text-white px-4 py-3 rounded-xl font-semibold flex items-center justify-center gap-2">

                                ${icon("plus",17)} Tambah Menu

                        </button>

                </div>


                <div class="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-4">

                        ${menus.map(menu => `

                        <div class="card overflow-hidden">

                                <img src="${menu.image}" class="w-full h-40 object-cover" onerror="this.src='https://placehold.co/600x400/fff0dd/dc6410?text=Menu'">

                                <div class="p-4">

                                        <span class="text-xs bg-brand-50 text-brand-700 px-2.5 py-1 rounded-full font-semibold">${menu.category}</span>

                                        <div class="font-bold mt-2 text-slate-900">${escapeHTML(menu.name)}</div>

                                        <div class="text-brand-600 font-extrabold mt-1">${rupiah(menu.price)}</div>

                                        <div class="flex gap-2 mt-4">

                                                <button onclick="openMenuModal(${menu.id})" class="flex-1 border border-stone-200 rounded-xl py-2 text-sm font-semibold hover:bg-stone-50">Edit</button>

                                                <button onclick="deleteMenu(${menu.id})" class="px-3 border border-red-100 text-red-500 rounded-xl hover:bg-red-50">${icon("trash-2",16)}</button>

                                        </div>

                                </div>

                        </div>

                        `).join("")}

                </div>

        </div>

        `;

}


function openMenuModal(id = null) {

        const menu = menus.find(m => m.id === id);

        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center">

                <div class="modal-container bg-white w-full sm:max-w-lg rounded-t-3xl sm:rounded-2xl">

                        <div class="p-5 border-b border-stone-100 flex justify-between items-center">

                                <h2 class="text-xl font-bold">${menu ? "Edit Menu" : "Tambah Menu"}</h2>

                                <button onclick="closeModal()">${icon("x",20)}</button>

                        </div>


                        <form onsubmit="saveMenu(event,${id || "null"})" class="p-5 space-y-4">

                                <div>

                                        <label class="block text-sm font-semibold mb-1">Nama Menu</label>

                                        <input id="menuName" required value="${escapeHTML(menu?.name || "")}" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Kategori</label>

                                        <select id="menuCategory" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                                ${["Makanan","Minuman","Extra"].map(c => `

                                                        <option ${menu?.category === c ? "selected" : ""}>${c}</option>

                                                `).join("")}

                                        </select>

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">Harga (Rp)</label>

                                        <input id="menuPrice" required inputmode="numeric" oninput="formatAmountInput(this)" value="${menu ? numberFormat(menu.price) : ""}" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <div>

                                        <label class="block text-sm font-semibold mb-1">URL Foto Menu</label>

                                        <input id="menuImage" value="${escapeHTML(menu?.image || "")}" placeholder="https://..." class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none focus:ring-2 focus:ring-brand-200">

                                </div>


                                <button class="w-full bg-brand-500 hover:bg-brand-600 text-white py-3.5 rounded-xl font-bold transition">

                                        Simpan Menu

                                </button>

                        </form>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function saveMenu(event, id) {

        event.preventDefault();

        const name = document.getElementById("menuName").value.trim();

        const category = document.getElementById("menuCategory").value;

        const price = Number(document.getElementById("menuPrice").value.replace(/\./g,""));

        const image = document.getElementById("menuImage").value.trim();


        if (id) {

                const menu = menus.find(m => m.id === id);

                menu.name = name;

                menu.category = category;

                menu.price = price;

                menu.image = image;

        } else {

                menus.push({

                        id: Date.now(),

                        name,

                        category,

                        price,

                        image: image || "https://placehold.co/600x400/fff0dd/dc6410?text=Menu"

                });

        }


        saveData();

        closeModal();

        showToast("Menu berhasil disimpan");

        render();

}


function deleteMenu(id) {

        if (!confirm("Hapus menu ini?")) return;

        menus = menus.filter(m => m.id !== id);

        saveData();

        showToast("Menu berhasil dihapus");

        render();

}


function reportsPage() {

        const sales = totalTransaction("Penjualan");

        const income = totalTransaction("Pemasukan");

        const business = totalTransaction("Pengeluaran Usaha");

        const personal = totalTransaction("Pengeluaran Pribadi");

        const profit = sales + income - business - personal;


        return `

        <div class="max-w-[1400px] mx-auto">

                <div class="mb-5">

                        <h1 class="text-2xl font-bold">Laporan & Analisis</h1>

                        <p class="text-sm text-slate-500 mt-1">Analisis penjualan dan performa keuangan bisnis.</p>

                </div>


                <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-5">

                        ${reportCard("Total Omzet", sales + income, "emerald")}

                        ${reportCard("Pengeluaran Usaha", business, "red")}

                        ${reportCard("Pengeluaran Pribadi", personal, "purple")}

                        ${reportCard("Keuntungan Bersih", profit, "green")}

                </div>


                <div class="grid lg:grid-cols-2 gap-5">

                        <div class="card p-5">

                                <h2 class="font-bold text-lg mb-4">Penjualan Menu</h2>

                                ${renderBestSeller()}

                        </div>

                        <div class="card p-5">

                                <h2 class="font-bold text-lg mb-4">Ringkasan Keuangan</h2>

                                <div class="space-y-4">

                                        ${financeLine("Penjualan", sales, "emerald")}

                                        ${financeLine("Pemasukan Lain", income, "emerald")}

                                        ${financeLine("Pengeluaran Usaha", business, "red")}

                                        ${financeLine("Pengeluaran Pribadi", personal, "purple")}

                                        <div class="border-t pt-4 flex justify-between">

                                                <span class="font-bold">Net Profit</span>

                                                <span class="font-extrabold text-emerald-600">${rupiah(profit)}</span>

                                        </div>

                                </div>

                        </div>

                </div>

        </div>

        `;

}


function reportCard(title, value, color) {

        return `

        <div class="card p-5">

                <div class="text-sm text-slate-500">${title}</div>

                <div class="text-2xl font-extrabold mt-2">${rupiah(value)}</div>

                <div class="text-xs mt-3 text-${color}-600 font-semibold">Berdasarkan transaksi tersimpan</div>

        </div>

        `;

}


function financeLine(name, value, color) {

        return `

        <div class="flex justify-between items-center">

                <div class="flex items-center gap-2">

                        <span class="w-2.5 h-2.5 rounded-full bg-${color}-500"></span>

                        <span class="text-sm">${name}</span>

                </div>

                <span class="font-bold text-sm">${rupiah(value)}</span>

        </div>

        `;

}


function financePage() {

        return reportsPage();

}


function usersPage() {

        if (currentUserRole !== "Owner") return `<div class="card p-6 text-center text-red-600">Hanya Owner yang dapat mengelola akun.</div>`;

        return `

        <div class="max-w-[1000px] mx-auto">

                <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5">

                        <div>

                                <h1 class="text-2xl font-bold">Manajemen Akun</h1>

                                <p class="text-sm text-slate-500">Tambah dan kelola akun Owner maupun Kasir.</p>

                        </div>

                        <button onclick="openUserModal()" class="bg-brand-500 hover:bg-brand-600 text-white px-4 py-3 rounded-xl font-semibold flex items-center gap-2">${icon("plus",17)} Tambah Akun</button>

                </div>


                <div class="card overflow-hidden divide-y divide-stone-100">

                        ${users.map(user => `

                        <div class="p-4 sm:p-5 flex flex-wrap items-center gap-3 sm:gap-4">

                                <div class="w-11 h-11 rounded-full ${user.role === "Owner" ? "bg-brand-100 text-brand-700" : "bg-blue-50 text-blue-600"} flex items-center justify-center">${icon(user.role === "Owner" ? "shield-check" : "user-round",20)}</div>

                                <div class="flex-1 min-w-[150px]">

                                        <div class="font-bold">${escapeHTML(user.name)} ${user.id === currentUserId ? '<span class="text-xs text-emerald-600">(Anda)</span>' : ""}</div>

                                        <div class="text-xs text-slate-500">Username: ${escapeHTML(user.username)}</div>

                                </div>

                                <span class="px-3 py-1 rounded-full ${user.role === "Owner" ? "bg-brand-50 text-brand-700" : "bg-stone-100 text-slate-600"} text-xs font-bold">${escapeHTML(user.role)}</span>

                                <div class="flex gap-1">

                                        <button onclick="openUserModal(${user.id})" title="Edit akun" class="p-2 rounded-lg text-amber-600 hover:bg-amber-50">${icon("pencil",16)}</button>

                                        <button onclick="deleteUser(${user.id})" title="Hapus akun" class="p-2 rounded-lg text-red-500 hover:bg-red-50">${icon("trash-2",16)}</button>

                                </div>

                        </div>`).join("")}

                </div>

                <p class="text-xs text-amber-700 bg-amber-50 border border-amber-200 rounded-xl p-3 mt-4">Mode lokal/demo: data akun dan password disimpan di browser. Jangan gunakan password sensitif atau untuk keamanan produksi.</p>

        </div>

        `;

}


function openUserModal(id = null) {

        if (currentUserRole !== "Owner") { showToast("Hanya Owner yang dapat mengelola akun.", "error"); return; }

        const user = users.find(item => item.id === id);

        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-end sm:items-center justify-center p-4">

                <div class="modal-container bg-white w-full sm:max-w-lg rounded-t-3xl sm:rounded-2xl overflow-y-auto">

                        <div class="p-5 border-b border-stone-100 flex items-center justify-between"><h2 class="text-xl font-bold">${user ? "Edit Akun" : "Tambah Akun"}</h2><button onclick="closeModal()" class="p-2 rounded-xl hover:bg-stone-100">${icon("x",20)}</button></div>

                        <form onsubmit="saveUser(event, ${id || "null"})" class="p-5 space-y-4">

                                <div><label class="block text-sm font-semibold mb-1">Nama</label><input id="userName" required maxlength="80" value="${escapeHTML(user?.name || "")}" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200"></div>

                                <div><label class="block text-sm font-semibold mb-1">Username</label><input id="userUsername" required maxlength="40" autocomplete="off" value="${escapeHTML(user?.username || "")}" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200"></div>

                                <div><label class="block text-sm font-semibold mb-1">Password ${user ? "(opsional, kosongkan jika tidak diubah)" : ""}</label><input id="userPassword" type="password" ${user ? "" : "required"} minlength="4" autocomplete="new-password" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200" placeholder="${user ? "Biarkan kosong untuk mempertahankan password" : "Minimal 4 karakter"}"></div>

                                <div><label class="block text-sm font-semibold mb-1">Role</label><select id="userRole" class="w-full border border-stone-200 rounded-xl px-4 py-3 outline-none focus:ring-2 focus:ring-brand-200"><option value="Owner" ${user?.role === "Owner" ? "selected" : ""}>Owner</option><option value="Kasir" ${user?.role === "Kasir" ? "selected" : ""}>Kasir</option></select></div>

                                <button type="submit" class="w-full bg-brand-500 hover:bg-brand-600 text-white py-3 rounded-xl font-bold">Simpan Akun</button>

                        </form>

                </div>

        </div>`;

        lucide.createIcons();

}


function saveUser(event, id) {

        event.preventDefault();

        if (currentUserRole !== "Owner") { showToast("Hanya Owner yang dapat mengelola akun.", "error"); return; }

        const name = document.getElementById("userName").value.trim();

        const username = document.getElementById("userUsername").value.trim();

        const password = document.getElementById("userPassword").value;

        const role = document.getElementById("userRole").value;

        const existing = users.find(item => item.id === id);

        const duplicate = users.some(item => item.id !== id && item.username.toLowerCase() === username.toLowerCase());

        if (duplicate) { showToast("Username sudah digunakan.", "error"); return; }

        if (!name || !username || (!existing && password.length < 4) || (password && password.length < 4)) { showToast("Lengkapi data. Password minimal 4 karakter.", "error"); return; }

        if (existing && existing.id === currentUserId && role !== "Owner") { showToast("Role akun Owner yang sedang digunakan tidak dapat diturunkan.", "error"); return; }

        const ownerCountAfter = users.filter(item => item.role === "Owner" && item.id !== id).length + (role === "Owner" ? 1 : 0);

        if (ownerCountAfter < 1) { showToast("Minimal harus ada satu akun Owner.", "error"); return; }


        const updated = existing

                ? { ...existing, name, username, role, password: password || existing.password }

                : { id: Date.now(), name, username, password, role };

        if (existing) users = users.map(item => item.id === id ? updated : item);

        else users.push(updated);

        if (existing && existing.id === currentUserId) {

                currentUserName = updated.name;

                currentUserRole = updated.role;

                localStorage.setItem("pmt_current_name", currentUserName);

                localStorage.setItem("pmt_current_role", currentUserRole);

        }

        saveData();

        closeModal();

        showToast(existing ? "Akun berhasil diperbarui." : "Akun berhasil ditambahkan.");

        render();

}


function deleteUser(id) {

        if (currentUserRole !== "Owner") { showToast("Hanya Owner yang dapat mengelola akun.", "error"); return; }

        const user = users.find(item => item.id === id);

        if (!user) return;

        if (id === currentUserId) { showToast("Akun yang sedang digunakan tidak dapat dihapus.", "error"); return; }

        if (user.role === "Owner" && users.filter(item => item.role === "Owner").length <= 1) { showToast("Minimal harus ada satu akun Owner.", "error"); return; }

        if (!confirm(`Hapus akun ${user.name}?`)) return;

        users = users.filter(item => item.id !== id);

        saveData();

        showToast("Akun berhasil dihapus.");

        render();

}


function brandPage() {

        return `

        <div class="max-w-[900px] mx-auto">

                <h1 class="text-2xl font-bold">Profil Brand</h1>

                <p class="text-sm text-slate-500 mt-1 mb-5">Informasi yang tampil pada struk cetak pelanggan.</p>


                <div class="card p-5 space-y-4">

                        <div>

                                <label class="block text-sm font-semibold mb-1">Nama Usaha</label>

                                <input value="Pangsit Mie Tetangga" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none">

                        </div>


                        <div>

                                <label class="block text-sm font-semibold mb-1">Alamat Outlet</label>

                                <textarea class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none" rows="2">Jl. Contoh No. 123, Malang</textarea>

                        </div>


                        <div>

                                <label class="block text-sm font-semibold mb-1">Nomor WhatsApp / Telepon</label>

                                <input value="081234567890" class="w-full border border-stone-200 rounded-xl px-4 py-2.5 outline-none">

                        </div>


                        <button onclick="showToast('Profil brand berhasil diperbarui')" class="bg-brand-500 hover:bg-brand-600 text-white px-5 py-3 rounded-xl font-bold transition">

                                Simpan Profil

                        </button>

                </div>

        </div>

        `;

}


function transactionsPage() {

        return `

        <div class="max-w-[1100px] mx-auto">

                <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5">

                        <div>

                                <h1 class="text-2xl font-bold">Tambah Transaksi Manual</h1>

                                <p class="text-sm text-slate-500">Input pemasukan dan pengeluaran kas dengan cepat.</p>

                        </div>

                        <button onclick="openTransactionModal()" class="bg-brand-500 text-white px-4 py-3 rounded-xl font-semibold">

                                + Tambah Transaksi

                        </button>

                </div>


                <div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4">

                        <button onclick="openTransactionModal('Pemasukan')" class="card p-5 text-left hover:shadow-lg transition">

                                <div class="food-icon green">${icon("coins",23)}</div>

                                <div class="font-bold mt-4 text-slate-900">Pemasukan</div>

                                <div class="text-xs text-slate-500 mt-1">Modal, transfer owner, dan arus masuk lainnya.</div>

                        </button>


                        <button onclick="openTransactionModal('Pengeluaran Usaha')" class="card p-5 text-left hover:shadow-lg transition">

                                <div class="food-icon red">${icon("shopping-basket",23)}</div>

                                <div class="font-bold mt-4 text-slate-900">Pengeluaran Usaha</div>

                                <div class="text-xs text-slate-500 mt-1">Bahan baku, operasional, listrik, gas, plastik.</div>

                        </button>


                        <button onclick="openTransactionModal('Pengeluaran Pribadi')" class="card p-5 text-left hover:shadow-lg transition">

                                <div class="food-icon purple">${icon("wallet",23)}</div>

                                <div class="font-bold mt-4 text-slate-900">Pengeluaran Pribadi</div>

                                <div class="text-xs text-slate-500 mt-1">Prive owner, bensin, dan kebutuhan pribadi.</div>

                        </button>

                </div>

        </div>

        `;

}


/* =========================================================

      RECEIPT & WHATSAPP

========================================================= */


function openReceipt(transaction) {

        const items = transaction.items || [];


        document.getElementById("modalRoot").innerHTML = `

        <div class="fixed inset-0 modal-backdrop z-[200] flex items-center justify-center p-4">

                <div class="bg-white rounded-2xl p-5 max-h-[95vh] overflow-y-auto shadow-2xl">

                        <div class="flex items-center justify-between mb-4 border-b border-stone-100 pb-3">

                                <h2 class="font-bold text-lg text-slate-900">Struk Pembayaran</h2>

                                <button onclick="closeModal()" class="p-1.5 rounded-lg hover:bg-stone-100">${icon("x",20)}</button>

                        </div>


                        <div id="receiptContent" class="receipt shadow-sm border border-stone-200 rounded-xl">

                                <div class="text-center">

                                        <div class="font-extrabold text-xl text-slate-900">Pangsit Mie Tetangga</div>

                                        <div class="text-xs text-slate-500">Rasa Enak, Harga Bersahabat</div>

                                        <div class="text-xs mt-1 text-slate-600">Jl. Contoh No. 123, Malang</div>

                                </div>


                                <div class="receipt-line"></div>

                                <div class="text-xs text-slate-600">${formatDateTime(transaction.date)}</div>

                                ${transaction.customer ? `<div class="text-xs mt-1 text-slate-700">Pelanggan: ${escapeHTML(transaction.customer)}</div>` : ""}


                                <div class="receipt-line"></div>


                                ${items.map(item => `

                                        <div class="flex justify-between text-sm mb-2">

                                                <div class="pr-3 text-slate-800">${escapeHTML(item.name)} x${item.qty}</div>

                                                <div class="font-semibold text-slate-900">${rupiah(item.price * item.qty)}</div>

                                        </div>

                                `).join("")}


                                <div class="receipt-line"></div>


                                <div class="flex justify-between font-bold text-base">

                                        <span>TOTAL</span>

                                        <span>${rupiah(transaction.amount)}</span>

                                </div>

                                ${transaction.amountReceived != null ? `

                                        <div class="flex justify-between text-xs mt-2">

                                                <span>Uang diterima</span>

                                                <span>${rupiah(transaction.amountReceived)}</span>

                                        </div>

                                        <div class="flex justify-between text-xs mt-1">

                                                <span>Kembalian</span>

                                                <span>${rupiah(transaction.change || 0)}</span>

                                        </div>

                                ` : ""}


                                <div class="text-center text-xs text-slate-500 mt-5">Terima kasih atas kunjungan Anda!</div>

                        </div>


                        <div class="grid grid-cols-3 gap-2 mt-4">

                                <button onclick="printReceipt()" class="border border-stone-200 rounded-xl py-2.5 text-xs font-semibold flex items-center justify-center gap-1 hover:bg-stone-50">

                                        ${icon("printer",15)} Print

                                </button>

                                <button onclick="downloadReceipt()" class="border border-stone-200 rounded-xl py-2.5 text-xs font-semibold flex items-center justify-center gap-1 hover:bg-stone-50">

                                        ${icon("download",15)} PNG

                                </button>

                                <button onclick="sendWhatsApp('${encodeURIComponent(transaction.whatsapp || "")}',${transaction.amount})" class="bg-emerald-500 hover:bg-emerald-600 text-white rounded-xl py-2.5 text-xs font-semibold flex items-center justify-center gap-1">

                                        ${icon("message-circle",15)} WhatsApp

                                </button>

                        </div>

                </div>

        </div>

        `;

        lucide.createIcons();

}


function printReceipt() {

        const receipt = document.getElementById("receiptContent");

        if (!receipt) return;

        const win = window.open("", "_blank", "width=400,height=700");

        win.document.write(`

                <html>

                <head>

                        <title>Struk Pangsit Mie Tetangga</title>

                        <style>

                                body { margin:0; display:flex; justify-center; font-family:Arial, sans-serif; }

                                .receipt { width:320px; padding:20px; }

                                .receipt-line { border-top:1px dashed #999; margin:12px 0; }

                                .flex { display:flex; }

                                .justify-between { justify-content:space-between; }

                        </style>

                </head>

                <body>

                        <div class="receipt">${receipt.innerHTML}</div>

                        <script>window.onload = function() { window.print(); }<\/script>

                </body>

                </html>

        `);

        win.document.close();

}


async function downloadReceipt() {

        const receipt = document.getElementById("receiptContent");

        if (!receipt) return;

        const canvas = await html2canvas(receipt, { scale: 2, backgroundColor: "#ffffff" });

        const link = document.createElement("a");

        link.download = `struk-${Date.now()}.png`;

        link.href = canvas.toDataURL("image/png");

        link.click();

        showToast("Struk berhasil didownload sebagai PNG");

}


function sendWhatsApp(encodedNumber) {

        let number = decodeURIComponent(encodedNumber || "");

        if (!number) { showToast("Nomor WhatsApp pelanggan belum diisi", "error"); return; }

        number = number.replace(/\D/g,"");

        if (number.startsWith("0")) { number = "62" + number.substring(1); }


        const text = `Halo, terima kasih telah berbelanja di Pangsit Mie Tetangga! Pesanan Anda telah kami proses.`;

        window.open(`https://wa.me/${number}?text=${encodeURIComponent(text)}`, "_blank");

}


function closeModal() {

        document.getElementById("modalRoot").innerHTML = "";

}


/* =========================================================

      MAIN RENDER & INITIALIZATION

========================================================= */


function render() {

        let html = "";

        switch(currentPage) {

                case "dashboard": html = dashboardPage(); break;

                case "pos": html = posPage(); break;

                case "history": html = historyPage(); break;

                case "accounts": html = accountsPage(); break;

                case "transactions": html = transactionsPage(); break;

                case "finance": html = financePage(); break;

                case "reports": html = reportsPage(); break;

                case "menus": html = menusPage(); break;

                case "users": html = usersPage(); break;

                case "brand": html = brandPage(); break;

                default: html = dashboardPage();

        }


        document.getElementById("content").innerHTML = html;

        updateNav();

        lucide.createIcons();

        updateCurrentUserUI();

}


// Load shared data from Apps Script before rendering the application.

startApp();


</script>


</body>

</html>

-->


    <script>

      // ⚠️ GANTI DENGAN URL WEB APP GOOGLE APPS SCRIPT ANDA (BERAKHIRAN /exec)

      const GAS_API_URL = "https://script.google.com/macros/s/AKfycbw1Hg_pc6yPYZJvitcMxg3Eg-AS9hhIdSk6iboreZo3XoAOvdZY7GmbS8p7qcIwhEya/exec";


      // Fungsi Ambil Data dari Google Sheets via GAS

      async function loadDataFromGAS() {

        try {

          const response = await fetch(GAS_API_URL, {

            method: "POST",

            body: JSON.stringify({ action: "getSharedData" })

          });

          const res = await response.json();

          if (res.status === "success") {

            return res.data;

          }

        } catch (err) {

          console.error("Gagal mengambil data:", err);

        }

      }


      // Fungsi Simpan Data ke Google Sheets via GAS

      async function saveDataToGAS(snapshotData) {

        try {

          const response = await fetch(GAS_API_URL, {

            method: "POST",

            body: JSON.stringify({ 

              action: "saveSharedData",

              payload: snapshotData 

            })

          });

          const res = await response.json();

          return res;

        } catch (err) {

          console.error("Gagal menyimpan data:", err);

        }

      }

    </script>

</body>

</html>