From ef2d5869b06538657412bb6da9c5cd20044f1e8f Mon Sep 17 00:00:00 2001 From: Giorgi Gordiashvili Date: Mon, 13 Apr 2026 14:49:51 +0400 Subject: [PATCH] feat: implement Products List, Add Product, and Category pages Add three pages under Pages > Products: - Products List: data table with 18 products, search, status filter, sort, pagination, row selection, and delete action - Add Product: form with General Information, Media, Pricing, and Inventory cards using react-hook-form + Zod validation - Categories: data table with 10 categories, add/edit dialogs, delete action, search, and sort Uses TanStack React Table, callback-based column factories for functional row actions, and local state for CRUD operations. --- .../add/_components/add-product-form.tsx | 69 +++++ .../_components/general-information-card.tsx | 129 +++++++++ .../add/_components/inventory-card.tsx | 71 +++++ .../products/add/_components/media-card.tsx | 17 ++ .../products/add/_components/pricing-card.tsx | 56 ++++ .../pages/products/add/_data/categories.ts | 25 ++ .../add/_schemas/add-product-schema.ts | 38 +++ .../pages/products/add/page.tsx | 16 ++ .../_components/add-category-dialog.tsx | 141 ++++++++++ .../_components/categories-table-columns.tsx | 68 +++++ .../categories-table-row-actions.tsx | 51 ++++ .../_components/categories-table-toolbar.tsx | 32 +++ .../category/_components/categories-table.tsx | 202 ++++++++++++++ .../_components/edit-category-dialog.tsx | 151 ++++++++++ .../products/category/_data/categories.ts | 74 +++++ .../category/_schemas/category-schema.ts | 15 + .../pages/products/category/page.tsx | 17 ++ .../_components/products-table-columns.tsx | 127 +++++++++ .../products-table-row-actions.tsx | 49 ++++ .../_components/products-table-toolbar.tsx | 60 ++++ .../list/_components/products-table.tsx | 143 ++++++++++ .../pages/products/list/_data/products.ts | 264 ++++++++++++++++++ .../pages/products/list/page.tsx | 17 ++ .../pages/products/types.ts | 36 +++ full-kit/src/data/navigations.ts | 9 +- 25 files changed, 1871 insertions(+), 6 deletions(-) create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/add-product-form.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/general-information-card.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/inventory-card.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/media-card.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/pricing-card.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_data/categories.ts create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_schemas/add-product-schema.ts create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/page.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_components/add-category-dialog.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_components/categories-table-columns.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_components/categories-table-row-actions.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_components/categories-table-toolbar.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_components/categories-table.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_components/edit-category-dialog.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_data/categories.ts create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/_schemas/category-schema.ts create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/category/page.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/list/_components/products-table-columns.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/list/_components/products-table-row-actions.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/list/_components/products-table-toolbar.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/list/_components/products-table.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/list/_data/products.ts create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/list/page.tsx create mode 100644 full-kit/src/app/[lang]/(dashboard-layout)/pages/products/types.ts diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/add-product-form.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/add-product-form.tsx new file mode 100644 index 00000000..7b5a88e7 --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/add-product-form.tsx @@ -0,0 +1,69 @@ +"use client" + +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import { Save } from "lucide-react" + +import type { AddProductFormType } from "../../types" + +import { AddProductSchema } from "../_schemas/add-product-schema" + +import { ButtonLoading } from "@/components/ui/button" +import { Form } from "@/components/ui/form" +import { GeneralInformationCard } from "./general-information-card" +import { InventoryCard } from "./inventory-card" +import { MediaCard } from "./media-card" +import { PricingCard } from "./pricing-card" + +export function AddProductForm() { + const form = useForm({ + resolver: zodResolver(AddProductSchema), + defaultValues: { + title: "", + sku: "", + description: "", + category: "", + price: undefined, + compareAtPrice: undefined, + stock: undefined, + status: "Active", + tags: [], + }, + }) + + const { isSubmitting, isDirty } = form.formState + const isDisabled = isSubmitting || !isDirty + + function onSubmit(data: AddProductFormType) { + // Demo only — no backend + console.log("Product data:", data) + } + + return ( +
+ +
+ +
+
+ +
+ + +
+ + Save Product + +
+ + + ) +} diff --git a/full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/general-information-card.tsx b/full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/general-information-card.tsx new file mode 100644 index 00000000..3261f6ab --- /dev/null +++ b/full-kit/src/app/[lang]/(dashboard-layout)/pages/products/add/_components/general-information-card.tsx @@ -0,0 +1,129 @@ +"use client" + +import type { UseFormReturn } from "react-hook-form" +import type { AddProductFormType } from "../../types" + +import { categoryOptionsData, tagSuggestionsData } from "../_data/categories" + +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" +import { + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { Input } from "@/components/ui/input" +import { InputTagsWithSuggestions } from "@/components/ui/input-tags" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { Textarea } from "@/components/ui/textarea" + +interface GeneralInformationCardProps { + form: UseFormReturn +} + +export function GeneralInformationCard({ form }: GeneralInformationCardProps) { + return ( + + + General Information + + +
+ ( + + Title + + + + + + )} + /> + ( + + SKU + + + + + + )} + /> +
+ ( + + Description + +