shoc-frontend-new/src/components/ui/resource-list-table.tsx
Arthur Bassi a3e8a533b1 fix(ui): align shared board plumbing with ky v2 and react-router
- api.ts: use ky v2 hook object args, prefix (not prefixUrl), and normalizeApiRequestError
- replace react-router-dom with react-router in layout, topbar, and vendor-pos view
- move MUI style props (justifyContent, alignItems, flexWrap, display, fontWeight) into sx
- resource-list-table/query-key: use local types instead of missing work-order-list module
2026-07-17 13:31:56 -03:00

96 lines
2.5 KiB
TypeScript

import type { ReactNode } from "react";
import {
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from "@mui/material";
import { TableEmptyRow, TableLoadingRow } from "@/components/ui/table-state-rows";
export type SortDirection = "asc" | "desc" | "";
export type ResourceListColumn<T> = {
id: string;
header: ReactNode;
render: (row: T) => ReactNode;
sortable?: boolean;
headerClassName?: string;
cellClassName?: string;
align?: "left" | "center" | "right";
};
type ResourceListTableProps<T> = {
columns: ResourceListColumn<T>[];
rows: T[];
rowKey: (row: T) => string;
isLoading: boolean;
emptyMessage?: string;
sort?: { column: string; direction: SortDirection };
onSort?: (column: string) => void;
size?: "small" | "medium";
};
function sortIndicator(direction: SortDirection): string {
if (direction === "desc") {
return " ↓";
}
if (direction === "asc") {
return " ↑";
}
return "";
}
export function ResourceListTable<T>({
columns,
rows,
rowKey,
isLoading,
emptyMessage,
sort,
onSort,
size = "small",
}: ResourceListTableProps<T>) {
const colSpan = columns.length;
return (
<TableContainer component={Paper} variant="outlined">
<Table size={size}>
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
key={column.id}
align={column.align}
className={`font-semibold ${column.sortable ? "cursor-pointer whitespace-nowrap" : ""} ${column.headerClassName ?? ""}`}
onClick={column.sortable && onSort ? () => onSort(column.id) : undefined}
>
{column.header}
{column.sortable && sort?.column === column.id ? sortIndicator(sort.direction) : ""}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{isLoading ? (
<TableLoadingRow colSpan={colSpan} />
) : rows.length === 0 ? (
<TableEmptyRow colSpan={colSpan} message={emptyMessage} />
) : (
rows.map((row) => (
<TableRow key={rowKey(row)} hover>
{columns.map((column) => (
<TableCell key={column.id} align={column.align} className={column.cellClassName}>
{column.render(row)}
</TableCell>
))}
</TableRow>
))
)}
</TableBody>
</Table>
</TableContainer>
);
}