fix(onboarding): adderss nits for invite link / spacing (#24742)

## What does this PR do?

- Redirects users to the personal settings page after organization creation instead of the getting-started page
- Adds a new `skipToPersonal` function in `useSubmitOnboarding` hook to handle this redirection
- Creates a new `getGettingStartedPathWhenInvited` method in `OnboardingPathService` to provide the correct path for invited users
- Updates all invitation-related code to use the new path method
- Improves UI spacing in the organization invite view

## Visual Demo (For contributors especially)

#### Image Demo (if applicable):
- Before: Users were redirected to `/onboarding/getting-started` or `/getting-started` after organization creation
- After: Users are now redirected to `/onboarding/personal/settings` or `/getting-started` based on feature flag

## Mandatory Tasks (DO NOT REMOVE)

- [ ] I have self-reviewed the code.
- [ ] I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Create a new organization through the onboarding flow
2. Verify you are redirected to the personal settings page instead of getting-started
3. Accept an invitation to an organization as a new user
4. Verify you are directed to the personal settings page after signup
5. Check that the UI spacing in the organization invite view looks correct

## Checklist

- I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code follows the style guidelines of this project
- I have commented my code, particularly in hard-to-understand areas
- I have checked if my changes generate no new warnings
This commit is contained in:
sean-brydon
2025-10-28 14:35:57 +00:00
committed by GitHub
parent d5894d9fbc
commit 51d78e6f9d
6 changed files with 21 additions and 10 deletions
@@ -1,10 +1,10 @@
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import { CreationSource } from "@calcom/prisma/enums";
import { trpc } from "@calcom/trpc/react";
import { showToast } from "@calcom/ui/components/toast";
import { useFlagMap } from "@calcom/features/flags/context/provider";
import type { OnboardingState } from "../store/onboarding-store";
@@ -81,9 +81,7 @@ export const useSubmitOnboarding = () => {
// Organization has already been created by the backend
showToast("Organization created successfully!", "success");
// TODO: after this redirect we need to hard refresh the page to see org
resetOnboarding();
const gettingStartedPath = flags["onboarding-v3"] ? "/onboarding/getting-started" : "/getting-started";
router.push(gettingStartedPath);
skipToPersonal(resetOnboarding);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : "Failed to create organization";
setError(errorMessage);
@@ -94,8 +92,15 @@ export const useSubmitOnboarding = () => {
}
};
const skipToPersonal = (resetOnboarding: () => void) => {
resetOnboarding();
const gettingStartedPath = flags["onboarding-v3"] ? "/onboarding/personal/settings" : "/getting-started";
router.push(gettingStartedPath);
};
return {
submitOnboarding,
skipToPersonal,
isSubmitting,
error,
};
@@ -188,7 +188,7 @@ export const OrganizationInviteView = ({ userEmail }: OrganizationInviteViewProp
<Form form={form} handleSubmit={handleContinue} className="w-full">
<div className="flex w-full flex-col gap-4">
{/* Email and Team inputs */}
<div className="flex flex-col gap-2">
<div className="flex flex-col">
<div className="grid grid-cols-2 gap-2">
<Label className="text-emphasis text-sm font-medium">{t("email")}</Label>
<Label className="text-emphasis text-sm font-medium">{t("team")}</Label>
@@ -235,7 +235,7 @@ export const OrganizationInviteView = ({ userEmail }: OrganizationInviteViewProp
color="secondary"
size="sm"
StartIcon="plus"
className="w-fit"
className="mt-2 w-fit"
onClick={() => append({ email: "", team: "", role: "MEMBER" })}>
{t("add")}
</Button>
@@ -103,7 +103,7 @@ export class TeamService {
if (!isOrgContext) {
return teamInviteLink;
}
const gettingStartedPath = await OnboardingPathService.getGettingStartedPath(prisma);
const gettingStartedPath = await OnboardingPathService.getGettingStartedPathWhenInvited(prisma);
const orgInviteLink = `${WEBAPP_URL}/signup?token=${token}&callbackUrl=${gettingStartedPath}`;
return orgInviteLink;
}
@@ -8,6 +8,12 @@ export class OnboardingPathService {
return onboardingV3Enabled ? "/onboarding/getting-started" : "/getting-started";
}
static async getGettingStartedPathWhenInvited(prisma: PrismaClient): Promise<string> {
const featuresRepository = new FeaturesRepository(prisma);
const onboardingV3Enabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("onboarding-v3");
return onboardingV3Enabled ? "/onboarding/personal/settings" : "/getting-started";
}
static async getGettingStartedPathWithParams(
prisma: PrismaClient,
queryParams?: Record<string, string>
@@ -504,7 +504,7 @@ export async function sendSignupToOrganizationEmail({
}) {
try {
const verificationToken = await createVerificationToken(usernameOrEmail, teamId);
const gettingStartedPath = await OnboardingPathService.getGettingStartedPath(prisma);
const gettingStartedPath = await OnboardingPathService.getGettingStartedPathWhenInvited(prisma);
await sendTeamInviteEmail({
language: translation,
from: inviterName || `${team.name}'s admin`,
@@ -719,7 +719,7 @@ export const sendExistingUserTeamInviteEmails = async ({
if (!user.completedOnboarding && !user.password?.hash && user.identityProvider === "CAL") {
const verificationToken = await createVerificationToken(user.email, teamId);
const gettingStartedPath = await OnboardingPathService.getGettingStartedPath(prisma);
const gettingStartedPath = await OnboardingPathService.getGettingStartedPathWhenInvited(prisma);
inviteTeamOptions.joinLink = `${WEBAPP_URL}/signup?token=${verificationToken.token}&callbackUrl=${gettingStartedPath}`;
inviteTeamOptions.isCalcomMember = false;
} else if (!isAutoJoin) {
@@ -52,7 +52,7 @@ export const resendInvitationHandler = async ({ ctx, input }: InviteMemberOption
if (user?.completedOnboarding) {
inviteTeamOptions.joinLink = `${WEBAPP_URL}/teams?token=${verificationToken.token}&autoAccept=true`;
} else {
const gettingStartedPath = await OnboardingPathService.getGettingStartedPath(prisma);
const gettingStartedPath = await OnboardingPathService.getGettingStartedPathWhenInvited(prisma);
inviteTeamOptions.joinLink = `${WEBAPP_URL}/signup?token=${verificationToken.token}&callbackUrl=${gettingStartedPath}`;
inviteTeamOptions.isCalcomMember = false;
}