fix: routing column filters (#17688)
* remove column filters * remove column filters * use a loading state while loading columns * fix
This commit is contained in:
1 parent
b1a0cdc8e2
commit
af9bf14d9e
4 files changed
+83
-40
No files matched your search
@@ -1,12 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import {
|
||||
RoutingFormResponsesTable,
|
||||
RoutingKPICards,
|
||||
FailedBookingsByField,
|
||||
type RoutingFormTableType,
|
||||
} from "@calcom/features/insights/components";
|
||||
import { FiltersProvider } from "@calcom/features/insights/context/FiltersProvider";
|
||||
import { Filters } from "@calcom/features/insights/filters";
|
||||
@@ -16,17 +13,16 @@ import InsightsLayout from "./layout";
|
||||
|
||||
export default function InsightsPage() {
|
||||
const { t } = useLocale();
|
||||
const [routingTable, setRoutingTable] = useState<RoutingFormTableType | null>(null);
|
||||
|
||||
return (
|
||||
<InsightsLayout>
|
||||
<FiltersProvider>
|
||||
<Filters showRoutingFilters routingTable={routingTable} />
|
||||
<Filters showRoutingFilters />
|
||||
|
||||
<div className="mb-4 space-y-4">
|
||||
<RoutingKPICards />
|
||||
|
||||
<RoutingFormResponsesTable onTableReady={setRoutingTable} />
|
||||
<RoutingFormResponsesTable />
|
||||
|
||||
<FailedBookingsByField />
|
||||
|
||||
|
||||
@@ -2783,6 +2783,8 @@
|
||||
"routing_form_insights_booked_by": "Booked by",
|
||||
"routing_form_insights_created_at": "Created at",
|
||||
"routing_form_insights_booking_status": "Booking Status",
|
||||
"routing_form_insights_booking_at": "Booking At",
|
||||
"routing_form_insights_submitted_at": "Submitted At",
|
||||
"access_denied": "Access Denied",
|
||||
"salesforce_route_to_owner": "Contact owner will be the Round Robin host if available",
|
||||
"salesforce_do_not_route_to_owner": "Contact owner will not be forced (can still be host if it matches the attributes and Round Robin criteria)",
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
createColumnHelper,
|
||||
} from "@tanstack/react-table";
|
||||
import Link from "next/link";
|
||||
import { useRef, useMemo, useId, useEffect } from "react";
|
||||
import { useRef, useMemo, useId } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
@@ -26,6 +26,12 @@ import {
|
||||
HoverCard,
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@calcom/ui";
|
||||
import type { BadgeProps } from "@calcom/ui/components/badge/Badge";
|
||||
|
||||
@@ -210,11 +216,7 @@ function BookingStatusCell({
|
||||
|
||||
export type RoutingFormTableType = ReturnType<typeof useReactTable<RoutingFormTableRow>>;
|
||||
|
||||
export function RoutingFormResponsesTable({
|
||||
onTableReady,
|
||||
}: {
|
||||
onTableReady?: (table: RoutingFormTableType) => void;
|
||||
}) {
|
||||
export function RoutingFormResponsesTable() {
|
||||
const { t } = useLocale();
|
||||
const { filter } = useFilterContext();
|
||||
const tableContainerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -233,16 +235,17 @@ export function RoutingFormResponsesTable({
|
||||
const initialConfigIsReady = !!(initialConfig?.teamId || initialConfig?.userId || initialConfig?.isAll);
|
||||
const [startDate, endDate] = dateRange;
|
||||
|
||||
const { data: headers } = trpc.viewer.insights.routingFormResponsesHeaders.useQuery(
|
||||
{
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
isAll: isAll ?? false,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
},
|
||||
{
|
||||
enabled: initialConfigIsReady,
|
||||
}
|
||||
);
|
||||
const { data: headers, isLoading: isHeadersLoading } =
|
||||
trpc.viewer.insights.routingFormResponsesHeaders.useQuery(
|
||||
{
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
isAll: isAll ?? false,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
},
|
||||
{
|
||||
enabled: initialConfigIsReady,
|
||||
}
|
||||
);
|
||||
|
||||
const { data, fetchNextPage, isFetching, hasNextPage } =
|
||||
trpc.viewer.insights.routingFormResponses.useInfiniteQuery(
|
||||
@@ -272,6 +275,7 @@ export function RoutingFormResponsesTable({
|
||||
const totalFetched = flatData.length;
|
||||
|
||||
const processedData = useMemo(() => {
|
||||
if (isHeadersLoading) return [];
|
||||
return flatData.map((response) => {
|
||||
const row: RoutingFormTableRow = {
|
||||
id: response.id,
|
||||
@@ -304,7 +308,7 @@ export function RoutingFormResponsesTable({
|
||||
|
||||
return row;
|
||||
});
|
||||
}, [flatData, headers]);
|
||||
}, [flatData, headers, isHeadersLoading]);
|
||||
|
||||
const columnHelper = createColumnHelper<RoutingFormTableRow>();
|
||||
|
||||
@@ -319,6 +323,7 @@ export function RoutingFormResponsesTable({
|
||||
return <BookedByCell attendees={row.routedToBooking?.attendees || []} rowId={row.id} />;
|
||||
},
|
||||
}),
|
||||
|
||||
...(headers?.map((header) => {
|
||||
return columnHelper.accessor(header.id, {
|
||||
id: header.id,
|
||||
@@ -335,10 +340,9 @@ export function RoutingFormResponsesTable({
|
||||
},
|
||||
});
|
||||
}) ?? []),
|
||||
|
||||
columnHelper.accessor("routedToBooking", {
|
||||
id: "bookingStatus",
|
||||
header: t("routing_form_insights_booking_status"),
|
||||
header: t("routing_form_insights_booking_at"),
|
||||
size: 250,
|
||||
cell: (info) => (
|
||||
<div className="max-w-[250px]">
|
||||
@@ -351,6 +355,14 @@ export function RoutingFormResponsesTable({
|
||||
</div>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor("createdAt", {
|
||||
id: "submittedAt",
|
||||
header: t("routing_form_insights_submitted_at"),
|
||||
size: 250,
|
||||
cell: (info) => (
|
||||
<div className="max-w-[250px]">{dayjs(info.getValue()).format("MMM D, YYYY HH:mm")}</div>
|
||||
),
|
||||
}),
|
||||
],
|
||||
[headers, t, copyToClipboard]
|
||||
);
|
||||
@@ -366,10 +378,6 @@ export function RoutingFormResponsesTable({
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
onTableReady?.(table);
|
||||
}, [table, onTableReady]);
|
||||
|
||||
const fetchMoreOnBottomReached = useFetchMoreOnBottomReached(
|
||||
tableContainerRef,
|
||||
fetchNextPage,
|
||||
@@ -378,6 +386,52 @@ export function RoutingFormResponsesTable({
|
||||
totalDBRowCount
|
||||
);
|
||||
|
||||
if (isHeadersLoading || (isFetching && !data)) {
|
||||
return (
|
||||
<div
|
||||
className="grid h-[75dvh]"
|
||||
style={{ gridTemplateRows: "auto 1fr auto", gridTemplateAreas: "'header' 'body' 'footer'" }}>
|
||||
<div
|
||||
className="scrollbar-thin border-subtle relative h-full overflow-auto rounded-md border"
|
||||
style={{ gridArea: "body" }}>
|
||||
<Table>
|
||||
<TableHeader className="bg-subtle sticky top-0 z-10">
|
||||
<TableRow>
|
||||
{[...Array(4)].map((_, index) => (
|
||||
<TableHead key={`skeleton-header-${index}`}>
|
||||
<div className="bg-subtle h-4 w-[200px] animate-pulse rounded-md" />
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{[...Array(10)].map((_, rowIndex) => (
|
||||
<TableRow key={`skeleton-row-${rowIndex}`}>
|
||||
{[...Array(4)].map((_, colIndex) => (
|
||||
<TableCell key={`skeleton-cell-${rowIndex}-${colIndex}`}>
|
||||
<div
|
||||
className={classNames(
|
||||
"bg-subtle h-6 animate-pulse rounded-md",
|
||||
colIndex === 0
|
||||
? "w-[200px]"
|
||||
: colIndex === 2
|
||||
? "w-[250px]"
|
||||
: colIndex === 3
|
||||
? "w-[250px]"
|
||||
: "w-[200px]"
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1">
|
||||
<DataTable
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { RoutingFormTableType } from "@calcom/features/insights/components/RoutingFormResponsesTable";
|
||||
import { useFilterContext } from "@calcom/features/insights/context/provider";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Button, Icon, Tooltip, DataTableFilters } from "@calcom/ui";
|
||||
import { Button, Icon, Tooltip } from "@calcom/ui";
|
||||
|
||||
import { BookingStatusFilter } from "./BookingStatusFilter";
|
||||
import { DateSelect } from "./DateSelect";
|
||||
@@ -38,13 +37,7 @@ const ClearFilters = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Filters = ({
|
||||
showRoutingFilters = false,
|
||||
routingTable = null,
|
||||
}: {
|
||||
showRoutingFilters?: boolean;
|
||||
routingTable?: RoutingFormTableType | null;
|
||||
}) => {
|
||||
export const Filters = ({ showRoutingFilters = false }: { showRoutingFilters?: boolean }) => {
|
||||
const { filter } = useFilterContext();
|
||||
const { selectedFilter } = filter;
|
||||
|
||||
@@ -105,8 +98,6 @@ export const Filters = ({
|
||||
<div className="flex flex-col-reverse sm:flex-row sm:flex-nowrap sm:justify-between">
|
||||
{showRoutingFilters ? <RoutingDownload /> : <Download />}
|
||||
<DateSelect />
|
||||
|
||||
{routingTable && <DataTableFilters.ColumnVisibilityButton table={routingTable} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user