From da0a65cf26cc9dbc8f73dad1ff0b40d8fa0e79f8 Mon Sep 17 00:00:00 2001 From: Andymick Date: Tue, 21 Jul 2026 17:54:57 +0100 Subject: [PATCH] Feat: Display hierarchical categories in shop filters Updated shop pages (/made-to-order and /products) to show categories hierarchically in the filter sidebar. Now displays both parent and child categories with visual hierarchy (e.g., "Apparel > Adults"). Changes: - Query only parent categories (parentId = null) with children included - Build flat category list showing hierarchy with > separator - Filter logic remains unchanged - still filters by category slug - Child categories only show if parent has showOnPersonalised/showOnProducts enabled User experience: - See all available category options - Visual indication of subcategories (Apparel > Adults, Apparel > Kids, etc.) - Click to filter by any level Co-Authored-By: Claude Haiku 4.5 --- src/app/made-to-order/page.tsx | 10 ++++++++-- src/app/products/page.tsx | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/app/made-to-order/page.tsx b/src/app/made-to-order/page.tsx index c395bea..195deb3 100644 --- a/src/app/made-to-order/page.tsx +++ b/src/app/made-to-order/page.tsx @@ -20,10 +20,16 @@ function toArray(v?: string | string[]) { export default async function ProductsPage({ searchParams }: { searchParams: SearchParams }) { const categoryRows = await prisma.category.findMany({ - where: { showOnPersonalised: true }, + where: { showOnPersonalised: true, parentId: null }, orderBy: { name: 'asc' }, + include: { children: { where: { showOnPersonalised: true }, orderBy: { name: 'asc' } } }, }); - const CATEGORIES = categoryRows.map((c) => ({ value: c.slug, label: c.name })); + // Build flat list of all categories (parents and children) for filtering + const allCategories = categoryRows.flatMap((parent) => [ + { value: parent.slug, label: parent.name }, + ...parent.children.map((child) => ({ value: child.slug, label: `${parent.name} > ${child.name}` })), + ]); + const CATEGORIES = allCategories; const collectionRows = await prisma.collection.findMany({ orderBy: { name: 'asc' } }); const OCCASIONS = collectionRows.filter((c) => c.group === 'OCCASION').map((c) => ({ value: c.slug, label: c.name })); diff --git a/src/app/products/page.tsx b/src/app/products/page.tsx index 4802676..79bf433 100644 --- a/src/app/products/page.tsx +++ b/src/app/products/page.tsx @@ -20,10 +20,16 @@ function toArray(v?: string | string[]) { export default async function ReadyMadeProductsPage({ searchParams }: { searchParams: SearchParams }) { const categoryRows = await prisma.category.findMany({ - where: { showOnProducts: true }, + where: { showOnProducts: true, parentId: null }, orderBy: { name: 'asc' }, + include: { children: { where: { showOnProducts: true }, orderBy: { name: 'asc' } } }, }); - const CATEGORIES = categoryRows.map((c) => ({ value: c.slug, label: c.name })); + // Build flat list of all categories (parents and children) for filtering + const allCategories = categoryRows.flatMap((parent) => [ + { value: parent.slug, label: parent.name }, + ...parent.children.map((child) => ({ value: child.slug, label: `${parent.name} > ${child.name}` })), + ]); + const CATEGORIES = allCategories; const collectionRows = await prisma.collection.findMany({ orderBy: { name: 'asc' } }); const OCCASIONS = collectionRows.filter((c) => c.group === 'OCCASION').map((c) => ({ value: c.slug, label: c.name }));