// VMAX Store Manager app — PIN sign-in, responsive shell (bottom tabs / side rail),
// nav + routing across all back-office views, the day banner, Tweaks dock.
(function () {
const DS = window.VMAX365DesignSystem_0f78b2;
const { Icon, Sheet, Overline, NetBadge, useViewport } = window.VMAXUI;
const { Avatar, PinDialog, Toaster, pushToast, NotifBadge } = window.VMAXW;
const { useVMAX, notifications } = window.VMAXStore;
const { Dashboard, Inventory, Transfers, Recipes } = window.VMAXMGR1;
const { Receiving, Counts } = window.VMAXMGR2;
const { Catalogue, People } = window.VMAXMGR3;
const { DailyClose, Reports, TheDay } = window.VMAXCLOSE;
const { Onboarding } = window.VMAXONBOARD;
const { Settings } = window.VMAXSETTINGS;
const { Shifts } = window.VMAXSHIFTS;
const { ReportsPage } = window.VMAXREPORTS;
const { TweakDock } = window.VMAXTWEAKS;
const NAV = [
{ key: 'setup', label: 'Setup', icon: 'home', group: 'Setup' },
{ key: 'dash', label: 'Dashboard', icon: 'dash', group: 'Today', primary: true },
{ key: 'close', label: 'Daily close', icon: 'register', group: 'Today', primary: true },
{ key: 'reports', label: 'Reports', icon: 'chart', group: 'Today' },
{ key: 'variance', label: 'Variance', icon: 'alert', group: 'Today' },
{ key: 'shifts', label: 'Shifts', icon: 'clock', group: 'Today' },
{ key: 'inv', label: 'Inventory', icon: 'box', group: 'Stock', primary: true },
{ key: 'transfers', label: 'Transfers', icon: 'swap', group: 'Stock' },
{ key: 'receiving', label: 'Receiving', icon: 'truck', group: 'Stock' },
{ key: 'counts', label: 'Counts', icon: 'clipboard', group: 'Stock' },
{ key: 'recipes', label: 'Recipes', icon: 'recipe', group: 'Catalogue' },
{ key: 'catalogue', label: 'Catalogue', icon: 'edit', group: 'Catalogue' },
{ key: 'people', label: 'People', icon: 'members', group: 'Catalogue' },
{ key: 'settings', label: 'Settings', icon: 'settings', group: 'Setup' },
];
const GROUPS = ['Today', 'Stock', 'Catalogue', 'Setup'];
function ViewBody({ view, who, mobile, go }) {
switch (view) {
case 'setup': return ;
case 'dash': return ;
case 'inv': return ;
case 'transfers': return ;
case 'receiving': return ;
case 'counts': return ;
case 'recipes': return ;
case 'close': return ;
case 'reports': return ;
case 'variance': return ;
case 'shifts': return ;
case 'catalogue': return ;
case 'people': return ;
case 'settings': return ;
default: return null;
}
}
function SignIn({ onPick, session }) {
const [s] = useVMAX();
const [pinFor, setPinFor] = React.useState(null);
const roster = s.people.filter((p) => p.roles.includes('manager') || p.roles.includes('owner'));
return (
Enter your PIN to open the back office
Demo PINs — Manager (Daniel) 1357 · Owner 2468. Or open Tweaks (⚙ lower-right) to jump in.
{roster.map((r) => (
))}
session.verify(pinFor.id, pin)} onClose={() => setPinFor(null)} onSuccess={() => { onPick(pinFor); pushToast('Signed in · ' + pinFor.name.split(' ')[0]); setPinFor(null); }} />
);
}
function App() {
const [s, a] = useVMAX();
const { mobile } = useViewport();
const notif = notifications(s);
const navCount = (k) => (k === 'inv' ? notif.front : k === 'transfers' ? notif.pendingReq : 0);
const [active, setActive] = React.useState(null);
const [switchTo, setSwitchTo] = React.useState(null);
const session = { verify: (id, pin) => a.verifyPin(id, pin) };
const [view, setView] = React.useState(s.mode === 'firstrun' ? 'setup' : 'dash');
const [moreOpen, setMoreOpen] = React.useState(false);
const cur = NAV.find((n) => n.key === view) || NAV[1];
const go = (k) => { setView(k); setMoreOpen(false); };
const who = active ? active.name : '—';
const pick = (id) => s.people.find((p) => p.id === id);
const roleJump = [pick('u_mgr') && { label: 'Manager', person: pick('u_mgr') }, pick('u_owner') && { label: 'Owner', person: pick('u_owner') }].filter(Boolean);
const dock = { setActive(p); }} />;
if (!active) return {dock};
const others = s.people.filter((p) => (p.roles.includes('manager') || p.roles.includes('owner')) && p.id !== active.id && p.pin);
const Header = () => (
{!mobile &&
VMAX 365STORE MANAGER
}
{mobile &&
{cur.label}
}
a.setTweak('net', v)} />
);
const showDay = view === 'dash' || view === 'close';
const userSheet = (
setMoreOpen(false)} width={360}>
{active.name}
{active.roles[0]}
{mobile &&
Sections{NAV.filter((n) => !n.primary).map((n) => go(n.key)} />)}
}
Switch user
{others.map((r) =>
{ setMoreOpen(false); setSwitchTo(r); }} />)}
{ setActive(null); setMoreOpen(false); }} />
);
const main = (
{showDay && }
);
if (mobile) {
return (
{Header()}
{s.day.date} · Heritage Park
{main}
{userSheet}
{dock}
setSwitchTo(null)} onDone={(p) => { setActive(p); setSwitchTo(null); }} />
);
}
return (
{Header()}
{main}
{userSheet}
{dock}
setSwitchTo(null)} onDone={(p) => { setActive(p); setSwitchTo(null); }} />
);
}
function SwitchDialog({ switchTo, session, onClose, onDone }) {
return session.verify(switchTo.id, pin)} onClose={onClose} onSuccess={() => { onDone(switchTo); pushToast('Switched · ' + switchTo.name.split(' ')[0]); }} />;
}
function Tab({ icon, label, active, onClick, badge }) {
return (
);
}
function Row({ icon, avatar, label, active, onClick, badge }) {
return (
);
}
window.VMAXMgrApp = App;
})();