<!-- This is an auto-generated description by cubic. --> ## Summary by cubic Revamps onboarding with subtle route transitions, new org/teams illustrations, and clearer invite flows with real-time previews. Adds “Skip for now” on invites and guardrails to avoid incomplete team creation. - **New Features** - Added email invite pages for organizations and teams with shared EmailInviteForm and RoleSelector. - Built a live invite browser preview that renders a 3×3 grid and updates as you type; works for orgs and teams. - Applied route-keyed framer-motion transitions to layout, cards, and browser views for smoother page changes. - Continuation prompt now detects saved org or team and routes to the right next step; localized copy. - Added loading state to plan selection to prevent double navigation. - Refreshed Organizations welcome modal with a new animated ring illustration and better scrolling. - Added “Skip for now” to org and team invite-by-email steps to proceed without invites. - Calendar browser preview now focuses on a time window around “now” for a more realistic demo. - Added an optional floating footer to keep actions visible on long, scrollable lists. - **Refactors and Fixes** - Unified invite browser and replaced the org preview on the org email step. - Split and simplified legacy invite views; team and org routes are cleaner and easier to extend. - Streamlined the team invite step by removing a redundant action; non-admins are redirected to the email invite page. - Prevented creating teams with empty details by redirecting back to team details. - Minor UI cleanup: tighter borders, padding, and mobile max-heights across onboarding screens. - Hide team select on org invites when no teams exist. <sup>Written for commit ae7f5277ab998560ae6e2f3f9144852a7b4959a7. Summary will update automatically on new commits.</sup> <!-- End of auto-generated description by cubic. -->
64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
import { useRouter } from "next/navigation";
|
|
import { useState } from "react";
|
|
|
|
import { useFlagMap } from "@calcom/features/flags/context/provider";
|
|
import { trpc } from "@calcom/trpc/react";
|
|
|
|
import type { OnboardingState } from "../store/onboarding-store";
|
|
|
|
export function useCreateTeam() {
|
|
const router = useRouter();
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const flags = useFlagMap();
|
|
|
|
const createTeamMutation = trpc.viewer.teams.create.useMutation();
|
|
|
|
const createTeam = async (store: OnboardingState) => {
|
|
setIsSubmitting(true);
|
|
|
|
try {
|
|
const { teamDetails, teamBrand } = store;
|
|
|
|
// Validate team details - if empty, redirect back to team details step
|
|
if (!teamDetails.name || !teamDetails.name.trim() || !teamDetails.slug || !teamDetails.slug.trim()) {
|
|
router.push("/onboarding/teams/details");
|
|
setIsSubmitting(false);
|
|
return;
|
|
}
|
|
|
|
// Create the team
|
|
const result = await createTeamMutation.mutateAsync({
|
|
name: teamDetails.name,
|
|
slug: teamDetails.slug,
|
|
logo: teamBrand.logo,
|
|
isOnboarding: true,
|
|
});
|
|
|
|
// If there's a checkout URL, redirect to Stripe payment
|
|
if (result.url && !result.team) {
|
|
window.location.href = result.url;
|
|
return;
|
|
}
|
|
|
|
if (result.team) {
|
|
// Not sure we need this flag check - keeping it here for safe keeping as this is called only from v3 onboarding flow
|
|
const gettingStartedPath = flags["onboarding-v3"]
|
|
? "/onboarding/personal/settings"
|
|
: "/getting-started";
|
|
router.push(gettingStartedPath);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to create team:", error);
|
|
throw error;
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return {
|
|
createTeam,
|
|
isSubmitting,
|
|
error: createTeamMutation.error,
|
|
};
|
|
}
|