mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
- 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
96 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|