import { prisma } from '@/lib/prisma'; import { toProductDTO } from '@/lib/product'; import { fetchActivePromotions } from '@/lib/promotions'; import ProductCard from '@/components/ProductCard'; import type { Prisma } from '@prisma/client'; type SearchParams = { category?: string | string[]; collection?: string | string[]; color?: string | string[]; min?: string; max?: string; q?: string; }; function toArray(v?: string | string[]) { if (!v) return []; return Array.isArray(v) ? v : [v]; } export default async function ReadyMadeProductsPage({ searchParams }: { searchParams: SearchParams }) { const categoryRows = await prisma.category.findMany({ where: { showOnProducts: true }, orderBy: { name: 'asc' }, }); const CATEGORIES = categoryRows.map((c) => ({ value: c.slug, label: c.name })); 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 })); const RECIPIENTS = collectionRows.filter((c) => c.group === 'RECIPIENT').map((c) => ({ value: c.slug, label: c.name })); const selectedCategories = toArray(searchParams.category); const selectedCollections = toArray(searchParams.collection); const selectedColors = toArray(searchParams.color); const q = searchParams.q?.trim() ?? ''; const minDollars = searchParams.min ? Number(searchParams.min) : undefined; const maxDollars = searchParams.max ? Number(searchParams.max) : undefined; // Full palette across ready-made products only, for the swatch filter. const allProducts = await prisma.product.findMany({ where: { showAsReadyMade: true }, select: { colors: true }, }); const paletteSet = new Set(); for (const p of allProducts) { (JSON.parse(p.colors) as string[]).forEach((c) => paletteSet.add(c)); } const palette = Array.from(paletteSet); const where: Prisma.ProductWhereInput = { showAsReadyMade: true }; if (selectedCategories.length) { where.category = { in: selectedCategories }; } if (selectedCollections.length) { where.collections = { some: { slug: { in: selectedCollections } } }; } if (selectedColors.length) { where.AND = [{ OR: selectedColors.map((c) => ({ colors: { contains: c } })) }]; } if (q) { where.name = { contains: q }; } if (minDollars !== undefined || maxDollars !== undefined) { where.basePrice = { ...(minDollars !== undefined ? { gte: Math.round(minDollars * 100) } : {}), ...(maxDollars !== undefined ? { lte: Math.round(maxDollars * 100) } : {}), }; } const activePromotions = await fetchActivePromotions(); const rows = await prisma.product.findMany({ where, orderBy: { createdAt: 'asc' } }); const products = rows.map((p) => toProductDTO(p, activePromotions, 'plain')); const hasFilters = selectedCategories.length > 0 || selectedCollections.length > 0 || selectedColors.length > 0 || q || minDollars !== undefined || maxDollars !== undefined; return (

Products

{products.length} item{products.length === 1 ? '' : 's'}

{products.length === 0 && !hasFilters ? (

Nothing here yet

Ready-made items will show up here once added — check Admin → Add product and enable "Products catalog".

) : (
{/* Sidebar filters */} {/* Grid */}
{products.length === 0 ? (

No products match those filters

Try widening your price range or clearing a filter.

) : (
{products.map((p) => ( ))}
)}
)}
); }