diff --git a/src/components/DesignCanvas.tsx b/src/components/DesignCanvas.tsx index 66ae779..cd37e32 100644 --- a/src/components/DesignCanvas.tsx +++ b/src/components/DesignCanvas.tsx @@ -204,6 +204,7 @@ function PrintSurface({ {/* Horizontal Ruler */} + {product.printAreaWidthMm > 0 && stageW > 0 && (
- {Array.from({ length: Math.ceil((stageW / (10 * (product.printAreaWidthMm / 100)))) }).map((_, i) => { - const cm = i * 2; - const px = (cm * stageW) / (product.printAreaWidthMm / 10); - if (px > stageW) return null; - return ( -
- {cm}cm -
- ); - })} + {(() => { + const marks = []; + const cmPerStageW = product.printAreaWidthMm / 10; // total cm width of stage + const pxPerCm = stageW / cmPerStageW; + + for (let cm = 0; cm <= Math.ceil(cmPerStageW); cm += 2) { + const px = cm * pxPerCm; + if (px > stageW) break; + marks.push( +
+ {cm} +
+ ); + } + return marks; + })()}
+ )} {/* Vertical Ruler */} + {product.printAreaHeightMm > 0 && stageH > 0 && (
- {Array.from({ length: Math.ceil((stageH / (10 * (product.printAreaWidthMm / 100)))) }).map((_, i) => { - const cm = i * 2; - const px = (cm * stageH) / (product.printAreaWidthMm / 10); - if (px > stageH) return null; - return ( -
- {cm} -
- ); - })} + {(() => { + const marks = []; + const cmPerStageH = product.printAreaHeightMm / 10; // total cm height of stage + const pxPerCm = stageH / cmPerStageH; + + for (let cm = 0; cm <= Math.ceil(cmPerStageH); cm += 2) { + const px = cm * pxPerCm; + if (px > stageH) break; + marks.push( +
+ {cm} +
+ ); + } + return marks; + })()}
+ )}
(px * cmPerPx).toFixed(2); + // printAreaWidthMm is in mm, divide by 10 to get cm + // printAreaWidthPx is in pixels + // cmPerPx = cm per pixel + const mmPerPx = printAreaWidthPx > 0 ? product.printAreaWidthMm / printAreaWidthPx : 0; + const cmPerPx = mmPerPx > 0 ? mmPerPx / 10 : 0; + const pxToCm = (px: number) => { + const cm = px * cmPerPx; + return isNaN(cm) ? '?' : cm.toFixed(2); + }; const setActiveElements = view === 'front' ? setElementsFront : setElementsBack; // Keep whichever transformer actually owns the selected element in sync, and diff --git a/src/lib/product.ts b/src/lib/product.ts index 66421fa..9b707d7 100644 --- a/src/lib/product.ts +++ b/src/lib/product.ts @@ -19,6 +19,8 @@ export function toProductDTO(p: PrismaProduct, activePromotions: ActivePromotion mockup: p.mockup, printArea: JSON.parse(p.printArea), printAreaBack: p.printAreaBack ? JSON.parse(p.printAreaBack) : null, + printAreaWidthMm: p.printAreaWidthMm, + printAreaHeightMm: p.printAreaHeightMm, imageUrl: p.imageUrl, imageUrlBack: p.imageUrlBack, photoRecolorable: p.photoRecolorable, diff --git a/src/lib/types.ts b/src/lib/types.ts index 1a35862..8216760 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -43,6 +43,8 @@ export type ProductDTO = { mockup: string; printArea: PrintArea; printAreaBack: PrintArea | null; + printAreaWidthMm: number; + printAreaHeightMm: number; imageUrl: string | null; imageUrlBack: string | null; photoRecolorable: boolean;