From 2fcf35235a557ead17f98f8bd433f403d8cf8215 Mon Sep 17 00:00:00 2001 From: Hardik Date: Fri, 15 May 2026 23:56:38 +0530 Subject: [PATCH] feat(cart): header cart icon with badge + fix PO pre-population from cart Cart icon: - CartIcon component in header: listens to cart-updated events, shows item count badge, navigates to /inventory/cart on click - Visible for TECHNICAL, MANNING, SUPERUSER, MANAGER roles only PO pre-population: - /po/new page reads ?cart= searchParam, parses CartItem[] into LineItemInput[], passes as initialLineItems prop to NewPoForm - NewPoForm accepts initialLineItems and seeds useState from them instead of always starting with one blank row - Cart is cleared immediately when "Create Purchase Order" is clicked so re-visiting cart doesn't re-submit the same items Cart fixes: - Empty state and "Add more items" links corrected from /admin/products to /inventory/items and /inventory/vendors Co-Authored-By: Claude Sonnet 4.6 --- .../app/(portal)/inventory/cart/cart-view.tsx | 9 ++--- .../app/(portal)/po/new/new-po-form.tsx | 11 ++++--- .../app/(portal)/po/new/page.tsx | 33 +++++++++++++++++-- .../components/layout/cart-icon.tsx | 33 +++++++++++++++++++ .../components/layout/header.tsx | 8 +++-- 5 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 App/pelagia-portal/components/layout/cart-icon.tsx diff --git a/App/pelagia-portal/app/(portal)/inventory/cart/cart-view.tsx b/App/pelagia-portal/app/(portal)/inventory/cart/cart-view.tsx index 43f6c36..aa8cfef 100644 --- a/App/pelagia-portal/app/(portal)/inventory/cart/cart-view.tsx +++ b/App/pelagia-portal/app/(portal)/inventory/cart/cart-view.tsx @@ -31,8 +31,9 @@ export function CartView() { } function createPO() { - // Encode cart into query params and navigate to new PO with prefill const encoded = encodeURIComponent(JSON.stringify(items)); + clearCart(); + setItems([]); router.push(`/po/new?cart=${encoded}`); } @@ -45,8 +46,8 @@ export function CartView() {

Your cart is empty

Browse Items or Vendors to add line items

- Browse Items - Browse Vendors + Browse Items + Browse Vendors
); @@ -107,7 +108,7 @@ export function CartView() {
- + + Add more items
- +
); } diff --git a/App/pelagia-portal/components/layout/cart-icon.tsx b/App/pelagia-portal/components/layout/cart-icon.tsx new file mode 100644 index 0000000..18fd948 --- /dev/null +++ b/App/pelagia-portal/components/layout/cart-icon.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { useRouter } from "next/navigation"; +import { ShoppingCart } from "lucide-react"; +import { getCart } from "@/lib/cart"; + +export function CartIcon() { + const router = useRouter(); + const [count, setCount] = useState(0); + + useEffect(() => { + const update = () => setCount(getCart().reduce((s, i) => s + i.quantity, 0)); + update(); + window.addEventListener("cart-updated", update); + return () => window.removeEventListener("cart-updated", update); + }, []); + + return ( + + ); +} diff --git a/App/pelagia-portal/components/layout/header.tsx b/App/pelagia-portal/components/layout/header.tsx index c8a5497..a40691c 100644 --- a/App/pelagia-portal/components/layout/header.tsx +++ b/App/pelagia-portal/components/layout/header.tsx @@ -3,6 +3,7 @@ import { signOut } from "next-auth/react"; import { LogOut } from "lucide-react"; import type { Role } from "@prisma/client"; +import { CartIcon } from "./cart-icon"; const ROLE_LABELS: Record = { TECHNICAL: "Technical", @@ -14,6 +15,8 @@ const ROLE_LABELS: Record = { ADMIN: "Admin", }; +const CART_ROLES: Role[] = ["TECHNICAL", "MANNING", "SUPERUSER", "MANAGER"]; + interface HeaderProps { user: { name: string; email: string; role: Role }; } @@ -22,8 +25,9 @@ export function Header({ user }: HeaderProps) { return (
-
-
+
+ {CART_ROLES.includes(user.role) && } +

{user.name}

{ROLE_LABELS[user.role]}