crane-cloud/frontend

View on GitHub
src/components/Elements/CustomTable.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import {
Table as MantineTable,
Text,
Skeleton,
Card,
Stack,
} from "@mantine/core";
import styled from "styled-components";
 
export interface Column {
id: string;
header: string;
noWrap?: boolean;
filter?: {
key?: string;
options?: any[];
// Add other filter props as needed
};
}
 
interface TableProps {
columns: Column[];
data: any[];
loading?: boolean;
hideFilters?: boolean;
startValue?: number;
tableTotals?: Record<string, any>;
tableFooter?: Record<string, any>;
noEmptyText?: boolean;
onFilterChange?: (values: any) => void;
filters?: any;
verticalSpacing?: string;
striped?: boolean | "odd" | "even";
noHeader?: boolean;
header?: () => React.ReactNode;
props?: any;
showIndex?: boolean;
rowHover?: boolean;
rowClick?: (item: any) => void;
}
 
export const Table = ({
columns,
data,
loading = false,
startValue = 1,
tableTotals,
tableFooter,
noEmptyText = false,
verticalSpacing = "xs",
striped = true,
noHeader = false,
header,
props,
showIndex = true,
rowHover = false,
rowClick,
}: TableProps) => {
return (
<Card withBorder p="md" radius="md">
<Stack gap={10}>
{header && header()}
<MantineTable.ScrollContainer minWidth="100%">
<MantineTable
striped={striped}
verticalSpacing={verticalSpacing}
{...props}
>
{!noHeader && (
<MantineTable.Thead>
<MantineTable.Tr>
{showIndex && <MantineTable.Th>#</MantineTable.Th>}
{columns?.map((column, columnIndex) => (
<MantineTable.Th
key={column.id}
className={column.noWrap ? "no-wrap" : ""}
style={{
textAlign:
columnIndex === columns.length - 1 ? "right" : "left",
}}
>
<Text className="capitalize" size="md" fw={500}>
{column.header}
</Text>
</MantineTable.Th>
))}
</MantineTable.Tr>
</MantineTable.Thead>
)}
 
<MantineTable.Tbody>
{loading ? (
<MantineTable.Tr>
<MantineTable.Td colSpan={columns.length + 1}>
<Skeleton height={50} animate />
</MantineTable.Td>
</MantineTable.Tr>
) : data?.length ? (
data.map((item, idx) => (
<StyledTableRow
key={item.id || idx}
onClick={() => rowClick && rowClick(item)}
$hover={rowHover}
$clickable={!!rowClick}
>
{showIndex && (
<MantineTable.Td>
{item?.index || startValue + idx}
</MantineTable.Td>
)}
{columns.map((column, columnIndex) => (
<MantineTable.Td
key={column.id}
className={column.noWrap ? "no-wrap" : ""}
style={{
textAlign:
columnIndex === columns.length - 1
? "right"
: "left",
}}
>
{item[column.id] ||
(noEmptyText && <Text c="dimmed">Empty</Text>)}
</MantineTable.Td>
))}
</StyledTableRow>
))
) : (
<MantineTable.Tr>
<MantineTable.Td colSpan={columns.length + 1} ta="center">
No data available
</MantineTable.Td>
</MantineTable.Tr>
)}
</MantineTable.Tbody>
 
{tableTotals && Object.keys(tableTotals).length > 0 && (
<MantineTable.Tfoot>
<MantineTable.Tr>
<MantineTable.Th>Totals</MantineTable.Th>
{columns.map((column, columnIndex) => (
<MantineTable.Th
key={column.id}
style={{
textAlign:
columnIndex === columns.length - 1 ? "right" : "left",
}}
>
<Text fw={700}>{tableTotals[column.id]}</Text>
</MantineTable.Th>
))}
</MantineTable.Tr>
</MantineTable.Tfoot>
)}
 
{tableFooter && (
<MantineTable.Tfoot>
<MantineTable.Tr>
<MantineTable.Th>#</MantineTable.Th>
{columns.map((column, columnIndex) => (
<MantineTable.Th
key={column.id}
style={{
textAlign:
columnIndex === columns.length - 1 ? "right" : "left",
}}
>
{tableFooter[column.id]}
</MantineTable.Th>
))}
</MantineTable.Tr>
</MantineTable.Tfoot>
)}
</MantineTable>
</MantineTable.ScrollContainer>
</Stack>
</Card>
);
};
 
const StyledTableRow = styled(MantineTable.Tr)<{
$hover: boolean;
$clickable: boolean;
}>`
cursor: ${(props) => (props.$clickable ? "pointer" : "default")};
 
&:hover {
${(props) =>
props.$hover &&
`
background-color: light-dark(var(--mantine-color-gray-2), var(--mantine-color-gray-7));
`}
}
`;
 
export const HorizontalTable = ({ data }: { data: any }) => {
return (
<MantineTable.ScrollContainer minWidth="100%">
<MantineTable variant="vertical" withTableBorder>
<MantineTable.Tbody>
{data &&
Object.keys(data)?.map((item, idx) => (
<MantineTable.Tr key={idx}>
<MantineTable.Th w={160}>{item}</MantineTable.Th>
<MantineTable.Td>{data[item]}</MantineTable.Td>
</MantineTable.Tr>
))}
</MantineTable.Tbody>
</MantineTable>
</MantineTable.ScrollContainer>
);
};