diff --git a/apps/web/modules/bookings/views/bookings-listing-view.tsx b/apps/web/modules/bookings/views/bookings-listing-view.tsx index 08e521660d..f13d235127 100644 --- a/apps/web/modules/bookings/views/bookings-listing-view.tsx +++ b/apps/web/modules/bookings/views/bookings-listing-view.tsx @@ -17,6 +17,7 @@ import { ZDateRangeFilterValue, ZTextFilterValue, } from "@calcom/features/data-table"; +import { useSegments } from "@calcom/features/data-table/hooks/useSegments"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { RouterOutputs } from "@calcom/trpc/react"; import { trpc } from "@calcom/trpc/react"; @@ -86,7 +87,7 @@ type BookingsProps = { export default function Bookings(props: BookingsProps) { return ( - + ); diff --git a/apps/web/modules/insights/insights-routing-view.tsx b/apps/web/modules/insights/insights-routing-view.tsx index 7406bf8830..c11b6198fb 100644 --- a/apps/web/modules/insights/insights-routing-view.tsx +++ b/apps/web/modules/insights/insights-routing-view.tsx @@ -1,6 +1,7 @@ "use client"; import { DataTableProvider } from "@calcom/features/data-table/DataTableProvider"; +import { useSegments } from "@calcom/features/data-table/hooks/useSegments"; import { RoutingFormResponsesTable, FailedBookingsByField, @@ -13,7 +14,7 @@ export default function InsightsRoutingFormResponsesPage() { const { t } = useLocale(); return ( - +
diff --git a/packages/features/data-table/DataTableProvider.tsx b/packages/features/data-table/DataTableProvider.tsx index b41760b12a..98ce77ddea 100644 --- a/packages/features/data-table/DataTableProvider.tsx +++ b/packages/features/data-table/DataTableProvider.tsx @@ -7,7 +7,7 @@ import { usePathname } from "next/navigation"; import { useQueryState, parseAsArrayOf, parseAsJson, parseAsInteger, parseAsString } from "nuqs"; import { createContext, useCallback, useEffect, useRef, useMemo } from "react"; -import { useSegments } from "./lib/segments"; +import { useSegmentsNoop } from "./hooks/useSegmentsNoop"; import { type FilterValue, ZSorting, @@ -16,6 +16,7 @@ import { ZColumnSizing, type FilterSegmentOutput, type ActiveFilters, + type UseSegments, } from "./lib/types"; import { CTA_CONTAINER_CLASS_NAME } from "./lib/utils"; @@ -51,6 +52,7 @@ export type DataTableContextType = { segmentId: number | undefined; setSegmentId: (id: number | null) => void; canSaveSegment: boolean; + isSegmentEnabled: boolean; searchTerm: string; setSearchTerm: (searchTerm: string | null) => void; @@ -65,6 +67,7 @@ const DEFAULT_COLUMN_SIZING: ColumnSizingState = {}; const DEFAULT_PAGE_SIZE = 10; interface DataTableProviderProps { + useSegments?: UseSegments; tableIdentifier?: string; children: React.ReactNode; ctaContainerClassName?: string; @@ -74,6 +77,7 @@ interface DataTableProviderProps { export function DataTableProvider({ tableIdentifier: _tableIdentifier, children, + useSegments = useSegmentsNoop, defaultPageSize = DEFAULT_PAGE_SIZE, ctaContainerClassName = CTA_CONTAINER_CLASS_NAME, }: DataTableProviderProps) { @@ -165,36 +169,38 @@ export function DataTableProvider({ [setPageSize, setPageIndex, defaultPageSize] ); - const { segments, selectedSegment, canSaveSegment, setSegmentIdAndSaveToLocalStorage } = useSegments({ - tableIdentifier, - activeFilters, - sorting, - columnVisibility, - columnSizing, - pageSize, - searchTerm, - defaultPageSize, - segmentId, - setSegmentId, - setActiveFilters, - setSorting, - setColumnVisibility, - setColumnSizing, - setPageSize, - setPageIndex, - setSearchTerm, - }); + const { segments, selectedSegment, canSaveSegment, setAndPersistSegmentId, isSegmentEnabled } = useSegments( + { + tableIdentifier, + activeFilters, + sorting, + columnVisibility, + columnSizing, + pageSize, + searchTerm, + defaultPageSize, + segmentId, + setSegmentId, + setActiveFilters, + setSorting, + setColumnVisibility, + setColumnSizing, + setPageSize, + setPageIndex, + setSearchTerm, + } + ); const clearAll = useCallback( (exclude?: string[]) => { - setSegmentIdAndSaveToLocalStorage(null); + setAndPersistSegmentId(null); setPageIndex(null); setActiveFilters((prev) => { const remainingFilters = prev.filter((filter) => exclude?.includes(filter.f)); return remainingFilters.length === 0 ? null : remainingFilters; }); }, - [setActiveFilters, setPageIndex, setSegmentIdAndSaveToLocalStorage] + [setActiveFilters, setPageIndex, setAndPersistSegmentId] ); const ctaContainerRef = useRef(null); @@ -230,8 +236,9 @@ export function DataTableProvider({ segments, selectedSegment, segmentId: segmentId || undefined, - setSegmentId: setSegmentIdAndSaveToLocalStorage, + setSegmentId: setAndPersistSegmentId, canSaveSegment, + isSegmentEnabled, searchTerm, setSearchTerm: setDebouncedSearchTerm, }}> diff --git a/packages/features/data-table/components/DataTable.tsx b/packages/features/data-table/components/DataTable.tsx index ccf3322623..08f666c586 100644 --- a/packages/features/data-table/components/DataTable.tsx +++ b/packages/features/data-table/components/DataTable.tsx @@ -23,7 +23,7 @@ import { } from "@calcom/ui/components/table"; import { useColumnSizingVars } from "../hooks"; -import { usePersistentColumnResizing } from "../lib/resizing"; +import { useColumnResizing } from "../hooks/useColumnResizing"; export type DataTablePropsFromWrapper = { table: ReactTableType; @@ -96,7 +96,7 @@ export function DataTable({ const columnSizingVars = useColumnSizingVars({ table }); - usePersistentColumnResizing({ + useColumnResizing({ enabled: Boolean(enableColumnResizing), table, tableContainerRef, diff --git a/packages/features/data-table/components/segment/FilterSegmentSelect.tsx b/packages/features/data-table/components/segment/FilterSegmentSelect.tsx index 100a5a61b1..eb33cfb147 100644 --- a/packages/features/data-table/components/segment/FilterSegmentSelect.tsx +++ b/packages/features/data-table/components/segment/FilterSegmentSelect.tsx @@ -31,7 +31,7 @@ type SubmenuItem = { export function FilterSegmentSelect() { const { t } = useLocale(); - const { segments, selectedSegment, segmentId, setSegmentId } = useDataTable(); + const { segments, selectedSegment, segmentId, setSegmentId, isSegmentEnabled } = useDataTable(); const [segmentToRename, setSegmentToRename] = useState(); const [segmentToDuplicate, setSegmentToDuplicate] = useState(); const [segmentToDelete, setSegmentToDelete] = useState(); @@ -99,6 +99,14 @@ export function FilterSegmentSelect() { ]; }, [segments, t]); + if (!isSegmentEnabled) { + return ( + + ); + } + return ( <> diff --git a/packages/features/data-table/components/segment/SaveFilterSegmentButton.tsx b/packages/features/data-table/components/segment/SaveFilterSegmentButton.tsx index 14896f20fe..dedc2a6168 100644 --- a/packages/features/data-table/components/segment/SaveFilterSegmentButton.tsx +++ b/packages/features/data-table/components/segment/SaveFilterSegmentButton.tsx @@ -50,6 +50,7 @@ export function SaveFilterSegmentButton() { columnSizing, selectedSegment, canSaveSegment, + isSegmentEnabled, setSegmentId, pageSize, searchTerm, @@ -161,6 +162,14 @@ export function SaveFilterSegmentButton() { setIsOpen(open); }; + if (!isSegmentEnabled) { + return ( + + ); + } + return ( diff --git a/packages/features/data-table/lib/resizing.ts b/packages/features/data-table/hooks/useColumnResizing.ts similarity index 96% rename from packages/features/data-table/lib/resizing.ts rename to packages/features/data-table/hooks/useColumnResizing.ts index 5a88bf5657..5f231897f6 100644 --- a/packages/features/data-table/lib/resizing.ts +++ b/packages/features/data-table/hooks/useColumnResizing.ts @@ -5,9 +5,9 @@ import type { Header, Table, ColumnSizingState } from "@tanstack/react-table"; import debounce from "lodash/debounce"; import { useCallback, useEffect, useRef, useMemo } from "react"; -import { useDebouncedWidth, useDataTable } from "../hooks"; +import { useDebouncedWidth, useDataTable } from "."; -type UsePersistentColumnResizingProps = { +type UseColumnResizingProps = { enabled: boolean; table: Table; tableContainerRef: React.RefObject; @@ -81,11 +81,11 @@ function getPartialColumnSizing(columnSizing: ColumnSizingState, columnsToExtrac }, {} as ColumnSizingState); } -export function usePersistentColumnResizing({ +export function useColumnResizing({ enabled, table, tableContainerRef, -}: UsePersistentColumnResizingProps) { +}: UseColumnResizingProps) { const initialized = useRef(false); const columnSizing = useRef({}); const initialColumnSizing = useRef({}); diff --git a/packages/features/data-table/lib/segments.ts b/packages/features/data-table/hooks/useSegments.ts similarity index 80% rename from packages/features/data-table/lib/segments.ts rename to packages/features/data-table/hooks/useSegments.ts index 21a45bf54b..736f679347 100644 --- a/packages/features/data-table/lib/segments.ts +++ b/packages/features/data-table/hooks/useSegments.ts @@ -1,33 +1,12 @@ -import type { SortingState, VisibilityState, ColumnSizingState } from "@tanstack/react-table"; // eslint-disable-next-line no-restricted-imports import { isEqual } from "lodash"; import { useCallback, useMemo, useEffect } from "react"; import { trpc } from "@calcom/trpc/react"; -import { type ActiveFilters, ZSegmentStorage } from "./types"; +import { ZSegmentStorage, type UseSegments } from "../lib/types"; -type UseSegmentsProps = { - tableIdentifier: string; - activeFilters: ActiveFilters; - sorting: SortingState; - columnVisibility: VisibilityState; - columnSizing: ColumnSizingState; - pageSize: number; - searchTerm: string; - defaultPageSize: number; - segmentId: number; - setSegmentId: (segmentId: number | null) => void; - setActiveFilters: (activeFilters: ActiveFilters) => void; - setSorting: (sorting: SortingState) => void; - setColumnVisibility: (columnVisibility: VisibilityState) => void; - setColumnSizing: (columnSizing: ColumnSizingState) => void; - setPageSize: (pageSize: number) => void; - setPageIndex: (pageIndex: number) => void; - setSearchTerm: (searchTerm: string | null) => void; -}; - -export function useSegments({ +export const useSegments: UseSegments = ({ tableIdentifier, activeFilters, sorting, @@ -45,7 +24,7 @@ export function useSegments({ setPageSize, setPageIndex, setSearchTerm, -}: UseSegmentsProps) { +}) => { const { data: segments, isFetching: isFetchingSegments } = trpc.viewer.filterSegments.list.useQuery({ tableIdentifier, }); @@ -132,7 +111,7 @@ export function useSegments({ defaultPageSize, ]); - const setSegmentIdAndSaveToLocalStorage = useCallback( + const setAndPersistSegmentId = useCallback( (segmentId: number | null) => { setSegmentId(segmentId); saveSegmentToLocalStorage({ tableIdentifier, segmentId }); @@ -144,9 +123,10 @@ export function useSegments({ segments: segments ?? [], selectedSegment, canSaveSegment, - setSegmentIdAndSaveToLocalStorage, + setAndPersistSegmentId, + isSegmentEnabled: true, }; -} +}; const LOCAL_STORAGE_KEY = "data-table:segments"; diff --git a/packages/features/data-table/hooks/useSegmentsNoop.ts b/packages/features/data-table/hooks/useSegmentsNoop.ts new file mode 100644 index 0000000000..0e2a659faa --- /dev/null +++ b/packages/features/data-table/hooks/useSegmentsNoop.ts @@ -0,0 +1,14 @@ +// eslint-disable-next-line no-restricted-imports +import { noop } from "lodash"; + +import { type UseSegments } from "../lib/types"; + +export const useSegmentsNoop: UseSegments = ({}) => { + return { + segments: [], + selectedSegment: undefined, + canSaveSegment: false, + setAndPersistSegmentId: noop, + isSegmentEnabled: false, + }; +}; diff --git a/packages/features/data-table/index.ts b/packages/features/data-table/index.ts index 3e592dc193..d2b8471a0f 100644 --- a/packages/features/data-table/index.ts +++ b/packages/features/data-table/index.ts @@ -2,5 +2,5 @@ export * from "./components"; export * from "./lib/types"; export * from "./lib/utils"; export * from "./DataTableProvider"; -export * from "./lib/resizing"; +export * from "./hooks/useColumnResizing"; export * from "./hooks"; diff --git a/packages/features/data-table/lib/types.ts b/packages/features/data-table/lib/types.ts index b82287f9a7..f7e1603647 100644 --- a/packages/features/data-table/lib/types.ts +++ b/packages/features/data-table/lib/types.ts @@ -1,7 +1,10 @@ +import type { SortingState, ColumnSort, VisibilityState, ColumnSizingState } from "@tanstack/react-table"; import { z } from "zod"; import type { IconName } from "@calcom/ui/components/icon"; +export type { SortingState } from "@tanstack/react-table"; + export enum ColumnFilterType { SINGLE_SELECT = "ss", MULTI_SELECT = "ms", @@ -200,11 +203,7 @@ export type TypedColumnFilter = { value: FilterValue; }; -export type Sorting = { - id: string; - desc: boolean; -}; -export type SortingState = Sorting[]; +export type Sorting = ColumnSort; export const ZSorting = z.object({ id: z.string(), @@ -267,3 +266,33 @@ export const ZSegmentStorage = z.record( segmentId: z.number(), }) ) satisfies z.ZodType; + +export type UseSegments = (props: UseSegmentsProps) => UseSegmentsReturn; + +type UseSegmentsProps = { + tableIdentifier: string; + activeFilters: ActiveFilters; + sorting: SortingState; + columnVisibility: VisibilityState; + columnSizing: ColumnSizingState; + pageSize: number; + searchTerm: string; + defaultPageSize: number; + segmentId: number; + setSegmentId: (segmentId: number | null) => void; + setActiveFilters: (activeFilters: ActiveFilters) => void; + setSorting: (sorting: SortingState) => void; + setColumnVisibility: (columnVisibility: VisibilityState) => void; + setColumnSizing: (columnSizing: ColumnSizingState) => void; + setPageSize: (pageSize: number) => void; + setPageIndex: (pageIndex: number) => void; + setSearchTerm: (searchTerm: string | null) => void; +}; + +type UseSegmentsReturn = { + segments: FilterSegmentOutput[]; + selectedSegment: FilterSegmentOutput | undefined; + canSaveSegment: boolean; + setAndPersistSegmentId: (segmentId: number | null) => void; + isSegmentEnabled: boolean; +}; diff --git a/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx b/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx index c009f1e09b..f8e79dd09e 100644 --- a/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx +++ b/packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx @@ -22,6 +22,7 @@ import { DataTableFilters, DataTableSegment, } from "@calcom/features/data-table"; +import { useSegments } from "@calcom/features/data-table/hooks/useSegments"; import ServerTrans from "@calcom/lib/components/ServerTrans"; import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; @@ -63,7 +64,7 @@ interface OutOfOfficeEntry { export default function OutOfOfficeEntriesList() { return ( - + ); diff --git a/packages/features/users/components/UserTable/PlatformManagedUsersTable.tsx b/packages/features/users/components/UserTable/PlatformManagedUsersTable.tsx index b0fb371aed..4391da1fd6 100644 --- a/packages/features/users/components/UserTable/PlatformManagedUsersTable.tsx +++ b/packages/features/users/components/UserTable/PlatformManagedUsersTable.tsx @@ -14,6 +14,7 @@ import { useColumnFilters, useDataTable, } from "@calcom/features/data-table"; +import { useSegments } from "@calcom/features/data-table/hooks/useSegments"; import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc"; @@ -58,7 +59,10 @@ type PlatformManagedUsersTableProps = { export function PlatformManagedUsersTable(props: PlatformManagedUsersTableProps) { return ( - + ); diff --git a/packages/features/users/components/UserTable/UserListTable.tsx b/packages/features/users/components/UserTable/UserListTable.tsx index 921acc7ef6..e885b57f30 100644 --- a/packages/features/users/components/UserTable/UserListTable.tsx +++ b/packages/features/users/components/UserTable/UserListTable.tsx @@ -20,6 +20,7 @@ import { convertFacetedValuesToMap, useDataTable, } from "@calcom/features/data-table"; +import { useSegments } from "@calcom/features/data-table/hooks/useSegments"; import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { @@ -104,7 +105,7 @@ function reducer(state: UserTableState, action: UserTableAction): UserTableState export function UserListTable() { return ( - + );