/* Sidebar + MobileNav + TopBar — role-aware */ const { useState: useStateSidebar } = React; const CLIENT_NAV = [ { id: "overview", icon: "home", label: "Overview" }, { id: "machines", icon: "grid", label: "Mesin Saya" }, { id: "profile", icon: "user", label: "Profil" }, ]; const ADMIN_NAV = [ { id: "overview", icon: "home", label: "Overview", group: "main" }, { id: "admin-clients", icon: "users", label: "Daftar Client", group: "main" }, { id: "admin-machines", icon: "grid", label: "Status Mesin", group: "main" }, { id: "admin-billing", icon: "wallet", label: "Billing", group: "finance" }, { id: "admin-invoices", icon: "receipt", label: "Invoice", group: "finance" }, { id: "admin-telemetron", icon: "cpu", label: "Telemetron", group: "account" }, { id: "admin-settings", icon: "settings", label: "Pengaturan", group: "account" }, { id: "profile", icon: "user", label: "Profil & Akun", group: "account" }, ]; function Sidebar() { const { route, navigate, logout, isAdmin, user } = useApp(); const items = isAdmin ? ADMIN_NAV : CLIENT_NAV; const groups = isAdmin ? [ { id: "main", label: "Operasional" }, { id: "finance", label: "Keuangan" }, { id: "account", label: "Akun" }, ] : [{ id: null }]; const isActive = (id) => route.name === id || (id === "machines" && route.name.startsWith("machine")); const initial = user?.name?.charAt(0) || "?"; return ( ); } function MobileNav() { const { route, navigate, isAdmin } = useApp(); const items = isAdmin ? [ { id: "overview", icon: "home", label: "Home" }, { id: "admin-clients", icon: "users", label: "Client" }, { id: "admin-machines", icon: "grid", label: "Mesin" }, { id: "admin-billing", icon: "wallet", label: "Billing" }, { id: "profile", icon: "user", label: "Profil" }, ] : [ { id: "overview", icon: "home", label: "Home" }, { id: "machines", icon: "grid", label: "Mesin" }, { id: "profile", icon: "user", label: "Profil" }, ]; const isActive = (id) => route.name === id || (id === "machines" && route.name.startsWith("machine")); return ( {items.map(it => { const active = isActive(it.id); return ( navigate({ name: it.id })} className={`flex-1 py-2.5 flex flex-col items-center gap-0.5 ${active ? "text-[#FF2D55]" : "text-stone-500"}`} > {it.label} ); })} ); } function TopBar() { const { route, user, isAdmin, navigate, toast, machines } = useApp(); const PAGE_TITLES = { overview: "Overview", machines: "Mesin Saya", profile: "Profil & Akun", "machine-detail": "Detail Mesin", "machine-renew": "Perpanjang Kontrak", "payment-success": "Pembayaran Berhasil", "payment-failed": "Pembayaran Gagal", "admin-clients": "Daftar Client", "admin-machines": "Status Mesin", "admin-billing": "Billing", "admin-invoices": "Invoice", "admin-telemetron": "Telemetron", "admin-settings": "Pengaturan Perusahaan", }; const expiring = machines.filter(m => statusForMachine(m).tone === "warning").length; return ( Yappari! {isAdmin ? "Admin Panel" : "Dashboard"} {PAGE_TITLES[route.name] || "Dashboard"} {/* Notification bell */} expiring > 0 ? toast(`${expiring} mesin mendekati expired. Cek halaman Status Mesin.`, "warning") : toast("Tidak ada notifikasi baru.", "info") } className="relative p-2.5 rounded-full text-stone-600 hover:bg-stone-100" > {expiring > 0 && ( )} {/* User chip */} {user?.name?.charAt(0) || "?"} {user?.name} {isAdmin && Admin} {user?.email} ); } // expose Icon name "users" if not in shared const _usersIcon = <>>; Object.assign(window, { Sidebar, MobileNav, TopBar });