"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import type { InventoryAvailability } from "@salixcommerce/core"; import { PriceDisplay, QuantitySelector } from "./storefront"; import { Notification, StatusBadge } from "./ui"; export interface PresentedVariant { readonly availability: InventoryAvailability; readonly formattedPrice: string; readonly id: string; readonly name: string; } export function VariantSelector({ commerceEnabled, variants, }: Readonly<{ commerceEnabled: boolean; variants: readonly PresentedVariant[] }>) { const router = useRouter(); const [selectedId, setSelectedId] = useState(variants[0]?.id ?? ""); const [quantity, setQuantity] = useState(1); const [pending, setPending] = useState(false); const [message, setMessage] = useState(null); const selected = variants.find((variant) => variant.id === selectedId) ?? variants[0]; if (selected === undefined) return null; const selectedVariantId = selected.id; const purchasable = commerceEnabled && selected.availability !== "out_of_stock" && Number.isInteger(quantity); async function addToCart() { if (!purchasable || quantity < 1 || quantity > 99) return; setPending(true); setMessage(null); try { const response = await fetch("/api/cart/items", { body: JSON.stringify({ idempotencyKey: crypto.randomUUID(), operation: "increment", quantity, variantId: selectedVariantId, }), headers: { "content-type": "application/json" }, method: "POST", }); const payload: unknown = await response.json(); if (!response.ok) { setMessage(readApiMessage(payload)); return; } router.push("/cart"); router.refresh(); } catch { setMessage("The cart request could not be completed."); } finally { setPending(false); } } return (
{availabilityLabel(selected.availability)} {message === null ? null : (

{message}

)}
); } function readApiMessage(value: unknown): string { if ( typeof value === "object" && value !== null && "error" in value && typeof value.error === "object" && value.error !== null && "message" in value.error && typeof value.error.message === "string" ) { return value.error.message; } return "The cart request could not be completed."; } function availabilityLabel(availability: InventoryAvailability): string { switch (availability) { case "backorder": return "Available to backorder"; case "in_stock": return "In stock"; case "out_of_stock": return "Out of stock"; case "untracked": return "Available"; } }