"use client"; import { Box, Card, Pagination, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, useMediaQuery, useTheme, } from "@mui/material"; import { ReactNode } from "react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; export type Column = { id: string; label: string; align?: "left" | "right" | "center"; width?: string | number; render?: (row: T) => ReactNode; }; type DataTableProps = { columns: Column[]; data: T[]; keyField: keyof T; emptyMessage?: string; loading?: boolean; onRowClick?: (row: T) => void; pagination?: { total: number; page: number; perPage: number; }; /** If provided, renders this instead of the table on xs/sm screens */ mobileCard?: (row: T) => ReactNode; }; function PaginationBar({ page, perPage, total }: { page: number; perPage: number; total: number }) { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const pageCount = Math.ceil(total / perPage); if (pageCount <= 1) return null; function handlePageChange(_: React.ChangeEvent, newPage: number) { const params = new URLSearchParams(searchParams.toString()); params.set("page", String(newPage)); router.push(`${pathname}?${params.toString()}`); } return ( ); } export function DataTable({ columns, data, keyField, emptyMessage = "No data available", loading = false, onRowClick, pagination, mobileCard, }: DataTableProps) { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("md")); const isEmpty = data.length === 0 && !loading; if (isMobile && mobileCard) { return ( {isEmpty ? ( {emptyMessage} ) : ( {data.map((row) => ( {mobileCard(row)} ))} )} {pagination && } ); } return ( {columns.map((col) => ( {col.label} ))} {isEmpty ? ( {emptyMessage} ) : ( data.map((row) => ( onRowClick(row) : undefined} sx={onRowClick ? { cursor: "pointer", "&:hover": { bgcolor: "action.hover" } } : undefined} > {columns.map((col) => ( {col.render ? col.render(row) : (row as Record)[col.id] as ReactNode} ))} )) )}
{pagination && }
); }