"use client"; import { useRef, useState } from "react"; import ImageCropDialog from "@/components/ImageCropDialog"; import styles from "./CatalogForm.module.css"; export type LocalImage = { key: string; file?: File; previewUrl: string; mediaId?: string; }; export function FeaturedImageField({ label = "Thumbnail", value, aspect = 1, disabled, onChange, }: { label?: string; value: LocalImage | null; aspect?: number; disabled?: boolean; onChange: (value: LocalImage | null) => void; }) { const inputRef = useRef(null); const [cropSource, setCropSource] = useState(null); const [cropName, setCropName] = useState("image.jpg"); const wide = aspect !== 1; return (
{label}
{value ? ( ) : null}
{ const file = event.target.files?.[0]; event.target.value = ""; if (!file) return; const url = URL.createObjectURL(file); setCropName(file.name || "image.jpg"); setCropSource(url); }} /> { if (cropSource?.startsWith("blob:")) URL.revokeObjectURL(cropSource); setCropSource(null); }} onComplete={(file, previewUrl) => { if (cropSource?.startsWith("blob:")) URL.revokeObjectURL(cropSource); if (value?.previewUrl.startsWith("blob:")) { URL.revokeObjectURL(value.previewUrl); } setCropSource(null); onChange({ key: `${Date.now()}`, file, previewUrl, }); }} />
); } export function GalleryImagesField({ items, disabled, onChange, }: { items: LocalImage[]; disabled?: boolean; onChange: (items: LocalImage[]) => void; }) { const inputRef = useRef(null); return (
Gallery images (optional)
{items.length ? (
{items.map((item) => (
))}
) : ( )} { const files = Array.from(event.target.files ?? []).filter((file) => file.type.startsWith("image/"), ); event.target.value = ""; if (!files.length) return; onChange([ ...items, ...files.map((file) => ({ key: `${file.name}-${file.size}-${Date.now()}-${Math.random()}`, file, previewUrl: URL.createObjectURL(file), })), ]); }} />
); } export function TagsField({ tags, disabled, onChange, }: { tags: string[]; disabled?: boolean; onChange: (tags: string[]) => void; }) { const [draft, setDraft] = useState(""); function addTag() { const next = draft.trim(); if (!next) return; if (tags.some((tag) => tag.toLowerCase() === next.toLowerCase())) { setDraft(""); return; } onChange([...tags, next]); setDraft(""); } return (
Tags (optional) {tags.length ? (
{tags.map((tag) => ( {tag} ))}
) : null}
setDraft(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter") { event.preventDefault(); addTag(); } }} />
); }