119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
import InfiniteScroll from "@Front/Components/Elements/InfiniteScroll";
|
|
import Table from "@mui/material/Table";
|
|
import TableBody from "@mui/material/TableBody";
|
|
import TableCell from "@mui/material/TableCell";
|
|
import TableContainer from "@mui/material/TableContainer";
|
|
import TableHead from "@mui/material/TableHead";
|
|
import TableRow from "@mui/material/TableRow";
|
|
|
|
import Typography, { ETypo, ETypoColor } from "../../Typography";
|
|
import classes from "./classes.module.scss";
|
|
import { SxProps, Theme } from "@mui/material";
|
|
|
|
export type IRowProps = { key: string } & Record<string, React.ReactNode | { sx: SxProps<Theme>; content: React.ReactNode }>;
|
|
|
|
type IRow = {
|
|
key?: string;
|
|
content: Record<string, CellContent>;
|
|
};
|
|
|
|
type IProps = {
|
|
header: readonly IHead[];
|
|
rows: IRowProps[];
|
|
onNext?: ((release: () => void, reset?: () => void) => Promise<void> | void) | null;
|
|
};
|
|
|
|
export type IHead = {
|
|
key: string;
|
|
title?: string;
|
|
};
|
|
|
|
type CellContent = {
|
|
key: string;
|
|
value: React.ReactNode | { sx: SxProps<Theme>; content: React.ReactNode };
|
|
};
|
|
|
|
export default function MuiTable(props: IProps) {
|
|
const rows: IRow[] = props.rows.map((rowProps) => {
|
|
const row: IRow = {
|
|
key: rowProps.key,
|
|
content: {},
|
|
};
|
|
props.header.forEach((column) => {
|
|
const cellContent: CellContent = {
|
|
key: column.key + rowProps.key,
|
|
value: rowProps[column.key],
|
|
};
|
|
row.content[column.key] = cellContent;
|
|
});
|
|
return row;
|
|
});
|
|
|
|
return (
|
|
<InfiniteScroll orientation="vertical" onNext={props.onNext} offset={0}>
|
|
<TableContainer
|
|
className={classes["root"]}
|
|
sx={{ height: "45vh", overflowY: "auto", overflowX: "hidden", backgroundColor: "var(--table-background-default)" }}>
|
|
<Table aria-label="simple table" sx={{ border: "0" }}>
|
|
<TableHead
|
|
sx={{
|
|
position: "sticky",
|
|
top: "0",
|
|
borderBottom: "1px solid var(--table-header-border)",
|
|
backgroundColor: "var(--table-background-default)",
|
|
}}>
|
|
<TableRow>
|
|
{props.header.map((column) => (
|
|
<TableCell key={column.key} align={"left"} sx={{ border: 0, padding: "4px 8px" }}>
|
|
{column.title && (
|
|
<span className={classes["head"]}>
|
|
<Typography
|
|
className={classes["text"]}
|
|
typo={ETypo.TEXT_SM_REGULAR}
|
|
color={ETypoColor.COLOR_NEUTRAL_600}>
|
|
{column.title}
|
|
</Typography>
|
|
{/* <ChevronDownIcon width={21} /> */}
|
|
</span>
|
|
)}
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{rows.map((row) => {
|
|
return (
|
|
<TableRow key={row.key} sx={{ verticalAlign: "middle" }} className={classes["row"]}>
|
|
{Object.values(row.content).map((cell) => (
|
|
<TableCell
|
|
className={classes["cell"]}
|
|
key={cell.key}
|
|
align="left"
|
|
sx={{ ...getCellValueStyle(cell.value), border: 0, padding: "4px 8px", height: "53px" }}>
|
|
<Typography
|
|
className={classes["content"]}
|
|
typo={ETypo.TEXT_MD_REGULAR}
|
|
color={ETypoColor.COLOR_NEUTRAL_900}>
|
|
{cell.value && typeof cell.value === "object" && "content" in cell.value
|
|
? cell.value.content
|
|
: cell.value}
|
|
</Typography>
|
|
</TableCell>
|
|
))}
|
|
</TableRow>
|
|
);
|
|
})}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
</InfiniteScroll>
|
|
);
|
|
|
|
function getCellValueStyle(value: React.ReactNode | { sx: SxProps<Theme>; content: React.ReactNode }) {
|
|
if (typeof value === "object" && value !== null && "sx" in value) {
|
|
return value.sx;
|
|
}
|
|
return {};
|
|
}
|
|
}
|