diff --git a/apps/web/modules/bookings/views/bookings-view.tsx b/apps/web/modules/bookings/views/bookings-view.tsx index f2102c9417..e951f53b7c 100644 --- a/apps/web/modules/bookings/views/bookings-view.tsx +++ b/apps/web/modules/bookings/views/bookings-view.tsx @@ -6,8 +6,8 @@ import FeatureOptInBannerWrapper from "~/feature-opt-in/components/FeatureOptInB import { useLocale } from "@calcom/lib/hooks/useLocale"; import classNames from "@calcom/ui/classNames"; import dynamic from "next/dynamic"; -import { usePathname } from "next/navigation"; -import { useMemo } from "react"; +import { usePathname, useRouter } from "next/navigation"; +import { useCallback, useMemo } from "react"; import { useFeatureOptInBanner } from "../../feature-opt-in/hooks/useFeatureOptInBanner"; import { BookingListContainer } from "../components/BookingListContainer"; import { useActiveFiltersValidator } from "../hooks/useActiveFiltersValidator"; @@ -78,7 +78,11 @@ export default function Bookings(props: BookingsProps) { function BookingsContent({ status, permissions, bookingsV3Enabled, bookingAuditEnabled }: BookingsProps) { const [view] = useBookingsView({ bookingsV3Enabled }); - const optInBanner = useFeatureOptInBanner("bookings-v3"); + const router = useRouter(); + const handleOptInSuccess = useCallback(() => { + router.refresh(); + }, [router]); + const optInBanner = useFeatureOptInBanner("bookings-v3", { onOptInSuccess: handleOptInSuccess }); return (
diff --git a/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.test.ts b/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.test.ts index a2835f52aa..a1bff759ff 100644 --- a/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.test.ts +++ b/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.test.ts @@ -75,7 +75,9 @@ describe("useFeatureOptInBanner", () => { it("shows banner for normal users when eligible", () => { mockUseSession.mockReturnValue({ data: { user: {} } }); - const { result } = renderHook(() => useFeatureOptInBanner("bookings-v3")); + const { result } = renderHook(() => + useFeatureOptInBanner("bookings-v3", { onOptInSuccess: vi.fn() }) + ); expect(result.current.shouldShow).toBe(true); }); @@ -85,8 +87,23 @@ describe("useFeatureOptInBanner", () => { data: { user: { impersonatedBy: { id: 999, email: "admin@cal.com" } } }, }); - const { result } = renderHook(() => useFeatureOptInBanner("bookings-v3")); + const { result } = renderHook(() => + useFeatureOptInBanner("bookings-v3", { onOptInSuccess: vi.fn() }) + ); expect(result.current.shouldShow).toBe(true); }); + + it("calls onOptInSuccess callback when markOptedIn is invoked", () => { + mockUseSession.mockReturnValue({ data: { user: {} } }); + const onOptInSuccess = vi.fn(); + + const { result } = renderHook(() => + useFeatureOptInBanner("bookings-v3", { onOptInSuccess }) + ); + + result.current.markOptedIn(); + + expect(onOptInSuccess).toHaveBeenCalledOnce(); + }); }); diff --git a/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.ts b/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.ts index e57a7a7686..db88b51b96 100644 --- a/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.ts +++ b/apps/web/modules/feature-opt-in/hooks/useFeatureOptInBanner.ts @@ -58,7 +58,14 @@ function isFeatureOptedIn(featureId: string): boolean { return getFeatureOptInTimestamp(featureId) !== null; } -function useFeatureOptInBanner(featureId: string): UseFeatureOptInBannerResult { +type UseFeatureOptInBannerOptions = { + onOptInSuccess: () => void; +}; + +function useFeatureOptInBanner( + featureId: string, + options: UseFeatureOptInBannerOptions +): UseFeatureOptInBannerResult { const [isDialogOpen, setIsDialogOpen] = useState(false); const [isDismissed, setIsDismissed] = useState(() => isFeatureDismissed(featureId)); const [isOptedIn, setIsOptedIn] = useState(() => isFeatureOptedIn(featureId)); @@ -135,7 +142,8 @@ function useFeatureOptInBanner(featureId: string): UseFeatureOptInBannerResult { const markOptedIn = useCallback(() => { setFeatureOptedIn(featureId); setIsOptedIn(true); - }, [featureId]); + options.onOptInSuccess(); + }, [featureId, options.onOptInSuccess]); const openDialog = useCallback(() => { posthog.capture("feature_opt_in_banner_try_it_clicked", {