-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #50 from FacundoInza/feature/login-connection
feat: add forgot password conection with error handler
- Loading branch information
Showing
7 changed files
with
549 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React, { FC } from 'react'; | ||
import { ForgotPassword } from '../../../components/ui/forgotPassword/ForgotPassword'; | ||
|
||
const InitWorkDay: FC = () => { | ||
return ( | ||
<div> | ||
<ForgotPassword /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default InitWorkDay; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
'use client'; | ||
|
||
import Image from 'next/image'; | ||
import React, { FC, useState } from 'react'; | ||
import logo from '../../../assets/deliverit-full.png'; | ||
import MainButton from '../../commons/buttons/MainButton'; | ||
import { RequestPasswordReset } from './RequestPasswordReset'; | ||
import { VerifyResetToken } from './VerfiyResetToken'; | ||
import { ResetPassword } from './ResetPassword'; | ||
import { useRouter } from 'next/navigation'; | ||
|
||
export const ForgotPassword: FC = () => { | ||
//Step 1: Request password reset | ||
//Step 2: Verify reset token | ||
//Step 3: Reset password | ||
const [step, setStep] = useState(1); | ||
const [email, setEmail] = useState(''); | ||
const [token, setToken] = useState(''); | ||
|
||
const router = useRouter(); | ||
|
||
const goToNextStep = () => { | ||
setStep((prevStep) => prevStep + 1); | ||
}; | ||
|
||
const goToPreviousStep = () => { | ||
if (step === 1) { | ||
router.push('/'); | ||
} | ||
setStep((prevStep) => prevStep - 1); | ||
}; | ||
|
||
const renderStepContent = () => { | ||
switch (step) { | ||
case 1: | ||
return ( | ||
<RequestPasswordReset | ||
onSuccess={setEmail} | ||
onNext={goToNextStep} | ||
/> | ||
); | ||
case 2: | ||
return ( | ||
<VerifyResetToken | ||
email={email} | ||
onSuccess={setToken} | ||
onNext={goToNextStep} | ||
/> | ||
); | ||
case 3: | ||
return <ResetPassword email={email} token={token} />; | ||
default: | ||
return ( | ||
<RequestPasswordReset | ||
onSuccess={setEmail} | ||
onNext={goToNextStep} | ||
/> | ||
); | ||
} | ||
}; | ||
|
||
return ( | ||
<> | ||
<div className='flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8'> | ||
<div className='sm:mx-auto sm:w-full sm:max-w-sm'> | ||
<Image | ||
className='mx-auto h-30 w-auto' | ||
width={900} | ||
height={400} | ||
src={logo} | ||
alt='DeliverIT' | ||
objectFit='cover' | ||
/> | ||
</div> | ||
{renderStepContent()} | ||
<div className='mt-4'> | ||
<MainButton | ||
text='Back' | ||
btnBlue | ||
onClick={goToPreviousStep} | ||
/> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import React, { FC, useState } from 'react'; | ||
import MainButton from '../../commons/buttons/MainButton'; | ||
import { RiUserLine } from 'react-icons/ri'; | ||
import { useForm } from 'react-hook-form'; | ||
import { api } from 'api/axiosInstance'; | ||
import { AxiosError } from 'axios'; | ||
import Notification from '../modal/Notification'; | ||
|
||
interface RequestPasswordResetProps { | ||
onSuccess: (email: string) => void; | ||
onNext: () => void; | ||
} | ||
|
||
interface emailInput { | ||
email: string; | ||
} | ||
|
||
interface ErrorResponse { | ||
message: string; | ||
} | ||
|
||
export const RequestPasswordReset: FC<RequestPasswordResetProps> = ({ | ||
onSuccess, | ||
onNext, | ||
}) => { | ||
const { | ||
register, | ||
handleSubmit, | ||
formState: { errors }, | ||
} = useForm<emailInput>({ mode: 'onBlur' }); | ||
|
||
const [showModal, setShowModal] = useState(false); | ||
const [modalMessage, setModalMessage] = useState(''); | ||
const [isModalSuccess, setIsModalSuccess] = useState(false); | ||
|
||
const onSubmit = async (email: emailInput) => { | ||
try { | ||
const response = await api.post( | ||
'/api/user/request-password-reset', | ||
); | ||
setModalMessage(response.data.message); | ||
setIsModalSuccess(true); | ||
onSuccess(email.email); | ||
onNext(); | ||
} catch (error) { | ||
const axiosError = error as AxiosError<ErrorResponse>; | ||
if (axiosError && axiosError.response) { | ||
setModalMessage(axiosError.response.data.message); | ||
} else { | ||
setModalMessage('Something went wrong on login'); | ||
} | ||
setIsModalSuccess(false); | ||
setShowModal(true); | ||
} | ||
}; | ||
|
||
const handleCloseModal = () => { | ||
setShowModal(false); | ||
}; | ||
|
||
return ( | ||
<> | ||
<div className='mt-8 sm:mx-auto sm:w-full sm:max-w-sm text-center text-white text-xl'> | ||
Enter your email below to reset your password: | ||
</div> | ||
<div className='mt-10 sm:mx-auto sm:w-full sm:max-w-sm'> | ||
<form | ||
className='space-y-6' | ||
action='#' | ||
method='POST' | ||
onSubmit={handleSubmit(onSubmit)} | ||
> | ||
<div> | ||
<div className='relative mt-2'> | ||
<input | ||
id='email' | ||
type='email' | ||
placeholder='[email protected]' | ||
autoComplete='email' | ||
{...register('email', { | ||
required: 'Email is required', | ||
pattern: { | ||
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, | ||
message: | ||
'Please enter a valid email address', | ||
}, | ||
})} | ||
className='block w-full rounded-lg border-1 px-12 py-3.5 text-white shadow-sm ring-1 ring-inset ring-white placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-gray-500 text-sm sm:text-sm text-center font-bold sm:leading-6 bg-transparent' | ||
/> | ||
<span className='absolute left-3 top-1/2 transform -translate-y-6 text-gray-400'> | ||
<RiUserLine size={25} /> | ||
</span> | ||
<div style={{ height: '20px' }}> | ||
{errors.email && ( | ||
<p className='text-red-400 text-right pe-2'> | ||
{errors.email.message} | ||
</p> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
<div className='space-y-6'> | ||
<div className='mt-20'> | ||
<MainButton text='Submit' btnGreen /> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
|
||
{showModal && ( | ||
<Notification | ||
isSuccess={isModalSuccess} | ||
message={modalMessage} | ||
onClose={handleCloseModal} | ||
buttonText={'Retry'} | ||
redirectLink={'/forgot-password'} | ||
/> | ||
)} | ||
</> | ||
); | ||
}; |
Oops, something went wrong.