// Dashy — main app (DB-backed via SQLite/WASM) const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "theme": "light", "accent": "#2A6FDB", "density": "cozy", "showTags": true }/*EDITMODE-END*/; const ACCENTS = ['#2A6FDB', '#1F8A5B', '#D97757', '#7A5AF8']; function useDashyDB() { const [ready, setReady] = React.useState(DashyDB.isReady); const [, force] = React.useReducer(x => x + 1, 0); React.useEffect(() => { if (!DashyDB.isReady) DashyDB.init().then(() => setReady(true)); const off = DashyDB.subscribe(() => force()); return off; }, []); return ready; } function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const ready = useDashyDB(); const [authed, setAuthed] = React.useState(false); const [meId, setMeId] = React.useState('rod'); const [tab, setTab] = React.useState('overview'); const [adding, setAdding] = React.useState(null); const [openTaskId, setOpenTaskId] = React.useState(null); const [showLogs, setShowLogs] = React.useState(false); const [showSettings, setShowSettings] = React.useState(false); const [showDB, setShowDB] = React.useState(false); const [headsUp, setHeadsUp] = React.useState([ { id: 'h1', kind: 'unsuccessful', taskId: 't7', title: 'WO #2188 auto-marked Unsuccessful', sub: 'Two missed bookings — assigned to Kirra for review' }, { id: 'h2', kind: 'billing', taskId: 't4', title: 'Form response switched to Billing', sub: 'K. Wynne · originally Service Booking' }, ]); if (!ready) return ; const tasks = DashyDB.listTasks(); const audit = DashyDB.listAudit(); const dbUsers = DashyDB.listUsers(); const userMap = Object.fromEntries(dbUsers.map(u => [u.id, u])); const merge = (id) => { const base = findUser(id); if (!base && !userMap[id]) return null; const live = userMap[id] || {}; if (!base) { // user added at runtime return { id, name: live.name, role: live.role, hue: live.hue, initials: live.initials, photo: live.photo || null, account_type: live.account_type || 'standard' }; } return { ...base, name: live.name || base.name, role: live.role || base.role, photo: live.photo || null, account_type: live.account_type || 'standard' }; }; const me = merge(meId); const isAdmin = me && me.account_type === 'admin'; const openTask = tasks.find(x => x.id === openTaskId); const handleLogin = (id) => { setMeId(id); setAuthed(true); DashyDB.addAudit({ actor: id, action: 'login', summary: (merge(id) || {}).name + ' signed in', }); }; const addTask = ({ title, description, assignee, priority }) => { const id = 't_' + Date.now().toString(36); const at = new Date('2026-05-08T10:30:00').toISOString(); DashyDB.createTask({ id, title, description, assignee, priority, addedBy: meId, source: 'manual', status: 'open', addedAt: at, tags: [] }); DashyDB.addAudit({ at, actor: meId, action: 'task_created', summary: 'Created task "' + title + '" for ' + (merge(assignee)||{}).name, target: id }); setAdding(null); }; const moveTask = (taskId, toUserId) => DashyDB.moveTask(taskId, toUserId, meId); const setPriority = (taskId, p) => DashyDB.setPriority(taskId, p); const dismissHU = (id) => setHeadsUp(h => h.filter(x => x.id !== id)); const openTaskFromAnywhere = (id) => { setOpenTaskId(id); setShowLogs(false); }; if (!authed) return ; return (
setAdding(meId)} onLogs={() => setShowLogs(true)} onProfile={() => setShowSettings(true)} onDB={() => setShowDB(true)} />
{tab === 'overview' && ( setOpenTaskId(task.id)} onAddFor={(uid) => setAdding(uid)} onMoveTask={moveTask} /> )} {tab !== 'overview' && ( setOpenTaskId(task.id)} onAddFor={(uid) => setAdding(uid)} /> )}
setAdding(null)} onSubmit={addTask} defaultAssignee={adding} me={me} /> {openTask && ( setOpenTaskId(null)} onMove={moveTask} onPriority={setPriority} /> )} {showLogs && ( setShowLogs(false)} wide> )} {showSettings && ( setShowSettings(false)} onSave={(edits) => { DashyDB.updateUser(meId, edits); DashyDB.addAudit({ actor: meId, action: 'profile_updated', summary: 'Updated profile details' }); }} onLogout={() => { setShowSettings(false); setAuthed(false); }} onSwitchUser={(id) => { setMeId(id); setShowSettings(false); }} onCreateUser={(u) => { const id = DashyDB.createUser(u); DashyDB.addAudit({ actor: meId, action: 'user_created', summary: 'Added ' + u.name + ' (' + (u.account_type||'standard') + ')', target: id }); }} onDeleteUser={(id) => { const u = userMap[id]; DashyDB.deleteUser(id); DashyDB.addAudit({ actor: meId, action: 'user_deleted', summary: 'Removed ' + (u?u.name:id), target: null }); }} onUpdateUserRole={(id, edits) => { DashyDB.updateUser(id, edits); DashyDB.addAudit({ actor: meId, action: 'user_updated', summary: 'Updated ' + (userMap[id]?userMap[id].name:id) + ' permissions', target: null }); }} /> )} {showDB && isAdmin && setShowDB(false)} />}
); } function BootSplash() { return (
opening dashy.db…
); } function DashyTweaks({ t, setTweak }) { return ( setTweak('theme', v)} /> setTweak('accent', v)} /> setTweak('density', v)} /> setTweak('showTags', v)} /> { if (confirm('Wipe and reseed dashy.db?')) DashyDB.reset(); }}> Reset ); } function ThemeBridge() { const [t] = useTweaks(TWEAK_DEFAULTS); React.useEffect(() => { document.documentElement.dataset.theme = t.theme; document.documentElement.style.setProperty('--accent', t.accent); document.documentElement.dataset.showTags = t.showTags ? 'on' : 'off'; }, [t.theme, t.accent, t.showTags]); return null; } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<>);