Waiter PWA fixes, and extra feautures. Also added Emergency Mode, search etc
This commit is contained in:
167
CLAUDE_DESIGN/tables-app.jsx
Normal file
167
CLAUDE_DESIGN/tables-app.jsx
Normal file
@@ -0,0 +1,167 @@
|
||||
// Wrapping screens — phone frame with the grid at each density
|
||||
|
||||
const { IOSDevice } = window;
|
||||
const { TABLES } = window;
|
||||
const { Card1x1, Card2x1, Card2x2, Card4x1, Card4x2 } = window.TableCards;
|
||||
const { DesignCanvas, DCSection, DCArtboard } = window;
|
||||
|
||||
// Density specs — each one has a column count, gap, and a card renderer.
|
||||
// "1x1" means 4 columns of tiny squares; "4x2" means 1 large card per row.
|
||||
//
|
||||
// The naming reflects relative density: 1x1 = highest density (smallest cards),
|
||||
// 4x2 = lowest density (biggest, most info).
|
||||
const DENSITIES = {
|
||||
'1x1': {
|
||||
label: '1×1 — Highest density',
|
||||
desc: 'Just the name. Status as color.',
|
||||
cols: 4, gap: 8,
|
||||
aspectW: 1, aspectH: 1,
|
||||
Card: Card1x1,
|
||||
},
|
||||
'2x1': {
|
||||
label: '2×1 — Compact',
|
||||
desc: 'Name + status pill.',
|
||||
cols: 2, gap: 10,
|
||||
aspectW: 2, aspectH: 1,
|
||||
Card: Card2x1,
|
||||
},
|
||||
'2x2': {
|
||||
label: '2×2 — Balanced',
|
||||
desc: 'Name, status, amount, waiters.',
|
||||
cols: 2, gap: 12,
|
||||
aspectW: 1, aspectH: 1,
|
||||
Card: Card2x2,
|
||||
},
|
||||
'4x1': {
|
||||
label: '4×1 — Wide row',
|
||||
desc: 'Name, amount, status, waiters.',
|
||||
cols: 1, gap: 10,
|
||||
aspectW: 4, aspectH: 1,
|
||||
Card: Card4x1,
|
||||
},
|
||||
'4x2': {
|
||||
label: '4×2 — Full detail',
|
||||
desc: 'Everything. Section, badges, waiter names.',
|
||||
cols: 1, gap: 12,
|
||||
aspectW: 2, aspectH: 1,
|
||||
Card: Card4x2,
|
||||
},
|
||||
};
|
||||
|
||||
// Top filter bar
|
||||
function FilterBar() {
|
||||
const filters = [
|
||||
{ label: 'All', active: true },
|
||||
{ label: 'Mine' },
|
||||
{ label: 'Free' },
|
||||
{ label: 'Zone (2)' },
|
||||
];
|
||||
return (
|
||||
<div style={{
|
||||
padding: '10px 16px 14px',
|
||||
background: 'white',
|
||||
display: 'flex', gap: 8,
|
||||
borderBottom: '1px solid #edeff1',
|
||||
}}>
|
||||
{filters.map(f => (
|
||||
<button key={f.label} style={{
|
||||
height: 38, padding: '0 16px',
|
||||
borderRadius: 10,
|
||||
background: f.active ? '#f5b740' : 'white',
|
||||
border: '1.5px solid ' + (f.active ? '#f5b740' : '#dfe2e6'),
|
||||
color: f.active ? '#3a2a05' : '#5a6169',
|
||||
fontSize: 14, fontWeight: 700,
|
||||
fontFamily: 'inherit',
|
||||
cursor: 'pointer',
|
||||
}}>{f.label}</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Header({ density }) {
|
||||
return (
|
||||
<div style={{
|
||||
padding: '54px 16px 10px',
|
||||
background: 'white',
|
||||
display: 'flex', alignItems: 'center', gap: 10,
|
||||
}}>
|
||||
<div style={{ flex: 1, fontSize: 20, fontWeight: 700, color: '#111315' }}>Tables</div>
|
||||
<button style={{
|
||||
width: 38, height: 38,
|
||||
borderRadius: 19, border: '1px solid #dfe2e6', background: 'white',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
}}>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 22C13.1 22 14 21.1 14 20H10C10 21.1 10.9 22 12 22ZM18 16V11C18 7.9 16.4 5.4 13.5 4.7V4C13.5 3.2 12.8 2.5 12 2.5C11.2 2.5 10.5 3.2 10.5 4V4.7C7.6 5.4 6 7.9 6 11V16L4 18V19H20V18L18 16Z" stroke="#2b2f33" strokeWidth="1.6"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 14, fontWeight: 600, color: '#2b2f33' }}>
|
||||
dimitris
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M6 9L12 15L18 9" stroke="#5a6169" strokeWidth="2"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DensityScreen({ densityKey }) {
|
||||
const d = DENSITIES[densityKey];
|
||||
// Compute card width: phone interior is ~370px wide, padding 12px each side
|
||||
const padding = 12;
|
||||
const innerW = 370 - padding * 2;
|
||||
const cardW = (innerW - d.gap * (d.cols - 1)) / d.cols;
|
||||
const cardH = cardW * (d.aspectH / d.aspectW);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
width: '100%', height: '100%',
|
||||
background: '#f4f4f2',
|
||||
display: 'flex', flexDirection: 'column',
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
<Header density={d.label} />
|
||||
<FilterBar />
|
||||
<div style={{ flex: 1, overflowY: 'auto', padding: padding }}>
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: `repeat(${d.cols}, 1fr)`,
|
||||
gap: d.gap,
|
||||
}}>
|
||||
{TABLES.map(t => (
|
||||
<d.Card key={t.name} table={t} w={cardW} h={cardH} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
const order = ['1x1', '2x1', '2x2', '4x1', '4x2'];
|
||||
return (
|
||||
<DesignCanvas title="Table grid — 5 density options">
|
||||
<DCSection id="densities" title="Density variants — selectable in user settings">
|
||||
{order.map(k => {
|
||||
const d = DENSITIES[k];
|
||||
return (
|
||||
<DCArtboard key={k} id={k} label={d.label + ' — ' + d.desc} width={460} height={920}>
|
||||
<div style={{
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
width: '100%', height: '100%',
|
||||
background: 'transparent',
|
||||
}}>
|
||||
<IOSDevice>
|
||||
<DensityScreen densityKey={k} />
|
||||
</IOSDevice>
|
||||
</div>
|
||||
</DCArtboard>
|
||||
);
|
||||
})}
|
||||
</DCSection>
|
||||
</DesignCanvas>
|
||||
);
|
||||
}
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(<App />);
|
||||
Reference in New Issue
Block a user