MeshiTrack/docs/design/MeshiTrack.html

144 lines
6.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>MeshiTrack</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
<link href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600&family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="styles/tokens.css"/>
<link rel="stylesheet" href="styles/shell.css"/>
<link rel="stylesheet" href="styles/cabinet.css"/>
<link rel="stylesheet" href="styles/dashboard.css"/>
<link rel="stylesheet" href="styles/schedule.css?v=2"/>
<link rel="stylesheet" href="styles/other.css?v=2"/>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
<script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
<script type="text/babel" src="src/data.jsx"></script>
<script type="text/babel" src="src/Icon.jsx"></script>
<script type="text/babel" src="src/Shell.jsx"></script>
<script type="text/babel" src="src/Cabinet.jsx"></script>
<script type="text/babel" src="src/Dashboard.jsx"></script>
<script type="text/babel" src="src/Schedule.jsx"></script>
<script type="text/babel" src="src/OtherPages.jsx"></script>
<script type="text/babel">
const { useState, useEffect } = React;
const TWEAKS = /*EDITMODE-BEGIN*/{
"theme": "light",
"accent": "sage"
}/*EDITMODE-END*/;
const ACCENTS = {
sage: { brand: '#2f6b4a', deep: '#1e4a32', soft: '#e6efe8' },
cobalt: { brand: '#2e5aa8', deep: '#1d3d75', soft: '#e4eaf5' },
terracotta: { brand: '#b55438', deep: '#7d3825', soft: '#f6e6de' },
graphite: { brand: '#2c2c28', deep: '#000', soft: '#e8e6df' },
};
const App = () => {
const [route, setRoute] = useState('dashboard');
const [theme, setTheme] = useState(TWEAKS.theme || 'light');
const [accent, setAccent] = useState(TWEAKS.accent || 'sage');
const [tweaksOpen, setTweaksOpen] = useState(false);
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
const a = ACCENTS[accent] || ACCENTS.sage;
document.documentElement.style.setProperty('--brand', a.brand);
document.documentElement.style.setProperty('--brand-deep', a.deep);
document.documentElement.style.setProperty('--brand-soft', a.soft);
document.documentElement.style.setProperty('--brand-soft-ink', a.deep);
document.documentElement.style.setProperty('--viz-1', a.brand);
}, [theme, accent]);
useEffect(() => {
const onMsg = (e) => {
if (!e.data || typeof e.data !== 'object') return;
if (e.data.type === '__activate_edit_mode') setTweaksOpen(true);
if (e.data.type === '__deactivate_edit_mode') setTweaksOpen(false);
};
window.addEventListener('message', onMsg);
window.parent.postMessage({ type: '__edit_mode_available' }, '*');
return () => window.removeEventListener('message', onMsg);
}, []);
const setTweak = (key, val) => {
window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [key]: val } }, '*');
};
const { Sidebar, Topbar, NAV } = window.Shell;
const current = NAV.find(n => n.id === route);
const pages = {
dashboard: { title: 'Dashboard', subtitle: 'Household: Red Panda Den', Page: window.DashboardPage },
cabinet: { title: 'Medicine Cabinet', subtitle: 'Everything on hand, with days of supply', Page: window.CabinetPage },
schedule: { title: 'Schedule & Log', subtitle: 'Today and this week', Page: window.SchedulePage },
regimens: { title: 'Regimens', subtitle: 'Daily medication schedules', crumbs: ['Medicines', 'Regimens'], Page: window.RegimensPage },
organizer: { title: 'Pill Organizer', subtitle: 'Fill a week of pills at once', crumbs: ['Medicines', 'Organizer'], Page: window.OrganizerPage },
activity: { title: 'Activity', subtitle: 'Spending and cabinet changes', crumbs: ['Medicines', 'Activity'], Page: window.ActivityPage },
library: { title: 'Library', subtitle: 'All known medicines', crumbs: ['Medicines', 'Library'], Page: window.LibraryPage },
refills: { title: 'Refills', subtitle: 'Running-low alerts and shopping lists', Page: window.RefillsPage },
purchases: { title: 'Purchases', subtitle: 'Order history and pending arrivals', Page: window.PurchasesPage },
prices: { title: 'Prices', subtitle: 'Track & compare across stores', Page: window.PricesPage },
stores: { title: 'Stores', subtitle: 'Pharmacies and vendors', Page: window.StoresPage },
settings: { title: 'Settings', subtitle: 'Household and account', Page: window.SettingsPage },
};
const pg = pages[route];
const Page = pg.Page;
return (
<div className="mt-app">
<Sidebar route={route} onNav={setRoute} />
<div className="mt-main" data-screen-label={'MT / ' + pg.title}>
<Topbar
title={pg.title}
subtitle={pg.subtitle}
crumbs={pg.crumbs}
theme={theme}
onToggleTheme={() => { const t = theme === 'light' ? 'dark' : 'light'; setTheme(t); setTweak('theme', t); }}
actions={route === 'cabinet' ? <button className="mt-btn mt-btn--primary"><span></span> Add to cabinet</button> : null}
/>
<Page onNav={setRoute} />
</div>
<div className={'mt-tweaks' + (tweaksOpen ? ' is-open' : '')}>
<div className="mt-tweaks__title">
<span>Tweaks</span>
<button className="mt-btn mt-btn--subtle" onClick={() => setTweaksOpen(false)} style={{padding:'2px 6px'}}>×</button>
</div>
<div className="mt-tweaks__row">
<span>Theme</span>
<div className="mt-seg">
<button className={theme==='light'?'is-active':''} onClick={()=>{setTheme('light'); setTweak('theme','light');}}>Light</button>
<button className={theme==='dark'?'is-active':''} onClick={()=>{setTheme('dark'); setTweak('theme','dark');}}>Dark</button>
</div>
</div>
<div className="mt-tweaks__row">
<span>Accent</span>
<div className="mt-seg">
{Object.keys(ACCENTS).map(k => (
<button key={k} className={accent===k?'is-active':''} onClick={()=>{setAccent(k); setTweak('accent',k);}} style={{textTransform:'capitalize'}}>{k}</button>
))}
</div>
</div>
<div style={{fontSize: 10, color: 'var(--ink-faint)', marginTop: 8, lineHeight: 1.5}}>
See alt-directions canvas for 3 novel cabinet layouts.
</div>
</div>
</div>
);
};
ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
</script>
</body>
</html>