From d7b455ab7d7611f01160683c8d3f8d3707c24b49 Mon Sep 17 00:00:00 2001 From: Hardik Date: Wed, 24 Jun 2026 05:04:29 +0530 Subject: [PATCH] =?UTF-8?q?refactor(routes):=20move=20/inventory/{items,ve?= =?UTF-8?q?ndors}=20=E2=86=92=20/catalogue/{items,vendors}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renames the product-catalogue pages (items + vendors, incl. their [id] detail pages) out of /inventory into /catalogue. /inventory/cart is unchanged. All internal links, redirects, revalidatePath calls, sidebar nav, and tests are updated; next.config redirects keep old /inventory/{items,vendors}[/...] URLs working (permanent) so existing bookmarks don't 404. Co-Authored-By: Claude Opus 4.8 (1M context) --- App/CLAUDE.md | 2 +- App/app/(portal)/admin/products/[id]/page.tsx | 2 +- .../admin/products/products-table.tsx | 2 +- App/app/(portal)/admin/vendors/actions.ts | 4 +-- App/app/(portal)/approvals/[id]/actions.ts | 4 +-- .../items/[id]/item-price-chart.tsx | 0 .../items/[id]/page.tsx | 4 +-- .../items/items-table.tsx | 4 +-- .../{inventory => catalogue}/items/page.tsx | 2 +- .../vendors/[id]/page.tsx | 2 +- .../vendors/[id]/vendor-items-table.tsx | 0 .../{inventory => catalogue}/vendors/page.tsx | 0 .../vendors/vendors-table.tsx | 4 +-- App/app/(portal)/inventory/cart/cart-view.tsx | 6 ++--- App/app/(portal)/po/[id]/receipt/actions.ts | 2 +- App/app/(portal)/po/import/actions.ts | 2 +- App/components/layout/sidebar.tsx | 8 +++--- App/lib/product-catalog.ts | 2 +- App/next.config.ts | 8 ++++++ App/tests/e2e/inventory/cart-icon.spec.ts | 18 ++++++------- App/tests/e2e/inventory/items-tags.spec.ts | 26 +++++++++---------- App/tests/unit/vendors-table.test.tsx | 2 +- 22 files changed, 56 insertions(+), 48 deletions(-) rename App/app/(portal)/{inventory => catalogue}/items/[id]/item-price-chart.tsx (100%) rename App/app/(portal)/{inventory => catalogue}/items/[id]/page.tsx (98%) rename App/app/(portal)/{inventory => catalogue}/items/items-table.tsx (98%) rename App/app/(portal)/{inventory => catalogue}/items/page.tsx (97%) rename App/app/(portal)/{inventory => catalogue}/vendors/[id]/page.tsx (98%) rename App/app/(portal)/{inventory => catalogue}/vendors/[id]/vendor-items-table.tsx (100%) rename App/app/(portal)/{inventory => catalogue}/vendors/page.tsx (100%) rename App/app/(portal)/{inventory => catalogue}/vendors/vendors-table.tsx (98%) diff --git a/App/CLAUDE.md b/App/CLAUDE.md index 008a3c6..49b28b8 100644 --- a/App/CLAUDE.md +++ b/App/CLAUDE.md @@ -134,7 +134,7 @@ Inventory (`ItemInventory`, keyed by `productId` + `siteId`) is **incremented at ### Product catalogue sync (`lib/product-catalog.ts`) -`syncProductCatalog(poId, lineItems, vendorId, actorId)` registers a PO's line items as reusable **`Product`s** (the `/inventory/items` catalogue): a line item with no `productId` is matched to an existing product by name (case-insensitive) or a new product is created, then the line item is linked back; `lastPrice`/`lastVendorId` and the per-vendor `ProductVendorPrice` are upserted. It runs **at approval** (`approvePo`) so an approved PO's items are immediately reusable in further POs, **and again at full payment** (`markPaid`) to refresh prices on the final figures. Idempotent — re-running matches the same product. (Import takes its own auto-create path.) +`syncProductCatalog(poId, lineItems, vendorId, actorId)` registers a PO's line items as reusable **`Product`s** (the `/catalogue/items` catalogue): a line item with no `productId` is matched to an existing product by name (case-insensitive) or a new product is created, then the line item is linked back; `lastPrice`/`lastVendorId` and the per-vendor `ProductVendorPrice` are upserted. It runs **at approval** (`approvePo`) so an approved PO's items are immediately reusable in further POs, **and again at full payment** (`markPaid`) to refresh prices on the final figures. Idempotent — re-running matches the same product. (Import takes its own auto-create path.) ### Import → Closed diff --git a/App/app/(portal)/admin/products/[id]/page.tsx b/App/app/(portal)/admin/products/[id]/page.tsx index 9ef538f..66ccfd9 100644 --- a/App/app/(portal)/admin/products/[id]/page.tsx +++ b/App/app/(portal)/admin/products/[id]/page.tsx @@ -7,7 +7,7 @@ import { formatCurrency, formatDate } from "@/lib/utils"; import { distanceKm, formatDistance } from "@/lib/geo"; import { ToggleProductButton, EditProductButton } from "../product-form"; import { AddToCartButton } from "@/components/inventory/add-to-cart-button"; -import { ItemPriceChart } from "@/app/(portal)/inventory/items/[id]/item-price-chart"; +import { ItemPriceChart } from "@/app/(portal)/catalogue/items/[id]/item-price-chart"; import { SiteSelect } from "@/components/inventory/site-select"; import type { Metadata } from "next"; diff --git a/App/app/(portal)/admin/products/products-table.tsx b/App/app/(portal)/admin/products/products-table.tsx index e6e1090..3fc13f7 100644 --- a/App/app/(portal)/admin/products/products-table.tsx +++ b/App/app/(portal)/admin/products/products-table.tsx @@ -67,7 +67,7 @@ function ProductActionsMenu({ product }: { product: ProductRow }) { export function ProductsTable({ products, canManage, - detailBase = "/inventory/items", + detailBase = "/catalogue/items", }: { products: ProductRow[]; canManage: boolean; diff --git a/App/app/(portal)/admin/vendors/actions.ts b/App/app/(portal)/admin/vendors/actions.ts index 59da9fa..dd45b5a 100644 --- a/App/app/(portal)/admin/vendors/actions.ts +++ b/App/app/(portal)/admin/vendors/actions.ts @@ -95,7 +95,7 @@ export async function createVendor(formData: FormData): Promise { }); revalidatePath("/admin/vendors"); - revalidatePath("/inventory/vendors"); + revalidatePath("/catalogue/vendors"); return { ok: true }; } @@ -108,7 +108,7 @@ export async function verifyVendor(vendorId: string): Promise { await db.vendor.update({ where: { id: vendorId }, data: { isVerified: true } }); revalidatePath("/admin/vendors"); - revalidatePath("/inventory/vendors"); + revalidatePath("/catalogue/vendors"); revalidatePath(`/admin/vendors/${vendorId}`); return { ok: true }; } diff --git a/App/app/(portal)/approvals/[id]/actions.ts b/App/app/(portal)/approvals/[id]/actions.ts index 0d9d288..3470cca 100644 --- a/App/app/(portal)/approvals/[id]/actions.ts +++ b/App/app/(portal)/approvals/[id]/actions.ts @@ -85,11 +85,11 @@ export async function approvePo({ revalidatePath(`/admin/sites/${siteId}`); } - // Register the line items in the product catalogue (/inventory/items) on + // Register the line items in the product catalogue (/catalogue/items) on // approval, so an approved PO's items are immediately reusable in further POs. // Idempotent; payment re-syncs to refresh prices on the final figures. await syncProductCatalog(poId, po.lineItems, po.vendorId, session.user.id); - revalidatePath("/inventory/items"); + revalidatePath("/catalogue/items"); const accounts = await db.user.findMany({ where: { role: "ACCOUNTS", isActive: true } }); await notify({ diff --git a/App/app/(portal)/inventory/items/[id]/item-price-chart.tsx b/App/app/(portal)/catalogue/items/[id]/item-price-chart.tsx similarity index 100% rename from App/app/(portal)/inventory/items/[id]/item-price-chart.tsx rename to App/app/(portal)/catalogue/items/[id]/item-price-chart.tsx diff --git a/App/app/(portal)/inventory/items/[id]/page.tsx b/App/app/(portal)/catalogue/items/[id]/page.tsx similarity index 98% rename from App/app/(portal)/inventory/items/[id]/page.tsx rename to App/app/(portal)/catalogue/items/[id]/page.tsx index 2bff472..f910bab 100644 --- a/App/app/(portal)/inventory/items/[id]/page.tsx +++ b/App/app/(portal)/catalogue/items/[id]/page.tsx @@ -26,7 +26,7 @@ export default async function ItemDetailPage({ params, searchParams }: Props) { const { id } = await params; const { site: siteId } = await searchParams; - const baseHref = `/inventory/items/${id}`; + const baseHref = `/catalogue/items/${id}`; const [product, sites] = await Promise.all([ db.product.findUnique({ @@ -85,7 +85,7 @@ export default async function ItemDetailPage({ params, searchParams }: Props) {
{/* Breadcrumb */}
- Items + Items / {product.name}
diff --git a/App/app/(portal)/inventory/items/items-table.tsx b/App/app/(portal)/catalogue/items/items-table.tsx similarity index 98% rename from App/app/(portal)/inventory/items/items-table.tsx rename to App/app/(portal)/catalogue/items/items-table.tsx index 7c8a670..655a978 100644 --- a/App/app/(portal)/inventory/items/items-table.tsx +++ b/App/app/(portal)/catalogue/items/items-table.tsx @@ -108,7 +108,7 @@ export function ItemsTable({ value={currentSiteId ?? ""} onChange={(e) => { const id = e.target.value; - router.push(id ? `/inventory/items?siteId=${id}` : "/inventory/items"); + router.push(id ? `/catalogue/items?siteId=${id}` : "/catalogue/items"); }} className="flex-1 max-w-xs rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-1.5 text-sm text-neutral-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" > @@ -254,7 +254,7 @@ export function ItemsTable({
e.stopPropagation()} className="font-medium text-neutral-800 hover:text-primary-600 hover:underline" > diff --git a/App/app/(portal)/inventory/items/page.tsx b/App/app/(portal)/catalogue/items/page.tsx similarity index 97% rename from App/app/(portal)/inventory/items/page.tsx rename to App/app/(portal)/catalogue/items/page.tsx index 99dd7be..df2b9cd 100644 --- a/App/app/(portal)/inventory/items/page.tsx +++ b/App/app/(portal)/catalogue/items/page.tsx @@ -20,7 +20,7 @@ export default async function InventoryItemsPage() { }, }); - // canManage lets managers/admins see the Edit/Delete controls even from /inventory/items + // canManage lets managers/admins see the Edit/Delete controls even from /catalogue/items const canManage = hasPermission(session.user.role, "manage_products"); return ( diff --git a/App/app/(portal)/inventory/vendors/[id]/page.tsx b/App/app/(portal)/catalogue/vendors/[id]/page.tsx similarity index 98% rename from App/app/(portal)/inventory/vendors/[id]/page.tsx rename to App/app/(portal)/catalogue/vendors/[id]/page.tsx index 184c08c..24e5ee2 100644 --- a/App/app/(portal)/inventory/vendors/[id]/page.tsx +++ b/App/app/(portal)/catalogue/vendors/[id]/page.tsx @@ -48,7 +48,7 @@ export default async function InventoryVendorDetailPage({ params }: Props) {
{/* Breadcrumb */}
- Vendors + Vendors / {vendor.name}
diff --git a/App/app/(portal)/inventory/vendors/[id]/vendor-items-table.tsx b/App/app/(portal)/catalogue/vendors/[id]/vendor-items-table.tsx similarity index 100% rename from App/app/(portal)/inventory/vendors/[id]/vendor-items-table.tsx rename to App/app/(portal)/catalogue/vendors/[id]/vendor-items-table.tsx diff --git a/App/app/(portal)/inventory/vendors/page.tsx b/App/app/(portal)/catalogue/vendors/page.tsx similarity index 100% rename from App/app/(portal)/inventory/vendors/page.tsx rename to App/app/(portal)/catalogue/vendors/page.tsx diff --git a/App/app/(portal)/inventory/vendors/vendors-table.tsx b/App/app/(portal)/catalogue/vendors/vendors-table.tsx similarity index 98% rename from App/app/(portal)/inventory/vendors/vendors-table.tsx rename to App/app/(portal)/catalogue/vendors/vendors-table.tsx index 01d9226..0759c69 100644 --- a/App/app/(portal)/inventory/vendors/vendors-table.tsx +++ b/App/app/(portal)/catalogue/vendors/vendors-table.tsx @@ -68,7 +68,7 @@ export function VendorsTable({ value={currentSiteId ?? ""} onChange={(e) => { const id = e.target.value; - router.push(id ? `/inventory/vendors?siteId=${id}` : "/inventory/vendors"); + router.push(id ? `/catalogue/vendors?siteId=${id}` : "/catalogue/vendors"); }} className="flex-1 max-w-xs rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-1.5 text-sm text-neutral-700 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20" > @@ -149,7 +149,7 @@ export function VendorsTable({
- + {vendor.name} {vendor.vendorId && ( diff --git a/App/app/(portal)/inventory/cart/cart-view.tsx b/App/app/(portal)/inventory/cart/cart-view.tsx index aa8cfef..cd94ca2 100644 --- a/App/app/(portal)/inventory/cart/cart-view.tsx +++ b/App/app/(portal)/inventory/cart/cart-view.tsx @@ -46,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
); @@ -108,7 +108,7 @@ export function CartView() {
- + + Add more items