174 lines
5.2 KiB
TypeScript
174 lines
5.2 KiB
TypeScript
import { useState } from "react";
|
|
import { Box, HStack, Image, Stack, Table, Text } from "@chakra-ui/react";
|
|
import {
|
|
PaginationItems,
|
|
PaginationNextTrigger,
|
|
PaginationPrevTrigger,
|
|
PaginationRoot,
|
|
} from "./ui/pagination";
|
|
import EmptyFile from "../assets/empty-file.png";
|
|
// import {
|
|
// PaginationItems,
|
|
// PaginationNextTrigger,
|
|
// PaginationPrevTrigger,
|
|
// PaginationRoot,
|
|
// } from "./ui/pagination";
|
|
|
|
interface TableProps {
|
|
tableHeadRow: string[];
|
|
data: Record<string, any>[];
|
|
sortableColumns?: string[]; // Specify which columns are sortable
|
|
paginationData?: {
|
|
current_page: number;
|
|
last_page: number;
|
|
per_page: number;
|
|
total: number;
|
|
};
|
|
onPageChange?: (page: number) => void;
|
|
}
|
|
|
|
const DataTable: React.FC<TableProps> = ({
|
|
tableHeadRow,
|
|
data,
|
|
sortableColumns = [],
|
|
paginationData,
|
|
onPageChange,
|
|
}: TableProps) => {
|
|
const { current_page = 1, last_page = 1 } = paginationData || {};
|
|
const [sortConfig, setSortConfig] = useState<{
|
|
key: string;
|
|
direction: "asc" | "desc";
|
|
} | null>(null);
|
|
|
|
const handlePageChange = (details: { page: number }) => {
|
|
const newPage = details.page;
|
|
if (newPage >= 1 && newPage <= last_page) {
|
|
onPageChange?.(newPage);
|
|
}
|
|
};
|
|
|
|
const handleSort = (column: string) => {
|
|
if (!sortableColumns.includes(column)) return;
|
|
|
|
let direction: "asc" | "desc" = "asc";
|
|
if (
|
|
sortConfig &&
|
|
sortConfig.key === column &&
|
|
sortConfig.direction === "asc"
|
|
) {
|
|
direction = "desc";
|
|
}
|
|
|
|
const newSortConfig = { key: column, direction };
|
|
setSortConfig(newSortConfig);
|
|
onPageChange?.(1);
|
|
};
|
|
|
|
return (
|
|
<Stack mt={0} color={"#000000CC"}>
|
|
<Table.ScrollArea mb={3}>
|
|
<Table.Root size="sm" variant={"line"} stickyHeader>
|
|
<Table.Header>
|
|
<Table.Row bg={"#02A0A0"}>
|
|
{tableHeadRow.map((item, index) => (
|
|
<Table.ColumnHeader
|
|
color="white"
|
|
fontSize={"xs"}
|
|
fontWeight={600}
|
|
px={4}
|
|
p={3}
|
|
textAlign={
|
|
index === tableHeadRow.length - 1 ? "center" : "left"
|
|
}
|
|
key={index}
|
|
border={"none"}
|
|
onClick={() => handleSort(item)}
|
|
cursor={
|
|
sortableColumns.includes(item) ? "pointer" : "default"
|
|
}
|
|
_hover={
|
|
sortableColumns.includes(item)
|
|
? { textDecoration: "underline" }
|
|
: {}
|
|
}
|
|
>
|
|
{item}
|
|
{sortableColumns.includes(item) &&
|
|
sortConfig?.key === item && (
|
|
<span style={{ marginLeft: "4px" }}>
|
|
{sortConfig.direction === "asc" ? "▲" : "▼"}
|
|
</span>
|
|
)}
|
|
</Table.ColumnHeader>
|
|
))}
|
|
</Table.Row>
|
|
</Table.Header>
|
|
{data?.length === 0 ? (
|
|
<Box>
|
|
<Box textAlign={"center"} py={20} position={'absolute'} w={'84%'}>
|
|
<Image src={EmptyFile} alt="No data" maxW="65px" mx="auto" />
|
|
<Text fontSize={"18px"} fontWeight={500} mt={2}>
|
|
We do not have any records
|
|
</Text>
|
|
</Box>
|
|
</Box>
|
|
) : (
|
|
<Table.Body h={"100%"}>
|
|
{data.map((item: any, index) => (
|
|
<Table.Row
|
|
key={index}
|
|
bg={index % 2 === 0 ? "#fff" : "#007F3310"}
|
|
>
|
|
{tableHeadRow.map((heading, colIndex) => (
|
|
<Table.Cell
|
|
px={4}
|
|
p={2}
|
|
key={`${index}-${colIndex}`}
|
|
fontSize={"xs"}
|
|
fontWeight={500}
|
|
border={"none"}
|
|
>
|
|
{(() => {
|
|
const words =
|
|
item[heading]?.toString().split(" ") || [];
|
|
return words.length > 5
|
|
? `${words.slice(0, 5).join(" ")}...`
|
|
: item[heading];
|
|
})()}
|
|
</Table.Cell>
|
|
))}
|
|
</Table.Row>
|
|
))}
|
|
</Table.Body>
|
|
)}
|
|
</Table.Root>
|
|
</Table.ScrollArea>
|
|
{last_page > 1 && (
|
|
<PaginationRoot
|
|
count={paginationData?.total ?? 0}
|
|
pageSize={paginationData?.per_page ?? 0}
|
|
page={current_page}
|
|
onPageChange={handlePageChange}
|
|
size={"xs"}
|
|
siblingCount={1}
|
|
mb={4}
|
|
>
|
|
<HStack justifyContent="flex-end">
|
|
<PaginationPrevTrigger
|
|
onClick={() => handlePageChange({ page: current_page - 1 })}
|
|
disabled={current_page === 1}
|
|
/>
|
|
<PaginationItems />
|
|
<PaginationNextTrigger
|
|
onClick={() => handlePageChange({ page: current_page + 1 })}
|
|
disabled={current_page === last_page}
|
|
/>
|
|
</HStack>
|
|
</PaginationRoot>
|
|
)}
|
|
</Stack>
|
|
);
|
|
};
|
|
|
|
export default DataTable;
|