WFDASHDRIVER-APP/components/CollectPrompt.tsx

96 lines
3.6 KiB
TypeScript
Raw Permalink Normal View History

'use client';
import { useState } from 'react';
import { Check } from 'lucide-react';
import BottomSheet from '@/components/BottomSheet';
import { getItemDisplayQty } from '@/lib/pocketbase';
import type { OrderItem } from '@/lib/types';
import { cn } from '@/lib/utils';
interface CollectPromptProps {
poLabel: string;
/** The PO's items still on the driver's list. */
items: OrderItem[];
onCollect: (items: OrderItem[]) => void;
onClose: () => void;
}
// Shown right after an invoice photo uploads. The photo alone collects
// nothing, and the green invoice button made it look done, so drivers left
// lines "assigned" and off Collection Confirm. Works with or without the AI
// match: it only lists what is still on the list. Every item starts ticked;
// a short or different item is unticked and collected on its own card.
export default function CollectPrompt({ poLabel, items, onCollect, onClose }: CollectPromptProps) {
const [picked, setPicked] = useState<Set<string>>(() => new Set(items.map((i) => i.id)));
const toggle = (id: string) =>
setPicked((prev) => {
const next = new Set(prev);
if (next.has(id)) next.delete(id);
else next.add(id);
return next;
});
const chosen = items.filter((i) => picked.has(i.id));
return (
<BottomSheet title="Invoice saved · collect these items?" subtitle={poLabel} onClose={onClose}>
<p className="text-[14px] text-[#26251e] mb-2">
The photo is saved, but the items aren’t collected yet. Tick what you picked up.
</p>
<ul className="divide-y divide-[rgba(38,37,30,0.08)] mb-2">
{items.map((item) => {
const on = picked.has(item.id);
return (
<li key={item.id}>
<button
type="button"
role="checkbox"
aria-checked={on}
onClick={() => toggle(item.id)}
className="w-full py-2.5 flex items-start gap-3 text-left touch-manipulation"
>
<span
className={cn(
'w-6 h-6 rounded-md border flex items-center justify-center flex-shrink-0 mt-0.5',
on ? 'bg-[#1f8a65] border-[#1f8a65]' : 'bg-white border-[rgba(38,37,30,0.3)]',
)}
aria-hidden="true"
>
{on && <Check size={16} className="text-white" />}
</span>
<span className="flex-1 min-w-0 text-[14px] text-[#26251e] leading-snug break-words">
{item.description}
<span className="text-[rgba(38,37,30,0.55)]"> × {getItemDisplayQty(item)}</span>
</span>
</button>
</li>
);
})}
</ul>
<p className="text-[12px] text-[rgba(38,37,30,0.6)] mb-3">
Short or different from the PO? Untick it and use Collect on that item to enter what you got.
</p>
<div className="flex gap-2">
<button
type="button"
onClick={onClose}
className="h-12 flex-1 rounded-xl text-[15px] font-semibold bg-[#efeaf7] text-[#6c5a99] touch-manipulation"
>
Not now
</button>
<button
type="button"
disabled={chosen.length === 0}
onClick={() => onCollect(chosen)}
className="h-12 flex-1 rounded-xl text-[15px] font-semibold bg-[#1f8a65] text-white disabled:opacity-50 touch-manipulation"
>
{chosen.length === items.length && items.length > 1
? `Collect all ${items.length}`
: `Collect ${chosen.length} item${chosen.length === 1 ? '' : 's'}`}
</button>
</div>
</BottomSheet>
);
}