diff --git a/apps/landing/src/app/(auth)/signup/_http/fetch-post-verify-turnstile.ts b/apps/landing/src/app/(auth)/_http/fetch-post-verify-turnstile.ts similarity index 100% rename from apps/landing/src/app/(auth)/signup/_http/fetch-post-verify-turnstile.ts rename to apps/landing/src/app/(auth)/_http/fetch-post-verify-turnstile.ts diff --git a/apps/landing/src/app/(auth)/forgot-password/_actions/forgot-password-action.ts b/apps/landing/src/app/(auth)/forgot-password/_actions/forgot-password-action.ts index 2149c4e..200d4db 100644 --- a/apps/landing/src/app/(auth)/forgot-password/_actions/forgot-password-action.ts +++ b/apps/landing/src/app/(auth)/forgot-password/_actions/forgot-password-action.ts @@ -1,6 +1,8 @@ 'use server'; import { fetcher } from '@/lib/fetcher'; +import { getRemoteIp } from '@/lib/headers'; +import { fetchPostverifyTurnstile } from '../../_http/fetch-post-verify-turnstile'; import { forgotPasswordValidationSchema, ForgotPasswordValidationType, @@ -10,6 +12,14 @@ export async function ForgotPasswordAction( request: ForgotPasswordValidationType ) { const validRequest = forgotPasswordValidationSchema.parse(request); + const remoteIp = await getRemoteIp(); + + const isCapchaValid = await fetchPostverifyTurnstile( + validRequest.token, + remoteIp + ); + + if (!isCapchaValid) throw new Error('Failed to verify captcha'); const { data, error } = await fetcher.POST('/v1/auth/forgot', { body: { diff --git a/apps/landing/src/app/(auth)/forgot-password/_components/forgot-password-form.tsx b/apps/landing/src/app/(auth)/forgot-password/_components/forgot-password-form.tsx index cca4bc3..5ead8e0 100644 --- a/apps/landing/src/app/(auth)/forgot-password/_components/forgot-password-form.tsx +++ b/apps/landing/src/app/(auth)/forgot-password/_components/forgot-password-form.tsx @@ -11,7 +11,7 @@ import { Input, } from '@components'; import { Turnstile, TurnstileInstance } from '@marsidev/react-turnstile'; -import { useRef } from 'react'; +import { useRef, useState } from 'react'; import { LuLoader } from 'react-icons/lu'; import { useFormForgotPassword } from '../_hooks/use-form-forgot-password'; import { usePostForgotPassowrd } from '../_hooks/use-post-forgot-password'; @@ -20,54 +20,74 @@ import { ForgotPasswordValidationType } from '../_validation/forgot-password-val export function ForgotPasswordForm() { const ref = useRef(null); + const [step, setStep] = useState(1); + const [emailValue, setEmailValue] = useState(''); + const form = useFormForgotPassword(); const { mutate, isPending, error } = usePostForgotPassowrd(form); - const onSubmit = (values: ForgotPasswordValidationType) => { - mutate(values); + const handleFirstStep = (values: ForgotPasswordValidationType) => { + setEmailValue(values.email); + setStep(2); + }; + + const handleSecondStep = () => { + mutate({ email: emailValue, token: form.getValues('token') }); }; return (
- + { + e.preventDefault(); + handleSecondStep(); + } + } + className="w-full space-y-4" + > {error && (
{(error as Error).message}
)} - ( - - Email - - - - - - )} - /> + {step === 1 && ( + ( + + Email + + + + + + )} + /> + )} - form.setValue('token', token)} - options={{ - theme: 'light', - size: 'flexible', - language: 'id', - }} - /> + {step === 2 && ( + form.setValue('token', token)} + options={{ theme: 'light', size: 'flexible', language: 'id' }} + /> + )}