import { useEffect, useMemo, useState } from "react"; import { Link, useParams } from "react-router-dom"; import { MapPin, Phone, User, Plus, Package, X } from "lucide-react"; import { toast } from "sonner"; import { useMaterials, useQuotes, useStoreData, useSuppliers } from "../../hooks"; import { topicByName } from "../../lib/topics"; import { useAppStore } from "../../store"; import { api } from "../../lib/api"; import { Header, PageLayout } from "../../components/layout/Header"; import { EmptyState } from "../../components/EmptyState"; import { Badge } from "../../components/ui/badge"; import { MultiSelectCombobox } from "../../components/MultiSelectCombobox"; import { ConfirmDeleteDialog } from "../../components/ConfirmDeleteDialog"; import { normalize } from "../../lib/normalize"; import { PurchaseHistory } from "./PurchaseHistory"; // صفحه‌ی مشخصات کامل تأمین‌کننده + سابقه خرید + مدیریت متریال‌های تأمین‌شده export function SupplierDetailPage() { useStoreData(); const { id = "" } = useParams(); const suppliers = useSuppliers(); const quotes = useQuotes(); const materials = useMaterials(); const topics = useAppStore((s) => s.topics); const s = useMemo(() => suppliers.find((x) => x.id === id) || null, [suppliers, id]); const [pendingRemove, setPendingRemove] = useState(null); // متریال‌های متصل واقعی (از اتصال تأمین‌کننده-متریال بک‌اند) const [linked, setLinked] = useState([]); const [busy, setBusy] = useState(false); useEffect(() => { if (!id) return; let alive = true; void api.supplierMaterials .list(id) .then((rows) => alive && setLinked(rows.map((r) => r.material_name).filter(Boolean))) .catch(() => alive && setLinked([])); return () => { alive = false; }; }, [id]); // متریال‌های تأمین‌شده (نام متریال‌ها) برای پیشنهاد در کومبوکس const materialOptions = useMemo(() => { const set = new Set(); materials.forEach((m) => m.name && set.add(m.name)); return [...set].sort((a, b) => a.localeCompare(b, "fa")); }, [materials]); // دسته‌ی این تأمین‌کننده — دسته فقط برچسبِ خودِ تأمین‌کننده است (v2.7) const purchased = useMemo(() => [...(s?.categories || [])].sort((a, b) => a.localeCompare(b, "fa")), [s]); if (!s) { return (
); } const topic = topicByName(s.topic, topics); const topicName = topic ? topic.name : s.topic; const firstCat = (s.categories || [])[0] || ""; const breadcrumb = `${topicName ? topicName + " — " : ""}${firstCat ? firstCat + " — " : ""}${s.name}`; const saveCategories = (names: string[]) => { // v2.6: اتصال واقعی تأمین‌کننده ↔ متریال (کاتالوگ) — با نام متریال if (!id || busy) return; setBusy(true); void (async () => { try { for (const name of names) { if (linked.some((x) => normalize(x) === normalize(name))) continue; const mat = materials.find((m) => normalize(m.name) === normalize(name)); if (!mat) { toast.error(`متریال «${name}» در کاتالوگ یافت نشد — ابتدا از ویزارد بسازید.`); continue; } await api.supplierMaterials.create(id, mat.id); } const rows = await api.supplierMaterials.list(id); setLinked(rows.map((r) => r.material_name).filter(Boolean)); toast.success("متریال‌ها ذخیره شدند."); } catch (err) { toast.error(err instanceof Error ? err.message : "ذخیره‌ی متریال‌ها ناموفق بود"); } finally { setBusy(false); } })(); }; const removeCat = (name: string) => { if (!id || busy) return; setBusy(true); void (async () => { try { const mat = materials.find((m) => normalize(m.name) === normalize(name)); if (mat) await api.supplierMaterials.remove(id, mat.id); const rows = await api.supplierMaterials.list(id); setLinked(rows.map((r) => r.material_name).filter(Boolean)); toast.success("متریال حذف شد."); } catch (err) { toast.error(err instanceof Error ? err.message : "حذف متریال ناموفق بود"); } finally { setBusy(false); } })(); }; return (
{s.name}
{topicName}
موقعیت: {s.location || "—"} تلفن: {s.phone || "—"} شخص رابط: {s.contact || "—"}
پیشنهاد جدید {firstCat ? ( ‹ بازگشت به دسته ) : ( ‹ بازگشت به دسته‌بندی‌ها )}
{/* متریال‌های این تأمین‌کننده — افزودن/حذف + مشاهده‌ی همه */}

متریال‌های تأمین‌شده

متریال‌هایی که این تأمین‌کننده عرضه می‌کند را اینجا مدیریت کنید.
{(linked || []).length > 0 && (
{linked.map((c) => ( {c} ))}
)} saveCategories(cats)} options={materialOptions} placeholder="افزودن متریال..." /> {purchased.length > 0 && (
متریال‌های خریداری‌شده (از پیشنهادها):
{purchased.map((c) => ( {c} ))}
)}
{/* سابقه خرید از این تأمین‌کننده — همه‌ی پیشنهادها + فاکتور/پیش‌فاکتور */}
{ if (pendingRemove !== null) removeCat(pendingRemove); setPendingRemove(null); }} onCancel={() => setPendingRemove(null)} />
); }