fix #52
@@ -3,7 +3,7 @@
|
||||
import { Fragment, Suspense, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { HugeiconsIcon } from '@hugeicons/react'
|
||||
import { ArrowLeft01Icon, ViewIcon } from '@hugeicons/core-free-icons'
|
||||
import { ArrowLeft01Icon, ViewIcon, PencilEdit01Icon } from '@hugeicons/core-free-icons'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -405,6 +405,17 @@ function LoadingSheetForm() {
|
||||
return Array.from(map.values()).sort((a, b) => a.itemName.localeCompare(b.itemName))
|
||||
}, [selectedRows, lines, manualItems, itemsList])
|
||||
|
||||
const reviewShopGroups = useMemo(() => {
|
||||
const map = new Map<string, { storeId: string; storeName: string; rows: { row: PickedLine; line: PickedLine }[] }>()
|
||||
for (const row of selectedRows) {
|
||||
const line = lines[row.shopPOItemId]
|
||||
const g = map.get(row.storeId) ?? { storeId: row.storeId, storeName: row.storeName, rows: [] }
|
||||
g.rows.push({ row, line })
|
||||
map.set(row.storeId, g)
|
||||
}
|
||||
return Array.from(map.values()).sort((a, b) => a.storeName.localeCompare(b.storeName))
|
||||
}, [selectedRows, lines])
|
||||
|
||||
const stockOverview = useMemo(() => {
|
||||
const map = new Map<string, { itemId: string; itemName: string; open: number }>()
|
||||
for (const row of rows) {
|
||||
@@ -1038,11 +1049,130 @@ function LoadingSheetForm() {
|
||||
)}
|
||||
|
||||
{step === 5 && (
|
||||
<div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="rounded-2xl border p-6">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium text-foreground">Route & Warehouse</h3>
|
||||
<Button type="button" variant="ghost" size="icon" aria-label="Edit route & warehouse" onClick={() => setStep(1)}>
|
||||
<HugeiconsIcon icon={PencilEdit01Icon} size={16} strokeWidth={2} />
|
||||
</Button>
|
||||
</div>
|
||||
<dl className="grid gap-3 text-sm sm:grid-cols-2 lg:grid-cols-4">
|
||||
<div>
|
||||
<dt className="text-xs text-muted-foreground">Region</dt>
|
||||
<dd className="font-medium text-foreground">{regionsList.find((r) => r.id === regionId)?.name ?? 'All regions'}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs text-muted-foreground">Route</dt>
|
||||
<dd className="font-medium text-foreground">{routesList.find((r) => r.id === routeId)?.routeName ?? '—'}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs text-muted-foreground">Shop filter</dt>
|
||||
<dd className="font-medium text-foreground">{storesList.find((s) => s.id === storeId)?.storeName ?? 'All shops'}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs text-muted-foreground">Warehouse</dt>
|
||||
<dd className="font-medium text-foreground">{warehousesList.find((w) => w.id === warehouseId)?.name ?? '—'}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border p-6">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium text-foreground">Ride & Assignment</h3>
|
||||
<Button type="button" variant="ghost" size="icon" aria-label="Edit ride & assignment" onClick={() => setStep(2)}>
|
||||
<HugeiconsIcon icon={PencilEdit01Icon} size={16} strokeWidth={2} />
|
||||
</Button>
|
||||
</div>
|
||||
<dl className="grid gap-3 text-sm sm:grid-cols-2">
|
||||
<div>
|
||||
<dt className="text-xs text-muted-foreground">Ride (vehicle)</dt>
|
||||
<dd className="font-medium text-foreground">
|
||||
{(() => {
|
||||
const r = ridesList.find((r) => r.id === rideId)
|
||||
return r ? `${r.vehicleNumberPlate} — ${r.driverFullName}` : '—'
|
||||
})()}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-xs text-muted-foreground">Populated by</dt>
|
||||
<dd className="font-medium text-foreground">{usersList.find((u) => u.id === populatedByUserId)?.fullName ?? '—'}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border p-6">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium text-foreground">Items from Shop POs</h3>
|
||||
<Button type="button" variant="ghost" size="icon" aria-label="Edit items from Shop POs" onClick={() => setStep(3)}>
|
||||
<HugeiconsIcon icon={PencilEdit01Icon} size={16} strokeWidth={2} />
|
||||
</Button>
|
||||
</div>
|
||||
{reviewShopGroups.length === 0 ? (
|
||||
<p className="rounded-xl border px-3 py-4 text-center text-sm text-muted-foreground">No Shop PO items selected.</p>
|
||||
) : (
|
||||
<div className="flex flex-col gap-3">
|
||||
{reviewShopGroups.map((group) => (
|
||||
<div key={group.storeId} className="overflow-hidden rounded-xl border">
|
||||
<div className="bg-muted/50 px-3 py-2 text-sm font-medium">{group.storeName}</div>
|
||||
<table className="w-full text-sm">
|
||||
<tbody>
|
||||
{group.rows.map(({ row, line }) => (
|
||||
<Fragment key={row.shopPOItemId}>
|
||||
<tr className="border-t">
|
||||
<td className="px-3 py-2">{row.itemName}</td>
|
||||
<td className="px-3 py-2 text-right text-muted-foreground">
|
||||
{warehousesList.find((w) => w.id === warehouseId)?.name}
|
||||
</td>
|
||||
<td className="w-24 px-3 py-2 text-right font-semibold">{line.quantity}</td>
|
||||
</tr>
|
||||
{line.extras.filter((e) => e.warehouseId && e.quantity > 0).map((extra, idx) => (
|
||||
<tr key={idx} className="border-t bg-muted/20">
|
||||
<td className="px-3 py-2 text-xs text-muted-foreground">— top-up</td>
|
||||
<td className="px-3 py-2 text-right text-muted-foreground">
|
||||
{warehousesList.find((w) => w.id === extra.warehouseId)?.name}
|
||||
</td>
|
||||
<td className="w-24 px-3 py-2 text-right font-semibold">{extra.quantity}</td>
|
||||
</tr>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border p-6">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium text-foreground">Additional Items</h3>
|
||||
<Button type="button" variant="ghost" size="icon" aria-label="Edit additional items" onClick={() => setStep(4)}>
|
||||
<HugeiconsIcon icon={PencilEdit01Icon} size={16} strokeWidth={2} />
|
||||
</Button>
|
||||
</div>
|
||||
{manualItems.length === 0 ? (
|
||||
<p className="rounded-xl border px-3 py-4 text-center text-sm text-muted-foreground">No additional items.</p>
|
||||
) : (
|
||||
<table className="w-full text-sm">
|
||||
<tbody>
|
||||
{manualItems.map((m) => (
|
||||
<tr key={m.key} className="border-t first:border-t-0">
|
||||
<td className="px-3 py-2">{itemsList.find((i) => i.id === m.itemId)?.name ?? '—'}</td>
|
||||
<td className="px-3 py-2 text-right text-muted-foreground">{warehousesList.find((w) => w.id === m.warehouseId)?.name ?? '—'}</td>
|
||||
<td className="w-24 px-3 py-2 text-right font-semibold">{m.quantity}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-full rounded-2xl border p-6">
|
||||
<h3 className="text-sm font-medium text-foreground">Loading Sheet Summary</h3>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
{selectedRows.length} item{selectedRows.length === 1 ? '' : 's'} selected.
|
||||
{selectedRows.length} item{selectedRows.length === 1 ? '' : 's'} from Shop POs, {manualItems.length} additional item{manualItems.length === 1 ? '' : 's'}.
|
||||
</p>
|
||||
|
||||
<Separator className="my-4" />
|
||||
|
||||
Reference in New Issue
Block a user