Product Detail

Product detail form with variants and media

SaaSProducts

Overview

ProductDetailForm provides a complete product editing experience with tabbed sections for basic information (name, SKU, type, description, tags), variant management (size/tier/color with price adjustments), and media gallery (image upload and reordering). Supports create and edit modes with loading and error states.

Usage

import { ProductDetailForm } from "@leanicon/web-builder-library/saas";

<ProductDetailForm
  product={existingProduct}
  onSubmit={async (data) => await saveProduct(data)}
  onCancel={() => router.back()}
  onUploadMedia={async (files) => await uploadFiles(files)}
  submitting={isSaving}
  submitError={saveError}
/>;

Variants

Create Mode

Create Product

0/5000 characters

Submitting

Edit Product

40/5000 characters

With Submit Error

Edit Product

Failed to save product. Please check your connection and try again.

40/5000 characters

Dark

Create Product

0/5000 characters

Edit Mode (code only)

<ProductDetailForm
  product={{
    id: "prod-123",
    sku: "ENT-SUITE-001",
    name: "Enterprise Suite",
    description: "A comprehensive enterprise software suite.",
    type: "digital",
    status: "published",
    tags: ["enterprise", "suite", "collaboration"],
    variants: [
      { id: "var-1", type: "tier", name: "Standard", isDefault: true },
      {
        id: "var-2",
        type: "tier",
        name: "Professional",
        priceAdjustment: { type: "fixed", value: 100 },
      },
    ],
    media: [
      {
        id: "media-1",
        url: "/screenshot.png",
        type: "image",
        alt: "Screenshot",
        order: 0,
        isPrimary: true,
      },
    ],
    createdAt: "2024-01-01T00:00:00Z",
    updatedAt: "2024-01-15T00:00:00Z",
  }}
  onSubmit={async (data) => await saveProduct(data)}
  onCancel={() => router.back()}
  onUploadMedia={async (files) => await uploadFiles(files)}
/>

Physical Product (code only)

<ProductDetailForm
  product={{
    id: "prod-widget",
    sku: "WIDGET-PRO-001",
    name: "Premium Widget",
    type: "physical",
    status: "published",
    variants: [
      { id: "size-s", type: "size", name: "Small", sku: "WIDGET-PRO-S", isDefault: true },
      {
        id: "size-m",
        type: "size",
        name: "Medium",
        sku: "WIDGET-PRO-M",
        priceAdjustment: { type: "fixed", value: 5 },
      },
      {
        id: "size-l",
        type: "size",
        name: "Large",
        sku: "WIDGET-PRO-L",
        priceAdjustment: { type: "fixed", value: 10 },
      },
    ],
    createdAt: "2024-01-01T00:00:00Z",
    updatedAt: "2024-01-15T00:00:00Z",
  }}
  onSubmit={async (data) => console.log("Submit:", data)}
  onCancel={() => console.log("Cancel")}
  onUploadMedia={async (files) => await uploadFiles(files)}
/>