rspace-online/modules/rswag/products.ts

170 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export interface PrintfulMeta {
sku: number;
sizes?: string[];
colors?: { id: string; name: string; hex: string }[];
}
export interface ProductTemplate {
id: string;
name: string;
description: string;
// Print area dimensions in mm
printArea: { widthMm: number; heightMm: number };
// Output DPI
dpi: number;
// Bleed in mm
bleedMm: number;
// What artifact spec fields to use
productType: string;
substrates: string[];
requiredCapabilities: string[];
finish: string;
// Printful product metadata (optional — cosmolocal-only products omit this)
printful?: PrintfulMeta;
// Computed pixel dimensions (at DPI)
get widthPx(): number;
get heightPx(): number;
}
function makeTemplate(opts: Omit<ProductTemplate, "widthPx" | "heightPx">): ProductTemplate {
return {
...opts,
get widthPx() {
return Math.round(((this.printArea.widthMm + this.bleedMm * 2) / 25.4) * this.dpi);
},
get heightPx() {
return Math.round(((this.printArea.heightMm + this.bleedMm * 2) / 25.4) * this.dpi);
},
};
}
export const PRODUCTS: Record<string, ProductTemplate> = {
sticker: makeTemplate({
id: "sticker",
name: "Sticker Sheet",
description: "A4 sheet of die-cut vinyl stickers",
printArea: { widthMm: 210, heightMm: 297 },
dpi: 300,
bleedMm: 2,
productType: "sticker-sheet",
substrates: ["vinyl-matte", "vinyl-gloss", "sticker-paper-matte"],
requiredCapabilities: ["vinyl-cut"],
finish: "matte",
printful: { sku: 358 },
}),
poster: makeTemplate({
id: "poster",
name: "Poster (A3)",
description: "A3 art print / poster",
printArea: { widthMm: 297, heightMm: 420 },
dpi: 300,
bleedMm: 3,
productType: "poster",
substrates: ["paper-160gsm-cover", "paper-100gsm"],
requiredCapabilities: ["inkjet-print"],
finish: "matte",
}),
tee: makeTemplate({
id: "tee",
name: "T-Shirt",
description: "Front print on cotton tee (12x16 inch print area)",
printArea: { widthMm: 305, heightMm: 406 },
dpi: 300,
bleedMm: 0,
productType: "tee",
substrates: ["cotton-standard", "cotton-organic"],
requiredCapabilities: ["dtg-print"],
finish: "none",
printful: {
sku: 71,
sizes: ["S", "M", "L", "XL", "2XL", "3XL"],
colors: [
{ id: "black", name: "Black", hex: "#0a0a0a" },
{ id: "white", name: "White", hex: "#ffffff" },
{ id: "forest_green", name: "Forest Green", hex: "#2d4a3e" },
{ id: "heather_charcoal", name: "Heather Charcoal", hex: "#4a4a4a" },
{ id: "maroon", name: "Maroon", hex: "#5a2d2d" },
],
},
}),
hoodie: makeTemplate({
id: "hoodie",
name: "Hoodie",
description: "Front print on pullover hoodie (14x16 inch print area)",
printArea: { widthMm: 356, heightMm: 406 },
dpi: 300,
bleedMm: 0,
productType: "hoodie",
substrates: ["cotton-polyester-blend", "cotton-organic"],
requiredCapabilities: ["dtg-print"],
finish: "none",
printful: {
sku: 146,
sizes: ["S", "M", "L", "XL", "2XL"],
colors: [
{ id: "black", name: "Black", hex: "#0a0a0a" },
{ id: "dark_grey_heather", name: "Dark Grey Heather", hex: "#3a3a3a" },
],
},
}),
};
export function getProduct(id: string): ProductTemplate | undefined {
return PRODUCTS[id];
}
// ── POD product configurations ──
// Maps design product types to POD provider SKUs and pricing
export interface PodProductConfig {
type: string;
provider: "printful" | "prodigi";
sku: string;
variants: string[];
retailPrice: number;
}
/** Default POD product configs applied to each design */
export const POD_PRODUCTS: Record<string, PodProductConfig[]> = {
sticker: [
{ type: "sticker", provider: "prodigi", sku: "GLOBAL-STI-KIS-3X3", variants: ["matte", "gloss"], retailPrice: 3.50 },
],
poster: [
{ type: "print", provider: "prodigi", sku: "GLOBAL-FAP-A4", variants: ["matte"], retailPrice: 12.99 },
],
tee: [
{ type: "shirt", provider: "printful", sku: "71", variants: ["S", "M", "L", "XL", "2XL"], retailPrice: 29.99 },
],
hoodie: [
{ type: "hoodie", provider: "printful", sku: "146", variants: ["S", "M", "L", "XL", "2XL"], retailPrice: 39.99 },
],
};
/**
* Get the POD product configs for a product type.
* Returns an array of purchasable SKU configurations.
*/
export function getPodProducts(productType: string): PodProductConfig[] {
return POD_PRODUCTS[productType] || [];
}
/**
* Flatten all designs into purchasable storefront products.
* Each design × product config = one storefront listing.
*/
export interface StorefrontProduct {
slug: string;
designSlug: string;
name: string;
description: string;
category: string;
productType: string;
imageUrl: string;
basePrice: number;
variants: string[];
provider: string;
sku: string;
isActive: boolean;
}