import { useCallback, useMemo, useState } from "react"; import { signupRepository } from "@/lib/api/api/repositories/signup-repository"; import { SignupOrganization, SignupOwner, SignupResult, } from "@/lib/models/signup.model"; export type SignupStep = "account" | "organization"; interface UseSignupFlowState { step: SignupStep; owner: SignupOwner; organization: SignupOrganization; isLoading: boolean; error: string | null; emailSent: boolean; result: SignupResult | null; stepIndex: number; canContinueAccount: boolean; canContinueOrganization: boolean; goBack: () => void; goNext: () => void; sendMagicLink: () => Promise; updateOwner: (updates: Partial) => void; updateOrganization: (updates: Partial) => void; reset: () => void; } const defaultOwner: SignupOwner = { fullName: "", email: "", }; const defaultOrganization: SignupOrganization = { displayName: "", industry: "Technology", }; export function useSignupFlow(): UseSignupFlowState { const [step, setStep] = useState("account"); const [owner, setOwner] = useState(defaultOwner); const [organization, setOrganization] = useState( defaultOrganization ); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [emailSent, setEmailSent] = useState(false); const [result, setResult] = useState(null); const stepIndex = useMemo(() => { switch (step) { case "account": return 0; case "organization": return 1; default: return 0; } }, [step]); const canContinueAccount = useMemo(() => { return ( owner.fullName.trim().length >= 2 && /.+@.+\..+/.test(owner.email) ); }, [owner]); const canContinueOrganization = useMemo(() => { return ( organization.displayName.trim().length >= 2 && organization.industry.trim().length > 0 ); }, [organization]); const goBack = useCallback(() => { setError(null); if (step === "organization") { setStep("account"); } }, [step]); const goNext = useCallback(() => { setError(null); if (step === "account" && canContinueAccount) { setStep("organization"); } }, [step, canContinueAccount]); const updateOwner = useCallback((updates: Partial) => { setOwner((prev) => ({ ...prev, ...updates })); setError(null); // Clear error when user types }, []); const updateOrganization = useCallback((updates: Partial) => { setOrganization((prev) => ({ ...prev, ...updates })); setError(null); // Clear error when user types }, []); const reset = useCallback(() => { setOwner(defaultOwner); setOrganization(defaultOrganization); setStep("account"); setError(null); setEmailSent(false); setResult(null); }, []); const sendMagicLink = useCallback(async () => { if (!canContinueOrganization) { setError("Please fill in all required fields correctly"); return; } setIsLoading(true); setError(null); try { // Call the API to create organization and send magic link const signupResult = await signupRepository.createOrganizationWithMagicLink( owner, organization ); setResult(signupResult); setEmailSent(true); // Immediately send magic link via login endpoint (bypass backend async) try { await fetch("/api/auth/magic-link", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ email: owner.email }), }); } catch (magicLinkError) { console.error("Failed to send magic link:", magicLinkError); // Don't block signup - user can retry login if needed } } catch (signupError) { const message = signupError instanceof Error ? signupError.message : "Failed to send magic link. Please try again."; setError(message); setEmailSent(false); } finally { setIsLoading(false); } }, [owner, organization, canContinueOrganization]); return { step, owner, organization, isLoading, error, emailSent, result, stepIndex, canContinueAccount, canContinueOrganization, goBack, goNext, sendMagicLink, updateOwner, updateOrganization, reset, }; }