Feat: Add hierarchical category support for menu organization
Added parent-child relationship to categories, allowing organization
of categories into submenus (e.g., Apparel > Adults, Kids, Babies).
Changes:
- Add parentId field to Category model
- Create foreign key relationship for category hierarchy
- Update homepage to query only top-level categories (parentId = null)
- Include children categories for future use in category menus
Database migration:
- Adds parentId column to Category table
- Sets up CASCADE delete to remove children when parent is deleted
This enables menu structure like:
Apparel
- Adults
- Kids
- Babies
Drinkware
Phone Cases
etc.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
86df5a6cf0
commit
23631b1bce
@@ -135,7 +135,14 @@
|
|||||||
"Bash(GIT_TRACE=1 git push origin main --force)",
|
"Bash(GIT_TRACE=1 git push origin main --force)",
|
||||||
"Bash(pkill -f \"node.exe\")",
|
"Bash(pkill -f \"node.exe\")",
|
||||||
"PowerShell(Stop-Process -Name node -Force -ErrorAction SilentlyContinue)",
|
"PowerShell(Stop-Process -Name node -Force -ErrorAction SilentlyContinue)",
|
||||||
"Bash(find \"D:\\\\Craft2Prints\\\\src\\\\app\" -path \"*/\\\\[slug\\\\]/*\" -name \"page.tsx\" | head -10)"
|
"Bash(find \"D:\\\\Craft2Prints\\\\src\\\\app\" -path \"*/\\\\[slug\\\\]/*\" -name \"page.tsx\" | head -10)",
|
||||||
|
"Read(//c/Users/Lyons/OneDrive/Desktop/Products/AWD T Shirts/**)",
|
||||||
|
"Read(//c/Users/Lyons/OneDrive/Desktop/Products/**)",
|
||||||
|
"Bash(mv AT001B_* \"Polo T Shirts/\")",
|
||||||
|
"Bash(mv AT001M_* \"Polo T Shirts/\")",
|
||||||
|
"Bash(mv AT002B_* \"Striped collar/\")",
|
||||||
|
"Bash(mv AT002M_* \"Striped collar/\")",
|
||||||
|
"Bash(cd \"/c/Users/Lyons/OneDrive/Desktop/Products/AWD T Shirts\" *)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Category" ADD COLUMN "parentId" TEXT;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Category" ADD CONSTRAINT "Category_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Category"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@@ -10,10 +10,14 @@ datasource db {
|
|||||||
// Categories are their own table so you can add/rename/remove them from the admin
|
// Categories are their own table so you can add/rename/remove them from the admin
|
||||||
// panel. Product.category stays a plain string (matching Category.slug) rather
|
// panel. Product.category stays a plain string (matching Category.slug) rather
|
||||||
// than a foreign key, so nothing breaks if a category is renamed after the fact.
|
// than a foreign key, so nothing breaks if a category is renamed after the fact.
|
||||||
|
// Categories can be hierarchical: parentId links to a parent category.
|
||||||
model Category {
|
model Category {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String // display label, e.g. "Phone Cases"
|
name String // display label, e.g. "Phone Cases"
|
||||||
slug String @unique // stored key, e.g. "PHONE_CASE" — matches Product.category
|
slug String @unique // stored key, e.g. "PHONE_CASE" — matches Product.category
|
||||||
|
parentId String? // parent category ID for hierarchical organization (e.g., "Apparel - Adults" has parent "Apparel")
|
||||||
|
parent Category? @relation("CategoryHierarchy", fields: [parentId], references: [id], onDelete: Cascade)
|
||||||
|
children Category[] @relation("CategoryHierarchy")
|
||||||
showOnPersonalised Boolean @default(true) // appears as a filter on /made-to-order
|
showOnPersonalised Boolean @default(true) // appears as a filter on /made-to-order
|
||||||
showOnProducts Boolean @default(true) // appears as a filter on /products
|
showOnProducts Boolean @default(true) // appears as a filter on /products
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|||||||
+2
-1
@@ -40,8 +40,9 @@ export default async function HomePage() {
|
|||||||
const readyMadeCount = readyMade.length;
|
const readyMadeCount = readyMade.length;
|
||||||
|
|
||||||
const categoryRows = await prisma.category.findMany({
|
const categoryRows = await prisma.category.findMany({
|
||||||
where: { showOnPersonalised: true },
|
where: { showOnPersonalised: true, parentId: null },
|
||||||
orderBy: { name: 'asc' },
|
orderBy: { name: 'asc' },
|
||||||
|
include: { children: { orderBy: { name: 'asc' } } },
|
||||||
});
|
});
|
||||||
const categories = categoryRows.map((c) => ({ label: c.name, value: c.slug }));
|
const categories = categoryRows.map((c) => ({ label: c.name, value: c.slug }));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user