create new product mapper page

This commit is contained in:
Samantha Kellow 2023-08-02 22:07:21 +01:00
parent 8f842f0efe
commit 6c016248fe
5 changed files with 163 additions and 16 deletions

25
@/components/ui/input.tsx Normal file
View File

@ -0,0 +1,25 @@
import * as React from "react"
import { cn } from "@/lib/utils"
export interface InputProps
extends React.InputHTMLAttributes<HTMLInputElement> {}
const Input = React.forwardRef<HTMLInputElement, InputProps>(
({ className, type, ...props }, ref) => {
return (
<input
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
ref={ref}
{...props}
/>
)
}
)
Input.displayName = "Input"
export { Input }

101
app/sos/page.tsx Normal file
View File

@ -0,0 +1,101 @@
// make a page where you can select from garment types, collection types and numbers to create a copyable name
"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, getKeyByValue } from "lib/helpers/actions";
import { useEffect, useState } from "react";
// type SKUSelectorState = {
// garment?: keyof typeof garmentHandleKeys,
// collection?: keyof typeof collectionsSKUs,
// };
export default async function NewProductHelpPage() {
// const [open, setOpen] = useState(false)
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 = () => {
let collectionMapper = getKeyByValue(collectionsSKUs, collection)
if (collectionMapper) collectionMapper = capitalizeFirstLetter(collectionMapper)
let garmentMapper = getKeyByValue(garmentHandleKeys, garment)
if (garmentMapper) garmentMapper = capitalizeFirstLetter(garmentMapper)
setTitle(`${collectionMapper}scape No.${number} ${garmentMapper}`)
}
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>
)
}

View File

@ -23,9 +23,17 @@ type Option = {
label: string, label: string,
} }
export function Combox({options}: {options: Option[]}) { export function Combox(
{
options,
currentKey,
onShow,
}: {
options: Option[],
currentKey: string | null,
onShow: ((key: string) => void),
}) {
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [currentKey, setCurrentKey] = useState<string | null>(null)
return ( return (
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>
@ -34,15 +42,15 @@ export function Combox({options}: {options: Option[]}) {
variant="outline" variant="outline"
role="combobox" role="combobox"
aria-expanded={open} aria-expanded={open}
className="w-[200px] justify-between" className="w-[200px] justify-between truncate text-ellipsis"
> >
{currentKey {currentKey
? options.find((option) => option.key === currentKey)?.label ? options.find((option) => option.key === currentKey)?.label
: "Select option..."} : "Select option..."}
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" /> <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button> </Button>
</PopoverTrigger> </PopoverTrigger> <br /><br />
<PopoverContent className="w-[200px] p-0"> <PopoverContent className="w-[200px] p-0 bg-popover">
<Command> <Command>
<CommandInput placeholder="Search option..." /> <CommandInput placeholder="Search option..." />
<CommandEmpty>No option found.</CommandEmpty> <CommandEmpty>No option found.</CommandEmpty>
@ -51,8 +59,9 @@ export function Combox({options}: {options: Option[]}) {
<CommandItem <CommandItem
key={option.key} key={option.key}
onSelect={() => { onSelect={() => {
setCurrentKey(option.key) // setCurrentKey(option.key)
setOpen(false) setOpen(false)
onShow(option.key)
}} }}
> >
<Check <Check

View File

@ -1,16 +1,21 @@
'use client' 'use client'
import clsx from "clsx"; import clsx from "clsx";
import { copyText } from "lib/helpers/actions";
import { createProductSKUs } from "lib/helpers/skus"; import { createProductSKUs } from "lib/helpers/skus";
import { useState } from "react"; import { useState } from "react";
export function ProductSKUs(productInfo: {productTitle: string}) { export function ProductSKUs(
const SKUs = createProductSKUs(productInfo.productTitle) {
productTitle,
noTitle = true
}: { productTitle: string, noTitle: boolean}) {
const SKUs = createProductSKUs(productTitle)
const [copyMessageState, setCopyMessageState] = useState< number | null >(null); const [copyMessageState, setCopyMessageState] = useState< number | null >(null);
const triggerCopyMessage = async (e: MouseEvent<HTMLButtonElement>, i: number) => { const triggerCopyMessage = async (i: number, SKU: string) => {
copyText(e.target.value) copyText(SKU)
console.log("copyMessageState", copyMessageState); console.log("copyMessageState", copyMessageState);
setCopyMessageState(i); setCopyMessageState(i);
@ -19,22 +24,18 @@ export function ProductSKUs(productInfo: {productTitle: string}) {
setTimeout(() => setCopyMessageState(null), 2500) setTimeout(() => setCopyMessageState(null), 2500)
} }
function copyText(text: string) {
navigator.clipboard.writeText(text);
}
return ( return (
<> <>
<div className="mx-auto max-w-screen-2xl px-4"> <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-12"> <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-12">
<div className="lg:col-span-6 lg:col-start-4"> <div className="lg:col-span-6 lg:col-start-4">
<h3 className="font-bold text-xl pb-4">{productInfo.productTitle}</h3> { !noTitle && <h3 className="font-bold text-xl pb-4">{productTitle}</h3> }
{/* {copyMessageState} */} {/* {copyMessageState} */}
{SKUs?.map((SKU, index) => { {SKUs?.map((SKU, index) => {
return ( return (
<div className="my-4 w-full" key={`${SKU}-${index}`}> <div className="my-4 w-full" key={`${SKU}-${index}`}>
<div <div
onClick={(e) => triggerCopyMessage(e, index)} onClick={() => triggerCopyMessage(index, SKU)}
className={clsx( className={clsx(
[ [
"cursor-pointer w-full border py-2 px-2 rounded", "cursor-pointer w-full border py-2 px-2 rounded",

11
lib/helpers/actions.tsx Normal file
View File

@ -0,0 +1,11 @@
export function copyText(text: string) {
navigator.clipboard.writeText(text);
}
export function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
export function getKeyByValue(object, value) {
return Object.keys(object).find(key => object[key] === value);
}