"use client";
import {
ColumnDef,
Row,
SortDirection,
SortingState,
flexRender,
getCoreRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { TableCell, TableHead, TableRow } from "@/components/ui/table";
import { HTMLAttributes, forwardRef, useState, useRef, useEffect } from "react";
import { TableVirtuoso } from "react-virtuoso";
import { cn } from "@/lib/utils"
import { ScrollArea } from "@/components/ui/scroll-area";
import { useMediaQuery } from "@/hooks/useMediaQuery";
// Original Table is wrapped with a
(see https://ui.shadcn.com/docs/components/table#radix-:r24:-content-manual),
// but here we don't want it, so let's use a new component with only
tag
const TableComponent = forwardRef<
HTMLTableElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
));
TableComponent.displayName = "TableComponent";
const TableRowComponent = (rows: Row[]) =>
function getTableRow(props: HTMLAttributes) {
// @ts-expect-error data-index is a valid attribute
const index = props["data-index"];
const row = rows[index];
if (!row) return null;
return (
{row.getVisibleCells().map((cell) => (
{flexRender(cell.column.columnDef.cell, cell.getContext())}
))}
);
};
function SortingIndicator({ isSorted }: { isSorted: SortDirection | false }) {
if (!isSorted) return null;
return (
{
{
asc: "↑",
desc: "↓",
}[isSorted]
}
);
}
interface DataTableProps {
columns: ColumnDef[];
data: TData[];
rowComponent?: (rows: Row[]) => (props: HTMLAttributes) => JSX.Element | null,
}
export function DataTable({
columns,
data,
rowComponent,
}: DataTableProps) {
const [sorting, setSorting] = useState([{
id: 'type',
desc: true,
}]);
const table = useReactTable({
data,
columns,
state: {
sorting,
},
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
});
const { rows } = table.getRowModel();
const [heightState, setHeight] = useState(0)
const ref = useRef(null);
const isDesktop = useMediaQuery("(min-width: 640px)");
useEffect(() => {
const calculateHeight = () => {
if (ref.current) {
const virtuosoElement = ref.current;
let topOffset = 0;
let currentElement = virtuosoElement as any;
// Calculate the total offset from the top of the document
while (currentElement) {
topOffset += currentElement.offsetTop || 0;
currentElement = currentElement.offsetParent as HTMLElement;
}
const totalHeight = window.innerHeight;
const calculatedHeight = totalHeight - topOffset;
setHeight(calculatedHeight);
}
};
calculateHeight(); // Initial calculation
if (isDesktop) {
window.addEventListener('resize', calculateHeight);
}
return () => { if (isDesktop) window.removeEventListener('resize', calculateHeight); }
}, [isDesktop]);
return (
table.getHeaderGroups().map((headerGroup) => (
// Change header background color to non-transparent
{headerGroup.headers.map((header) => {
return (
{header.isPlaceholder ? null : (
{flexRender(
header.column.columnDef.header,
header.getContext(),
)}
)}
);
})}
))
}
/>
);
}