From 9707ef596c8308efbd9f197bc44bf285d5782124 Mon Sep 17 00:00:00 2001 From: DeepnaPooja Date: Fri, 2 Oct 2026 13:17:32 +0530 Subject: [PATCH] UI changes --- .../app/(dashboard)/configuration/page.tsx | 54 +++++++++++++++++++ .../operations/loading/new/page.tsx | 33 +++++++++--- .../components/layout/app-sidebar.tsx | 20 ++++++- 3 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 distribution_fe/app/(dashboard)/configuration/page.tsx diff --git a/distribution_fe/app/(dashboard)/configuration/page.tsx b/distribution_fe/app/(dashboard)/configuration/page.tsx new file mode 100644 index 0000000..e515190 --- /dev/null +++ b/distribution_fe/app/(dashboard)/configuration/page.tsx @@ -0,0 +1,54 @@ +'use client' + +import Link from 'next/link' +import { HugeiconsIcon } from '@hugeicons/react' +import { Package01Icon, ArrowRight01Icon } from '@hugeicons/core-free-icons' +import { Card, CardHeader, CardTitle, CardDescription, CardAction } from '@/components/ui/card' + +interface ConfigCategory { + title: string + description: string + href: string + icon: typeof Package01Icon +} + +const CATEGORIES: ConfigCategory[] = [ + { + title: 'Products', + description: 'Serial number, batch, expiry and warranty tracking for catalogue items', + href: '/configuration/products', + icon: Package01Icon, + }, +] + +export default function configurationPage() { + return ( +
+
+

Configuration

+

System-wide settings, grouped by area

+
+ +
+ {CATEGORIES.map((category) => ( + + + +
+
+ +
+ {category.title} +
+ {category.description} + + + +
+
+ + ))} +
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/operations/loading/new/page.tsx b/distribution_fe/app/(dashboard)/operations/loading/new/page.tsx index 64fb407..07fe7db 100644 --- a/distribution_fe/app/(dashboard)/operations/loading/new/page.tsx +++ b/distribution_fe/app/(dashboard)/operations/loading/new/page.tsx @@ -71,7 +71,7 @@ const STEPS = [ n: 3, label: 'Items', title: 'What should be loaded from Shop POs?', - help: "Expand a shop to tick items and set quantities. If the main warehouse doesn't have enough stock, use \"Take remaining from another warehouse\" to top up the rest.", + help: "Expand a shop to tick items and set quantities. If the main warehouse can't cover an item, a top-up row is added automatically — just pick which other warehouse to take the rest from.", }, { n: 4, @@ -321,10 +321,16 @@ function LoadingSheetForm() { let changed = false const next: Record = {} for (const [key, l] of Object.entries(prev)) { - const extras = l.extras.filter((e) => e.warehouseId !== warehouseId) + let extras = l.extras.filter((e) => e.warehouseId !== warehouseId) const avail = stockByWh[warehouseId]?.[l.itemId] ?? 0 const quantity = Math.min(l.quantity, avail) const checked = l.checked && (quantity > 0 || extras.length > 0) + // Pre-add an empty top-up row if the new main warehouse leaves this line short + // and one isn't already pending, mirroring toggleLine's auto-suggestion. + const shortBy = l.remainingQty - quantity - extras.reduce((sum, e) => sum + (Number(e.quantity) || 0), 0) + if (checked && shortBy > 0 && !extras.some((e) => !e.warehouseId)) { + extras = [...extras, { warehouseId: '', quantity: 0 }] + } if (extras.length !== l.extras.length || quantity !== l.quantity || checked !== l.checked) changed = true next[key] = { ...l, extras, quantity, checked } } @@ -452,7 +458,12 @@ function LoadingSheetForm() { const avail = availIn(warehouseId, line.itemId) if (!stockLoaded || avail <= 0) return const quantity = Math.max(0, Math.min(line.remainingQty - extrasTotal(line), avail)) - setLines((prev) => ({ ...prev, [line.shopPOItemId]: { ...line, checked, quantity } })) + // The main warehouse can't cover the full remaining quantity, so a top-up row is + // pre-added (still editable/removable) instead of making the user click "Take + // remaining from another warehouse" themselves. + const shortBy = line.remainingQty - quantity - extrasTotal(line) + const extras = shortBy > 0 ? [...line.extras, { warehouseId: '', quantity: 0 }] : line.extras + setLines((prev) => ({ ...prev, [line.shopPOItemId]: { ...line, checked, quantity, extras } })) return } setLines((prev) => ({ ...prev, [line.shopPOItemId]: { ...line, checked } })) @@ -912,10 +923,18 @@ function LoadingSheetForm() { - {shortBy} will stay open on the PO for another sheet - + {line.extras.some((e) => !e.warehouseId) ? ( + + {shortBy} short — pick a warehouse above to top it up, or it stays open on the PO for another sheet. + + ) : ( + <> + {shortBy} will stay open on the PO for another sheet + + + )} )} diff --git a/distribution_fe/components/layout/app-sidebar.tsx b/distribution_fe/components/layout/app-sidebar.tsx index 22883c0..d3786e3 100644 --- a/distribution_fe/components/layout/app-sidebar.tsx +++ b/distribution_fe/components/layout/app-sidebar.tsx @@ -38,7 +38,7 @@ import { TooltipTrigger, } from '@/components/ui/tooltip' import { useAuth, type Role } from '@/contexts/auth-context' -import { DASHBOARD_ITEM, NAV_GROUPS, type NavGroup, type NavItem } from '@/config/nav' +import { DASHBOARD_ITEM, CONFIGURATION_ITEM, NAV_GROUPS, type NavGroup, type NavItem } from '@/config/nav' function canSee(item: NavItem, permissions: string[]): boolean { if (!item.permission) return true @@ -54,6 +54,8 @@ export function AppSidebar() { const pathname = usePathname() const dashboardActive = pathname === DASHBOARD_ITEM.href + const configurationActive = + pathname === CONFIGURATION_ITEM.href || pathname.startsWith(CONFIGURATION_ITEM.href + '/') const [openGroups, setOpenGroups] = useState>({}) useEffect(() => { @@ -182,6 +184,22 @@ export function AppSidebar() { ) })} + + {/* Configuration — standalone, no sub-nav */} + + + + } + isActive={configurationActive} + tooltip={CONFIGURATION_ITEM.title} + > + + {CONFIGURATION_ITEM.title} + + + +