- vinyl-config route + data file for shape/font/pricing config - CatalogItem: vinylEnabled, vinylPromo fields - ItemOverride: vinylEnabled, vinylPromo fields - catalog route: applies vinylEnabled/vinylPromo overrides - ColorPicker: full vinyl configurator UI (shape picker, text/font, pricing) - CartContext: vinyl cart fields (vinylText, vinylFontId, vinylShape, etc.) - CartDrawer: vinyl line items flatMap (shape balloon + custom vinyl service) - admin/items route: synced more-complete version from balloons-shop - admin page: vinyl configurator and promo note checkboxes in ItemEditor Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
78 lines
3.6 KiB
TypeScript
78 lines
3.6 KiB
TypeScript
import { NextResponse } from 'next/server'
|
|
import { getCatalog } from '@/lib/catalog-cache'
|
|
import { readOverrides } from '@/lib/overrides'
|
|
|
|
export async function GET() {
|
|
try {
|
|
const [{ items, fetchedAt }, overrides] = await Promise.all([
|
|
getCatalog(),
|
|
Promise.resolve(readOverrides()),
|
|
])
|
|
|
|
const withOverrides = items.map((item) => {
|
|
const ov = overrides[item.id] ?? {}
|
|
const toSlug = (n: string) => n.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')
|
|
|
|
// Resolve categories (same logic as catalog route)
|
|
const resolvedCats = ov.categoriesOverride?.length
|
|
? (() => {
|
|
const cats = ov.categoriesOverride!.map(toSlug)
|
|
return {
|
|
categories: cats,
|
|
categoryLabels: ov.categoriesOverride!,
|
|
category: cats[0],
|
|
categoryLabel: ov.categoriesOverride![0],
|
|
}
|
|
})()
|
|
: {
|
|
category: ov.categoryOverride ?? item.category,
|
|
categoryLabel: ov.categoryLabelOverride ?? item.categoryLabel,
|
|
categories: ov.categoryOverride
|
|
? [ov.categoryOverride, ...(item.categories ?? [item.category]).slice(1)]
|
|
: (item.categories ?? [item.category]),
|
|
categoryLabels: ov.categoryLabelOverride
|
|
? [ov.categoryLabelOverride, ...(item.categoryLabels ?? [item.categoryLabel]).slice(1)]
|
|
: (item.categoryLabels ?? [item.categoryLabel]),
|
|
}
|
|
|
|
return {
|
|
...item,
|
|
// Resolved values (what the customer sees)
|
|
hidden: ov.hidden ?? false,
|
|
featured: ov.featured ?? item.featured ?? false,
|
|
...resolvedCats,
|
|
sortOrder: ov.sortOrder ?? 0,
|
|
showColors: ov.showColors != null ? ov.showColors : item.showColors,
|
|
colorMin: ov.colorMin ?? item.colorMin,
|
|
colorMax: ov.colorMax !== undefined ? ov.colorMax : item.colorMax,
|
|
chromeSurchargePerColor: ov.chromeSurchargePerColor ?? item.chromeSurchargePerColor,
|
|
disabledColors: ov.disabledColors?.length ? ov.disabledColors : item.disabledColors,
|
|
requiresDelivery: ov.requiresDelivery != null ? ov.requiresDelivery : item.requiresDelivery,
|
|
deliveryBaseOverride: ov.deliveryBaseOverride !== undefined ? ov.deliveryBaseOverride : item.deliveryBaseOverride,
|
|
deliveryPerMileOverride: ov.deliveryPerMileOverride !== undefined ? ov.deliveryPerMileOverride : item.deliveryPerMileOverride,
|
|
description: ov.descriptionOverride ?? item.description,
|
|
variations: item.variations.filter((v) => !(ov.hiddenVariationIds ?? []).includes(v.id)),
|
|
modifiers: item.modifiers
|
|
.filter((m) => !(ov.hiddenModifierIds ?? []).includes(m.id))
|
|
.map((m) => {
|
|
const minOverride = ov.modifierMinSelected?.[m.id]
|
|
return minOverride !== undefined ? { ...m, minSelected: minOverride } : m
|
|
}),
|
|
// Raw Square values (for admin display)
|
|
_rawCategory: item.category,
|
|
_rawCategoryLabel: item.categoryLabel,
|
|
_rawShowColors: item.showColors,
|
|
_rawVariations: item.variations,
|
|
_rawModifiers: item.modifiers,
|
|
_rawDescription: item.description,
|
|
_override: ov,
|
|
}
|
|
})
|
|
|
|
return NextResponse.json({ items: withOverrides, overrides, fetchedAt })
|
|
} catch (err) {
|
|
console.error('[admin/items] error:', err)
|
|
return NextResponse.json({ error: 'Failed to load catalog' }, { status: 500 })
|
|
}
|
|
}
|