Add loading sheet view fix
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
'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 { LoadingSheetResponse, LoadingSheetStatus } from '@/types/api'
|
||||
|
||||
const LS_STATUS_VARIANT: Record<LoadingSheetStatus, 'default' | 'secondary' | 'destructive'> = {
|
||||
Pending: 'secondary',
|
||||
DispatchConfirmed: 'default',
|
||||
ReceiptConfirmed: 'default',
|
||||
DiscrepancyFlagged: 'destructive',
|
||||
Resolved: 'secondary',
|
||||
}
|
||||
|
||||
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 LoadingSheetViewSheetProps {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
sheet: LoadingSheetResponse | 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 LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetViewSheetProps) {
|
||||
if (!sheet) return null
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(v) => !v && onClose()}>
|
||||
<DialogContent className="overflow-y-auto sm:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Loading Sheet Details</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<Row label="Sheet ID" value={<span className="font-mono">{sheet.id.substring(0, 8)}</span>} />
|
||||
<Row label="Warehouse" value={sheet.warehouseName} />
|
||||
<Row label="Status" value={<Badge variant={LS_STATUS_VARIANT[sheet.status]}>{sheet.status}</Badge>} />
|
||||
<Row label="Dispatch Confirmed By" value={sheet.dispatchConfirmedBy ?? '—'} />
|
||||
<Row label="Dispatch Confirmed At" value={fmtDateTime(sheet.dispatchConfirmedAt)} />
|
||||
<Row label="Receipt Confirmed By" value={sheet.receiptConfirmedBy ?? '—'} />
|
||||
<Row label="Receipt Confirmed At" value={fmtDateTime(sheet.receiptConfirmedAt)} />
|
||||
<Row label="Created At" value={fmtDateTime(sheet.createdAt)} />
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
||||
<div>
|
||||
<p className="text-sm font-medium mb-2">Items ({sheet.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">Dispatched</th>
|
||||
<th className="text-right font-medium px-3 py-2">Received</th>
|
||||
<th className="text-right font-medium px-3 py-2">Resolved</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sheet.items.length === 0 ? (
|
||||
<tr>
|
||||
<td colSpan={4} className="text-center text-muted-foreground px-3 py-4">
|
||||
No items on this sheet.
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
sheet.items.map((item) => (
|
||||
<tr key={item.id} className="border-t">
|
||||
<td className="px-3 py-2">{item.itemName}</td>
|
||||
<td className="text-right px-3 py-2">{item.quantityDispatched}</td>
|
||||
<td className="text-right px-3 py-2">{item.quantityReceived}</td>
|
||||
<td className="text-right px-3 py-2">{item.quantityResolved}</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
+21
@@ -8,6 +8,8 @@ import { toast } from '@/components/ui/toast'
|
||||
import { loadingSheets as loadingSheetsApi, getApiError, getPaginatedItems } from '@/lib/api/index'
|
||||
import type { LoadingSheetResponse, LoadingSheetStatus } from '@/types/api'
|
||||
|
||||
import { LoadingSheetViewSheet } from './loading-sheet-view-sheet'
|
||||
|
||||
const fmtDate = (v: string) =>
|
||||
new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })
|
||||
|
||||
@@ -28,6 +30,9 @@ export function LoadingSheetsClient() {
|
||||
const [page, setPage] = useState(1)
|
||||
const [pageSize, setPageSize] = useState(20)
|
||||
|
||||
const [viewOpen, setViewOpen] = useState(false)
|
||||
const [selectedSheet, setSelectedSheet] = useState<LoadingSheetResponse | null>(null)
|
||||
|
||||
const fetchData = useCallback(async (p: number, ps: number) => {
|
||||
setLoading(true)
|
||||
try {
|
||||
@@ -45,6 +50,11 @@ export function LoadingSheetsClient() {
|
||||
fetchData(page, pageSize)
|
||||
}, [fetchData, page, pageSize])
|
||||
|
||||
function handleView(row: LoadingSheetResponse) {
|
||||
setSelectedSheet(row)
|
||||
setViewOpen(true)
|
||||
}
|
||||
|
||||
async function handleConfirmDispatch(row: LoadingSheetResponse) {
|
||||
try {
|
||||
await loadingSheetsApi.confirmDispatch(row.id)
|
||||
@@ -114,6 +124,11 @@ export function LoadingSheetsClient() {
|
||||
],
|
||||
rowActions: {
|
||||
actions: () => [
|
||||
{
|
||||
action: 'view',
|
||||
label: 'View sheet',
|
||||
onClick: handleView,
|
||||
},
|
||||
{
|
||||
action: 'confirm',
|
||||
label: 'Confirm dispatch',
|
||||
@@ -151,6 +166,12 @@ export function LoadingSheetsClient() {
|
||||
setPageSize(p.pageSize)
|
||||
}}
|
||||
/>
|
||||
|
||||
<LoadingSheetViewSheet
|
||||
open={viewOpen}
|
||||
onClose={() => setViewOpen(false)}
|
||||
sheet={selectedSheet}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user