Files
SSA-Admin-Panel/src/components/DataTable.tsx

174 lines
5.2 KiB
TypeScript
Raw Normal View History

import { useState } from "react";
2025-06-05 15:18:16 +05:30
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";
2025-02-04 13:56:43 +05:30
// 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;
2025-06-05 15:18:16 +05:30
};
onPageChange?: (page: number) => void;
2025-02-04 13:56:43 +05:30
}
const DataTable: React.FC<TableProps> = ({
tableHeadRow,
data,
sortableColumns = [],
paginationData,
2025-06-05 15:18:16 +05:30
onPageChange,
}: TableProps) => {
const { current_page = 1, last_page = 1 } = paginationData || {};
2025-02-04 13:56:43 +05:30
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);
}
};
2025-02-04 13:56:43 +05:30
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);
2025-02-04 13:56:43 +05:30
};
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" }}>
2025-06-05 15:18:16 +05:30
{sortConfig.direction === "asc" ? "▲" : "▼"}
2025-02-04 13:56:43 +05:30
</span>
)}
</Table.ColumnHeader>
))}
</Table.Row>
</Table.Header>
2025-06-05 15:18:16 +05:30
{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>
)}
2025-02-04 13:56:43 +05:30
</Table.Root>
</Table.ScrollArea>
2025-06-05 15:18:16 +05:30
{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>
)}
2025-02-04 13:56:43 +05:30
</Stack>
);
};
export default DataTable;