mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 23:46:58 +00:00
creating SKU generator from product.Title
This commit is contained in:
parent
e8cc4863fb
commit
decb61bee3
55
app/product/[handle]/sku/page.tsx
Normal file
55
app/product/[handle]/sku/page.tsx
Normal file
@ -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<Metadata> {
|
||||
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 (
|
||||
<>
|
||||
<ProductSKUs productTitle={product.title} />
|
||||
</>
|
||||
)
|
||||
};
|
30
components/product/sku-generator.tsx
Normal file
30
components/product/sku-generator.tsx
Normal file
@ -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 (
|
||||
<>
|
||||
<div className="mx-auto max-w-screen-2xl px-4">
|
||||
<div className="rounded-lg border border-neutral-200 bg-white p-8 px-4 dark:border-neutral-800 dark:bg-black md:p-12 lg:grid lg:grid-cols-6">
|
||||
<div className="lg:col-span-3">
|
||||
{SKUs?.map(SKU => {
|
||||
return (
|
||||
<div className="my-4 w-full">
|
||||
<input type="text" value={SKU} onClick={copyText} className="cursor-pointer w-full border py-2 px-2" />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
};
|
69
constants/sku.tsx
Normal file
69
constants/sku.tsx
Normal file
@ -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',
|
||||
};
|
||||
|
54
lib/helpers/skus.tsx
Normal file
54
lib/helpers/skus.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import { baseArtworkNumber, collectionsSKUs, colorSKUs, customisationSKUs, garmentHandleKeys, garmentSKUs, garmentSizes, sizeSKUs } from "constants/sku";
|
||||
|
||||
type TitleInfo = Awaited<ReturnType<typeof extractInfoFromTitle>>;
|
||||
|
||||
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}`
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user