task-managment / src / hooks / useRegisterUserInvitation.ts
useRegisterUserInvitation.ts
Raw
import { trpc } from "@/app/_trpc/client";
import { useToast } from "@/components/ui/use-toast";
import { User } from "@/server/user/domain/models";
import { useSignUp, useUser } from "@clerk/nextjs";
import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";

type RegisteredUser = User & {sessionId:string}

const STORAGE_KEY = "registeredUser";

export default function useRegisterUserInvitation() {
  const { user } = useUser();
  const router = useRouter();
  const { isLoaded, signUp, setActive } = useSignUp();
  const { toast } = useToast();
  const [isRegistering, setIsRegistering] = useState(false);

  const { mutateAsync: registerUserDb } =
    trpc.users.findOrCreateUser.useMutation();
  const searchParams = useSearchParams();
  const token = searchParams.get("__clerk_ticket");

  useEffect(() => {
    if (user?.id) {
      router.push("/");
    }
  }, [user, router]);

  const retryRegisterStoredUser = async () => {
    const storedUserStr = localStorage.getItem(STORAGE_KEY);
    if (!storedUserStr || !isLoaded) return false;

    try {
      const storedUser = JSON.parse(storedUserStr) as RegisteredUser;
      await registerUserDb(storedUser);
      await setActive({ session: storedUser.sessionId });
      localStorage.removeItem(STORAGE_KEY);
      return true;
    } catch (err) {
      toast({
        title: "Error",
        description:
          "Error al reintentar el registro. Por favor, inténtalo de nuevo más tarde.",
        variant: "destructive",
      });
      return false;
    }
  };

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!isLoaded || isRegistering) return;

    try {
      setIsRegistering(true);

      const recovered = await retryRegisterStoredUser();
      if (recovered) return;

      if (!token) {
        toast({
          title: "Error",
          description: "No se encontró un token de invitación válido.",
          variant: "destructive",
        });
        return;
      }

      const formData = new FormData(e.target as any);
      const firstName = formData.get("firstName") as string;
      const lastName = formData.get("lastName") as string;

      
      const signUpAttempt = await signUp.create({
        strategy: "ticket",
        ticket: token,
        firstName,
        lastName,
      });

      if (signUpAttempt.status !== "complete") {
        toast({
          title: "Error",
          description: "El proceso de registro no pudo completarse.",
          variant: "destructive",
        });
        return;
      }

      const newUser: RegisteredUser = {
        id: signUpAttempt.createdUserId!,
        firstName,
        lastName,
        email: signUpAttempt.emailAddress!,
        sessionId: signUpAttempt.createdSessionId!,
      };

      localStorage.setItem(STORAGE_KEY, JSON.stringify(newUser));

      await registerUserDb(newUser);
      await setActive({ session: newUser.sessionId });

      localStorage.removeItem(STORAGE_KEY);
    } catch (err) {
      const recovered = await retryRegisterStoredUser();
      if (!recovered) {
        toast({
          title: "Error",
          description:
            "Un error inesperado ocurrió. Por favor, inténtalo de nuevo más tarde.",
          variant: "destructive",
        });
      }
    } finally {
      setIsRegistering(false);
    }
  };

  return {
    token,
    handleSubmit,
    isRegistering,
  };
}