MIF_E31221222/sigap-website/app/(pages)/(auth)/handler.tsx

177 lines
5.2 KiB
TypeScript

import { AuthenticationError } from "@/src/entities/errors/auth";
import { useState } from "react";
import { useAuthActions } from "./mutation";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { defaultSignInPasswordlessValues, SignInFormData, SignInPasswordless, SignInPasswordlessSchema, SignInSchema } from "@/src/entities/models/auth/sign-in.model";
import { createFormData } from "@/app/_utils/common";
import { useFormHandler } from "@/app/_hooks/use-form-handler";
import { toast } from "sonner";
import { signIn } from "./action";
import { useNavigations } from "@/app/_hooks/use-navigations";
import { VerifyOtpFormData, verifyOtpSchema } from "@/src/entities/models/auth/verify-otp.model";
/**
* Hook untuk menangani proses sign in
*
* @returns {Object} Object berisi handler dan state untuk form sign in
* @example
* const { handleSubmit, isPending, error } = useSignInHandler();
* <form onSubmit={handleSubmit}>...</form>
*/
export function useSignInHandler() {
const { signIn } = useAuthActions();
const { router } = useNavigations();
const [error, setError] = useState<string>();
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (signIn.isPending) return;
setError(undefined);
const formData = new FormData(event.currentTarget);
const email = formData.get("email")?.toString()
try {
await signIn.mutateAsync(formData, {
onSuccess: () => {
toast("An email has been sent to you. Please check your inbox.");
if (email) router.push(`/verify-otp?email=${encodeURIComponent(email)}`);
},
onError: (error) => {
setError(error.message);
}
});
} catch (error) {
if (error instanceof Error) {
setError(error.message);
}
}
};
return {
// formData,
// handleChange,
handleSignIn: handleSubmit,
error,
isPending: signIn.isPending,
errors: !!error || signIn.error,
clearError: () => setError(undefined)
};
}
export function useVerifyOtpHandler(email: string) {
const { router } = useNavigations()
const { verifyOtp } = useAuthActions()
const [error, setError] = useState<string>()
const {
register,
handleSubmit: hookFormSubmit,
control,
formState: { errors },
setValue
} = useForm<VerifyOtpFormData>({
resolver: zodResolver(verifyOtpSchema),
defaultValues: {
email,
token: ""
}
})
const handleOtpChange = (value: string, onChange: (value: string) => void) => {
onChange(value)
// Clear error when user starts typing
if (error) {
setError(undefined)
}
}
const handleSubmit = hookFormSubmit(async (data) => {
if (verifyOtp.isPending) return
setError(undefined)
// Create FormData object
const formData = new FormData()
formData.append("email", data.email)
formData.append("token", data.token)
try {
await verifyOtp.mutateAsync(formData, {
onSuccess: () => {
toast.success("OTP verified successfully")
// Navigate to dashboard on success
router.push("/dashboard")
},
onError: (error) => {
setError(error.message)
}
})
} catch (error) {
if (error instanceof Error) {
setError(error.message)
}
}
})
return {
register,
control,
handleVerifyOtp: handleSubmit,
handleOtpChange,
errors: {
...errors,
token: error ? { message: error } : errors.token
},
isPending: verifyOtp.isPending,
clearError: () => setError(undefined)
}
}
export function useSignOutHandler() {
const { signOut } = useAuthActions()
const { router } = useNavigations()
const [error, setError] = useState<string>()
const handleSignOut = async () => {
if (signOut.isPending) return
setError(undefined)
try {
await signOut.mutateAsync(undefined, {
onSuccess: () => {
toast.success("You have been signed out successfully")
router.push("/sign-in")
},
onError: (error) => {
if (error instanceof AuthenticationError) {
setError(error.message)
toast.error(error.message)
}
}
})
} catch (error) {
if (error instanceof Error) {
setError(error.message)
toast.error(error.message)
// toast.error("An error occurred during sign out. Please try again later.")
}
}
}
return {
handleSignOut,
error,
isPending: signOut.isPending,
errors: !!error || signOut.error,
clearError: () => setError(undefined)
}
}