-
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 #23 from atlp-rwanda/187354199-ft-password-reset
finishing password reset
- Loading branch information
Showing
11 changed files
with
315 additions
and
79 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
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
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
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 |
---|---|---|
@@ -1,79 +1,80 @@ | ||
import FooterTitle from "../../containers/footer/FooterTitle" | ||
import SocialIcon from "../../containers/footer/SocialIcon" | ||
import FooterLink from "../../containers/footer/FooterLink" | ||
import FooterTitle from '../../containers/footer/FooterTitle'; | ||
import SocialIcon from '../../containers/footer/SocialIcon'; | ||
import FooterLink from '../../containers/footer/FooterLink'; | ||
|
||
function Footer() { | ||
return ( | ||
<> | ||
<div className="w-full flex flex-col gap-2 bg-grayColor font-roboto 2xl:items-center "> | ||
<div className="p-3 md:p-4 xl:px-10 2xl:w-[1440px] grid grid-cols-2 md:grid-cols-5 xl:grid-cols-6 gap-x-20 gap-y-5 sm:gap-5 md:gap-2"> | ||
<div className="flex flex-col md:row-span-1 md:col-start-1 md:col-end-3 gap-3"> | ||
<FooterTitle title={"mavericks"} /> | ||
<div className="leading-none text-xs md:text-base break-words flex flex-col gap-3 font-light flex-grow"> | ||
<p> | ||
K309 St , Makuza plaza, Nyarugenge , | ||
Kigali, Rwanda | ||
</p> | ||
<p> | ||
[email protected] | ||
</p> | ||
<p>+250 788888888</p> | ||
</div> | ||
<div className="flex gap-2"> | ||
<a href="#" target="_blank"> | ||
<SocialIcon name="instagram" /> | ||
</a> | ||
<a href="#" target="_blank"> | ||
<SocialIcon name="facebook" /> | ||
</a> | ||
<a href="#" target="_blank"> | ||
<SocialIcon name="twitter" /> | ||
</a> | ||
</div> | ||
</div> | ||
<div className="flex flex-col gap-3"> | ||
<FooterTitle title={"company"} /> | ||
<div className="flex flex-col gap-1 font-light"> | ||
<FooterLink name={"about us"} /> | ||
<FooterLink name={"contact us"} /> | ||
</div> | ||
</div> | ||
<div className="flex flex-col gap-3"> | ||
<FooterTitle title={"shop"} /> | ||
<div className="flex flex-col gap-1 font-light"> | ||
<FooterLink name={"new arrival"} /> | ||
<FooterLink name={"all products"} /> | ||
<FooterLink name={"babies"} /> | ||
<FooterLink name={"father"} /> | ||
<FooterLink name={"electronics"} /> | ||
</div> | ||
</div> | ||
<div className="flex flex-col gap-3"> | ||
<FooterTitle title={"help"} /> | ||
<div className="flex flex-col gap-2 md:gap-1 font-light"> | ||
<FooterLink name={"customer services"} /> | ||
<FooterLink name={"my account"} /> | ||
<FooterLink name={"find store"} /> | ||
<FooterLink name={"legal & privacy"} /> | ||
</div> | ||
</div> | ||
<div className="flex flex-col items-center gap-3 row-span-1 md:row-span-1 col-span-2 md:col-start-3 md:col-end-6 lg:col-start-4 xl:col-start-6 xl:auto-cols-max"> | ||
<FooterTitle title={"subscribe"} /> | ||
<p className="hidden xl:flex leading-none text-base font-light">Be the first to get latest news about trends,Promotions and many more.</p> | ||
<form className="w-full flex flex-col"> | ||
<div className=" w-full flex"> | ||
<label htmlFor="email"></label> | ||
<input type="text" id="email" placeholder="Email address" className="p-2 flex-grow xl:w-3/4" /> | ||
<button type="submit" className="leading-none bg-greenColor text-whiteColor w-20">Join</button> | ||
</div> | ||
<span className="text-xs text-redColor text-left">Email is not valid</span> | ||
</form> | ||
</div> | ||
</div> | ||
<p className="p-3 md:p-4 xl:px-10 2xl:w-[1440px] text-xs text-center xl:text-left ">© 2024 Mavericks Shop. All rights reserved.</p> | ||
return ( | ||
<> | ||
<div className='w-full flex flex-col gap-2 bg-grayColor font-roboto 2xl:items-center'> | ||
<div className='p-3 md:p-4 xl:px-10 2xl:w-[1440px] grid grid-cols-2 md:grid-cols-5 xl:grid-cols-6 gap-x-20 gap-y-5 sm:gap-5 md:gap-2'> | ||
<div className='flex flex-col md:row-span-1 md:col-start-1 md:col-end-3 gap-3'> | ||
<FooterTitle title={'mavericks'} /> | ||
<div className='leading-none text-xs md:text-base break-words flex flex-col gap-3 font-light flex-grow'> | ||
<p>K309 St , Makuza plaza, Nyarugenge , Kigali, Rwanda</p> | ||
<p>[email protected]</p> | ||
<p>+250 788888888</p> | ||
</div> | ||
</> | ||
) | ||
<div className='flex gap-2'> | ||
<a href='#' target='_blank'> | ||
<SocialIcon name='instagram' /> | ||
</a> | ||
<a href='#' target='_blank'> | ||
<SocialIcon name='facebook' /> | ||
</a> | ||
<a href='#' target='_blank'> | ||
<SocialIcon name='twitter' /> | ||
</a> | ||
</div> | ||
</div> | ||
<div className='flex flex-col gap-3'> | ||
<FooterTitle title={'company'} /> | ||
<div className='flex flex-col gap-1 font-light'> | ||
<FooterLink name={'about us'} /> | ||
<FooterLink name={'contact us'} /> | ||
</div> | ||
</div> | ||
<div className='flex flex-col gap-3'> | ||
<FooterTitle title={'shop'} /> | ||
<div className='flex flex-col gap-1 font-light'> | ||
<FooterLink name={'new arrival'} /> | ||
<FooterLink name={'all products'} /> | ||
<FooterLink name={'babies'} /> | ||
<FooterLink name={'father'} /> | ||
<FooterLink name={'electronics'} /> | ||
</div> | ||
</div> | ||
<div className='flex flex-col gap-3'> | ||
<FooterTitle title={'help'} /> | ||
<div className='flex flex-col gap-2 md:gap-1 font-light'> | ||
<FooterLink name={'customer services'} /> | ||
<FooterLink name={'my account'} /> | ||
<FooterLink name={'find store'} /> | ||
<FooterLink name={'legal & privacy'} /> | ||
</div> | ||
</div> | ||
<div className='flex flex-col items-center gap-3 row-span-1 md:row-span-1 col-span-2 md:col-start-3 md:col-end-6 lg:col-start-4 xl:col-start-6 xl:auto-cols-max'> | ||
<FooterTitle title={'subscribe'} /> | ||
<p className='hidden xl:flex leading-none text-base font-light'> | ||
Be the first to get latest news about trends,Promotions and many more. | ||
</p> | ||
<form className='w-full flex flex-col'> | ||
<div className=' w-full flex'> | ||
<label htmlFor='email'></label> | ||
<input type='text' id='email' placeholder='Email address' className='p-2 flex-grow xl:w-3/4' /> | ||
<button type='submit' className='leading-none bg-greenColor text-whiteColor w-20'> | ||
Join | ||
</button> | ||
</div> | ||
<span className='text-xs text-redColor text-left'>Email is not valid</span> | ||
</form> | ||
</div> | ||
</div> | ||
<p className='p-3 md:p-4 xl:px-10 2xl:w-[1440px] text-xs text-center xl:text-left '> | ||
© 2024 Mavericks Shop. All rights reserved. | ||
</p> | ||
</div> | ||
</> | ||
); | ||
} | ||
|
||
export default Footer | ||
export default Footer; |
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,81 @@ | ||
import 'react-toastify/dist/ReactToastify.css'; | ||
import { toast } from 'react-toastify'; | ||
|
||
import { cn } from '../../utils'; | ||
import Button from '../common/Button'; | ||
import Input from '../common/Input'; | ||
import { useForm } from 'react-hook-form'; | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import { resetPasswordSchema } from '../../utils/schemas'; | ||
import { useParams, useNavigate } from 'react-router-dom'; | ||
|
||
import { useNewPasswordMutation } from '../../services/resetPassword'; | ||
|
||
interface PasswordData { | ||
newPassword: string; | ||
passwordConfirm: string; | ||
} | ||
const NewPasswordComponent = () => { | ||
const navigate = useNavigate(); | ||
const { token } = useParams<{ token: string }>(); | ||
const [mutate, { isLoading }] = useNewPasswordMutation(); | ||
const { | ||
register, | ||
handleSubmit, | ||
reset, | ||
formState: { errors }, | ||
} = useForm<PasswordData>({ resolver: zodResolver(resetPasswordSchema) }); | ||
|
||
const onSubmit = async (data: PasswordData) => { | ||
try { | ||
const { newPassword } = data; | ||
const res = await mutate({ newPassword, token }); | ||
if (res.error) { | ||
const { data } = res.error as any; | ||
return toast.error(data.error || 'Failed, please try again later!'); | ||
} else { | ||
reset(); | ||
const { | ||
data: { message }, | ||
} = res; | ||
toast.success(message || 'Password reset successfully!'); | ||
setTimeout(() => navigate('/login'), 3000); | ||
} | ||
} catch (err) { | ||
toast.error('An unexpected error occurred'); | ||
} | ||
}; | ||
return ( | ||
<main className='flex-grow'> | ||
<form | ||
action='#' | ||
className={cn( | ||
' font-roboto shadow-xl mt-4 mb-12 lg:w-1/3 sm:mt-10 h-1/2 md:w-1/2 mx-auto py-12 px-4 flex flex-col gap-4 sm:border-darkGreen sm:border-2 rounded-lg sm:w-3/4 w-full' | ||
)} | ||
onSubmit={handleSubmit(onSubmit)} | ||
> | ||
<Input | ||
type='password' | ||
placeholder='Type your new Password' | ||
label='New Password' | ||
id='newPassword' | ||
{...register('newPassword')} | ||
/> | ||
{errors.newPassword && <p className={cn('text-sm text-redColor -mt-4')}>{errors.newPassword.message}</p>} | ||
<Input | ||
type='password' | ||
placeholder='Confirm your new Password' | ||
label='Confirm Password' | ||
id='passwordConfirm' | ||
{...register('passwordConfirm')} | ||
/> | ||
{errors.passwordConfirm && ( | ||
<p className={cn('text-sm text-redColor -mt-4')}>{errors.passwordConfirm.message}</p> | ||
)} | ||
<Button type='submit' text={isLoading ? 'Loading...' : 'Change Password'} /> | ||
</form> | ||
</main> | ||
); | ||
}; | ||
|
||
export default NewPasswordComponent; |
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,63 @@ | ||
import 'react-toastify/dist/ReactToastify.css'; | ||
import { toast } from 'react-toastify'; | ||
import { useEffect } from 'react'; | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import { useForm } from 'react-hook-form'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import { cn } from '../../utils'; | ||
import Button from '../common/Button'; | ||
import Input from '../common/Input'; | ||
import { emailSchema } from '../../utils/schemas'; | ||
import { useResetPasswordMutation } from '../../services/resetPassword'; | ||
import { useAppSelector } from '../../hooks/customHooks'; | ||
interface UserData { | ||
email: string; | ||
} | ||
|
||
const PasswordResetComponent = () => { | ||
const token: string | undefined = useAppSelector(state => state.user.token)?.replace(/"/g, ''); | ||
const navigate = useNavigate(); | ||
useEffect(() => { | ||
if (token !== undefined) { | ||
navigate('/login'); | ||
} | ||
}, []); | ||
const { | ||
register, | ||
handleSubmit, | ||
reset, | ||
formState: { errors }, | ||
} = useForm<UserData>({ | ||
resolver: zodResolver(emailSchema), | ||
}); | ||
const [resetPassword, { isLoading }] = useResetPasswordMutation(); | ||
|
||
const onSubmit = async (data: UserData) => { | ||
try { | ||
const res = await resetPassword(data.email).unwrap(); | ||
toast.success(res.message || 'Password reset email sent, Please verify your email!'); | ||
reset(); | ||
} catch (err) { | ||
toast.error('Failed to send email, check your provided email and try again!'); | ||
} | ||
}; | ||
return ( | ||
<main className='flex-grow'> | ||
<h1 className={cn('font-roboto text-center mt-6 sm:text-3xl text-xl')}>Forgot Password?</h1> | ||
<form | ||
action='#' | ||
className={cn( | ||
'font-roboto sm:shadow-xl mt-4 mb-12 sm:mt-10 h-1/2 md:w-1/2 lg:w-1/3 mx-auto py-12 px-4 flex flex-col gap-4 sm:border-darkGreen sm:border-2 rounded-lg sm:w-3/4 w-full' | ||
)} | ||
onSubmit={handleSubmit(onSubmit)} | ||
> | ||
<Input type='text' placeholder='Type your email' label='Email' id='email' {...register('email')} /> | ||
{errors.email && <p className={cn('text-sm text-redColor -mt-4')}>{errors.email.message}</p>} | ||
<Button type='submit' text={!isLoading ? 'Reset Password' : 'Sending Email...'} /> | ||
</form> | ||
</main> | ||
); | ||
}; | ||
|
||
export default PasswordResetComponent; |
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,5 @@ | ||
import { TypedUseSelectorHook, useSelector, useDispatch } from 'react-redux'; | ||
import { RootState, AppDispatch } from '../redux/store'; | ||
|
||
export const useAppDispatch = () => useDispatch<AppDispatch>(); | ||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector; |
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,15 @@ | ||
import Footer from '../components/footer/Footer'; | ||
import Navbar from '../components/navbar/Navbar'; | ||
import NewPasswordComponent from '../components/passwordReset/NewPasswordComponent'; | ||
|
||
const NewPassword = () => { | ||
return ( | ||
<div className='min-h-screen flex flex-col'> | ||
<Navbar /> | ||
<NewPasswordComponent /> | ||
<Footer /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default NewPassword; |
Oops, something went wrong.