From d2bc81758c8c4725237e4420237b5b4562b82034 Mon Sep 17 00:00:00 2001 From: Eunjae Lee Date: Thu, 6 Mar 2025 11:24:50 +0100 Subject: [PATCH] feat: add booking id & booking link columns to /insights/routing (#19697) * feat: add booking id & booking link columns to /insights/routing * update style * update i18n * update i18n keys * update host * useCopy instead of raw navigator.clipboard --- apps/web/public/static/locales/en/common.json | 2 + packages/features/data-table/lib/context.tsx | 10 +++- .../insights/hooks/useInsightsColumns.tsx | 56 ++++++++++++++++++- .../hooks/useInsightsFacetedUniqueValues.ts | 43 +++++++++----- 4 files changed, 93 insertions(+), 18 deletions(-) diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index c209bab9b8..ce3662f8f7 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -3001,5 +3001,7 @@ "ooo_team_redirect_infinite_not_allowed": "There is already a reverse forwarding between these users.", "previous_ooo_empty_title": "No previous OOO found", "previous": "Previous", + "uid": "UID", + "link": "Link", "ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑" } diff --git a/packages/features/data-table/lib/context.tsx b/packages/features/data-table/lib/context.tsx index 485eb5755f..6f65f4d581 100644 --- a/packages/features/data-table/lib/context.tsx +++ b/packages/features/data-table/lib/context.tsx @@ -30,18 +30,22 @@ export type DataTableContextType = { export const DataTableContext = createContext(null); +const DEFAULT_ACTIVE_FILTERS: ActiveFilter[] = []; +const DEFAULT_SORTING: SortingState = []; +const DEFAULT_COLUMN_VISIBILITY: VisibilityState = {}; + export function DataTableProvider({ children }: { children: React.ReactNode }) { const [activeFilters, setActiveFilters] = useQueryState( "activeFilters", - parseAsArrayOf(parseAsJson(ZActiveFilter.parse)).withDefault([]) + parseAsArrayOf(parseAsJson(ZActiveFilter.parse)).withDefault(DEFAULT_ACTIVE_FILTERS) ); const [sorting, setSorting] = useQueryState( "sorting", - parseAsArrayOf(parseAsJson(ZSorting.parse)).withDefault([]) + parseAsArrayOf(parseAsJson(ZSorting.parse)).withDefault(DEFAULT_SORTING) ); const [columnVisibility, setColumnVisibility] = useQueryState( "cols", - parseAsJson(ZColumnVisibility.parse).withDefault({}) + parseAsJson(ZColumnVisibility.parse).withDefault(DEFAULT_COLUMN_VISIBILITY) ); const clearAll = useCallback( diff --git a/packages/features/insights/hooks/useInsightsColumns.tsx b/packages/features/insights/hooks/useInsightsColumns.tsx index 2c22741c66..3bac82aa6f 100644 --- a/packages/features/insights/hooks/useInsightsColumns.tsx +++ b/packages/features/insights/hooks/useInsightsColumns.tsx @@ -6,9 +6,11 @@ import { z } from "zod"; import dayjs from "@calcom/dayjs"; import { dataTableFilter, ColumnFilterType } from "@calcom/features/data-table"; +import { WEBAPP_URL } from "@calcom/lib/constants"; +import { useCopy } from "@calcom/lib/hooks/useCopy"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { RoutingFormFieldType } from "@calcom/routing-forms/lib/FieldTypes"; -import { Badge } from "@calcom/ui"; +import { Badge, Icon } from "@calcom/ui"; import { BookedByCell } from "../components/BookedByCell"; import { BookingAtCell } from "../components/BookingAtCell"; @@ -68,6 +70,32 @@ export const useInsightsColumns = ({ return dataTableFilter(cellValue, filterValue); }, }), + columnHelper.accessor("bookingUid", { + id: "bookingUid", + header: t("uid"), + size: 100, + enableColumnFilter: false, + enableSorting: false, + cell: (info) => { + const bookingUid = info.getValue(); + if (!bookingUid) return null; + return ; + }, + }), + columnHelper.accessor("bookingUid", { + id: "bookingLink", + header: t("link"), + size: 100, + enableColumnFilter: false, + enableSorting: false, + cell: (info) => { + const bookingUid = info.getValue(); + if (!bookingUid) return null; + const bookingUrl = `${WEBAPP_URL}/booking/${bookingUid}`; + const displayedUrl = bookingUrl.replace(/^https?:\/\//, ""); + return ; + }, + }), columnHelper.accessor("bookingAttendees", { id: "bookingAttendees", header: t("routing_form_insights_booked_by"), @@ -225,3 +253,29 @@ export const useInsightsColumns = ({ ]; }, [isHeadersSuccess, headers]); }; + +function CopyButton({ label, value }: { label: string; value: string }) { + const { copyToClipboard, isCopied } = useCopy(); + const { t } = useLocale(); + return ( + + ); +} diff --git a/packages/features/insights/hooks/useInsightsFacetedUniqueValues.ts b/packages/features/insights/hooks/useInsightsFacetedUniqueValues.ts index bff56e7e96..91ecd67cce 100644 --- a/packages/features/insights/hooks/useInsightsFacetedUniqueValues.ts +++ b/packages/features/insights/hooks/useInsightsFacetedUniqueValues.ts @@ -27,22 +27,37 @@ export const useInsightsFacetedUniqueValues = ({ teamId: number | undefined; isAll: boolean; }) => { - const { data: forms } = trpc.viewer.insights.getRoutingFormsForFilters.useQuery({ - userId, - teamId, - isAll, - }); + const { data: forms } = trpc.viewer.insights.getRoutingFormsForFilters.useQuery( + { + userId, + teamId, + isAll, + }, + { + refetchOnWindowFocus: false, + } + ); - const { data: users } = trpc.viewer.insights.userList.useQuery({ - teamId, - isAll, - }); + const { data: users } = trpc.viewer.insights.userList.useQuery( + { + teamId, + isAll, + }, + { + refetchOnWindowFocus: false, + } + ); - const { data: eventTypes } = trpc.viewer.insights.eventTypeList.useQuery({ - teamId, - userId, - isAll, - }); + const { data: eventTypes } = trpc.viewer.insights.eventTypeList.useQuery( + { + teamId, + userId, + isAll, + }, + { + refetchOnWindowFocus: false, + } + ); return useCallback( (_: Table, columnId: string) => (): Map => {