Files
SSA-Admin-Panel/src/components/DataTable.tsx
2025-09-11 20:16:37 +05:30

190 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
isLoading?: boolean;
isError?: boolean;
}
const DataTable: React.FC<TableProps> = ({
tableHeadRow,
data,
sortableColumns = [],
paginationData,
onPageChange,
isLoading,
isError
}: 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>
{isLoading ? (
<Box textAlign={"center"} py={20} position="absolute" w="84%">
<Text fontSize={"18px"} fontWeight={500} mt={2}>
Loading...
</Text>
</Box>
) : isError ? (
<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}>
No records found theyll appear here if available.
</Text>
</Box>
) : (
<Table.Body h="100%">
{data.length === 0 && (
<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}>
No records found theyll appear here if available.
</Text>
</Box>
)}
{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 && !isLoading && !isError && (
<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;