From ecd85cd15a4aaf4fb024be96ecccc18f850af324 Mon Sep 17 00:00:00 2001
From: Ayush Agarwal <114819135+ayush110404@users.noreply.github.com>
Date: Tue, 25 Mar 2025 23:43:09 +0530
Subject: [PATCH] feat: enhance onboarding steps with loading state and button
component (#20350)
- Added loading state to ConnectedCalendars and ConnectedVideoStep components.
- Replaced native button elements with a custom Button component for consistency.
- Updated SetupAvailability to use async mutation methods.
- Integrated loading state into the onboarding view for smoother transitions between steps.
---
.../steps-views/ConnectCalendars.tsx | 13 +++++++------
.../steps-views/ConnectedVideoStep.tsx | 13 +++++++------
.../steps-views/SetupAvailability.tsx | 4 ++--
.../[[...step]]/onboarding-view.tsx | 15 +++++++++++----
4 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/apps/web/components/getting-started/steps-views/ConnectCalendars.tsx b/apps/web/components/getting-started/steps-views/ConnectCalendars.tsx
index 3e612edfba..462e8f7c42 100644
--- a/apps/web/components/getting-started/steps-views/ConnectCalendars.tsx
+++ b/apps/web/components/getting-started/steps-views/ConnectCalendars.tsx
@@ -1,7 +1,7 @@
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import classNames from "@calcom/ui/classNames";
-import { Icon } from "@calcom/ui/components/icon";
+import { Button } from "@calcom/ui/components/button";
import { List } from "@calcom/ui/components/list";
import { AppConnectionItem } from "../components/AppConnectionItem";
@@ -11,10 +11,11 @@ import { StepConnectionLoader } from "../components/StepConnectionLoader";
interface IConnectCalendarsProps {
nextStep: () => void;
+ isPageLoading: boolean;
}
const ConnectedCalendars = (props: IConnectCalendarsProps) => {
- const { nextStep } = props;
+ const { nextStep, isPageLoading } = props;
const queryConnectedCalendars = trpc.viewer.connectedCalendars.useQuery({
onboarding: true,
eventTypeId: null,
@@ -81,18 +82,18 @@ const ConnectedCalendars = (props: IConnectCalendarsProps) => {
{queryIntegrations.isPending && }
-
+
>
);
};
diff --git a/apps/web/components/getting-started/steps-views/ConnectedVideoStep.tsx b/apps/web/components/getting-started/steps-views/ConnectedVideoStep.tsx
index 3a60e7e1b7..873a4dacd3 100644
--- a/apps/web/components/getting-started/steps-views/ConnectedVideoStep.tsx
+++ b/apps/web/components/getting-started/steps-views/ConnectedVideoStep.tsx
@@ -3,7 +3,7 @@ import { userMetadata } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
import classNames from "@calcom/ui/classNames";
-import { Icon } from "@calcom/ui/components/icon";
+import { Button } from "@calcom/ui/components/button";
import { List } from "@calcom/ui/components/list";
import { AppConnectionItem } from "../components/AppConnectionItem";
@@ -11,10 +11,11 @@ import { StepConnectionLoader } from "../components/StepConnectionLoader";
interface ConnectedAppStepProps {
nextStep: () => void;
+ isPageLoading: boolean;
}
const ConnectedVideoStep = (props: ConnectedAppStepProps) => {
- const { nextStep } = props;
+ const { nextStep, isPageLoading } = props;
const { data: queryConnectedVideoApps, isPending } = trpc.viewer.apps.integrations.useQuery({
variant: "conferencing",
onlyInstalled: false,
@@ -70,18 +71,18 @@ const ConnectedVideoStep = (props: ConnectedAppStepProps) => {
)}
{isPending && }
-
+
>
);
};
diff --git a/apps/web/components/getting-started/steps-views/SetupAvailability.tsx b/apps/web/components/getting-started/steps-views/SetupAvailability.tsx
index 9fd7efdddb..46f2a2d666 100644
--- a/apps/web/components/getting-started/steps-views/SetupAvailability.tsx
+++ b/apps/web/components/getting-started/steps-views/SetupAvailability.tsx
@@ -51,13 +51,13 @@ const SetupAvailability = (props: ISetupAvailabilityProps) => {
handleSubmit={async (values) => {
try {
if (defaultScheduleId) {
- await updateSchedule.mutate({
+ await updateSchedule.mutateAsync({
scheduleId: defaultScheduleId,
name: t("default_schedule_name"),
...values,
});
} else {
- await createSchedule.mutate({
+ await createSchedule.mutateAsync({
name: t("default_schedule_name"),
...values,
});
diff --git a/apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx b/apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx
index 02c9d65d6f..19a3d24c93 100644
--- a/apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx
+++ b/apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx
@@ -3,7 +3,7 @@
import type { TFunction } from "i18next";
import { signOut } from "next-auth/react";
import { usePathname, useRouter } from "next/navigation";
-import { Suspense } from "react";
+import { Suspense, useTransition } from "react";
import { Toaster } from "sonner";
import { z } from "zod";
@@ -93,6 +93,7 @@ const OnboardingPage = (props: PageProps) => {
const router = useRouter();
const [user] = trpc.viewer.me.get.useSuspenseQuery();
const { t } = useLocale();
+ const [isNextStepLoading, startTransition] = useTransition();
const result = stepRouteSchema.safeParse({
...params,
@@ -126,7 +127,9 @@ const OnboardingPage = (props: PageProps) => {
const goToNextStep = () => {
const nextIndex = currentStepIndex + 1;
const newStep = steps[nextIndex];
- router.push(`/getting-started/${stepTransform(newStep)}`);
+ startTransition(() => {
+ router.push(`/getting-started/${stepTransform(newStep)}`);
+ });
};
return (
@@ -161,9 +164,13 @@ const OnboardingPage = (props: PageProps) => {
{currentStep === "user-settings" && (
)}
- {currentStep === "connected-calendar" && }
+ {currentStep === "connected-calendar" && (
+
+ )}
- {currentStep === "connected-video" && }
+ {currentStep === "connected-video" && (
+
+ )}
{currentStep === "setup-availability" && (