Files
calendar/packages/features/data-table/components/DataTableWrapper.tsx
T
Eunjae LeeandGitHub 641193bd61 fix: replace filter implementations on bookings (#19445)
* fix: replace filter implementation on /bookings

* add eventTypeId column

* add eventType filter

* add team filter

* add people filter

* fix type error

* support date range filter

* fix empty view

* fix date range filter

* add comment

* fix type error

* fix type error

* fix type error

* fix type error

* fix type error

* address feedback

* remove reverted functionality
2025-02-24 17:11:40 +01:00

124 lines
3.4 KiB
TypeScript

"use client";
import type { Table as ReactTableType, VisibilityState } from "@tanstack/react-table";
import { useEffect, useRef } from "react";
import {
DataTable,
DataTablePagination,
useFetchMoreOnBottomReached,
useDataTable,
useColumnFilters,
} from "@calcom/features/data-table";
import { classNames } from "@calcom/lib";
export type DataTableWrapperProps<TData, TValue> = {
testId?: string;
bodyTestId?: string;
table: ReactTableType<TData>;
isPending: boolean;
hasNextPage: boolean;
fetchNextPage: () => void;
isFetching: boolean;
hideHeader?: boolean;
variant?: "default" | "compact";
totalDBRowCount?: number;
ToolbarLeft?: React.ReactNode;
ToolbarRight?: React.ReactNode;
EmptyView?: React.ReactNode;
className?: string;
containerClassName?: string;
children?: React.ReactNode;
tableContainerRef?: React.RefObject<HTMLDivElement>;
};
export function DataTableWrapper<TData, TValue>({
testId,
bodyTestId,
table,
isPending,
hasNextPage,
fetchNextPage,
isFetching,
totalDBRowCount,
variant,
hideHeader,
ToolbarLeft,
ToolbarRight,
EmptyView,
className,
containerClassName,
children,
tableContainerRef: externalRef,
}: DataTableWrapperProps<TData, TValue>) {
const internalRef = useRef<HTMLDivElement>(null);
const tableContainerRef = externalRef || internalRef;
const fetchMoreOnBottomReached = useFetchMoreOnBottomReached({
tableContainerRef,
hasNextPage,
fetchNextPage,
isFetching,
});
const { sorting, setSorting, columnVisibility, setColumnVisibility } = useDataTable();
const columnFilters = useColumnFilters();
useEffect(() => {
const mergedColumnVisibility = {
...(table.initialState?.columnVisibility || {}),
...columnVisibility,
} satisfies VisibilityState;
table.setState((prev) => ({
...prev,
sorting,
columnFilters,
columnVisibility: mergedColumnVisibility,
}));
table.setOptions((prev) => ({
...prev,
onSortingChange: setSorting,
onColumnVisibilityChange: setColumnVisibility,
}));
}, [table, sorting, columnFilters, columnVisibility]);
const showEmptyView = table.getRowCount() === 0 && EmptyView;
return (
<>
{(ToolbarLeft || ToolbarRight || children) && (
<div className={classNames("grid w-full items-center gap-2 py-4", className)}>
<div className="flex w-full flex-col gap-2">
<div className="flex w-full flex-wrap justify-between gap-2">
<div className="flex flex-wrap items-center gap-2">{ToolbarLeft}</div>
<div className="flex flex-wrap items-center gap-2">{ToolbarRight}</div>
</div>
</div>
{children}
</div>
)}
{showEmptyView && EmptyView}
{!showEmptyView && (
<DataTable
testId={testId}
bodyTestId={bodyTestId}
table={table}
tableContainerRef={tableContainerRef}
isPending={isPending}
enableColumnResizing={true}
hideHeader={hideHeader}
variant={variant}
className={className}
containerClassName={containerClassName}
onScroll={(e) => fetchMoreOnBottomReached(e.target as HTMLDivElement)}>
{totalDBRowCount && (
<div style={{ gridArea: "footer", marginTop: "1rem" }}>
<DataTablePagination table={table} totalDbDataCount={totalDBRowCount} />
</div>
)}
</DataTable>
)}
</>
);
}