Files
calendar/apps/web/modules/insights/insights-view.tsx
T
Eunjae LeeGitHubeunjae@cal.com <hey@eunjae.dev>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
59c76141ce feat: add Recent No-Show Guests chart to insights page (#23381)
* feat: add Recent No-Show Guests chart to insights page

- Add RecentNoShowGuestsChart component with ChartCard wrapper
- Add tRPC handler for recentNoShowGuests query
- Add getRecentNoShowGuests method to InsightsBookingBaseService
- Display guest name, booking time, event type, and copy email button
- Filter for bookings where ALL attendees are no-shows
- Add translation strings for new UI elements
- Integrate chart into insights view grid layout

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* re-order charts

* clean up

* feat: add optional tooltip functionality to PanelCard

- Add titleTooltip prop to PanelCard component with InfoBadge
- Pass through titleTooltip prop in ChartCard
- Add tooltip to RecentNoShowGuestsChart explaining complete no-show filtering
- Add translation string for tooltip explanation

Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>

* style adjustment

* update style

* address feedback

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-08-28 14:01:27 +00:00

129 lines
4.2 KiB
TypeScript

"use client";
import {
DataTableProvider,
DataTableFilters,
DateRangeFilter,
ColumnFilterType,
type FilterableColumn,
} from "@calcom/features/data-table";
import { useSegments } from "@calcom/features/data-table/hooks/useSegments";
import {
AverageEventDurationChart,
BookingKPICards,
BookingsByHourChart,
EventTrendsChart,
HighestNoShowHostTable,
HighestRatedMembersTable,
LeastBookedTeamMembersTable,
LowestRatedMembersTable,
MostBookedTeamMembersTable,
MostCancelledBookingsTables,
MostCompletedTeamMembersTable,
LeastCompletedTeamMembersTable,
PopularEventsTable,
RecentNoShowGuestsChart,
RecentFeedbackTable,
TimezoneBadge,
} from "@calcom/features/insights/components/booking";
import { InsightsOrgTeamsProvider } from "@calcom/features/insights/context/InsightsOrgTeamsProvider";
import { Download } from "@calcom/features/insights/filters/Download";
import { OrgTeamsFilter } from "@calcom/features/insights/filters/OrgTeamsFilter";
import { useInsightsBookings } from "@calcom/features/insights/hooks/useInsightsBookings";
import { useInsightsOrgTeams } from "@calcom/features/insights/hooks/useInsightsOrgTeams";
import { useLocale } from "@calcom/lib/hooks/useLocale";
export default function InsightsPage({ timeZone }: { timeZone: string }) {
return (
<DataTableProvider useSegments={useSegments} timeZone={timeZone}>
<InsightsOrgTeamsProvider>
<InsightsPageContent />
</InsightsOrgTeamsProvider>
</DataTableProvider>
);
}
const createdAtColumn: Extract<FilterableColumn, { type: ColumnFilterType.DATE_RANGE }> = {
id: "createdAt",
title: "createdAt",
type: ColumnFilterType.DATE_RANGE,
};
function InsightsPageContent() {
const { t } = useLocale();
const { table } = useInsightsBookings();
const { isAll, teamId, userId } = useInsightsOrgTeams();
return (
<>
<div
className="flex flex-wrap items-center gap-2"
data-testid={`insights-filters-${isAll}-${teamId}-${userId}`}>
<OrgTeamsFilter />
<DataTableFilters.AddFilterButton table={table} hideWhenFilterApplied />
<DataTableFilters.ActiveFilters table={table} />
<DataTableFilters.AddFilterButton table={table} variant="sm" showWhenFilterApplied />
<DataTableFilters.ClearFiltersButton exclude={["createdAt"]} />
<div className="grow" />
<Download />
<DateRangeFilter column={createdAtColumn} />
<TimezoneBadge />
</div>
<div className="my-4 space-y-4">
<BookingKPICards />
<EventTrendsChart />
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
<div className="sm:col-span-2">
<BookingsByHourChart />
</div>
<div className="sm:col-span-2">
<AverageEventDurationChart />
</div>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
<MostBookedTeamMembersTable />
<LeastBookedTeamMembersTable />
<MostCompletedTeamMembersTable />
<LeastCompletedTeamMembersTable />
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
<MostCancelledBookingsTables />
<HighestNoShowHostTable />
<div className="sm:col-span-2">
<RecentNoShowGuestsChart />
</div>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
<HighestRatedMembersTable />
<LowestRatedMembersTable />
<div className="sm:col-span-2">
<RecentFeedbackTable />
</div>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-4">
<div className="sm:col-span-2">
<PopularEventsTable />
</div>
</div>
<small className="text-default block text-center">
{t("looking_for_more_insights")}{" "}
<a
className="text-blue-500 hover:underline"
href="mailto:updates@cal.com?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>
</>
);
}