Skip to content

Commit

Permalink
fix: stats on /insights/routing (calcom#18985)
Browse files Browse the repository at this point in the history
* fix: replace filter implementation on /insights/routing

* remove unused functions

* fix type error

* refactor: extract insights parameters

* remove FiltersProvider
  • Loading branch information
eunjae-lee authored Jan 31, 2025
1 parent 195e645 commit fdc8e08
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 327 deletions.
39 changes: 21 additions & 18 deletions apps/web/modules/insights/insights-routing-view.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
"use client";

import { DataTableProvider } from "@calcom/features/data-table";
import {
FailedBookingsByField,
RoutingFormResponsesTable,
FailedBookingsByField,
RoutedToPerPeriod,
} from "@calcom/features/insights/components";
import { FiltersProvider } from "@calcom/features/insights/context/FiltersProvider";
import { InsightsOrgTeamsProvider } from "@calcom/features/insights/context/InsightsOrgTeamsProvider";
import { useLocale } from "@calcom/lib/hooks/useLocale";

export default function InsightsRoutingFormResponsesPage() {
const { t } = useLocale();

return (
<FiltersProvider>
<div className="mb-4 space-y-4">
<RoutingFormResponsesTable />
<DataTableProvider>
<InsightsOrgTeamsProvider>
<div className="mb-4 space-y-4">
<RoutingFormResponsesTable />

<RoutedToPerPeriod />
<RoutedToPerPeriod />

<FailedBookingsByField />
<FailedBookingsByField />

<small className="text-default block text-center">
{t("looking_for_more_insights")}{" "}
<a
className="text-blue-500 hover:underline"
href="mailto:[email protected]?subject=Feature%20Request%3A%20More%20Analytics&body=Hey%20Cal.com%20Team%2C%20I%20love%20the%20analytics%20page%20but%20I%20am%20looking%20for%20...">
{" "}
{t("contact_support")}
</a>
</small>
</div>
</FiltersProvider>
<small className="text-default block text-center">
{t("looking_for_more_insights")}{" "}
<a
className="text-blue-500 hover:underline"
href="mailto:[email protected]?subject=Feature%20Request%3A%20More%20Analytics&body=Hey%20Cal.com%20Team%2C%20I%20love%20the%20analytics%20page%20but%20I%20am%20looking%20for%20...">
{" "}
{t("contact_support")}
</a>
</small>
</div>
</InsightsOrgTeamsProvider>
</DataTableProvider>
);
}
16 changes: 14 additions & 2 deletions packages/features/data-table/components/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,19 @@ export function DataTable<TData, TValue>({
...rest.style,
}}
data-testid={testId ?? "data-table"}>
{/*
Invalidate left & right properties for <= sm screen size,
because we pin columns only for >= sm screen sizes.
*/}
<style jsx global>{`
@media (max-width: 640px) {
.data-table th,
.data-table td {
left: initial !important;
right: initial !important;
}
}
`}</style>
<div
ref={tableContainerRef}
onScroll={onScroll}
Expand All @@ -124,7 +137,7 @@ export function DataTable<TData, TValue>({
)}
style={{ gridArea: "body" }}>
<TableNew
className="grid border-0"
className="data-table grid border-0"
style={{
...columnSizingVars,
...(Boolean(enableColumnResizing) && { width: table.getTotalSize() }),
Expand All @@ -135,7 +148,6 @@ export function DataTable<TData, TValue>({
<TableRow key={headerGroup.id} className="hover:bg-subtle flex w-full">
{headerGroup.headers.map((header) => {
const { column } = header;
const meta = column.columnDef.meta;
return (
<TableHead
key={header.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function DataTableWrapper<TData, TValue>({
className={className}
containerClassName={containerClassName}
onScroll={(e) => fetchMoreOnBottomReached(e.target as HTMLDivElement)}>
{(ToolbarLeft || ToolbarRight) && (
{(ToolbarLeft || ToolbarRight || children) && (
<DataTableToolbar.Root>
<div className="flex w-full flex-col gap-2">
<div className="flex w-full flex-wrap justify-between gap-2">
Expand Down
16 changes: 16 additions & 0 deletions packages/features/data-table/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ export const numberFilter = (cellValue: unknown, filterValue: NumberFilterValue)
return false;
};

export const dateRangeFilter = (cellValue: unknown, filterValue: DateRangeFilterValue) => {
if (!(cellValue instanceof Date)) {
return false;
}

if (!filterValue.data.startDate || !filterValue.data.endDate) {
return true;
}

const cellValueStr = cellValue.toISOString();

return filterValue.data.startDate <= cellValueStr && filterValue.data.endDate >= cellValueStr;
};

export const isNumberFilterValue = (filterValue: unknown): filterValue is NumberFilterValue => {
return ZNumberFilterValue.safeParse(filterValue).success;
};
Expand All @@ -128,6 +142,8 @@ export const dataTableFilter = (cellValue: unknown, filterValue: FilterValue) =>
return textFilter(cellValue, filterValue);
} else if (isNumberFilterValue(filterValue)) {
return numberFilter(cellValue, filterValue);
} else if (isDateRangeFilterValue(filterValue)) {
return dateRangeFilter(cellValue, filterValue);
}
return false;
};
24 changes: 8 additions & 16 deletions packages/features/insights/components/FailedBookingsByField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { classNames } from "@calcom/lib";
import { trpc } from "@calcom/trpc";
import { ToggleGroup } from "@calcom/ui";

import { useFilterContext } from "../context/provider";
import { useInsightsParameters } from "../hooks/useInsightsParameters";
import { BarList } from "./tremor/BarList";

interface FormCardProps {
Expand Down Expand Up @@ -55,21 +55,13 @@ function FormCard({ formName, fields }: FormCardProps) {
}

export function FailedBookingsByField() {
const { filter } = useFilterContext();
const { selectedTeamId, selectedUserId, isAll, initialConfig, selectedRoutingFormId } = filter;
const initialConfigIsReady = !!(initialConfig?.teamId || initialConfig?.userId || initialConfig?.isAll);

const { data } = trpc.viewer.insights.failedBookingsByField.useQuery(
{
userId: selectedUserId ?? undefined,
teamId: selectedTeamId ?? undefined,
isAll: !!isAll,
routingFormId: selectedRoutingFormId ?? undefined,
},
{
enabled: initialConfigIsReady,
}
);
const { userId, teamId, startDate, endDate, isAll, routingFormId } = useInsightsParameters();
const { data } = trpc.viewer.insights.failedBookingsByField.useQuery({
userId,
teamId,
isAll,
routingFormId,
});

if (!data) return null;

Expand Down
64 changes: 34 additions & 30 deletions packages/features/insights/components/RoutedToPerPeriod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { TFunction } from "next-i18next";
import { useQueryState } from "nuqs";
import { type ReactNode, useMemo, useRef, useState } from "react";

import type { Dayjs } from "@calcom/dayjs";
import { DataTableSkeleton } from "@calcom/features/data-table";
import classNames from "@calcom/lib/classNames";
import { downloadAsCsv } from "@calcom/lib/csvUtils";
Expand All @@ -29,14 +28,15 @@ import {
TableRow,
} from "@calcom/ui/components/table/TableNew";

import { useFilterContext } from "../context/provider";
import { useInsightsParameters } from "../hooks/useInsightsParameters";

interface DownloadButtonProps {
teamId?: number;
userId?: number;
isAll?: boolean;
routingFormId?: string;
dateRange: [Dayjs, Dayjs, string | null];
startDate: string;
endDate: string;
selectedPeriod: string;
searchQuery?: string;
}
Expand All @@ -46,7 +46,8 @@ function DownloadButton({
teamId,
isAll,
routingFormId,
dateRange,
startDate,
endDate,
selectedPeriod,
searchQuery,
}: DownloadButtonProps) {
Expand All @@ -59,13 +60,13 @@ function DownloadButton({

try {
const result = await utils.viewer.insights.routedToPerPeriodCsv.fetch({
userId: userId ?? undefined,
teamId: teamId ?? undefined,
startDate: dateRange[0]?.toISOString() ?? "",
endDate: dateRange[1]?.toISOString() ?? "",
userId,
teamId,
startDate,
endDate,
period: selectedPeriod as "perDay" | "perWeek" | "perMonth",
isAll: !!isAll,
routingFormId: routingFormId ?? undefined,
isAll,
routingFormId,
searchQuery: searchQuery || undefined,
});

Expand Down Expand Up @@ -103,7 +104,8 @@ interface FormCardProps {
userId?: number;
isAll?: boolean;
routingFormId?: string;
dateRange: [Dayjs, Dayjs, string | null];
startDate: string;
endDate: string;
}

function FormCard({
Expand All @@ -116,7 +118,8 @@ function FormCard({
userId,
isAll,
routingFormId,
dateRange,
startDate,
endDate,
}: FormCardProps) {
const { t } = useLocale();

Expand Down Expand Up @@ -150,7 +153,8 @@ function FormCard({
teamId={teamId}
isAll={isAll}
routingFormId={routingFormId}
dateRange={dateRange}
startDate={startDate}
endDate={endDate}
selectedPeriod={selectedPeriod}
searchQuery={searchQuery}
/>
Expand Down Expand Up @@ -219,8 +223,7 @@ const getPerformanceBadge = (performance: RoutedToTableRow["performance"], t: TF

export function RoutedToPerPeriod() {
const { t } = useLocale();
const { filter } = useFilterContext();
const { selectedTeamId, selectedUserId, isAll, selectedRoutingFormId, dateRange } = filter;
const { userId, teamId, startDate, endDate, isAll, routingFormId } = useInsightsParameters();
const [selectedPeriod, setSelectedPeriod] = useQueryState("selectedPeriod", {
defaultValue: "perWeek",
});
Expand All @@ -239,13 +242,13 @@ export function RoutedToPerPeriod() {
const { data, fetchNextPage, isFetchingNextPage, hasNextPage, isLoading } =
trpc.viewer.insights.routedToPerPeriod.useInfiniteQuery(
{
userId: selectedUserId ?? undefined,
teamId: selectedTeamId ?? undefined,
startDate: dateRange[0]?.toISOString() ?? "",
endDate: dateRange[1]?.toISOString() ?? "",
userId,
teamId,
startDate,
endDate,
period: selectedPeriod as "perDay" | "perWeek" | "perMonth",
isAll: !!isAll,
routingFormId: selectedRoutingFormId ?? undefined,
isAll,
routingFormId,
searchQuery: searchQuery || undefined,
limit: 10,
},
Expand All @@ -260,7 +263,6 @@ export function RoutedToPerPeriod() {
periodCursor: lastPage.periodStats.nextCursor,
};
},
enabled: !!dateRange[0] && !!dateRange[1],
}
);

Expand Down Expand Up @@ -334,11 +336,12 @@ export function RoutedToPerPeriod() {
onPeriodChange={setSelectedPeriod}
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
userId={selectedUserId ?? undefined}
teamId={selectedTeamId ?? undefined}
userId={userId}
teamId={teamId}
isAll={isAll}
routingFormId={selectedRoutingFormId ?? undefined}
dateRange={dateRange}>
routingFormId={routingFormId}
startDate={startDate}
endDate={endDate}>
<div className="mt-6">
<DataTableSkeleton columns={5} columnWidths={[200, 120, 120, 120, 120]} />
</div>
Expand Down Expand Up @@ -377,11 +380,12 @@ export function RoutedToPerPeriod() {
onPeriodChange={setSelectedPeriod}
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
userId={selectedUserId ?? undefined}
teamId={selectedTeamId ?? undefined}
userId={userId}
teamId={teamId}
isAll={isAll}
routingFormId={selectedRoutingFormId ?? undefined}
dateRange={dateRange}>
routingFormId={routingFormId}
startDate={startDate}
endDate={endDate}>
<div className="mt-6">
<div
className="scrollbar-thin border-subtle relaitve relative h-[80dvh] overflow-auto rounded-md border"
Expand Down
Loading

0 comments on commit fdc8e08

Please sign in to comment.