Feature: Split products catalog into Plain and Ready-Made

Replaces generic 'showOnProducts' boolean with separate catalog options:
- showAsPlain: for blank/unprinted items (/products/plain)
- showAsReadyMade: for pre-finished items (/products/ready-made)

Changes:
- Updated Product schema to replace showOnProducts with new fields
- Updated product creation and edit forms with new checkboxes
- Updated product listing pages to use showAsReadyMade filter
- Updated ProductDTO type to reflect new catalog flags

Products can now be precisely categorized by type with unique pricing for each.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Andymick
2026-07-20 18:26:13 +01:00
co-authored by Claude Haiku 4.5
parent 5bd6f3de39
commit 8fe99d9d35
7 changed files with 38 additions and 16 deletions
+10 -5
View File
@@ -76,7 +76,8 @@ export async function createProduct(formData: FormData) {
const imageBackFile = formData.get('imageBack') as File | null;
const photoRecolorable = String(formData.get('photoRecolorable') ?? '') === '1';
const showOnPersonalised = String(formData.get('showOnPersonalised') ?? '') === '1';
const showOnProducts = String(formData.get('showOnProducts') ?? '') === '1';
const showAsPlain = String(formData.get('showAsPlain') ?? '') === '1';
const showAsReadyMade = String(formData.get('showAsReadyMade') ?? '') === '1';
const collectionIds = formData.getAll('collections').map((v) => String(v));
if (!name || !category || !priceDollars) {
@@ -151,7 +152,8 @@ export async function createProduct(formData: FormData) {
imageUrlBack,
photoRecolorable,
showOnPersonalised,
showOnProducts,
showAsPlain,
showAsReadyMade,
collections: { connect: collectionIds.map((id) => ({ id })) },
},
});
@@ -174,7 +176,8 @@ export async function updateProduct(formData: FormData) {
const imageBackFile = formData.get('imageBack') as File | null;
const photoRecolorable = String(formData.get('photoRecolorable') ?? '') === '1';
const showOnPersonalised = String(formData.get('showOnPersonalised') ?? '') === '1';
const showOnProducts = String(formData.get('showOnProducts') ?? '') === '1';
const showAsPlain = String(formData.get('showAsPlain') ?? '') === '1';
const showAsReadyMade = String(formData.get('showAsReadyMade') ?? '') === '1';
const collectionIds = formData.getAll('collections').map((v) => String(v));
const referenceWidthCmInput = String(formData.get('referenceWidthCm') ?? '').trim();
const referenceHeightCmInput = String(formData.get('referenceHeightCm') ?? '').trim();
@@ -267,7 +270,8 @@ export async function updateProduct(formData: FormData) {
mockup: string;
photoRecolorable: boolean;
showOnPersonalised: boolean;
showOnProducts: boolean;
showAsPlain: boolean;
showAsReadyMade: boolean;
referenceWidthCm: number | null;
referenceHeightCm: number | null;
weightGrams: number | null;
@@ -290,7 +294,8 @@ export async function updateProduct(formData: FormData) {
mockup,
photoRecolorable,
showOnPersonalised,
showOnProducts,
showAsPlain,
showAsReadyMade,
referenceWidthCm,
referenceHeightCm,
weightGrams,