Make the clock app's oil & diesel screen scan-only
Remove the manual product buttons and the on-device booked-out list; the full history stays in the Booked out table on the Oil & Diesel Stock page. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
df53130861
commit
1dc1472841
2 changed files with 4 additions and 25 deletions
|
|
@ -1,7 +1,6 @@
|
|||
import { requireClockUser } from '@/lib/auth';
|
||||
import { clockPB } from '@/lib/clock-store';
|
||||
import { movementAt } from '@/lib/oil-log';
|
||||
import { StockOut, type StockLogRow } from '@/components/StockOut';
|
||||
import { StockOut } from '@/components/StockOut';
|
||||
export const dynamic = 'force-dynamic';
|
||||
export const metadata = { title: 'Book out oil & diesel · Mega Plant' };
|
||||
|
||||
|
|
@ -14,13 +13,8 @@ export default async function StockPage() {
|
|||
pb.collection('oil_stock_movements').getFullList({ expand: 'item,asset' }),
|
||||
]);
|
||||
const onHand = (id: string) => moves.filter(m => m.item === id).reduce((s, m) => s + (m.kind === 'used' ? -(m.litres || 0) : m.litres || 0), 0);
|
||||
const log: StockLogRow[] = moves.filter(m => m.kind === 'used').map((m): any => ({ ...m, at: movementAt(m) })).sort((a, b) => b.at.localeCompare(a.at)).slice(0, 15).map(m => ({
|
||||
id: m.id, at: m.at, litres: m.litres, item: String(m.expand?.item?.name || ''),
|
||||
colour: String(m.expand?.item?.colour || ''), asset: String(m.expand?.asset?.code || ''), by: String(m.booked_by || ''),
|
||||
}));
|
||||
return <StockOut
|
||||
items={items.map(i => ({ id: i.id, code: i.code, name: i.name, colour: i.colour || '#30638E', onHand: Math.round(onHand(i.id) * 100) / 100, tank: String(i.code).startsWith('FUEL') }))}
|
||||
assets={assets.map(a => ({ id: a.id, code: a.code, name: a.name }))}
|
||||
log={log}
|
||||
/>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
'use client';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { AlertTriangle, CheckCircle2, Droplets, ScanLine, X } from 'lucide-react';
|
||||
import { AlertTriangle, CheckCircle2, Droplets, X } from 'lucide-react';
|
||||
import { BadgeCamera } from './BadgeCamera';
|
||||
import { clockDate, clockTime } from '@/lib/clock-display';
|
||||
import { oilCodeFromQr } from '@/lib/stock-out';
|
||||
|
||||
type Item = { id: string; code: string; name: string; colour: string; onHand: number; tank: boolean };
|
||||
type Asset = { id: string; code: string; name: string };
|
||||
export type StockLogRow = { id: string; at: string; litres: number; item: string; colour: string; asset: string; by: string };
|
||||
|
||||
const fmt = (n: number) => n.toLocaleString('en-ZA', { maximumFractionDigits: 2 });
|
||||
|
||||
/** Scan the drum/tank QR, say how many litres and which vehicle, and it is booked out. */
|
||||
export function StockOut({ items, assets, log }: { items: Item[]; assets: Asset[]; log: StockLogRow[] }) {
|
||||
export function StockOut({ items, assets }: { items: Item[]; assets: Asset[] }) {
|
||||
const router = useRouter();
|
||||
const [item, setItem] = useState<Item | null>(null);
|
||||
const [litres, setLitres] = useState('');
|
||||
|
|
@ -64,11 +62,7 @@ export function StockOut({ items, assets, log }: { items: Item[]; assets: Asset[
|
|||
|
||||
{!item ? <>
|
||||
<div className="mt-4"><BadgeCamera onDecode={onDecode} paused={busy} hint="Scan the QR on the drum or tank"/></div>
|
||||
{unknownScan && <p role="alert" className="plant-clock-warning mt-3">That QR is not an oil or diesel label ({unknownScan}). Scan the label on the drum or tank, or pick below.</p>}
|
||||
<div className="mt-4"><p className="text-sm font-medium">Or choose the product</p>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2 mt-2">{items.map(i =>
|
||||
<button key={i.id} onClick={() => pick(i)} className="plant-clock-button plant-clock-secondary justify-start" style={{ borderColor: i.colour }}>
|
||||
<Droplets size={18} style={{ color: i.colour }}/><span className="text-left min-w-0 truncate">{i.name}</span></button>)}</div></div>
|
||||
{unknownScan && <p role="alert" className="plant-clock-warning mt-3">That QR is not an oil or diesel label ({unknownScan}). Scan the label on the drum or tank.</p>}
|
||||
</> : <form onSubmit={submit} className="plant-clock-panel mt-4 p-4 sm:p-5">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0"><div className="flex items-center gap-2"><Droplets size={20} style={{ color: item.colour }}/><h2 className="text-lg font-semibold break-words">{item.name}</h2></div>
|
||||
|
|
@ -84,15 +78,6 @@ export function StockOut({ items, assets, log }: { items: Item[]; assets: Asset[
|
|||
{busy ? 'Saving…' : 'Book out'}</button>
|
||||
</form>}
|
||||
|
||||
<div className="plant-clock-panel mt-5 p-4 sm:p-5">
|
||||
<h2 className="text-base font-semibold flex items-center gap-2"><ScanLine size={16}/>Booked out</h2>
|
||||
{log.length === 0 ? <p className="text-sm text-text-muted mt-3">Nothing booked out yet.</p>
|
||||
: <ul className="divide-y divide-border mt-2">{log.map(r => <li key={r.id} className="py-3 flex items-center gap-3">
|
||||
<Droplets size={18} className="shrink-0" style={{ color: r.colour }}/>
|
||||
<span className="min-w-0 flex-1"><span className="block text-sm font-medium break-words">{fmt(r.litres)} L {r.item} → {r.asset || 'no vehicle'}</span>
|
||||
<span className="block text-xs text-text-muted">{r.at?clockDate(r.at.replace(' ','T')):''}{r.by ? ` · ${r.by}` : ''}</span></span>
|
||||
<span className="text-sm tabular-nums shrink-0">{r.at.includes('T')?clockTime(r.at):''}</span></li>)}</ul>}
|
||||
</div>
|
||||
</section>;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue