From 5168553bae6d006bb5fb987375f709252034000e Mon Sep 17 00:00:00 2001 From: ianshaloom Date: Thu, 5 Mar 2026 17:38:13 +0300 Subject: [PATCH] =?UTF-8?q?feat(admin):=20implement=20product=20management?= =?UTF-8?q?=20=E2=80=94=20list,=20create,=20edit,=20archive=20(Plan=2003)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Covers checklist items 3.1–3.4, 3.10–3.11 (product list, create, edit, archive/restore, SEO fields, admin search). Backend (convex/products.ts): - Extended create/update with shortDescription, brand, attributes, seoTitle, seoDescription, canonicalSlug - Both mutations now set createdAt/updatedAt timestamps - Added getByIdForAdmin (admin-only, returns full product with relations) UI — new pages: - products/page.tsx: table with debounced search, column visibility dropdown, client-side sort, 10-row skeleton, load-more pagination, row preview dialog, per-row actions menu - products/new/page.tsx: create product page - products/[id]/edit/page.tsx: pre-populated edit page with archive button UI — new components: - ProductForm: shared form (create + edit); zod + react-hook-form, auto-slug, collapsible Attributes + SEO sections, submit spinner - ProductPreviewDialog: read-only full-product dialog - ProductActionsMenu: kebab menu (Edit link + Archive AlertDialog) ShadCN components installed: table, badge, alert-dialog, dialog, scroll-area, form, select, label, checkbox, textarea Also: - Updated CLAUDE.md: form submit buttons must use inline SVG spinner with data-icon="inline-start"; link-styled buttons use buttonVariants on (Button render prop not in TS types) - Updated docs: checklist and plan marked complete Co-Authored-By: Claude Sonnet 4.6 --- apps/admin/CLAUDE.md | 114 ++ apps/admin/components.json | 2 +- .../00-admin-dashboard-feature-checklist.md | 273 +++++ .../docs/01-admin-auth-implementation-plan.md | 1049 +++++++++++++++++ ...2-navigation-layout-implementation-plan.md | 304 +++++ ...03-products-feature-implementation-plan.md | 240 ++++ apps/admin/package.json | 7 +- .../(dashboard)/products/[id]/edit/page.tsx | 204 ++++ .../src/app/(dashboard)/products/new/page.tsx | 71 ++ .../src/app/(dashboard)/products/page.tsx | 470 +++++++- .../components/layout/DynamicBreadcrumb.tsx | 10 +- .../components/layout/sidebar/app-sidebar.tsx | 2 +- .../components/layout/sidebar/nav-main.tsx | 116 +- .../products/ProductActionsMenu.tsx | 117 ++ .../src/components/products/ProductForm.tsx | 576 +++++++++ .../products/ProductPreviewDialog.tsx | 231 ++++ apps/admin/src/components/ui/alert-dialog.tsx | 187 +++ apps/admin/src/components/ui/avatar.tsx | 22 +- apps/admin/src/components/ui/badge.tsx | 52 + apps/admin/src/components/ui/breadcrumb.tsx | 60 +- apps/admin/src/components/ui/button.tsx | 50 +- apps/admin/src/components/ui/checkbox.tsx | 29 + apps/admin/src/components/ui/collapsible.tsx | 24 +- apps/admin/src/components/ui/dialog.tsx | 157 +++ .../admin/src/components/ui/dropdown-menu.tsx | 269 +++-- apps/admin/src/components/ui/form.tsx | 136 +++ apps/admin/src/components/ui/input.tsx | 7 +- apps/admin/src/components/ui/label.tsx | 20 + apps/admin/src/components/ui/scroll-area.tsx | 55 + apps/admin/src/components/ui/select.tsx | 200 ++++ apps/admin/src/components/ui/separator.tsx | 11 +- apps/admin/src/components/ui/sheet.tsx | 70 +- apps/admin/src/components/ui/sidebar.tsx | 300 +++-- apps/admin/src/components/ui/skeleton.tsx | 2 +- apps/admin/src/components/ui/table.tsx | 116 ++ apps/admin/src/components/ui/textarea.tsx | 18 + apps/admin/src/components/ui/tooltip.tsx | 55 +- convex/products.ts | 40 + package-lock.json | 41 +- 39 files changed, 5209 insertions(+), 498 deletions(-) create mode 100644 apps/admin/CLAUDE.md create mode 100644 apps/admin/docs/00-admin-dashboard-feature-checklist.md create mode 100644 apps/admin/docs/01-admin-auth-implementation-plan.md create mode 100644 apps/admin/docs/02-navigation-layout-implementation-plan.md create mode 100644 apps/admin/docs/03-products-feature-implementation-plan.md create mode 100644 apps/admin/src/app/(dashboard)/products/[id]/edit/page.tsx create mode 100644 apps/admin/src/app/(dashboard)/products/new/page.tsx create mode 100644 apps/admin/src/components/products/ProductActionsMenu.tsx create mode 100644 apps/admin/src/components/products/ProductForm.tsx create mode 100644 apps/admin/src/components/products/ProductPreviewDialog.tsx create mode 100644 apps/admin/src/components/ui/alert-dialog.tsx create mode 100644 apps/admin/src/components/ui/badge.tsx create mode 100644 apps/admin/src/components/ui/checkbox.tsx create mode 100644 apps/admin/src/components/ui/dialog.tsx create mode 100644 apps/admin/src/components/ui/form.tsx create mode 100644 apps/admin/src/components/ui/label.tsx create mode 100644 apps/admin/src/components/ui/scroll-area.tsx create mode 100644 apps/admin/src/components/ui/select.tsx create mode 100644 apps/admin/src/components/ui/table.tsx create mode 100644 apps/admin/src/components/ui/textarea.tsx diff --git a/apps/admin/CLAUDE.md b/apps/admin/CLAUDE.md new file mode 100644 index 0000000..a15e18f --- /dev/null +++ b/apps/admin/CLAUDE.md @@ -0,0 +1,114 @@ +# Admin Dashboard UI — Implementation Rules + +Applies to all UI work inside `apps/admin/`. These rules take precedence over +general project conventions for anything under this directory. + +--- + +## 1. Component Library — ShadCN UI Only + +All UI must be composed strictly from ShadCN UI components. No other component +libraries, no raw HTML element styling where a ShadCN component exists. + +**Before building any UI, check if ShadCN has a component for it:** + +| Category | Components | +|--------------|-----------| +| Layout | `Sheet`, `Separator`, `ScrollArea`, `ResizablePanel` | +| Navigation | `NavigationMenu`, `Breadcrumb`, `Tabs` | +| Data display | `Table`, `Card`, `Badge`, `Avatar` | +| Forms | `Form`, `Input`, `Select`, `Checkbox`, `Switch`, `Textarea`, `RadioGroup`, `DatePicker` | +| Feedback | `Toast` (via Sonner), `Alert`, `Dialog`, `AlertDialog` | +| Loading | `Skeleton` | +| Actions | `Button`, `DropdownMenu`, `ContextMenu`, `Command` | + +**Install components via the ShadCN CLI — never copy-paste or hand-write ShadCN component source:** + +```bash +npx shadcn@latest add button +npx shadcn@latest add table +``` + +**ShadCN best practices:** + +- Use `cn()` from `lib/utils.ts` for all conditional className merging — never string concatenation +- Extend ShadCN components via `className` props, never modify files in `components/ui/` directly +- Use `variant` and `size` props before reaching for custom styles +- Compose complex components by combining primitives — a stat card is `Card` + `CardHeader` + `CardContent`, not a custom div +- Use `asChild` when you need to change the rendered element (e.g. wrapping a Next.js `Link` in a `Button`) + +--- + +## 2. Skills & MCP Usage + +**Always invoke the `shadcn-ui` skill** before starting any new page or significant component: + +``` +/shadcn-ui +``` + +The skill guides intentional layout, spacing, and visual hierarchy decisions within the ShadCN constraint. + +**If the ShadCN MCP server is available**, use it to look up component APIs before implementing. Do not guess prop names or variant values from memory. + +**When MCP is unavailable**, refer to https://ui.shadcn.com/docs/components before writing component usage. + +--- + +## 3. No SEO + +- No `` metadata beyond the bare minimum `layout.tsx` title +- No `generateMetadata` functions on admin pages +- No Open Graph, Twitter card, or structured data tags +- No sitemap or robots.txt entries for admin routes + +--- + +## 4. Accessibility — Required Minimums + +ShadCN handles most accessibility via Radix UI primitives. Additionally ensure: + +- All interactive elements are keyboard navigable (use ShadCN correctly and this is automatic) +- Form fields always have an associated `