mirror of
https://github.com/vercel/commerce.git
synced 2025-05-13 05:07:51 +00:00
Fix sos page
This commit is contained in:
parent
95a77f1cb8
commit
f571d7fab3
83
app/sos/NewProductHelpComponent.tsx
Normal file
83
app/sos/NewProductHelpComponent.tsx
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Combox } from "components/combox";
|
||||||
|
import { ProductSKUs } from "components/product/sku-generator";
|
||||||
|
import { collectionsSKUs, garmentHandleKeys } from "constants/sku";
|
||||||
|
import { capitalizeFirstLetter, copyText } from "lib/helpers/actions";
|
||||||
|
import { useMemo, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// type SKUSelectorState = {
|
||||||
|
// garment?: keyof typeof garmentHandleKeys,
|
||||||
|
// collection?: keyof typeof collectionsSKUs,
|
||||||
|
// };
|
||||||
|
|
||||||
|
export function NewProductHelpComponent() {
|
||||||
|
// const [open, setOpen] = useState(false)
|
||||||
|
const [collection, setCollection] = useState<keyof typeof collectionsSKUs | null>(null);
|
||||||
|
// TODO: preselect tshirt
|
||||||
|
const [garment, setGarment] = useState<keyof typeof garmentHandleKeys | null>(null);
|
||||||
|
// const [title, setTitle] = useState<string | null>(null);
|
||||||
|
const [number, setNumber] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const title = useMemo(() => {
|
||||||
|
const title = collection && garment && `${capitalizeFirstLetter(collection)}scape No.${number} ${garment}`;
|
||||||
|
console.log("🍓🍋🍊 title", title);
|
||||||
|
return title;
|
||||||
|
}, [collection, garment, number]);
|
||||||
|
|
||||||
|
const garmentOptions = Object.entries(garmentHandleKeys).map(([fullGarmentName, garmentHandle]) => ({
|
||||||
|
label: fullGarmentName as keyof typeof garmentHandleKeys,
|
||||||
|
key: fullGarmentName as keyof typeof garmentHandleKeys,
|
||||||
|
}))
|
||||||
|
const collectionOptions = Object.entries(collectionsSKUs).map(([scape, scapeNumber]) => ({
|
||||||
|
label: scape as keyof typeof collectionsSKUs,
|
||||||
|
key: scape as keyof typeof collectionsSKUs
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-20">
|
||||||
|
<div className="grid grid-cols-5">
|
||||||
|
<div className="py-6 col-span-4 col-start-2">
|
||||||
|
<p className="title">New Product Creator</p>
|
||||||
|
</div>
|
||||||
|
<div className="py-6 col-span-1 col-start-2">
|
||||||
|
<Combox
|
||||||
|
options={collectionOptions}
|
||||||
|
onShow={(key: string): void => setCollection(key as keyof typeof collectionsSKUs)}
|
||||||
|
currentKey={collection || null} />
|
||||||
|
</div>
|
||||||
|
<div className="pt-6 mx-30 col-span-1 col-start-3 flex justify-center items-start">
|
||||||
|
<Input
|
||||||
|
className="w-2/3"
|
||||||
|
type="number"
|
||||||
|
placeholder="No."
|
||||||
|
onChange={(e) => setNumber(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="pt-6 col-span-1 col-start-4">
|
||||||
|
<Combox
|
||||||
|
options={garmentOptions}
|
||||||
|
onShow={(key: string): void => setGarment(key as keyof typeof garmentHandleKeys)}
|
||||||
|
currentKey={garment || null} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{garment && collection && number && title &&
|
||||||
|
<>
|
||||||
|
<div className="pb-6 col-span-3 col-start-2">
|
||||||
|
<div
|
||||||
|
className="border p-2 px-4 cursor-pointer"
|
||||||
|
onClick={() => copyText(title)}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="my-5 col-span-5">
|
||||||
|
<ProductSKUs productTitle={title} noTitle={true} />
|
||||||
|
</div>
|
||||||
|
</>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,97 +1,6 @@
|
|||||||
// make a page where you can select from garment types, collection types and numbers to create a copyable name
|
import { NewProductHelpComponent } from "./NewProductHelpComponent"
|
||||||
"use client"
|
|
||||||
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Combox } from "components/combox";
|
|
||||||
import { ProductSKUs } from "components/product/sku-generator";
|
|
||||||
import { collectionsSKUs, garmentHandleKeys } from "constants/sku";
|
|
||||||
import { capitalizeFirstLetter, copyText } from "lib/helpers/actions";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
// type SKUSelectorState = {
|
|
||||||
// garment?: keyof typeof garmentHandleKeys,
|
|
||||||
// collection?: keyof typeof collectionsSKUs,
|
|
||||||
// };
|
|
||||||
|
|
||||||
export default async function NewProductHelpPage() {
|
export default async function NewProductHelpPage() {
|
||||||
// const [open, setOpen] = useState(false)
|
return <NewProductHelpComponent/>
|
||||||
const [collection, setCollection] = useState<keyof typeof collectionsSKUs | null>(null)
|
|
||||||
const [garment, setGarment] = useState<keyof typeof garmentHandleKeys | null>(null)
|
|
||||||
const [title, setTitle] = useState<string | null>(null)
|
|
||||||
const [number, setNumber] = useState<string | null>(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const title = createTitle()
|
|
||||||
console.log("🍓🍋🍊 title", title);
|
|
||||||
|
|
||||||
}, [collection, garment])
|
|
||||||
|
|
||||||
const garmentValues = Object.keys(garmentHandleKeys)
|
|
||||||
const collectionValues = Object.keys(collectionsSKUs)
|
|
||||||
|
|
||||||
const optionsMapper = (keys: {}, values: string[]) => {
|
|
||||||
return values.map(value => {
|
|
||||||
return {
|
|
||||||
key: keys[value as keyof typeof keys],
|
|
||||||
label: value,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const garmentOptions = optionsMapper(garmentHandleKeys, garmentValues);
|
|
||||||
const collectionOptions = optionsMapper(collectionsSKUs, collectionValues);
|
|
||||||
|
|
||||||
const createTitle = () => {
|
|
||||||
setTitle(collection && garment && `${capitalizeFirstLetter(collection)}scape No.${number} ${garment}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="m-20">
|
|
||||||
<div className="grid grid-cols-5">
|
|
||||||
<div className="py-6 col-span-4 col-start-2">
|
|
||||||
<p className="title">New Product Creator</p>
|
|
||||||
</div>
|
|
||||||
<div className="py-6 col-span-1 col-start-2">
|
|
||||||
<Combox
|
|
||||||
options={collectionOptions}
|
|
||||||
onShow={(key: string): void => setCollection(key as keyof typeof collectionsSKUs)}
|
|
||||||
currentKey={collection || null}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="pt-6 mx-30 col-span-1 col-start-3 flex justify-center items-start">
|
|
||||||
<Input
|
|
||||||
className="w-2/3"
|
|
||||||
type="number"
|
|
||||||
placeholder="No."
|
|
||||||
onChange={(e) => setNumber(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="pt-6 col-span-1 col-start-4">
|
|
||||||
<Combox
|
|
||||||
options={garmentOptions}
|
|
||||||
onShow={(key: string): void => setGarment(key as keyof typeof garmentHandleKeys)}
|
|
||||||
currentKey={garment || null}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{garment && collection && number && title &&
|
|
||||||
<>
|
|
||||||
<div className="pb-6 col-span-3 col-start-2">
|
|
||||||
<div
|
|
||||||
className="border p-2 px-4 cursor-pointer"
|
|
||||||
onClick={() => copyText(title)}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="my-5 col-span-5">
|
|
||||||
<ProductSKUs productTitle={title} noTitle={true} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +49,16 @@ export default async function Footer() {
|
|||||||
</div> */}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-neutral-200 py-6 text-sm dark:border-neutral-700">
|
<div className="border-t border-neutral-200 py-6 text-sm dark:border-neutral-700">
|
||||||
<div className="mx-auto flex w-full max-w-7xl flex-col items-center gap-1 md:flex-row md:gap-0">
|
<div className="mx-auto flex w-full max-w-7xl flex-col items-center gap-1 md:flex-row md:gap-0 pl-4">
|
||||||
<p>
|
<p>
|
||||||
© {copyrightDate} {copyrightName}
|
© {copyrightDate} {copyrightName}
|
||||||
{copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved.
|
{copyrightName.length && !copyrightName.endsWith('.') ? '.' : ''} All rights reserved.
|
||||||
</p>
|
</p>
|
||||||
<hr className="mx-4 hidden h-4 w-[1px] border-l border-neutral-400 md:inline-block" />
|
{/* <hr className="mx-4 hidden h-4 w-[1px] border-l border-neutral-400 md:inline-block" /> */}
|
||||||
<p>Designed in England</p>
|
{/* <p>Designed in England</p> */}
|
||||||
<p className="md:ml-auto">
|
<p className="md:ml-auto">
|
||||||
Crafted by{' '}
|
Crafted by{' '}
|
||||||
<Link href="https://www.instagram.com/sammiisparkle" className="text-black dark:text-white" target="_blank">
|
<Link href="https://www.instagram.com/sammiisparkle" className="text-black dark:text-white pr-2" target="_blank">
|
||||||
Sammii Sparkle
|
Sammii Sparkle
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
|
62
components/store/themeContext.tsx
Normal file
62
components/store/themeContext.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { createContext, ReactElement, useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const ThemeContext = createContext({
|
||||||
|
isDarkTheme: true,
|
||||||
|
toggleThemeHandler: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
interface ThemePropsInterface {
|
||||||
|
children?: JSX.Element | Array<JSX.Element>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyThemeContextProvider(
|
||||||
|
props: ThemePropsInterface
|
||||||
|
): ReactElement {
|
||||||
|
const [isDarkTheme, setIsDarkTheme] = useState(true);
|
||||||
|
useEffect(() => initialThemeHandler());
|
||||||
|
|
||||||
|
function isLocalStorageEmpty(): boolean {
|
||||||
|
return !localStorage.getItem("isDarkTheme");
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialThemeHandler(): void {
|
||||||
|
if (isLocalStorageEmpty()) {
|
||||||
|
localStorage.setItem("isDarkTheme", `true`);
|
||||||
|
document!.querySelector("body")!.classList.add("dark");
|
||||||
|
setIsDarkTheme(true);
|
||||||
|
} else {
|
||||||
|
const isDarkTheme: boolean = JSON.parse(
|
||||||
|
localStorage.getItem("isDarkTheme")!
|
||||||
|
);
|
||||||
|
isDarkTheme && document!.querySelector("body")!.classList.add("dark");
|
||||||
|
setIsDarkTheme(() => {
|
||||||
|
return isDarkTheme;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleThemeHandler(): void {
|
||||||
|
const isDarkTheme: boolean = JSON.parse(
|
||||||
|
localStorage.getItem("isDarkTheme")!
|
||||||
|
);
|
||||||
|
setIsDarkTheme(!isDarkTheme);
|
||||||
|
toggleDarkClassToBody();
|
||||||
|
setValueToLocalStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleDarkClassToBody(): void {
|
||||||
|
document!.querySelector("body")!.classList.toggle("dark");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setValueToLocalStorage(): void {
|
||||||
|
localStorage.setItem("isDarkTheme", `${!isDarkTheme}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={{ isDarkTheme: true, toggleThemeHandler }}>
|
||||||
|
{props.children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThemeContext;
|
@ -3,12 +3,12 @@ export const baseArtworkNumber = '000';
|
|||||||
export const sizes = [ 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl' ];
|
export const sizes = [ 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl' ];
|
||||||
|
|
||||||
export const garmentTypes = {
|
export const garmentTypes = {
|
||||||
tshirt: 'tshirt',
|
tshirt: 'tshirt' as const,
|
||||||
cropT: 'cropT',
|
cropT: 'cropT' as const,
|
||||||
hoodie: 'hoodie',
|
hoodie: 'hoodie' as const,
|
||||||
zipHood: 'zipHood',
|
zipHood: 'zipHood' as const,
|
||||||
crew: 'crew',
|
crew: 'crew' as const,
|
||||||
cropCrew: 'cropCrew',
|
cropCrew: 'cropCrew' as const,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const garmentHandleKeys = {
|
export const garmentHandleKeys = {
|
||||||
|
@ -25,6 +25,6 @@ export const TAGS = {
|
|||||||
products: 'products'
|
products: 'products'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HIDDEN_PRODUCT_TAG = 'nextjs-frontend-hidden';
|
export const HIDDEN_PRODUCT_TAG = 'hidden-product';
|
||||||
export const DEFAULT_OPTION = 'Default Title';
|
export const DEFAULT_OPTION = 'Default Title';
|
||||||
export const SHOPIFY_GRAPHQL_API_ENDPOINT = '/api/2023-01/graphql.json';
|
export const SHOPIFY_GRAPHQL_API_ENDPOINT = '/api/2023-01/graphql.json';
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
import { baseArtworkNumber, collectionsSKUs, colorSKUs, customisationSKUs, garmentHandleKeys, garmentSKUs, garmentSizes, sizeSKUs } from "constants/sku";
|
import { collectionsSKUs, colorSKUs, customisationSKUs, garmentHandleKeys, garmentSKUs, garmentSizes, sizeSKUs } from "constants/sku";
|
||||||
|
|
||||||
type TitleInfo = Awaited<ReturnType<typeof extractInfoFromTitle>>;
|
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 garmentHandleKeyMapper = (garmentKeys: string[]) => {
|
||||||
const garmentTitle = garmentKeys.join(' ');
|
const garmentTitle = garmentKeys.join(' ');
|
||||||
const garmentKey = garmentHandleKeys[garmentTitle as keyof typeof garmentHandleKeys]
|
const garmentKey = garmentHandleKeys[garmentTitle as keyof typeof garmentHandleKeys]
|
||||||
@ -30,7 +24,7 @@ const extractInfoFromTitle = (productTitle: string) => {
|
|||||||
|
|
||||||
const collectionSKUMapper = (titleInfo: TitleInfo) => {
|
const collectionSKUMapper = (titleInfo: TitleInfo) => {
|
||||||
const collectionSKU = collectionsSKUs[titleInfo.collectionKey as keyof typeof collectionsSKUs];
|
const collectionSKU = collectionsSKUs[titleInfo.collectionKey as keyof typeof collectionsSKUs];
|
||||||
const artworkSKU = artworkNumberCompiler(titleInfo.artworkNumber!);
|
const artworkSKU = titleInfo.artworkNumber!.padStart(4, "0");
|
||||||
const garmentSKU = garmentHandleKeyMapper(titleInfo.garmentKeys);
|
const garmentSKU = garmentHandleKeyMapper(titleInfo.garmentKeys);
|
||||||
|
|
||||||
return `SCSQ${collectionSKU}${artworkSKU}_${garmentSKU}`;
|
return `SCSQ${collectionSKU}${artworkSKU}_${garmentSKU}`;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user