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", {