import { useMemo, useState, type ReactNode } from 'react'; import { ChevronLeft, ChevronRight, Search } from 'lucide-react'; import { Button, Card } from './ui'; export type DataTableColumn = { key: string; header: string; className?: string; cell: (row: T) => ReactNode; }; export type DataTableFilter = { key: string; label: string; options: Array<{ label: string; value: string }>; getValue: (row: T) => string; }; export function DataTableCard({ title, description, rows, columns, filters = [], searchPlaceholder = '검색', getSearchText, getRowKey, pageSize = 8, minWidth = 980, loading = false, emptyMessage = '데이터가 없습니다.' }: { title: string; description?: string; rows: T[]; columns: Array>; filters?: Array>; searchPlaceholder?: string; getSearchText: (row: T) => string; getRowKey: (row: T) => string; pageSize?: number; minWidth?: number; loading?: boolean; emptyMessage?: string; }) { const [search, setSearch] = useState(''); const [filterValues, setFilterValues] = useState>({}); const [page, setPage] = useState(1); const filteredRows = useMemo(() => { const normalizedSearch = search.trim().toLowerCase(); return rows.filter((row) => { const matchesSearch = normalizedSearch ? getSearchText(row).toLowerCase().includes(normalizedSearch) : true; const matchesFilters = filters.every((filter) => { const selected = filterValues[filter.key]; return !selected || filter.getValue(row) === selected; }); return matchesSearch && matchesFilters; }); }, [filterValues, filters, getSearchText, rows, search]); const totalPages = Math.max(1, Math.ceil(filteredRows.length / pageSize)); const currentPage = Math.min(page, totalPages); const pageRows = filteredRows.slice((currentPage - 1) * pageSize, currentPage * pageSize); const updateFilter = (key: string, value: string) => { setFilterValues((prev) => ({ ...prev, [key]: value })); setPage(1); }; return (

{title}

{description ?

{description}

: null}
{ setSearch(event.target.value); setPage(1); }} />
{filters.length ? (
{filters.map((filter) => ( ))}
) : null}
{columns.map((column) => ( ))} {!loading && pageRows.map((row) => ( {columns.map((column) => ( ))} ))} {!loading && pageRows.length === 0 ? ( ) : null}
{column.header}
{column.cell(row)}
{emptyMessage}
{loading ? '불러오는 중' : `총 ${filteredRows.length}건 · ${currentPage} / ${totalPages}`}
); }