{
  "name": "product-variant-02-block",
  "type": "registry:block",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "button",
    "badge",
    "separator",
    "https://ui.stackzero.co/r/image-viewer-basic.json",
    "https://ui.stackzero.co/r/price-format-sale.json",
    "https://ui.stackzero.co/r/variant-selector-basic.json",
    "https://ui.stackzero.co/r/quantity-input-basic.json"
  ],
  "files": [
    {
      "type": "registry:block",
      "content": "\"use client\";\n\nimport ImageViewer from \"@/components/commerce-ui/image-viewer-basic\";\nimport PriceFormat_Sale from \"@/components/commerce-ui/price-format-sale\";\nimport QuantityInputBasic from \"@/components/commerce-ui/quantity-input-basic\";\nimport VariantSelectorBasic, {\n  VariantItem as BaseVariantItem,\n} from \"@/components/commerce-ui/variant-selector-basic\";\nimport { Button } from \"@/components/ui/button\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { Clock } from \"lucide-react\";\nimport Link from \"next/link\";\nimport { useState } from \"react\";\n\ninterface VariantItem extends BaseVariantItem {\n  price: number;\n  salePrice?: number;\n  imageUrl?: string;\n  isInStock?: boolean; // Added stock status per variant\n  availableQuantity?: number | null; // Added quantity per variant\n}\n\ninterface VariantSelectionPayload {\n  variantId: string;\n  variantLabel: string;\n  quantity: number;\n  price: number;\n  originalPrice?: number;\n  salePrice?: number;\n  totalPrice: number;\n  isOnSale: boolean;\n}\n\ninterface ProductVariant02Props {\n  title?: string;\n  description?: string;\n  badge?: string | null;\n  shippingInfo?: string;\n  variants: VariantItem[];\n  defaultImage?: string;\n  initialVariant?: string;\n  variantLabel?: string;\n  onAddToCart?: (payload: VariantSelectionPayload) => void;\n  onBuyNow?: (payload: VariantSelectionPayload) => void;\n  selectedVariant?: string;\n  onVariantChange?: (variant: string) => void;\n  quantity?: number;\n  onQuantityChange?: (quantity: number) => void;\n  isLoading?: boolean;\n  errorMessage?: string | null;\n  sellerName?: string;\n  marketplaceName?: string;\n  returnPolicyUrl?: string;\n}\n\nfunction ProductVariant_02({\n  badge = \"New\",\n  defaultImage,\n  description = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\",\n  errorMessage = null,\n  initialVariant,\n  isLoading = false,\n  marketplaceName = \"Lorem Marketplace\",\n  onAddToCart = () => {},\n  onBuyNow = () => {},\n  onQuantityChange,\n  onVariantChange,\n  quantity: controlledQuantity,\n  returnPolicyUrl = \"/\",\n  selectedVariant: controlledVariant,\n  sellerName = \"Seller Name\",\n  shippingInfo = \"Free shipping\",\n  title = \"Product Variant Title\",\n  variantLabel = \"Variant\",\n  variants = [],\n}: ProductVariant02Props) {\n  // Ensure variants array is not empty\n  if (!variants.length) {\n    throw new Error(\"At least one variant must be provided\");\n  }\n\n  const defaultInitialVariant = initialVariant || variants[0].value;\n\n  const [internalSelectedVariant, setInternalSelectedVariant] = useState(\n    defaultInitialVariant\n  );\n  const [internalQuantity, setInternalQuantity] = useState(1);\n\n  // Determine if we're in controlled or uncontrolled mode\n  const isVariantControlled = controlledVariant !== undefined;\n  const isQuantityControlled = controlledQuantity !== undefined;\n  const selectedVariantId = isVariantControlled\n    ? controlledVariant\n    : internalSelectedVariant;\n  const quantity = isQuantityControlled ? controlledQuantity : internalQuantity;\n\n  const handleVariantChange = (newVariant: string) => {\n    if (isVariantControlled) {\n      onVariantChange?.(newVariant);\n    } else {\n      setInternalSelectedVariant(newVariant);\n\n      // Reset quantity if changing to a variant with less available quantity\n      const newSelectedVariant = variants.find((v) => v.value === newVariant);\n      if (\n        newSelectedVariant?.isInStock &&\n        newSelectedVariant.availableQuantity !== null &&\n        newSelectedVariant.availableQuantity !== undefined &&\n        quantity > newSelectedVariant.availableQuantity\n      ) {\n        handleQuantityChange(newSelectedVariant.availableQuantity);\n      }\n    }\n  };\n\n  const handleQuantityChange = (newQuantity: number) => {\n    if (isQuantityControlled) {\n      onQuantityChange?.(newQuantity);\n    } else {\n      setInternalQuantity(newQuantity);\n    }\n  };\n\n  const selectedVariant =\n    variants.find((v) => v.value === selectedVariantId) || variants[0];\n\n  const currentImage = selectedVariant?.imageUrl || defaultImage;\n  const currentPrice = selectedVariant.price;\n  const currentSalePrice = selectedVariant.salePrice;\n  const isOnSale =\n    currentSalePrice !== undefined && currentSalePrice < currentPrice;\n\n  // Get stock status from the selected variant\n  const isInStock =\n    selectedVariant.isInStock !== undefined ? selectedVariant.isInStock : true; // Default to in stock if not specified\n\n  const availableQuantity = selectedVariant.availableQuantity;\n\n  const effectivePrice = isOnSale ? currentSalePrice : currentPrice;\n\n  const handleAddToCart = () => {\n    onAddToCart({\n      isOnSale,\n      originalPrice: isOnSale ? currentPrice : undefined,\n      price: currentPrice,\n      quantity,\n      salePrice: isOnSale ? currentSalePrice : undefined,\n      totalPrice: quantity * effectivePrice,\n      variantId: selectedVariantId,\n      variantLabel: selectedVariant?.label || \"\",\n    });\n  };\n\n  const handleBuyNow = () => {\n    onBuyNow({\n      isOnSale,\n      originalPrice: isOnSale ? currentPrice : undefined,\n      price: currentPrice,\n      quantity,\n      salePrice: isOnSale ? currentSalePrice : undefined,\n      totalPrice: quantity * effectivePrice,\n      variantId: selectedVariantId,\n      variantLabel: selectedVariant?.label || \"\",\n    });\n  };\n\n  if (errorMessage) {\n    return (\n      <div className=\"my-6 rounded-lg border border-red-200 bg-red-50 p-6 text-red-600 dark:border-red-900 dark:bg-red-900/20 dark:text-red-400\">\n        <p className=\"font-medium\">Error loading product</p>\n        <p className=\"text-sm\">{errorMessage}</p>\n      </div>\n    );\n  }\n\n  // Add visual indicator for out of stock items in variant selector\n  const variantsWithStockIndicator = variants.map((variant) => {\n    const isVariantInStock =\n      variant.isInStock !== undefined ? variant.isInStock : true;\n    return {\n      ...variant,\n      disabled: !isVariantInStock,\n      label: variant.label + (isVariantInStock ? \"\" : \" (Out of Stock)\"),\n    };\n  });\n\n  return (\n    <div className=\"grid max-w-screen-lg grid-cols-1 gap-6 md:grid-cols-3 md:gap-8\">\n      <div className=\"col-span-1 md:col-span-2\">\n        <div>\n          <div className=\"relative w-full overflow-hidden rounded-xl bg-gradient-to-br from-rose-50 to-orange-50 p-6 dark:from-rose-950/30 dark:to-orange-950/30\">\n            {badge && (\n              <span className=\"absolute top-4 left-4 z-10 rounded-full bg-gradient-to-r from-rose-500 to-red-700 px-3 py-1.5 text-xs font-semibold text-white\">\n                {badge}\n              </span>\n            )}\n            <div className=\"transition-transform duration-500 hover:scale-105\">\n              {isLoading ? (\n                <div className=\"flex h-[300px] items-center justify-center\">\n                  <div className=\"h-10 w-10 animate-spin rounded-full border-4 border-rose-200 border-t-rose-600\"></div>\n                </div>\n              ) : (\n                <ImageViewer\n                  imageUrl={currentImage || \"\"}\n                  classNameThumbnailViewer=\"rounded-lg object-contain h-[300px] mx-auto\"\n                />\n              )}\n            </div>\n          </div>\n        </div>\n        <div className=\"mt-4 flex flex-col gap-4 md:mt-6 md:gap-6\">\n          <div>\n            <h2 className=\"text-xl font-bold tracking-tight text-gray-900 sm:text-2xl dark:text-gray-100\">\n              {title}\n            </h2>\n            <p className=\"mt-2 text-sm text-gray-600 sm:text-base dark:text-gray-400\">\n              {description}\n            </p>\n          </div>\n\n          <div className=\"space-y-4\">\n            <div>\n              <label className=\"mb-2 block text-sm font-medium text-gray-700 dark:text-gray-300\">\n                {variantLabel}\n              </label>\n              <VariantSelectorBasic\n                value={selectedVariantId}\n                onValueChange={handleVariantChange}\n                variants={variantsWithStockIndicator}\n                className=\"grid-cols-2 sm:grid-cols-2\"\n                itemClassName=\"bg-gray-50 border-gray-200 hover:border-rose-300 dark:bg-gray-800 dark:border-gray-700\n                            data-[state=checked]:border-rose-500 data-[state=checked]:bg-rose-50 \n                            data-[state=checked]:text-rose-700 dark:data-[state=checked]:bg-gray-700 \n                            dark:data-[state=checked]:border-rose-500 dark:data-[state=checked]:text-rose-300\n                            focus:ring-2 focus:ring-rose-500/50 focus:ring-offset-2 focus:border-rose-400\n                            dark:focus:ring-rose-500/40 dark:focus:ring-offset-gray-900\"\n              />\n            </div>\n          </div>\n\n          {isInStock ? (\n            <div className=\"rounded-md bg-green-50 p-3 text-green-800 dark:bg-green-900/20 dark:text-green-300\">\n              <p className=\"text-sm font-bold\">In Stock</p>\n              {availableQuantity !== null &&\n                availableQuantity !== undefined &&\n                availableQuantity > 0 && (\n                  <span className=\"mt-1 text-sm font-normal\">\n                    {availableQuantity} units available\n                  </span>\n                )}\n            </div>\n          ) : (\n            <div className=\"rounded-md bg-amber-50 p-3 text-amber-800 dark:bg-amber-900/20 dark:text-amber-300\">\n              <p className=\"text-sm font-bold\">Currently out of stock</p>\n            </div>\n          )}\n\n          <div className=\"mt-2 md:mt-4\">\n            <p className=\"text-sm font-medium text-gray-800 dark:text-gray-200\">\n              Selected Configuration:\n            </p>\n            <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n              {selectedVariant.label} - ${effectivePrice.toFixed(2)}\n            </p>\n            <p className=\"mt-1 text-xs text-gray-500\">\n              {isInStock ? \"In Stock\" : \"Out of Stock\"}\n              {isInStock &&\n                availableQuantity !== null &&\n                availableQuantity !== undefined &&\n                ` (${availableQuantity} available)`}\n            </p>\n          </div>\n        </div>\n      </div>\n      <div className=\"flex flex-col gap-4 md:gap-2\">\n        <div className=\"rounded-md outline outline-rose-500\">\n          <div className=\"rounded-md rounded-b-none bg-gradient-to-r from-rose-500 to-red-600 p-3\">\n            <p className=\"font-semibold text-white\">\n              Get Free Shipping and 1-day delivery!\n            </p>\n          </div>\n\n          <div className=\"bg-rose-50/60 p-4 dark:bg-rose-900/20\">\n            <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n              Enjoy exclusive benefits and discounts. 30-day free trial.\n            </p>\n            <Button\n              variant=\"link\"\n              className=\"mt-1 w-full text-rose-600 hover:text-rose-700 dark:text-rose-400 dark:hover:text-rose-300\"\n            >\n              Join Now\n            </Button>\n          </div>\n        </div>\n        <div className=\"flex flex-col gap-4 rounded-md border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-800 dark:bg-gray-900\">\n          <PriceFormat_Sale\n            prefix=\"$\"\n            originalPrice={currentPrice}\n            salePrice={isOnSale ? currentSalePrice : undefined}\n            showSavePercentage\n            className=\"text-3xl font-semibold text-gray-600 dark:text-gray-300\"\n            classNameSalePrice=\"text-3xl font-bold text-rose-600 dark:text-rose-400\"\n            classNameSalePercentage=\"rounded-sm bg-green-500/50 p-1 text-xs font-medium text-white\"\n          />\n          {shippingInfo && (\n            <p className=\"mt-1 inline-flex items-center text-sm text-green-600 dark:text-green-400\">\n              <Clock className=\"mr-1 h-4 w-4\" />\n              {shippingInfo}\n            </p>\n          )}\n\n          <div className=\"flex items-center gap-2\">\n            <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n              Quantity:{\" \"}\n            </label>\n            <QuantityInputBasic\n              quantity={quantity}\n              onChange={handleQuantityChange}\n              max={\n                availableQuantity !== null && availableQuantity !== undefined\n                  ? availableQuantity\n                  : undefined\n              }\n              min={1}\n              className=\"border-gray-300 dark:border-gray-700\"\n              disabled={!isInStock}\n            />\n          </div>\n\n          <div className=\"flex w-full flex-col gap-3 sm:gap-4\">\n            <Button\n              variant=\"outline\"\n              className=\"w-full border-gray-300 bg-white py-5 text-base text-gray-800 transition-all duration-200 hover:border-rose-500 hover:bg-rose-50 hover:text-rose-700 sm:py-2 sm:text-sm dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:border-rose-500 dark:hover:bg-gray-700\"\n              onClick={handleAddToCart}\n              disabled={!isInStock || isLoading}\n            >\n              {isLoading ? \"Loading...\" : \"Add to Cart\"}\n            </Button>\n            <Button\n              className=\"w-full bg-gradient-to-r from-rose-600 to-red-600 py-5 text-base text-white transition-all hover:from-rose-700 hover:to-red-700 sm:py-2 sm:text-sm\"\n              onClick={handleBuyNow}\n              disabled={!isInStock || isLoading}\n            >\n              {isLoading ? \"Loading...\" : \"Buy Now\"}\n            </Button>\n          </div>\n\n          <Separator className=\"my-4\" />\n\n          {/* Bottom section: Stock info and call-to-action buttons */}\n          <div className=\"grid grid-cols-3 gap-2 text-xs sm:text-sm\">\n            <div className=\"col-span-1 text-gray-600 dark:text-gray-400\">\n              Sold by:\n            </div>\n            <div className=\"col-span-2\">\n              <Link\n                href=\"/\"\n                className=\"text-rose-600 hover:text-rose-700 hover:underline dark:text-rose-400 dark:hover:text-rose-300\"\n              >\n                {sellerName}\n              </Link>\n            </div>\n            <div className=\"col-span-1 text-gray-600 dark:text-gray-400\">\n              Shipping:\n            </div>\n            <div className=\"col-span-2\">\n              <Link\n                href=\"/\"\n                className=\"text-rose-600 hover:text-rose-700 hover:underline dark:text-rose-400 dark:hover:text-rose-300\"\n              >\n                {marketplaceName}\n              </Link>\n            </div>\n            <div className=\"col-span-1 text-gray-600 dark:text-gray-400\">\n              Return Policy:{\" \"}\n            </div>\n            <div className=\"col-span-2\">\n              <Link\n                href={returnPolicyUrl}\n                className=\"text-rose-600 hover:text-rose-700 hover:underline dark:text-rose-400 dark:hover:text-rose-300\"\n              >\n                View our Return Policy\n              </Link>\n            </div>\n            <div className=\"col-span-1 text-gray-600 dark:text-gray-400\">\n              Payment:\n            </div>\n            <div className=\"col-span-2\">Secure Payment</div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport default ProductVariant_02;\nexport type { ProductVariant02Props, VariantItem, VariantSelectionPayload };\n",
      "path": "/components/commerce-ui/blocks/product-variants/product-variants-02.tsx",
      "target": "components/commerce-ui/product-variants-02.tsx"
    }
  ]
}