Dev #23
+100
@@ -0,0 +1,100 @@
|
||||
'use client'
|
||||
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import type { DeliveryTaskResponse, DeliveryTaskStatus } from '@/types/api'
|
||||
|
||||
const TASK_STATUS_VARIANT: Record<DeliveryTaskStatus, 'default' | 'secondary' | 'destructive'> = {
|
||||
Pending: 'secondary',
|
||||
Delivered: 'default',
|
||||
PartiallyDelivered: 'secondary',
|
||||
Failed: 'destructive',
|
||||
}
|
||||
|
||||
const fmtDateTime = (v: string | null) =>
|
||||
v
|
||||
? new Date(v).toLocaleString('en-GB', {
|
||||
day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit',
|
||||
})
|
||||
: '—'
|
||||
|
||||
interface DeliveryTaskViewSheetProps {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
task: DeliveryTaskResponse | null
|
||||
}
|
||||
|
||||
function Row({ label, value }: { label: string; value: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between py-2 text-sm border-b last:border-0">
|
||||
<span className="text-muted-foreground">{label}</span>
|
||||
<span className="font-medium text-right">{value}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function DeliveryTaskViewSheet({ open, onClose, task }: DeliveryTaskViewSheetProps) {
|
||||
if (!task) return null
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(v) => !v && onClose()}>
|
||||
<DialogContent className="overflow-y-auto sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delivery Task Details</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<Row label="Store" value={task.storeName} />
|
||||
<Row label="Sequence" value={task.sequence} />
|
||||
<Row label="Status" value={<Badge variant={TASK_STATUS_VARIANT[task.status]}>{task.status}</Badge>} />
|
||||
<Row label="Customer Confirmed" value={task.customerConfirmed ? 'Yes' : 'No'} />
|
||||
<Row label="Confirmed At" value={fmtDateTime(task.confirmedAt)} />
|
||||
<Row label="Note" value={task.note ?? '—'} />
|
||||
<Row label="Created At" value={fmtDateTime(task.createdAt)} />
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Items ({task.items.length})</p>
|
||||
<div className="overflow-x-auto rounded-md border">
|
||||
<table className="w-full text-sm">
|
||||
<thead className="bg-muted/50">
|
||||
<tr>
|
||||
<th className="text-left font-medium px-3 py-2">Item</th>
|
||||
<th className="text-right font-medium px-3 py-2">Ordered</th>
|
||||
<th className="text-right font-medium px-3 py-2">Fulfilled</th>
|
||||
<th className="text-right font-medium px-3 py-2">Unit Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{task.items.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={4} className="text-center text-muted-foreground px-3 py-4">
|
||||
No items on this task.
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
task.items.map((item) => (
|
||||
<tr key={item.itemId} className="border-t">
|
||||
<td className="px-3 py-2">{item.itemName}</td>
|
||||
<td className="text-right px-3 py-2">{item.quantity}</td>
|
||||
<td className="text-right px-3 py-2">{item.quantityFulfilled}</td>
|
||||
<td className="text-right px-3 py-2">{item.unitPrice}</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user