"use client"; import React from "react"; import Paper from "@mui/material/Paper"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableCell, { TableCellProps } from "@mui/material/TableCell"; import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TablePagination, { TablePaginationProps, } from "@mui/material/TablePagination"; import TableRow from "@mui/material/TableRow"; import IconButton, { IconButtonOwnProps } from "@mui/material/IconButton"; import { ButtonOwnProps, Icon, IconOwnProps, SxProps, Theme } from "@mui/material"; import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; import { decimalFormatter, integerFormatter } from "@/app/utils/formatUtil"; export interface ResultWithId { id: string | number; } type ColumnType = "icon" | "decimal" | "integer"; interface BaseColumn { name: keyof T; label: string; align?: TableCellProps["align"]; headerAlign?: TableCellProps["align"]; sx?: SxProps | undefined; style?: Partial & { [propName: string]: string }; type?: ColumnType; renderCell?: (params: T) => React.ReactNode; } interface IconColumn extends BaseColumn { name: keyof T; type: "icon"; icon?: React.ReactNode; icons?: { [columnValue in keyof T]: React.ReactNode }; color?: IconOwnProps["color"]; colors?: { [columnValue in keyof T]: IconOwnProps["color"] }; } interface DecimalColumn extends BaseColumn { type: "decimal"; } interface IntegerColumn extends BaseColumn { type: "integer"; } interface ColumnWithAction extends BaseColumn { onClick: (item: T) => void; buttonIcon: React.ReactNode; buttonIcons: { [columnValue in keyof T]: React.ReactNode }; buttonColor?: IconButtonOwnProps["color"]; } export type Column = | BaseColumn | IconColumn | DecimalColumn | ColumnWithAction; interface Props { items: T[], columns: Column[], noWrapper?: boolean, setPagingController?: (value: (((prevState: { pageNum: number; pageSize: number; totalCount: number }) => { pageNum: number; pageSize: number; totalCount: number }) | { pageNum: number; pageSize: number; totalCount: number })) => void, pagingController: { pageNum: number; pageSize: number; totalCount: number }, isAutoPaging?: boolean } function isActionColumn( column: Column, ): column is ColumnWithAction { return Boolean((column as ColumnWithAction).onClick); } function isIconColumn( column: Column, ): column is IconColumn { return column.type === "icon"; } function isDecimalColumn( column: Column, ): column is DecimalColumn { return column.type === "decimal"; } function isIntegerColumn( column: Column, ): column is IntegerColumn { return column.type === "integer"; } // Icon Component Functions function convertObjectKeysToLowercase(obj: T): object | undefined { return obj ? Object.fromEntries( Object.entries(obj).map(([key, value]) => [key.toLowerCase(), value]) ) : undefined; } function handleIconColors( column: IconColumn, value: T[keyof T], ): IconOwnProps["color"] { const colors = convertObjectKeysToLowercase(column.colors ?? {}); const valueKey = String(value).toLowerCase() as keyof typeof colors; if (colors && valueKey in colors) { return colors[valueKey]; } return column.color ?? "primary"; }; function handleIconIcons( column: IconColumn, value: T[keyof T], ): React.ReactNode { const icons = convertObjectKeysToLowercase(column.icons ?? {}); const valueKey = String(value).toLowerCase() as keyof typeof icons; if (icons && valueKey in icons) { return icons[valueKey]; } return column.icon ?? ; }; function SearchResults({ items, columns, noWrapper, pagingController, setPagingController, isAutoPaging = true, }: Props) { const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(10); /// this const handleChangePage: TablePaginationProps["onPageChange"] = ( _event, newPage, ) => { console.log(_event) setPage(newPage); if (setPagingController) { setPagingController({ ...pagingController, pageNum: newPage + 1, }) } } const handleChangeRowsPerPage: TablePaginationProps["onRowsPerPageChange"] = ( event, ) => { console.log(event) setRowsPerPage(+event.target.value); setPage(0); if (setPagingController) { setPagingController({ ...pagingController, pageNum: +event.target.value, }) } }; const table = ( <> {columns.map((column, idx) => ( {column.label} ))} { isAutoPaging ? items .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) .map((item) => { return ( {columns.map((column, idx) => { const columnName = column.name; return ( ); })} ); }) : items .map((item) => { return ( {columns.map((column, idx) => { const columnName = column.name; return ( ); })} ); }) }
); return noWrapper ? table : {table}; } // Table cells interface TableCellsProps { column: Column, columnName: keyof T, idx: number, item: T, } function TabelCells({ column, columnName, idx, item }: TableCellsProps) { return ( {isActionColumn(column) ? ( column.onClick(item)} > {column.buttonIcon} ) : isIconColumn(column) ? ( {handleIconIcons(column, item[columnName])} ) : isDecimalColumn(column) ? ( <>{decimalFormatter.format(Number(item[columnName]))} ) : isIntegerColumn(column) ? ( <>{integerFormatter.format(Number(item[columnName]))} ) : ( column.renderCell ? column.renderCell(item) : <>{item[columnName] as string} )} ) } export default SearchResults;