"use client"; import { useQuery } from "@tanstack/react-query"; import { PageHeader, LoadingState, ErrorState, Badge, Card, CardContent, EmptyState, } from "@/components/ds"; import { crmApi, CrmApiError } from "@/modules/crm/services/crm-api"; import { useTenantId } from "@/hooks/useTenantId"; import { CrmStatGrid } from "@/modules/crm/design-system"; export function CrmPageLoader({ label = "در حال بارگذاری…" }: { label?: string }) { return ; } export function CrmPageError({ error, onRetry, }: { error: unknown; onRetry?: () => void; }) { if (error instanceof CrmApiError && error.status === 403) { return ( ); } const message = error instanceof Error ? error.message : "خطا در دریافت داده‌ها"; return ; } export function useCrmHealth() { return useQuery({ queryKey: ["crm", "health"], queryFn: () => crmApi.health(), }); } export function CrmServiceBadge() { const healthQ = useCrmHealth(); if (!healthQ.data) return null; return ( CRM v{healthQ.data.version} ); } export function useCrmCounts(tenantId: string | null) { return useQuery({ queryKey: ["crm", tenantId, "counts"], queryFn: async () => { const [leads, contacts, orgs, opps, activities, tasks, meetings, calls] = await Promise.all([ crmApi.leads.list(tenantId!, { page: 1, page_size: 500 }), crmApi.contacts.list(tenantId!, { page: 1, page_size: 500 }), crmApi.organizations.list(tenantId!, { page: 1, page_size: 500 }), crmApi.opportunities.list(tenantId!, { page: 1, page_size: 500 }), crmApi.activities.list(tenantId!, { page: 1, page_size: 500 }), crmApi.tasks.list(tenantId!, { page: 1, page_size: 500 }), crmApi.meetings.list(tenantId!, { page: 1, page_size: 500 }), crmApi.calls.list(tenantId!, { page: 1, page_size: 500 }), ]); return { leads: leads.length, contacts: contacts.length, organizations: orgs.length, opportunities: opps.length, activities: activities.length, tasks: tasks.length, meetings: meetings.length, calls: calls.length, openDeals: opps.filter((o) => o.status === "open").length, wonDeals: opps.filter((o) => o.status === "won").length, }; }, enabled: !!tenantId, }); } export function CrmCountsGrid({ tenantId }: { tenantId: string }) { const q = useCrmCounts(tenantId); if (q.isLoading) return ; if (q.error) return q.refetch()} />; const c = q.data!; return ( ); } export function exportToCsv(filename: string, rows: Record[], columns: string[]) { const header = columns.join(","); const lines = rows.map((r) => columns.map((c) => JSON.stringify(r[c] ?? "")).join(",") ); const blob = new Blob(["\uFEFF" + [header, ...lines].join("\n")], { type: "text/csv;charset=utf-8;", }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); }