'use client';
import { Download, FileText, Image as ImageIcon } from 'lucide-react';
import { CdnImage as Image } from '@/ui/shared/cdn-image';
import type { Product, ProductMetafield, DownloadFile } from 'brainerce';
import { useProductPage } from '@/core/hooks/use-product-page';
import { PriceDisplay } from '@/ui/product/price-display';
import { LoadingSpinner } from '@/ui/shared/loading-spinner';
import { VariantSelector } from '@/ui/product/variant-selector';
import { StockBadge } from '@/ui/product/stock-badge';
import { DiscountBadge } from '@/ui/product/discount-badge';
import { BackInStockForm, canOfferStockAlert } from '@/ui/product/back-in-stock-form';
import { RecommendationSection } from '@/ui/product/recommendation-section';
import { FrequentlyBoughtTogether } from '@/ui/product/frequently-bought-together';
import { CustomizationFields } from '@/ui/product/customization-fields';
import { ModifierGroupSelector } from '@/ui/product/modifier-group-selector';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
import { useTranslations } from '@/core/lib/translations';
import { cn } from '@/core/lib/utils';
import { sanitizeProductHtml } from '@/core/lib/sanitize-html';
/** Render a metafield value based on its type */
function MetafieldValue({ field }: { field: ProductMetafield }) {
const tc = useTranslations('common');
switch (field.type) {
case 'IMAGE': {
if (!field.value) return -;
return (
);
}
case 'GALLERY': {
let urls: string[] = [];
try {
const parsed = JSON.parse(field.value);
urls = Array.isArray(parsed)
? parsed.filter((u: unknown) => typeof u === 'string' && u)
: [];
} catch {
urls = field.value ? [field.value] : [];
}
if (urls.length === 0) return -;
return (
{t('filesIncluded')} ({product.downloads.length})
{modifierError}
)}{addToCartError === 'CART_FULL' ? t('cartFull') : t('addToCartFailed')}
)} {/* Sold out is not the end of the page. `canOfferStockAlert` is the whole gate — it also covers the merchant's switch and backorderable items, where an alert would tell someone to come back and do what they can already do. The selected variant is passed on purpose: without it a shopper who wanted the medium gets mailed when the small returns. */} {canOfferStockAlert(inventory, stockAlertsEnabled) && ({t('downloadAfterPurchase')}
)} {/* Description */} {description && ({description.text}
)}| {field.definitionName} |
|