import { useMemo, useState } from "react"; import { Plus, X, Trash2, Ruler } from "lucide-react"; import type { SizeChart } from "../../../src/api/types"; import { cn } from "../../lib/utils"; import { FormField } from "../ui/FormField"; import { getDefaultColumns, getSizeSuggestions, } from "../../lib/sizeChartSuggestions"; interface SizeChartSectionProps { value: SizeChart | null; onChange: (value: SizeChart | null) => void; categoryName?: string | null; /** Sizes the product currently offers (from its variants), used to seed rows. */ productSizes?: string[]; /** Product offers sizes → the chart is expected (visual emphasis + error). */ required?: boolean; /** Show the "must fill" error (set when the seller tried to proceed). */ showError?: boolean; } export function SizeChartSection({ value, onChange, categoryName, productSizes = [], required = false, showError = false, }: SizeChartSectionProps) { const [customColumn, setCustomColumn] = useState(""); const columns = value?.columns ?? []; const rows = value?.rows ?? []; const unit = value?.unit ?? "cm"; // Quick-add chips: category suggestions not already used as a column. const suggestionChips = useMemo(() => { const used = new Set(columns.map((c) => c.trim())); return getSizeSuggestions(categoryName).filter((s) => !used.has(s)); }, [categoryName, columns]); // Product sizes that don't yet have a row (offer to add them). const missingSizes = useMemo(() => { const present = new Set(rows.map((r) => r.label.trim())); return productSizes.filter((s) => s && s.trim() && !present.has(s.trim())); }, [productSizes, rows]); // Offered sizes still lacking a row or any filled measurement (blocks publish). const incompleteSizes = useMemo(() => { return productSizes.filter((s) => { const row = rows.find((r) => r.label.trim() === s.trim()); return !row || !row.values.some((v) => v && v.trim() !== ""); }); }, [productSizes, rows]); const emit = (next: Partial) => { onChange({ unit, columns, rows, ...next }); }; const initialize = () => { const seededColumns = getDefaultColumns(categoryName); const seededRows = (productSizes.length ? productSizes : [""]).map((s) => ({ label: s, values: seededColumns.map(() => ""), })); onChange({ unit: "cm", columns: seededColumns, rows: seededRows }); }; const addColumn = (name: string) => { const trimmed = name.trim(); if (!trimmed || columns.includes(trimmed)) return; emit({ columns: [...columns, trimmed], rows: rows.map((r) => ({ ...r, values: [...r.values, ""] })), }); }; const renameColumn = (index: number, name: string) => { emit({ columns: columns.map((c, i) => (i === index ? name : c)) }); }; const removeColumn = (index: number) => { emit({ columns: columns.filter((_, i) => i !== index), rows: rows.map((r) => ({ ...r, values: r.values.filter((_, i) => i !== index), })), }); }; const addRow = (label = "") => { emit({ rows: [...rows, { label, values: columns.map(() => "") }] }); }; const addMissingSizes = () => { emit({ rows: [ ...rows, ...missingSizes.map((label) => ({ label, values: columns.map(() => ""), })), ], }); }; const setRowLabel = (index: number, label: string) => { emit({ rows: rows.map((r, i) => (i === index ? { ...r, label } : r)) }); }; const setCell = (rowIndex: number, colIndex: number, val: string) => { emit({ rows: rows.map((r, i) => i === rowIndex ? { ...r, values: r.values.map((v, j) => (j === colIndex ? val : v)), } : r ), }); }; const removeRow = (index: number) => { emit({ rows: rows.filter((_, i) => i !== index) }); }; const cellInput = "w-20 rounded-lg border border-GRAY3 bg-WHITE px-2 py-1.5 text-center text-R12 outline-none focus:border-VITROWN_BLUE"; return (

اندازه‌های هر سایز را وارد کنید تا خریدار بداند مثلاً «لارج» برای این محصول چه اندازه‌ای است.

{value == null ? ( <> {required && showError && (

این محصول سایز دارد؛ پر کردن راهنمای سایز الزامی است.

)} ) : (
{required && showError && incompleteSizes.length > 0 && (

برای این سایزها هنوز اندازه‌ای وارد نشده: {incompleteSizes.join("، ")}

)}
اندازه‌ها به سانتی‌متر
{/* Grid */}
{columns.map((col, ci) => ( ))} {rows.map((row, ri) => ( {columns.map((_, ci) => ( ))} ))}
سایز
renameColumn(ci, e.target.value)} placeholder="نام اندازه" className="w-24 rounded-lg border border-GRAY3 bg-WHITE3 px-2 py-1.5 text-center text-R12 font-bold outline-none focus:border-VITROWN_BLUE" />
setRowLabel(ri, e.target.value)} placeholder="سایز" className="w-16 rounded-lg border border-GRAY3 bg-WHITE3 px-2 py-1.5 text-center text-R12 font-bold outline-none focus:border-VITROWN_BLUE" />
setCell(ri, ci, e.target.value)} inputMode="numeric" placeholder="—" dir="ltr" className={cellInput} />
{/* Add row / add missing product sizes */}
{missingSizes.length > 0 && ( )}
{/* Quick-add measurement columns */} {suggestionChips.length > 0 && (
اندازه‌های پیشنهادی:
{suggestionChips.map((chip) => ( ))}
)} {/* Custom column */}
setCustomColumn(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addColumn(customColumn); setCustomColumn(""); } }} placeholder="اندازه دلخواه (مثلاً دور یقه)" className="w-full rounded-lg border border-GRAY3 bg-WHITE pr-7 pl-2 py-1.5 text-R12 outline-none focus:border-VITROWN_BLUE" />
{/* Remove whole chart */}
)}
); } export default SizeChartSection;