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;