Commit 84c78b4f authored by Lorenzo Trujillo Rojas's avatar Lorenzo Trujillo Rojas
Browse files

Refactorización de la página de reseteo de contraseña

parent 44c7e41a
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
export enum ChangePaswordError {
    PASSWORD_MISMATCH,
    UNDEFINED
}

export class ResetPasswordError extends Error {
    public readonly type: ChangePaswordError;
    constructor(type: ChangePaswordError, message?: string,) {
        super(message);
        this.type = type;
    }
} 
 No newline at end of file
+77 −0
Original line number Diff line number Diff line
import { useForm } from "react-hook-form";
import { useDataContext } from "../../common/contexts/data_context";
import { useState } from "react";
import { ApiRequestStatus } from "../../common/constants/api_request_states";
import { router } from "expo-router";
import { ChangePaswordError, ResetPasswordError } from "../errors/reset_password_error";

export interface ResetPasswordFormValues {
    email: string;
    newPassword: string;
    newPasswordConfirmation: string;
    code: string;
}

export const useResetPassword = () => {
    const { authRepository } = useDataContext();
    const { control, handleSubmit, getValues, setError, setValue } = useForm<ResetPasswordFormValues>({
        defaultValues: {
            email: "",
            newPassword: "",
            newPasswordConfirmation: "",
            code: "",
        }
    });
    const [status, setStatus] = useState(ApiRequestStatus.IDLE);

    const setLoading = async () => {
        setStatus(ApiRequestStatus.LOADING);
    };

    const getResetCode = async () => {
        await setLoading();
        if (!getValues().email) {
            console.log(getValues())
            setError("email", { type: "manual", message: "Email is required" });
            throw new Error("Email is required");
        }
        await authRepository!.getResetCode(getValues().email);
        setStatus(ApiRequestStatus.SUCCESS);
    };

    const validSubmit = async (data: ResetPasswordFormValues) => {
        try {
            await setLoading();
            if (data.newPassword !== data.newPasswordConfirmation) {
                setError("newPasswordConfirmation", { type: "manual", message: "Passwords do not match" });
                return;
            }
            await authRepository!.resetPassword({
                newPassword: data.newPassword,
                code: data.code,
                email: data.email
            })
            router.replace("/login");
        } catch (error) {
            if (error instanceof ResetPasswordError && error.type == ChangePaswordError.UNDEFINED) {
                throw new Error();
            }
        }
    };

    const errorSubmit = async () => {
        throw new Error();
    };

    const onSubmit = async () => {
        await handleSubmit(validSubmit, errorSubmit)();
    };

    return {
        control,
        getResetCode,
        setValue,
        onSubmit,
        status
    };
}
+83 −0
Original line number Diff line number Diff line
import { useEffect, useState } from "react";
import { ResetPasswordForm } from "../components/reset_password_form";
import { CodeForm } from "../components/code_form";
import { PasswordForm } from "../components/password_form";
import { useResetPassword } from "./useResetPassword";

interface ResetPasswordSlide {
  slide: JSX.Element;
  callback: () => Promise<void>;
  onError?: () => void;
}

export const useResetPasswordControl = () => {
  const {
    control,
    getResetCode,
    setValue,
    onSubmit,
    status: requestStatus,
  } = useResetPassword();
  const slides: ResetPasswordSlide[] = [
    {
      slide: <ResetPasswordForm control={control} />,
      callback: async () => {
        await getResetCode();
      },
    },
    {
      slide: <CodeForm setValue={setValue} />,
      callback: async () => {
        console.log("Reset Password 1");
      },
    },
    {
      slide: <PasswordForm control={control} />,
      callback: async () => {
        onSubmit();
      },
    },
  ];
  const [step, setStep] = useState(0);
  const [slide, setSlide] = useState(slides[step]);
  const [isLast, setIsLast] = useState(step === slides.length - 1);
  const [isFirst, setIsFirst] = useState(step === 0);

  const onNext = async () => {
    try {
      await slide.callback();
      setStep(step + 1);
    } catch (error) {
      console.log(error);
      slide.onError && slide.onError();
    }
  };

  const onPrevious = () => {
    setStep(step - 1);
  };

  const onFinish = () => {
    try {
      slide.callback();
    } catch (e) {
      slide.onError && slide.onError();
    }
  };

  useEffect(() => {
    setSlide(slides[step]);
    setIsFirst(step === 0);
    setIsLast(step === slides.length - 1);
  }, [step]);

  return {
    onNext,
    onFinish,
    slide: slide.slide,
    isFirst,
    isLast,
    onPrevious,
    requestStatus,
  };
};
+12 −162
Original line number Diff line number Diff line
import { useEffect, useState, useCallback } from "react";
import { SlideControl } from "../../common/components/slide_control";
import { ResetPasswordForm } from "../components/reset_password_form";
import { View, StyleSheet } from "react-native";
import { CodeForm } from "../components/code_form";
import { useDataContext } from "../../common/contexts/data_context";
import { useForm } from "react-hook-form";
import { ApiRequestStatus } from "../../common/constants/api_request_states";
import { PasswordForm } from "../components/password_form";
import { router } from "expo-router";
import { FullPageLoader } from "../../common/components/full_page_loader";

interface ResetPasswordSlide {
  slide: JSX.Element;
  callback: () => Promise<void>;
  onError?: () => void;
}

export interface ResetPasswordFormValues {
  email: string;
  newPassword: string;
  newPasswordConfirmation: string;
  code: string;
}

export enum ChangePaswordError {
  PASSWORD_MISMATCH,
  UNDEFINED
}

export class ResetPasswordError extends Error {
  public readonly type: ChangePaswordError;
  constructor( type: ChangePaswordError, message? :string,){
    super(message);
    this.type = type;
  }
  
} 

export const useResetPassword = () => {
  const { authRepository } = useDataContext();
  const { control, handleSubmit, getValues, setError, setValue } = useForm<ResetPasswordFormValues>({
    defaultValues: {
      email: "",
      newPassword: "",
      newPasswordConfirmation: "",
      code: "",
    }
  });
  const [status, setStatus] = useState(ApiRequestStatus.IDLE);

  const setLoading = async () => {
    setStatus(ApiRequestStatus.LOADING);
  };

  const getResetCode = async () => {
    await setLoading();
    if (!getValues().email) {
      console.log(getValues())
      setError("email", { type: "manual", message: "Email is required" });
      throw new Error("Email is required");
    }
    await authRepository!.getResetCode(getValues().email);
    setStatus(ApiRequestStatus.SUCCESS);
  };

  const validSubmit = async (data: ResetPasswordFormValues) => {
    try {
      await setLoading();
      if (data.newPassword !== data.newPasswordConfirmation) {
        setError("newPasswordConfirmation", { type: "manual", message: "Passwords do not match" });
        return;
      }
      await authRepository!.resetPassword({
        newPassword: data.newPassword,
        code: data.code,
        email: data.email
      })
      router.replace("/login");
    } catch(error) {
      if (error instanceof ResetPasswordError && error.type == ChangePaswordError.UNDEFINED) {
        throw new Error();
      }
    }
  };

  const errorSubmit = async () => {
    throw new Error();
  };

  const onSubmit = async () => {
    await handleSubmit(validSubmit, errorSubmit)();
  };

  return {
    control,
    getResetCode,
    setValue,
    onSubmit,
    status
  };
}

const useResetPasswordControl = () => {
  const { control, getResetCode, setValue, onSubmit, status: requestStatus } = useResetPassword();
  const slides: ResetPasswordSlide[] = [
    {
      slide: <ResetPasswordForm control={control}/>,
      callback: async () => {
        await getResetCode();
      }
    },
    {
      slide: <CodeForm setValue={setValue}/>,
      callback: async () => {
        console.log("Reset Password 1");
      }
    },
    {
      slide: <PasswordForm control={control}/>,
      callback: async () => {
        onSubmit();
      }
    }
  ];
  const [step, setStep] = useState(0);
  const [slide, setSlide] = useState(slides[step]);
  const [isLast, setIsLast] = useState(step === slides.length - 1);
  const [isFirst, setIsFirst] = useState(step === 0);

  const onNext = async () => {
    try {
      await slide.callback();
      setStep(step + 1);
    } catch (error) {
      console.log(error);
      slide.onError && slide.onError();
    }
  };

  const onPrevious = () => {
    setStep(step - 1);
  };

  const onFinish = () => {
    try {
      slide.callback();
    } catch (e) {
      slide.onError && slide.onError();
    }
  };

  useEffect(() => {
    setSlide(slides[step]);
    setIsFirst(step === 0);
    setIsLast(step === slides.length - 1);
  }, [step]);

  return { onNext, onFinish, slide: slide.slide, isFirst, isLast, onPrevious, requestStatus };
};
import { useResetPasswordControl } from "../hooks/useResetPasswordControl";

export const ResetPasswordPage = () => {
  const { onNext, onFinish, slide, isFirst, isLast, onPrevious, requestStatus } =
    useResetPasswordControl();


  const {
    onNext,
    onFinish,
    slide,
    isFirst,
    isLast,
    onPrevious,
    requestStatus,
  } = useResetPasswordControl();
  if (requestStatus === ApiRequestStatus.LOADING) {
    return <FullPageLoader/>
    return <FullPageLoader />;
  }
  return (
    <View style={styles.mainContainer}>