-
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 #10 from atlp-rwanda/fit-signup-page
[Finshes #187354196] Sign up page
- Loading branch information
Showing
19 changed files
with
457 additions
and
24 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,38 @@ | ||
import { RouterProvider, createBrowserRouter } from "react-router-dom"; | ||
import Login from "./pages/Login"; | ||
import LandingPage from "./pages/LandingPage"; | ||
import Register from './pages/Register'; | ||
import Success from './components/register/Success'; | ||
import RegisterSection from './components/register/RegisterSection'; | ||
import { RouterProvider, createBrowserRouter } from 'react-router-dom'; | ||
import Login from './pages/Login'; | ||
import LandingPage from './pages/LandingPage'; | ||
|
||
const App = () => { | ||
const router = createBrowserRouter([ | ||
{ | ||
path: "/", | ||
path: '/', | ||
children: [ | ||
{ | ||
index: true, | ||
element: <LandingPage /> | ||
element: <LandingPage />, | ||
}, | ||
{ | ||
path: "login", | ||
element: <Login /> | ||
} | ||
] | ||
path: 'login', | ||
element: <Login />, | ||
}, | ||
], | ||
}, | ||
{ | ||
path: 'register', | ||
element: <Register />, | ||
children: [ | ||
{ | ||
path: '/register', | ||
element: <RegisterSection />, | ||
}, | ||
{ path: 'success', element: <Success /> }, | ||
], | ||
}, | ||
]) | ||
return ( | ||
<RouterProvider router={router} /> | ||
); | ||
]); | ||
return <RouterProvider router={router} />; | ||
}; | ||
|
||
export default App; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,22 @@ | ||
import { cn } from "../utils"; | ||
|
||
interface ButtonProps { | ||
text: string; | ||
buttonId?: string; | ||
type?: 'submit' | 'reset' | 'button'; | ||
className?: string; | ||
onClick?: () => void; | ||
} | ||
const Button = ({ text, type, className, onClick }: ButtonProps) => { | ||
return ( | ||
<button | ||
type={type} | ||
className={cn('p-2 rounded-lg bg-greenColor hover:bg-darkGreen transition-all text-whiteColor font-bold', className)} | ||
onClick={onClick} | ||
> | ||
{text} | ||
</button> | ||
); | ||
}; | ||
|
||
export default Button; |
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,34 @@ | ||
import { forwardRef } from 'react'; | ||
import { cn } from '../utils'; | ||
|
||
interface InputProps { | ||
type: string; | ||
label: string; | ||
id: string; | ||
placeholder: string; | ||
error?: string; | ||
labelClassName?: string; | ||
inputClasname?: string; | ||
} | ||
|
||
// Use React.forwardRef to forward the ref to the input element | ||
const Input = forwardRef<HTMLInputElement, InputProps>( | ||
({ type, labelClassName, inputClasname, label, id, placeholder, error = '', ...rest }, ref) => { | ||
return ( | ||
<label className={cn('flex flex-col gap-1 font-lg font-medium flex-1 w', labelClassName)}> | ||
{label} | ||
<input | ||
type={type} | ||
id={id} | ||
placeholder={placeholder} | ||
className={cn('p-1 px-3 rounded-lg border border-blackColor outline-none font-normal', inputClasname)} | ||
ref={ref} | ||
{...rest} | ||
/> | ||
{error && <p className='text-redColor text-xs'>{error}</p>} | ||
</label> | ||
); | ||
} | ||
); | ||
|
||
export default Input; |
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,24 @@ | ||
import { forwardRef } from 'react'; | ||
|
||
interface SelectProps { | ||
placeholder: string; | ||
error?: string; | ||
options: string[]; | ||
} | ||
const Select = forwardRef<HTMLSelectElement, SelectProps>(({ placeholder, options,error,...rest }, ref) => { | ||
return ( | ||
<> | ||
<select ref={ref} name='role' id='role' className='p-2 outline-0 border border-blackColor flex-1 rounded-lg' {...rest}> | ||
<option value=''>{placeholder}</option> | ||
{options.map((option, index) => ( | ||
<option key={index} value={option}> | ||
{option[0].toUpperCase() + option.slice(1)} | ||
</option> | ||
))} | ||
</select> | ||
<p className='text-redColor text-xs -mt-3'>{error}</p> | ||
</> | ||
); | ||
}); | ||
|
||
export default Select; |
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 |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import GoogleIcon from '../../assets/googleIcon.svg'; | ||
import Button from '../Button'; | ||
import Input from '../Input'; | ||
import Select from '../Select'; | ||
import { SubmitHandler, useForm } from 'react-hook-form'; | ||
import { extendedSchema, ExtendedFormFields } from '../../utils/schemas'; | ||
import { useNavigate } from 'react-router-dom'; | ||
import { useDispatch } from 'react-redux'; | ||
import { useRegisterUserMutation } from '../../services/authAPI'; | ||
import { setUserRegistered } from '../../state/register/registerSlice'; | ||
import { useEffect } from 'react'; | ||
import { QueryErrorData } from '../../utils/schemas'; | ||
|
||
const RegisterSection = () => { | ||
const navigate = useNavigate(); | ||
const dispatch = useDispatch(); | ||
|
||
const { | ||
register, | ||
setError, | ||
handleSubmit, | ||
formState: { errors, isSubmitting }, | ||
} = useForm<ExtendedFormFields>({ | ||
resolver: zodResolver(extendedSchema), | ||
}); | ||
const [registerUser, { data, isLoading, isSuccess, isError, error }] = useRegisterUserMutation(); | ||
let loginData: any; | ||
|
||
const onSubmit: SubmitHandler<ExtendedFormFields> = async retrievedData => { | ||
const { password, lastName, firstName, gender, phoneNumber, email } = retrievedData; | ||
|
||
loginData = { password, lastName, firstName, gender, phoneNumber, email }; | ||
await registerUser({ email, password, lastName, firstName, gender, phoneNumber }); | ||
}; | ||
useEffect(() => { | ||
const loginError = error as QueryErrorData; | ||
|
||
if (isError) { | ||
console.log(loginError); | ||
setError('root', { | ||
message: loginError.data?.error || loginError.data?.message, | ||
}); | ||
if (/email is already used/gi.test(loginError.data?.error || (loginError.data?.message as string))) { | ||
setTimeout(() => { | ||
setError('root', { | ||
message: 'Redirecting you to login page....', | ||
}); | ||
setTimeout(() => { | ||
navigate('/login'); | ||
}, 3000); | ||
}, 2000); | ||
} | ||
return; | ||
} | ||
if (isSuccess) { | ||
dispatch(setUserRegistered({ ...loginData })); | ||
navigate('/register/success'); | ||
} | ||
}, [isLoading, isError, error, isSuccess, data]); | ||
|
||
return ( | ||
<> | ||
<div | ||
className={`w-full xl:container flex flex-col-reverse gap-14 md:flex-row px-4 items-center md:gap-5 transition-all | ||
md:justify-between md:px-10 lg:justify-around mt-5 md:mt-10 `} | ||
> | ||
<div className='w-full md:w-7/12 xl:w-4/12 '> | ||
<p className='font-bold text-3xl '>New Customer?</p> | ||
<p>Sign Up to continue</p> | ||
<form action='' className='flex flex-col gap-4 justify-center mt-8 ' onSubmit={handleSubmit(onSubmit)}> | ||
<div className='grid grid-rows-2 md:grid-rows-1 md:grid-cols-2 gap-3'> | ||
<Input | ||
id='firstName' | ||
label='First Name' | ||
type='text' | ||
placeholder='Enter your fisrt name' | ||
{...register('firstName')} | ||
error={errors.firstName && errors.firstName?.message} | ||
/> | ||
<Input | ||
id='lastName' | ||
label='Last Name' | ||
type='text' | ||
placeholder='Enter your last name' | ||
{...register('lastName')} | ||
error={errors.lastName && errors.lastName?.message} | ||
/> | ||
</div> | ||
<Input | ||
id='registerEmail' | ||
label='Email' | ||
type='email' | ||
placeholder='Enter your email' | ||
{...register('email')} | ||
error={errors.email && errors.email?.message} | ||
/> | ||
<Input | ||
type='tel' | ||
label='Phone Number' | ||
id='phoneNumber' | ||
placeholder='Enter your Phone Number' | ||
{...register('phoneNumber')} | ||
error={errors.phoneNumber && errors.phoneNumber.message} | ||
/> | ||
<Input | ||
id='password' | ||
label='Enter your Password' | ||
type='password' | ||
placeholder='Enter your Password' | ||
{...register('password')} | ||
error={errors.password && errors.password?.message} | ||
/> | ||
|
||
<Input | ||
id='confirm__password' | ||
label='Confirm your Password' | ||
type='password' | ||
placeholder='Confirm your password' | ||
{...register('confirmPassword')} | ||
error={errors.confirmPassword && errors.confirmPassword?.message} | ||
/> | ||
<Select | ||
placeholder='Gender' | ||
options={['male', 'female']} | ||
{...register('gender')} | ||
error={errors.gender && errors.gender.message} | ||
/> | ||
<button | ||
type='submit' | ||
className='p-2 rounded-lg bg-greenColor hover:bg-darkGreen transition-all text-whiteColor font-bold' | ||
> | ||
{isSubmitting ? 'Loading..' : 'Sign Up'} | ||
</button> | ||
<p | ||
className={`text-sm bg-redColor text-whiteColor -mt-2 p-1 rounded-lg px-3 ${!errors.root ? 'hidden' : 'block'}`} | ||
> | ||
{errors.root?.message} | ||
</p> | ||
<span className='self-center font-bold text-grayColor'>or</span> | ||
<button | ||
className='p-2 font-bold text-greenColor border-2 border-greenColor rounded-lg flex flex-row | ||
items-center justify-center gap-2 hover:bg-teal-100 transition-all' | ||
> | ||
<img src={GoogleIcon} alt='Google Icon' className='w-5' /> | ||
Continue with Google | ||
</button> | ||
</form> | ||
</div> | ||
<div className='w-full md:w-3/12 mt-0 p-5 border-b-2 md:p-0 md:border-b-0 h-fit flex flex-col gap-3 justify-self-start self-start '> | ||
<p className='font-bold text-3xl'>Existing Customer?</p> | ||
<p>Go to Login Page to sign in</p> | ||
<Button type='submit' text='Sign In' onClick={() => navigate('/login')} /> | ||
</div> | ||
</div> | ||
<Button className={`my-10 mx-auto block`} text='Back to Home Page' onClick={() => navigate('/')} /> | ||
</> | ||
); | ||
}; | ||
|
||
export default RegisterSection; |
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,17 @@ | ||
import { useNavigate } from 'react-router-dom'; | ||
import Button from '../Button'; | ||
|
||
const Success = () => { | ||
const navigate = useNavigate(); | ||
return ( | ||
<div className='w-full h-screen flex flex-col items-center justify-center gap-10'> | ||
<p className=' text-5xl text-blackColor font-bold'>Success!</p> | ||
<p className='text-xl text-blackColor '> | ||
Account was created successfully. Please check your email to activate the account | ||
</p> | ||
<Button text='Go to Home' className='-mt-5' onClick={() => navigate('/')} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Success; |
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,18 @@ | ||
import { Outlet } from 'react-router-dom'; | ||
import Navbar from '../components/navbar/Navbar'; | ||
import Footer from '../components/footer/Footer'; | ||
const Register = () => { | ||
return ( | ||
<div className='mx-auto flex flex-col items-center justify-center'> | ||
<div className='min-h-screen h-fit w-full'> | ||
<Navbar /> | ||
<div> | ||
<Outlet /> | ||
</div> | ||
</div> | ||
<Footer /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Register; |
Oops, something went wrong.