"use client"; import { useMemo, useState } from "react"; import { PageHeader, DataTable, EmptyState, Input, Pagination, Skeleton } from "@/components/ds"; import { Search } from "lucide-react"; import { CommunicationBreadcrumbs } from "@/modules/communication/components/CommunicationBreadcrumbs"; export type CommunicationTableColumn = { key: string; header: string; className?: string; render?: (row: Record) => React.ReactNode; searchable?: boolean; sortable?: boolean; defaultVisible?: boolean; }; export function CommunicationTablePage({ title, description, breadcrumb, columns, rows, empty, actions, searchPlaceholder = "جستجو…", filterFn, toolbar, page, pageSize, onPageChange, selectedIds, onSelectionChange, bulkActions, loading, }: { title: string; description?: string; breadcrumb?: string; columns: CommunicationTableColumn[]; rows: Record[]; empty?: React.ReactNode; actions?: React.ReactNode; searchPlaceholder?: string; filterFn?: (row: Record, query: string) => boolean; toolbar?: React.ReactNode; page?: number; pageSize?: number; onPageChange?: (page: number) => void; selectedIds?: Set; onSelectionChange?: (ids: Set) => void; bulkActions?: React.ReactNode; loading?: boolean; }) { const [query, setQuery] = useState(""); const [sortKey, setSortKey] = useState(null); const [sortDir, setSortDir] = useState<"asc" | "desc">("asc"); const visibleColumns = columns; const filtered = useMemo(() => { let data = rows; const q = query.trim().toLowerCase(); if (q) { data = filterFn ? data.filter((r) => filterFn(r, q)) : data.filter((r) => visibleColumns.some((c) => { if (c.searchable === false) return false; const val = r[c.key]; return val != null && String(val).toLowerCase().includes(q); }) ); } if (sortKey) { data = [...data].sort((a, b) => { const av = a[sortKey]; const bv = b[sortKey]; const cmp = String(av ?? "").localeCompare(String(bv ?? ""), "fa"); return sortDir === "asc" ? cmp : -cmp; }); } return data; }, [rows, query, visibleColumns, filterFn, sortKey, sortDir]); const paged = useMemo(() => { if (!pageSize || !page) return filtered; const start = (page - 1) * pageSize; return filtered.slice(start, start + pageSize); }, [filtered, page, pageSize]); const totalPages = pageSize ? Math.max(1, Math.ceil(filtered.length / pageSize)) : 1; if (loading) { return (
); } return (
{breadcrumb ? : null}
setQuery(e.target.value)} />
{toolbar}
{selectedIds && selectedIds.size > 0 && bulkActions ? (
{selectedIds.size} مورد انتخاب شده {bulkActions}
) : null} {paged.length === 0 ? ( empty ?? ) : ( <> ({ key: c.key, header: c.header, className: c.className, render: c.render ? (row: Record) => c.render!(row) : undefined, }))} rows={paged} /> {pageSize && page && onPageChange ? ( ) : null} )}
); }