From decb61bee3b2984ddc080c841f57a94488bdf499 Mon Sep 17 00:00:00 2001 From: Samantha Kellow Date: Fri, 28 Jul 2023 15:11:35 +0100 Subject: [PATCH] creating SKU generator from product.Title --- app/product/[handle]/sku/page.tsx | 55 ++++++++++++++++++++++ components/product/sku-generator.tsx | 30 ++++++++++++ constants/sku.tsx | 69 ++++++++++++++++++++++++++++ lib/helpers/skus.tsx | 54 ++++++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 app/product/[handle]/sku/page.tsx create mode 100644 components/product/sku-generator.tsx create mode 100644 constants/sku.tsx create mode 100644 lib/helpers/skus.tsx diff --git a/app/product/[handle]/sku/page.tsx b/app/product/[handle]/sku/page.tsx new file mode 100644 index 000000000..bcc983536 --- /dev/null +++ b/app/product/[handle]/sku/page.tsx @@ -0,0 +1,55 @@ +import { ProductSKUs } from "components/product/sku-generator"; +import { HIDDEN_PRODUCT_TAG } from "lib/constants"; +import { getProduct } from "lib/shopify"; +import { Metadata } from "next"; +import { notFound } from "next/navigation"; + +export async function generateMetadata({ + params +}: { + params: { handle: string }; +}): Promise { + const product = await getProduct(params.handle); + + if (!product) return notFound(); + + const { url, width, height, altText: alt } = product.featuredImage || {}; + const hide = !product.tags.includes(HIDDEN_PRODUCT_TAG); + + return { + title: product.seo.title || product.title, + description: product.seo.description || product.description, + robots: { + index: hide, + follow: hide, + googleBot: { + index: hide, + follow: hide + } + }, + openGraph: url + ? { + images: [ + { + url, + width, + height, + alt + } + ] + } + : null + }; +} + +export default async function ViewSKUs({ params }: { params: { handle: string } }) { + const product = await getProduct(params.handle); + + if (!product) return + + return ( + <> + + + ) +}; \ No newline at end of file diff --git a/components/product/sku-generator.tsx b/components/product/sku-generator.tsx new file mode 100644 index 000000000..6ffbfffc2 --- /dev/null +++ b/components/product/sku-generator.tsx @@ -0,0 +1,30 @@ +'use client' + +import { createProductSKUs } from "lib/helpers/skus"; + + +export function ProductSKUs(productInfo: {productTitle: string}) { + const SKUs = createProductSKUs(productInfo.productTitle) + + function copyText(e) { + navigator.clipboard.writeText(e.target.value); + } + + return ( + <> +
+
+
+ {SKUs?.map(SKU => { + return ( +
+ +
+ ) + })} +
+
+
+ + ) +}; diff --git a/constants/sku.tsx b/constants/sku.tsx new file mode 100644 index 000000000..fcc5476c3 --- /dev/null +++ b/constants/sku.tsx @@ -0,0 +1,69 @@ +export const baseArtworkNumber = '000'; + +export const sizes = [ 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl' ]; + +export const garmentTypes = { + tshirt: 'tshirt', + cropT: 'cropT', + hoodie: 'hoodie', + zipHood: 'zipHood', + crew: 'crew', + cropCrew: 'cropCrew', +}; + +export const garmentHandleKeys = { + 'T-shirt': garmentTypes.tshirt, + 'Crop T-shirt': garmentTypes.cropT, + 'Hoodie': garmentTypes.hoodie, + 'Zipped Hoodie': garmentTypes.zipHood, + 'Crew Neck Sweatshirt': garmentTypes.crew, + 'Cropped Crew Neck Sweatshirt': garmentTypes.cropCrew, +}; + +const xsTo2xl = sizes.slice(1, 7); + +export const garmentSizes = { + [garmentTypes.tshirt]: sizes, + [garmentTypes.cropT]: xsTo2xl, + [garmentTypes.hoodie]: sizes, + [garmentTypes.zipHood]: sizes, + [garmentTypes.crew]: xsTo2xl, + [garmentTypes.cropCrew]: xsTo2xl, +}; + +export const garmentSKUs = { + [garmentTypes.tshirt]: 'STTU788', + [garmentTypes.cropT]: 'STTW089', + [garmentTypes.hoodie]: 'STSU867', + [garmentTypes.zipHood]: 'STSU953', + [garmentTypes.crew]: 'STSU886', + [garmentTypes.cropCrew]: 'STSW873', +}; + +export const colorSKUs = { + black: 'C002' +}; + +export const collectionsSKUs = { + 'flower': 1, + 'foliage': 2, + 'nature': 3, + 'sky': 4, + 'urban': 5, +}; + +export const customisationSKUs = { + printArea: 'B', + tags: 'NT' +}; + +export const sizeSKUs = { + xs: 'XS', + s: 'S', + m: 'M', + l: 'L', + xl: 'XL', + xxl: '2XL', + xxxl: '3XL', +}; + diff --git a/lib/helpers/skus.tsx b/lib/helpers/skus.tsx new file mode 100644 index 000000000..f57400355 --- /dev/null +++ b/lib/helpers/skus.tsx @@ -0,0 +1,54 @@ +import { baseArtworkNumber, collectionsSKUs, colorSKUs, customisationSKUs, garmentHandleKeys, garmentSKUs, garmentSizes, sizeSKUs } from "constants/sku"; + +type TitleInfo = Awaited>; + +const artworkNumberCompiler = (artworkNumber: string) => { + const length = artworkNumber.length + const slice = baseArtworkNumber.slice(0, length + 1) + return slice + artworkNumber +} + +const garmentHandleKeyMapper = (garmentKeys: string[]) => { + const garmentTitle = garmentKeys.join(' '); + const garmentKey = garmentHandleKeys[garmentTitle as keyof typeof garmentHandleKeys] + return garmentSKUs[garmentKey as keyof typeof garmentSKUs] +} + +const extractInfoFromTitle = (productTitle: string) => { + const title = productTitle.split(' '); + const collection = title[0]?.toLowerCase(); + const garmentKeys = title.slice(2) + return { + title, + collection, + garmentTitle: garmentKeys.join(' '), + artworkNumber: title[1]?.replace('No.', ''), + garmentKeys, + collectionKey: collection!.replace('scape', ''), + } +} + +const collectionSKUMapper = (titleInfo: TitleInfo) => { + const collectionSKU = collectionsSKUs[titleInfo.collectionKey as keyof typeof collectionsSKUs]; + const artworkSKU = artworkNumberCompiler(titleInfo.artworkNumber!); + const garmentSKU = garmentHandleKeyMapper(titleInfo.garmentKeys); + + return `SCSQ${collectionSKU}${artworkSKU}_${garmentSKU}`; +} + +const customisationSKUMapper = () => + `${colorSKUs.black}_${customisationSKUs.printArea}_${customisationSKUs.tags}` + +export const createProductSKUs = (productTitle: string) => { + const titleInfo = extractInfoFromTitle(productTitle); + const garmentKey = garmentHandleKeys[titleInfo.garmentTitle as keyof typeof garmentHandleKeys] + const getGarmentSizes = garmentSizes[garmentKey] + const customisationSKUs = customisationSKUMapper(); + + return getGarmentSizes?.map(size => { + const currentSizeSKU = sizeSKUs[size as keyof typeof sizeSKUs] + const collectionSKU = collectionSKUMapper(titleInfo) + + return `${collectionSKU}_${currentSizeSKU}_${customisationSKUs}` + }) +}