93 lines
3.2 KiB
TypeScript
93 lines
3.2 KiB
TypeScript
import { useState } from "react";
|
||
import { normalize } from "../lib/normalize";
|
||
import { faNum } from "../lib/formatters";
|
||
import { useClickOutside } from "./useClickOutside";
|
||
import { ConfirmDeleteDialog } from "./ConfirmDeleteDialog";
|
||
|
||
export interface SpecDrawerProps {
|
||
specs: string[];
|
||
onChange: (specs: string[]) => void;
|
||
}
|
||
|
||
// کشوی چیپ مشخصههای فنی: دکمهی «نوع (N)» → کشو با چیپها + input برای افزودن
|
||
export function SpecDrawer({ specs, onChange }: SpecDrawerProps) {
|
||
const [open, setOpen] = useState(false);
|
||
const [draft, setDraft] = useState("");
|
||
const [pendingRemove, setPendingRemove] = useState<string | null>(null);
|
||
const ref = useClickOutside<HTMLDivElement>(() => setOpen(false));
|
||
|
||
const addChip = (val?: string) => {
|
||
const v = String(val ?? draft).trim();
|
||
if (!v) return;
|
||
if (specs.some((s) => normalize(s) === normalize(v))) return;
|
||
onChange([...specs, v]);
|
||
setDraft("");
|
||
};
|
||
|
||
const removeChip = (v: string) => {
|
||
onChange(specs.filter((s) => s !== v));
|
||
};
|
||
|
||
return (
|
||
<div ref={ref} className="spec-cell">
|
||
<button
|
||
type="button"
|
||
className="spec-trigger"
|
||
title="مشخصههای فنی"
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
setOpen(true);
|
||
}}
|
||
>
|
||
<span className={`spec-trigger-label${specs.length ? "" : " muted"}`}>
|
||
{specs.length ? `مشخصه (${faNum(specs.length)})` : "مشخصه"}
|
||
</span>
|
||
<span className="text-muted">▾</span>
|
||
</button>
|
||
{open && (
|
||
<div className="spec-drawer open">
|
||
<div className="spec-chips">
|
||
{specs.map((s) => (
|
||
<span key={s} className="spec-chip">
|
||
<span className="spec-chip-t">{s}</span>
|
||
<button type="button" className="spec-chip-x" title="حذف" onClick={() => setPendingRemove(s)}>
|
||
×
|
||
</button>
|
||
</span>
|
||
))}
|
||
</div>
|
||
<div className="spec-add-row">
|
||
<input
|
||
type="text"
|
||
className="h-8 w-full rounded-lg border border-line bg-panel px-2 text-[12px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40"
|
||
placeholder="مشخصه را تایپ کنید..."
|
||
autoComplete="off"
|
||
value={draft}
|
||
onChange={(e) => setDraft(e.target.value)}
|
||
onKeyDown={(e) => {
|
||
if (e.key === "Escape") setOpen(false);
|
||
if (e.key === "Enter") {
|
||
e.preventDefault();
|
||
addChip();
|
||
}
|
||
}}
|
||
/>
|
||
<button type="button" className="spec-add-btn" title="افزودن مشخصه" onClick={() => addChip()}>
|
||
+
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
<ConfirmDeleteDialog
|
||
open={pendingRemove !== null}
|
||
itemName={pendingRemove || ""}
|
||
onConfirm={() => {
|
||
if (pendingRemove !== null) removeChip(pendingRemove);
|
||
setPendingRemove(null);
|
||
}}
|
||
onCancel={() => setPendingRemove(null)}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|