Files
calendar/packages/ui/components/card/PanelCard.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

59 lines
1.7 KiB
TypeScript

import type { ReactNode } from "react";
import classNames from "@calcom/ui/classNames";
import { InfoBadge } from "@calcom/ui/components/badge";
import { Button } from "@calcom/ui/components/button";
export function PanelCard({
title,
subtitle,
cta,
headerContent,
className,
titleTooltip,
children,
}: {
title: string | ReactNode;
subtitle?: string;
cta?: { label: string; onClick: () => void };
headerContent?: ReactNode;
className?: string;
titleTooltip?: string;
children: ReactNode;
}) {
return (
<div
className={classNames(
"bg-muted group relative flex w-full flex-col items-center rounded-2xl px-1 pb-1",
className
)}>
<div className="flex h-11 w-full shrink-0 items-center justify-between gap-2 px-4">
{typeof title === "string" ? (
<div className="mr-4 flex shrink-0 items-center gap-1">
<h2 className="text-emphasis shrink-0 text-sm font-semibold">{title}</h2>
{titleTooltip && <InfoBadge content={titleTooltip} />}
</div>
) : (
title
)}
<div className="no-scrollbar flex items-center gap-2 overflow-x-auto">
{headerContent}
{cta && (
<Button className="shrink-0" color="secondary" onClick={cta.onClick}>
{cta.label}
</Button>
)}
</div>
</div>
<div className="bg-default border-muted w-full grow gap-3 rounded-xl border">
{subtitle && (
<h3 className="text-subtle border-muted border-b p-3 text-sm font-medium leading-none">
{subtitle}
</h3>
)}
{children}
</div>
</div>
);
}