|
|
@@ -1,6 +1,6 @@ |
|
|
|
"use client"; |
|
|
|
|
|
|
|
import React, { useEffect } from "react"; |
|
|
|
import React, { useCallback, useEffect, useState } from "react"; |
|
|
|
import Paper from "@mui/material/Paper"; |
|
|
|
import Table from "@mui/material/Table"; |
|
|
|
import TableBody from "@mui/material/TableBody"; |
|
|
@@ -18,6 +18,9 @@ import { convertDateArrayToString, moneyFormatter } from "@/app/utils/formatUtil |
|
|
|
import DoneIcon from '@mui/icons-material/Done'; |
|
|
|
import CloseIcon from '@mui/icons-material/Close'; |
|
|
|
import { Button, Link, LinkOwnProps } from "@mui/material"; |
|
|
|
import { orderBy, sortBy } from "lodash"; |
|
|
|
import ArrowUp from '@mui/icons-material/KeyboardArrowUp'; |
|
|
|
import ArrowDown from '@mui/icons-material/KeyboardArrowDown'; |
|
|
|
|
|
|
|
export interface ResultWithId { |
|
|
|
id: string | number; |
|
|
@@ -155,7 +158,50 @@ function SearchResults<T extends ResultWithId>({ |
|
|
|
|
|
|
|
return column.underline ?? "always"; |
|
|
|
}; |
|
|
|
|
|
|
|
type OrderProps = Record<keyof T, Boolean> |
|
|
|
const [sortedItems, setSortedItems] = useState(items) |
|
|
|
const [orderProps, setOrderProps] = useState<OrderProps>(() => { |
|
|
|
if (items.length === 0) { |
|
|
|
return {} as OrderProps |
|
|
|
} |
|
|
|
return Object.keys(sortedItems[0]).reduce((acc, key) => { |
|
|
|
if (key === "deleted" || key === "id") return acc |
|
|
|
acc[key as keyof T] = false; |
|
|
|
return acc; |
|
|
|
}, {} as OrderProps); |
|
|
|
}); |
|
|
|
const changeOrder = useCallback((key: keyof T) => { |
|
|
|
// preserve all column sorting |
|
|
|
// setOrderProps( |
|
|
|
// (prev) => ({ |
|
|
|
// [...prev]: false, |
|
|
|
// [key]: !prev[key] |
|
|
|
// }) |
|
|
|
// ) |
|
|
|
// only sort 1 column |
|
|
|
setOrderProps( |
|
|
|
(prev) => { |
|
|
|
const newOrderProps = Object.keys(prev).reduce((acc, currKey) => { |
|
|
|
acc[currKey as keyof T] = currKey === key ? !prev[currKey as keyof T] : false; |
|
|
|
return acc; |
|
|
|
}, {} as OrderProps); |
|
|
|
return newOrderProps; |
|
|
|
} |
|
|
|
) |
|
|
|
}, []) |
|
|
|
const sortingItems = useCallback( |
|
|
|
(key: keyof T) => { |
|
|
|
// true === asc |
|
|
|
// false === desc |
|
|
|
console.log(orderProps) |
|
|
|
if (orderProps[key]) { |
|
|
|
return orderBy(sortedItems, key, 'asc') |
|
|
|
} else { |
|
|
|
return orderBy(sortedItems, key, 'desc') |
|
|
|
} |
|
|
|
} |
|
|
|
, [sortedItems, orderProps] |
|
|
|
) |
|
|
|
const table = ( |
|
|
|
<> |
|
|
|
<TableContainer sx={{ maxHeight: 440 }}> |
|
|
@@ -163,14 +209,25 @@ function SearchResults<T extends ResultWithId>({ |
|
|
|
<TableHead> |
|
|
|
<TableRow> |
|
|
|
{columns.filter(item => item.isHidden !== true).map((column, idx) => ( |
|
|
|
<TableCell key={`${column.name.toString()}${idx}`}> |
|
|
|
<TableCell |
|
|
|
key={`${column.name.toString()}${idx}`} |
|
|
|
onClick={() => { |
|
|
|
changeOrder(column.name) |
|
|
|
setSortedItems(sortingItems(column.name)) |
|
|
|
}} |
|
|
|
> |
|
|
|
{column?.type === "money" ? <div style={{display: "flex", justifyContent: "flex-end"}}>{column.label}</div> : column.label} |
|
|
|
{(() => { |
|
|
|
const isAscending = orderProps[column.name]; |
|
|
|
if (isAscending === undefined) return undefined; |
|
|
|
return isAscending ? <ArrowUp /> : <ArrowDown />; |
|
|
|
})()} |
|
|
|
</TableCell> |
|
|
|
))} |
|
|
|
</TableRow> |
|
|
|
</TableHead> |
|
|
|
<TableBody> |
|
|
|
{items |
|
|
|
{sortedItems |
|
|
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) |
|
|
|
.map((item) => { |
|
|
|
return ( |
|
|
@@ -223,7 +280,7 @@ function SearchResults<T extends ResultWithId>({ |
|
|
|
<TablePagination |
|
|
|
rowsPerPageOptions={[10, 25, 100]} |
|
|
|
component="div" |
|
|
|
count={items.length} |
|
|
|
count={sortedItems.length} |
|
|
|
rowsPerPage={rowsPerPage} |
|
|
|
page={page} |
|
|
|
onPageChange={handleChangePage} |
|
|
|