import { AuthenticationError } from "@/src/entities/errors/auth";
import { useState } from "react";
import { useAuthActions } from './queries';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';;
import { toast } from 'sonner';
import { useNavigations } from '@/app/_hooks/use-navigations';
import {
IVerifyOtpSchema,
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();
*
*/
export function useSignInHandler() {
const { signIn } = useAuthActions();
const { router } = useNavigations();
const [error, setError] = useState();
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
if (signIn.isPending) return;
setError(undefined);
const formData = new FormData(event.currentTarget);
const email = formData.get('email')?.toString();
const res = await signIn.mutateAsync(formData);
if (!res?.error) {
toast('An email has been sent to you. Please check your inbox.');
if (email) router.push(`/verify-otp?email=${encodeURIComponent(email)}`);
} else {
setError(res.error);
}
};
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();
const {
register,
handleSubmit: hookFormSubmit,
control,
formState: { errors },
setValue,
} = useForm({
resolver: zodResolver(verifyOtpSchema),
defaultValues: {
email,
token: '',
},
});
const handleOtpChange = (
value: string,
onChange: (value: string) => void
) => {
onChange(value);
if (value.length === 6) {
handleSubmit();
}
// 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);
await verifyOtp.mutateAsync(formData, {
onSuccess: () => {
toast.success('OTP verified successfully');
// Navigate to dashboard on success
router.push('/dashboard');
},
onError: (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();
const handleSignOut = async () => {
if (signOut.isPending) return;
setError(undefined);
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);
}
},
});
};
return {
handleSignOut,
error,
isPending: signOut.isPending,
errors: !!error || signOut.error,
clearError: () => setError(undefined),
};
}