import type { GetServerSidePropsContext } from "next"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import Head from "next/head"; import { usePathname, useRouter } from "next/navigation"; import type { CSSProperties } from "react"; import { Suspense } from "react"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { APP_NAME } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { useParamsWithFallback } from "@calcom/lib/hooks/useParamsWithFallback"; import prisma from "@calcom/prisma"; import { trpc } from "@calcom/trpc"; import { Button, StepCard, Steps } from "@calcom/ui"; import { Loader } from "@calcom/ui/components/icon"; import PageWrapper from "@components/PageWrapper"; import { ConnectedCalendars } from "@components/getting-started/steps-views/ConnectCalendars"; import { ConnectedVideoStep } from "@components/getting-started/steps-views/ConnectedVideoStep"; import { SetupAvailability } from "@components/getting-started/steps-views/SetupAvailability"; import UserProfile from "@components/getting-started/steps-views/UserProfile"; import { UserSettings } from "@components/getting-started/steps-views/UserSettings"; import { ssrInit } from "@server/lib/ssr"; const INITIAL_STEP = "user-settings"; const steps = [ "user-settings", "connected-calendar", "connected-video", "setup-availability", "user-profile", ] as const; const stepTransform = (step: (typeof steps)[number]) => { const stepIndex = steps.indexOf(step); if (stepIndex > -1) { return steps[stepIndex]; } return INITIAL_STEP; }; const stepRouteSchema = z.object({ step: z.array(z.enum(steps)).default([INITIAL_STEP]), from: z.string().optional(), }); // TODO: Refactor how steps work to be contained in one array/object. Currently we have steps,initalsteps,headers etc. These can all be in one place const OnboardingPage = () => { const pathname = usePathname(); const params = useParamsWithFallback(); const router = useRouter(); const [user] = trpc.viewer.me.useSuspenseQuery(); const { t } = useLocale(); const result = stepRouteSchema.safeParse(params); const currentStep = result.success ? result.data.step[0] : INITIAL_STEP; const from = result.success ? result.data.from : ""; const headers = [ { title: `${t("welcome_to_cal_header", { appName: APP_NAME })}`, subtitle: [`${t("we_just_need_basic_info")}`, `${t("edit_form_later_subtitle")}`], }, { title: `${t("connect_your_calendar")}`, subtitle: [`${t("connect_your_calendar_instructions")}`], skipText: `${t("connect_calendar_later")}`, }, { title: `${t("connect_your_video_app")}`, subtitle: [`${t("connect_your_video_app_instructions")}`], skipText: `${t("set_up_later")}`, }, { title: `${t("set_availability")}`, subtitle: [ `${t("set_availability_getting_started_subtitle_1")}`, `${t("set_availability_getting_started_subtitle_2")}`, ], }, { title: `${t("nearly_there")}`, subtitle: [`${t("nearly_there_instructions")}`], }, ]; // TODO: Add this in when we have solved the ability to move to tokens accept invite and note invitedto // Ability to accept other pending invites if any (low priority) // if (props.hasPendingInvites) { // headers.unshift( // props.hasPendingInvites && { // title: `${t("email_no_user_invite_heading", { appName: APP_NAME })}`, // subtitle: [], // TODO: come up with some subtitle text here // } // ); // } const goToIndex = (index: number) => { const newStep = steps[index]; router.push(`/getting-started/${stepTransform(newStep)}`); }; const currentStepIndex = steps.indexOf(currentStep); return (
{headers[currentStepIndex]?.title || "Undefined title"}
{headers[currentStepIndex]?.subtitle.map((subtitle, index) => ({subtitle}
))}