Merge pull request 'fix' (#52) from refactor/main_flow into dev
Reviewed-on: #52
This commit was merged in pull request #52.
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
import { Fragment, Suspense, useEffect, useMemo, useRef, useState } from 'react'
|
import { Fragment, Suspense, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useRouter, useSearchParams } from 'next/navigation'
|
import { useRouter, useSearchParams } from 'next/navigation'
|
||||||
import { HugeiconsIcon } from '@hugeicons/react'
|
import { HugeiconsIcon } from '@hugeicons/react'
|
||||||
import { ArrowLeft01Icon, ViewIcon } from '@hugeicons/core-free-icons'
|
import { ArrowLeft01Icon, ViewIcon, PencilEdit01Icon } from '@hugeicons/core-free-icons'
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -405,6 +405,17 @@ function LoadingSheetForm() {
|
|||||||
return Array.from(map.values()).sort((a, b) => a.itemName.localeCompare(b.itemName))
|
return Array.from(map.values()).sort((a, b) => a.itemName.localeCompare(b.itemName))
|
||||||
}, [selectedRows, lines, manualItems, itemsList])
|
}, [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 stockOverview = useMemo(() => {
|
||||||
const map = new Map<string, { itemId: string; itemName: string; open: number }>()
|
const map = new Map<string, { itemId: string; itemName: string; open: number }>()
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
@@ -1038,11 +1049,130 @@ function LoadingSheetForm() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{step === 5 && (
|
{step === 5 && (
|
||||||
|
<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>
|
<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">
|
<div className="w-full rounded-2xl border p-6">
|
||||||
<h3 className="text-sm font-medium text-foreground">Loading Sheet Summary</h3>
|
<h3 className="text-sm font-medium text-foreground">Loading Sheet Summary</h3>
|
||||||
<p className="mt-1 text-sm text-muted-foreground">
|
<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>
|
</p>
|
||||||
|
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
|
|||||||
Reference in New Issue
Block a user