- {/* Header */}
-
-
-
- {/* Progress dots - centered */}
-
-
-
-
-
+
+
+ {t("continue")}
+
+ }>
+
+ {queryIntegrations.data?.items?.map((app) => (
+
+ ))}
+
-
-
-
- {/* Main content */}
-
-
- {/* Card */}
-
-
- {/* Card Header */}
-
-
-
{t("connect_your_calendar")}
-
- {t("connect_calendar_to_prevent_conflicts")}
-
-
-
-
- {/* Content */}
-
- {queryIntegrations.isPending ? (
-
-
-
-
- ) : (
-
- {queryIntegrations.data?.items.map((app) => (
-
- {app.logo &&

}
-
- {app.name}
-
-
- {app.description}
-
-
-
- ))}
-
- )}
-
-
- {/* Footer */}
-
-
-
-
-
-
- {/* Skip button */}
-
-
-
-
-
-
+
+
);
};
diff --git a/apps/web/modules/onboarding/personal/video/personal-video-view.tsx b/apps/web/modules/onboarding/personal/video/personal-video-view.tsx
index 8a1809ac70..1fda826eb0 100644
--- a/apps/web/modules/onboarding/personal/video/personal-video-view.tsx
+++ b/apps/web/modules/onboarding/personal/video/personal-video-view.tsx
@@ -5,10 +5,16 @@ import { useRouter } from "next/navigation";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { useTelemetry } from "@calcom/lib/hooks/useTelemetry";
import { telemetryEventTypes } from "@calcom/lib/telemetry";
+import { userMetadata } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import { Button } from "@calcom/ui/components/button";
-import { Logo } from "@calcom/ui/components/logo";
-import { SkeletonText } from "@calcom/ui/components/skeleton";
+import { showToast } from "@calcom/ui/components/toast";
+
+import { InstallableAppCard } from "../_components/InstallableAppCard";
+import { OnboardingCard } from "../_components/OnboardingCard";
+import { OnboardingLayout } from "../_components/OnboardingLayout";
+import { SkipButton } from "../_components/SkipButton";
+import { useAppInstallation } from "../_components/useAppInstallation";
type PersonalVideoViewProps = {
userEmail: string;
@@ -38,6 +44,8 @@ export const PersonalVideoView = ({ userEmail }: PersonalVideoViewProps) => {
const router = useRouter();
const { t } = useLocale();
const telemetry = useTelemetry();
+ const utils = trpc.useUtils();
+ const { installingAppSlug, setInstallingAppSlug, createInstallHandlers } = useAppInstallation();
const { data: queryConnectedVideoApps, isPending } = trpc.viewer.apps.integrations.useQuery({
variant: "conferencing",
@@ -46,10 +54,19 @@ export const PersonalVideoView = ({ userEmail }: PersonalVideoViewProps) => {
sortByInstalledFirst: true,
});
+ const setDefaultConferencingApp = trpc.viewer.apps.setDefaultConferencingApp.useMutation({
+ onSuccess: async () => {
+ await utils.viewer.me.invalidate();
+ },
+ onError: (error) => {
+ showToast(t("something_went_wrong"), "error");
+ console.error(error);
+ },
+ });
+
const { data: eventTypes } = trpc.viewer.eventTypes.list.useQuery();
const createEventType = trpc.viewer.eventTypesHeavy.create.useMutation();
- const utils = trpc.useUtils();
const mutation = trpc.viewer.me.updateProfile.useMutation({
onSuccess: async () => {
try {
@@ -77,8 +94,6 @@ export const PersonalVideoView = ({ userEmail }: PersonalVideoViewProps) => {
const handleContinue = async () => {
telemetry.event(telemetryEventTypes.onboardingFinished);
-
- // Complete onboarding
mutation.mutate({
completedOnboarding: true,
});
@@ -86,118 +101,62 @@ export const PersonalVideoView = ({ userEmail }: PersonalVideoViewProps) => {
const handleSkip = async () => {
telemetry.event(telemetryEventTypes.onboardingFinished);
-
- // Complete onboarding
mutation.mutate({
completedOnboarding: true,
});
};
if (!user) {
- return null; // or a loading spinner
+ return null;
}
+ // Check if user has a default conferencing app
+ const result = userMetadata.safeParse(user.metadata);
+ const metadata = result?.success ? result.data : null;
+ const hasDefaultConferencingApp = !!metadata?.defaultConferencingApp?.appSlug;
+
return (
-
- {/* Header */}
-
-
+
+
+ {t("finish_and_start")}
+
+ }>
+
+ {queryConnectedVideoApps?.items
+ .filter((app) => app.slug !== "daily-video")
+ .map((app) => {
+ const shouldAutoSetDefault =
+ !hasDefaultConferencingApp && app.appData?.location?.linkType === "dynamic";
- {/* Progress dots - centered */}
-
-
-
-
-
+ return (
+
{
+ // Auto-set as default if it's the first connected video app
+ if (shouldAutoSetDefault) {
+ setDefaultConferencingApp.mutate({ slug: appSlug });
+ }
+ })}
+ />
+ );
+ })}
+
-
-
-
- {/* Main content */}
-
-
- {/* Card */}
-
-
- {/* Card Header */}
-
-
-
{t("connect_video_app")}
-
- {t("video_app_connection_subtitle")}
-
-
-
-
- {/* Content */}
-
- {isPending ? (
-
-
-
-
- ) : (
-
- {queryConnectedVideoApps?.items
- .filter((app) => app.slug !== "daily-video")
- .map((app) => (
-
- {app.userCredentialIds.length > 0 && (
-
- {t("connected")}
-
- )}
- {app.logo &&

}
-
- {app.name}
-
-
- {app.description}
-
-
-
- ))}
-
- )}
-
-
- {/* Footer */}
-
-
-
-
-
-
- {/* Skip button */}
-
-
-
-
-
-
+
+
);
};