TorbatYar/frontend/modules/beauty/design-system/BeautyTablePage.tsx
Mortezakoohjani 6f4a484051 Migrate Beauty, Healthcare, and Accounting frontend to modular src/modules architecture.
Move business logic out of App Router into module packages, add boundary validation scripts, and keep all routes as thin re-exports without changing URLs or API behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 22:28:27 +03:30

69 lines
1.9 KiB
TypeScript

"use client";
import { useMemo, useState } from "react";
import { PageHeader, DataTable, EmptyState, Input } from "@/components/ds";
import { Search } from "lucide-react";
export type BeautyTableColumn = {
key: string;
header: string;
className?: string;
render?: (row: Record<string, unknown>) => React.ReactNode;
searchable?: boolean;
};
export function BeautyTablePage({
title,
description,
columns,
rows,
empty,
actions,
searchPlaceholder = "جستجو…",
filterFn,
}: {
title: string;
description?: string;
columns: BeautyTableColumn[];
rows: Record<string, unknown>[];
empty?: React.ReactNode;
actions?: React.ReactNode;
searchPlaceholder?: string;
filterFn?: (row: Record<string, unknown>, query: string) => boolean;
}) {
const [query, setQuery] = useState("");
const filtered = useMemo(() => {
const q = query.trim().toLowerCase();
if (!q) return rows;
if (filterFn) return rows.filter((r) => filterFn(r, q));
return rows.filter((r) =>
columns.some((c) => {
if (c.searchable === false) return false;
const val = r[c.key];
return val != null && String(val).toLowerCase().includes(q);
})
);
}, [rows, query, columns, filterFn]);
return (
<div>
<PageHeader title={title} description={description} actions={actions} />
<div className="relative mb-4 max-w-md">
<Search className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--muted)]" />
<Input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder={searchPlaceholder}
className="pr-10"
/>
</div>
<DataTable
columns={columns}
rows={filtered}
empty={empty ?? <EmptyState title="موردی یافت نشد" />}
/>
</div>
);
}