diff --git a/src/app/dashboard/(user-dashboard)/products/[productId]/form-images/project-logo.tsx b/src/app/dashboard/(user-dashboard)/products/[productId]/form-images/project-logo.tsx new file mode 100644 index 000000000..6490e506e --- /dev/null +++ b/src/app/dashboard/(user-dashboard)/products/[productId]/form-images/project-logo.tsx @@ -0,0 +1,128 @@ +import { X } from "lucide-react"; +import React, { useState } from "react"; +import { UseFormReturn } from "react-hook-form"; + +import BlurImage from "~/components/miscellaneous/blur-image"; +import { Button } from "~/components/ui/button"; +import { cn } from "~/lib/utils"; +import { EditProduct } from "../../_components/schema/schema"; + +type Properties = { + form: UseFormReturn; + name: string; +}; +const handleImageChange = (event: React.ChangeEvent) => { + event.preventDefault(); +}; +const ProjectLogo = ({ form, name }: Properties) => { + const [isDragging, setIsDragging] = useState(false); + + const projectLogo = form.getValues("media"); + + const handleDrop = (event: React.DragEvent) => { + event.preventDefault(); + event.stopPropagation(); + + const target = event.dataTransfer.files[0] as File; + + if (target.type === "image/gif") { + return name; + } + const event_data = { + target: { + files: event.dataTransfer.files, + }, + }; + handleImageChange( + event_data as unknown as React.ChangeEvent, + ); + setIsDragging(false); + }; + + return ( +
+
+
+

+ Uploading...{" "} + 10% +

+
+
+ + {isDragging && ( +
+

Drop to upload

+
+ )} + + {projectLogo.url && typeof projectLogo.url === "string" ? ( +
+
+ +
+ +
+ ) : ( +
{ + event.preventDefault(); + event.stopPropagation(); + setIsDragging(true); + }} + onDragLeave={(event) => { + event.preventDefault(); + event.stopPropagation(); + setIsDragging(false); + }} + className="grid h-full w-full place-items-center" + > + + +
+ )} +
+ ); +}; + +export default ProjectLogo; diff --git a/src/app/dashboard/(user-dashboard)/products/[productId]/page.tsx b/src/app/dashboard/(user-dashboard)/products/[productId]/page.tsx new file mode 100644 index 000000000..3d166772b --- /dev/null +++ b/src/app/dashboard/(user-dashboard)/products/[productId]/page.tsx @@ -0,0 +1,16 @@ +import { notFound } from "next/navigation"; + +import ProductDetailsContent from "./product-details-content"; + +const ProductDetailsPage = async ({ + params, +}: { + params: { productId: string }; +}) => { + const id = params.productId; + if (!id) return notFound(); + + return ; +}; + +export default ProductDetailsPage; diff --git a/src/app/dashboard/(user-dashboard)/products/[productId]/product-details-component.tsx b/src/app/dashboard/(user-dashboard)/products/[productId]/product-details-component.tsx new file mode 100644 index 000000000..07d3bd696 --- /dev/null +++ b/src/app/dashboard/(user-dashboard)/products/[productId]/product-details-component.tsx @@ -0,0 +1,468 @@ +"use client"; + +import { zodResolver } from "@hookform/resolvers/zod"; +import { AnimatePresence, motion } from "framer-motion"; +import { ArrowLeft, Loader, Plus } from "lucide-react"; +import { useRouter } from "next-nprogress-bar"; +import Link from "next/link"; +import { useTransition } from "react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import WordCounter from "~/components/miscellaneous/WordCounter"; +import { Button } from "~/components/ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "~/components/ui/form"; +import { Input } from "~/components/ui/input"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue, +} from "~/components/ui/select"; +import { Textarea } from "~/components/ui/textarea"; +import { useProducts } from "~/hooks/admin-product/use-products.persistence"; +import { cn, generateId, getCurrentDateTime, simulateDelay } from "~/lib/utils"; +import { ProductTableProperties } from "~/types/admin-product.types"; +import { EditProductSchema, MAX_CHAR } from "../_components/schema/schema"; +import { STOCKS_SELECT } from "../data/categories.mock"; +import { shouldDisableAddStocksButton } from "../data/stocks.mock"; +import ProjectLogo from "./form-images/project-logo"; + +const ProductDetailsComponent = ({ + product, +}: { + product: ProductTableProperties; +}) => { + const { addProduct } = useProducts(); + const [isLoading, startTransition] = useTransition(); + const router = useRouter(); + + const new_product_form = useForm>({ + defaultValues: { + product_name: product.name || "", + description: product.description || "", + price: "", + category: "", + quantity: "", + media: { + url: product.image || "", + id: "", + }, + stocks: [ + { + id: "P0001", + size: "Small", + stock: "0", + price: "", + }, + { + id: "P0002", + size: "Standard", + stock: String(product.stock) || "0", + price: String(product.price) || "", + }, + { + id: "P0003", + size: "Large", + stock: "0", + price: "", + }, + ], + }, + resolver: zodResolver(EditProductSchema), + }); + const FORM_STOCKS = new_product_form.getValues("stocks"); + const handleAddNewStock = () => { + const previousStocks = FORM_STOCKS; + new_product_form.setValue("stocks", [ + ...previousStocks, + { + id: `S${generateId(5)}`, + size: "", + stock: "", + price: "", + }, + ]); + }; + + const hasProjectLogo = new_product_form.getValues("media.url"); + new_product_form.watch("stocks"); + // DISABLE + const disableAddStockButton = shouldDisableAddStocksButton({ + stocks: FORM_STOCKS, + }); + const onSubmit = async (values: z.infer) => { + startTransition(async () => { + const date_data = getCurrentDateTime(); + await simulateDelay(3); + addProduct({ + product_id: `P${generateId(6)}`, + category: values.category, + description: values.description, + name: values.product_name, + price: Number(values.price), + stock: Number(values.quantity), + image: "/product/product-image.webp", + status: "in_stock", + date_added: date_data.date_added, + time: date_data.time, + }); + new_product_form.reset(); + }); + }; + + return ( +
+ +
+
+ + + + + {product.name} + + + + {product.status === "in_stock" && "In Stock"} + {product.status === "low_on_stock" && "Low on Stock"} + {product.status === "out_of_stock" && "Out of Stock"} + +
+
+ + +
+
+
+ {" "} +
+
+
+

+ Product Details +

+

+ Make quick changes to your product. +

+
+ ( + + + Title* + + + + + + + )} + /> + ( + + + Description + + +
+