terminal redesign
This commit is contained in:
110
src/features/store-admin/CounterDrawer.tsx
Normal file
110
src/features/store-admin/CounterDrawer.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@astryxdesign/core/Button';
|
||||
import { HStack } from '@astryxdesign/core/HStack';
|
||||
import { Text } from '@astryxdesign/core/Text';
|
||||
import { TextInput } from '@astryxdesign/core/TextInput';
|
||||
import { VStack } from '@astryxdesign/core/VStack';
|
||||
import { EyeOff } from 'lucide-react';
|
||||
import { Drawer } from './Drawer';
|
||||
import type { CounterLabels } from './counterLabels';
|
||||
import type { CounterRow } from './counterRows';
|
||||
import { money } from './format';
|
||||
import { shortAge } from './posStatus';
|
||||
|
||||
/**
|
||||
* One counter, in full.
|
||||
*
|
||||
* The list answers "which counters need me"; this answers "what is this one
|
||||
* doing" — the readings a person wants before walking over to it, plus the two
|
||||
* things they can change about it.
|
||||
*
|
||||
* Rename and hide live here rather than on the row. They are rare actions, and
|
||||
* a control on every row of a fifteen-row table is fifteen chances to hide a
|
||||
* counter by mistake.
|
||||
*/
|
||||
export interface CounterDrawerProps {
|
||||
row: CounterRow;
|
||||
labels: CounterLabels;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function CounterDrawer({ row, labels, onClose }: CounterDrawerProps) {
|
||||
const [draft, setDraft] = useState(() =>
|
||||
labels.isNamed(row.terminalId) ? labels.nameFor(row.terminalId) : '',
|
||||
);
|
||||
const status = row.status;
|
||||
|
||||
const readings: [string, string][] = [
|
||||
['Counter code', row.terminalId],
|
||||
['Branch', row.branchName],
|
||||
['Sold in this period', `${row.periodBills} bills · ${money(row.periodAmount)}`],
|
||||
];
|
||||
|
||||
if (status) {
|
||||
readings.push(['Today on the till', `${status.todayBills} bills · ${money(status.todayAmount)}`]);
|
||||
readings.push(['Last sale', status.lastBillAt ? `${shortAge(Date.now() - status.lastBillAt.getTime())} ago` : 'never']);
|
||||
readings.push(['Last heard from', status.silentForMs == null ? 'never' : `${shortAge(status.silentForMs)} ago`]);
|
||||
// The number that explains a revenue figure reading low, so it is stated
|
||||
// even when it is zero rather than hidden as "nothing to report".
|
||||
readings.push(['Waiting to send', String(status.pendingBills)]);
|
||||
if (status.reason) readings.push(['Reported', status.reason]);
|
||||
} else {
|
||||
readings.push(['Status', 'This counter has never reported in.']);
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
title={labels.isNamed(row.terminalId) ? labels.nameFor(row.terminalId) : row.terminalId}
|
||||
subtitle={labels.isNamed(row.terminalId) ? row.terminalId : row.branchName}
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
>
|
||||
<VStack gap={3}>
|
||||
<div className="reading-list">
|
||||
{readings.map(([label, value]) => (
|
||||
<div key={label} className="reading">
|
||||
<span>{label}</span>
|
||||
<strong>{value}</strong>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<VStack gap={1.5}>
|
||||
<TextInput
|
||||
label="Name this counter"
|
||||
value={draft}
|
||||
onChange={setDraft}
|
||||
placeholder={row.terminalId}
|
||||
description="Shown instead of the code. The code stays on the receipts."
|
||||
/>
|
||||
<HStack justify="between" align="center" gap={2} wrap="wrap">
|
||||
<Button
|
||||
label="Hide this counter"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
icon={<EyeOff size={14} />}
|
||||
onClick={() => {
|
||||
labels.hide(row.terminalId);
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
label="Save name"
|
||||
variant="primary"
|
||||
size="sm"
|
||||
isDisabled={draft.trim() === '' && !labels.isNamed(row.terminalId)}
|
||||
onClick={() => {
|
||||
labels.rename(row.terminalId, draft.trim());
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
<Text type="body" size="xsm" color="secondary">
|
||||
Hiding removes a counter from this page. It keeps recording sales — use it for a till
|
||||
that has been retired.
|
||||
</Text>
|
||||
</VStack>
|
||||
</VStack>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user