* feat: redirect to new onboarding flow * Getting started * Brand details * Preview organization brands * Orgs team pages * Invite team steps * Move to global zustand store * Few darkmdoe fixes * Wip onboarding + stripe flow * Default plan state Server Action for gettting slug satus of org * Remove onboardingId * Confirmation prompt * Update old onboarding flow handlers to handle new fields * update onboarding hook * Filter out organization section for none -company emails * Match placeholders to users domain * Drop migration * Wip new onboarding intent * WIP flow for self-hosted. Same service call just split logic * WIP * Add TODO * Use onboarding user type instead of trpc session * WIP * WIP * pass role and team name from onboarding to save in schema * Add test to ensure role + name + team are persisted into onboarding table * migrate roles to enum values * Update ENUM * Fix type error * Redirect if flag is disabled * Revert packages * Revert all packages/* changes to original branch point * Layout fixes + design * Add slugify * Support saving brand,logo and banner * Cleanup * iMobile fixes * More mobile and darkmdoe fixes * Add I18n * Fix lock file * Fix types * Fix types errors * Copy changes
100 lines
3.0 KiB
TypeScript
100 lines
3.0 KiB
TypeScript
import { useRouter } from "next/navigation";
|
|
import { useState } from "react";
|
|
|
|
import { CreationSource } from "@calcom/prisma/enums";
|
|
import { trpc } from "@calcom/trpc/react";
|
|
import { showToast } from "@calcom/ui/components/toast";
|
|
|
|
import type { OnboardingState } from "../store/onboarding-store";
|
|
|
|
export const useSubmitOnboarding = () => {
|
|
const router = useRouter();
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const intentToCreateOrg = trpc.viewer.organizations.intentToCreateOrg.useMutation();
|
|
|
|
const submitOnboarding = async (store: OnboardingState, userEmail: string) => {
|
|
setIsSubmitting(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const {
|
|
selectedPlan,
|
|
organizationDetails,
|
|
organizationBrand,
|
|
teams,
|
|
invites,
|
|
inviteRole,
|
|
resetOnboarding,
|
|
} = store;
|
|
|
|
if (selectedPlan !== "organization") {
|
|
throw new Error("Only organization plan is currently supported");
|
|
}
|
|
|
|
// Prepare teams data
|
|
const teamsData = teams
|
|
.filter((team) => team.name.trim().length > 0)
|
|
.map((team) => ({
|
|
id: -1, // New team
|
|
name: team.name,
|
|
isBeingMigrated: false,
|
|
slug: null,
|
|
}));
|
|
|
|
// Prepare invites data
|
|
const invitedMembersData = invites
|
|
.filter((invite) => invite.email.trim().length > 0)
|
|
.map((invite) => ({
|
|
email: invite.email,
|
|
teamName: invite.team,
|
|
teamId: -1,
|
|
role: inviteRole,
|
|
}));
|
|
|
|
const result = await intentToCreateOrg.mutateAsync({
|
|
name: organizationDetails.name,
|
|
slug: organizationDetails.link,
|
|
bio: organizationDetails.bio || null,
|
|
logo: organizationBrand.logo,
|
|
brandColor: organizationBrand.color,
|
|
bannerUrl: organizationBrand.banner,
|
|
orgOwnerEmail: userEmail,
|
|
seats: null,
|
|
pricePerSeat: null,
|
|
isPlatform: false,
|
|
creationSource: CreationSource.WEBAPP,
|
|
teams: teamsData,
|
|
invitedMembers: invitedMembersData,
|
|
});
|
|
|
|
// If there's a checkout URL, redirect to Stripe (billing enabled flow)
|
|
if (result.checkoutUrl) {
|
|
window.location.href = result.checkoutUrl;
|
|
return;
|
|
}
|
|
|
|
// No checkout URL means billing is disabled (self-hosted flow)
|
|
// 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();
|
|
router.push("/getting-started");
|
|
} catch (err) {
|
|
const errorMessage = err instanceof Error ? err.message : "Failed to create organization";
|
|
setError(errorMessage);
|
|
showToast(errorMessage, "error");
|
|
console.error("Organization creation error:", err);
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return {
|
|
submitOnboarding,
|
|
isSubmitting,
|
|
error,
|
|
};
|
|
};
|