Fixes #21

Merged
DeepnaPooja merged 61 commits from fixes into dev 2026-09-10 16:00:04 +05:30
3 changed files with 124 additions and 1 deletions
Showing only changes of commit 35fe512bd1 - Show all commits
+1 -1
View File
@@ -6,7 +6,6 @@ Running log of backend API failures found during testing and the corresponding f
| # | Area | Backend API Failure | Frontend Change Needed | Date |
|---|------|----------------------|--------------------------|------|
| 2 | Operations → Loading Sheets | | Add a View icon to the action column in Operations → Loading Sheets table | 2026-09-01 |
| 3 | Sales (Create Sale) | Sale create not working | Update the Create Sale modal UI |Sale summary calculation not display | Add view icon to the action | 2026-09-01 |
| 4 | Orders | | Add a View icon to the action column in Orders table | 2026-09-01 |
| 5 | Payments (Record Payment) | Cannot add new payment | Add a View icon to the action column in Payments table | 2026-09-01 |
@@ -40,6 +39,7 @@ Running log of backend API failures found during testing and the corresponding f
|---|------|----------------------|--------------------------|----------|------|
| 1 | Operations → Rides (Create Ride) | Create Ride failed with "Vehicle not found" | — | Fixed DTO field naming mismatch | 2026-09-02 |
| 29 | Operations → Rides | Cancel-request API routes mismatched | Added View, Edit, and Cancel icons to Rides table | Fixed API routes + added action icons | 2026-09-02 |
| 2 | Operations → Loading Sheets | — | Missing View icon | Added View icon + details modal (status, dispatch/receipt confirmer + timestamps, item-level dispatched/received/resolved breakdown) | 2026-09-02 |
## Implementation Guide
@@ -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>
)
}
@@ -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}
/>
</>
)
}