From b6aad5a3fce46cce06587e2b893057479ba96d7a Mon Sep 17 00:00:00 2001 From: favor-star Date: Tue, 4 Jun 2024 17:48:48 +0200 Subject: [PATCH] [Finshes #187354196] Sign up page --- package.json | 8 +- src/App.tsx | 38 +++-- src/assets/googleIcon.svg | 6 + src/components/Button.tsx | 22 +++ src/components/Input.tsx | 34 ++++ src/components/Select.tsx | 24 +++ src/components/navbar/Navbar.tsx | 2 +- src/components/register/RegisterSection.tsx | 161 ++++++++++++++++++ src/components/register/Success.tsx | 17 ++ src/pages/Register.tsx | 18 ++ src/services/authAPI.ts | 22 +++ src/services/index.ts | 10 ++ src/state/register/registerSlice.ts | 23 +++ src/state/store.ts | 9 + src/utils/index.ts | 6 + src/utils/schemas.ts | 38 +++++ tailwind.config.js | 15 +- tsconfig.json | 1 - ....timestamp-1717503390378-4d6707c4e34b1.mjs | 27 +++ 19 files changed, 457 insertions(+), 24 deletions(-) create mode 100644 src/assets/googleIcon.svg create mode 100644 src/components/Button.tsx create mode 100644 src/components/Input.tsx create mode 100644 src/components/Select.tsx create mode 100644 src/components/register/RegisterSection.tsx create mode 100644 src/components/register/Success.tsx create mode 100644 src/pages/Register.tsx create mode 100644 src/services/authAPI.ts create mode 100644 src/services/index.ts create mode 100644 src/state/register/registerSlice.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/schemas.ts create mode 100644 vite.config.ts.timestamp-1717503390378-4d6707c4e34b1.mjs diff --git a/package.json b/package.json index 3be7aea..110a940 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,19 @@ "build-storybook": "storybook build" }, "dependencies": { + "@hookform/resolvers": "^3.6.0", "@reduxjs/toolkit": "^2.2.5", "@types/react-redux": "^7.1.33", + "clsx": "^2.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.51.5", "react-icons": "^5.2.1", "react-redux": "^9.1.2", "react-router-dom": "^6.23.1", - "sass": "^1.77.2" + "sass": "^1.77.2", + "tailwind-merge": "^2.3.0", + "zod": "^3.23.8" }, "devDependencies": { "@chromatic-com/storybook": "^1.4.0", @@ -56,7 +61,6 @@ "prettier": "3.2.5", "storybook": "^8.1.3", "tailwindcss": "^3.4.3", - "typescript": "^5.2.2", "typescript-eslint": "^7.10.0", "vite": "^5.2.0", "vitest": "^1.6.0" diff --git a/src/App.tsx b/src/App.tsx index 85b8fde..5787502 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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: + element: , }, { - path: "login", - element: - } - ] + path: 'login', + element: , + }, + ], + }, + { + path: 'register', + element: , + children: [ + { + path: '/register', + element: , + }, + { path: 'success', element: }, + ], }, - ]) - return ( - - ); + ]); + return ; }; export default App; diff --git a/src/assets/googleIcon.svg b/src/assets/googleIcon.svg new file mode 100644 index 0000000..17322ec --- /dev/null +++ b/src/assets/googleIcon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..9db07d4 --- /dev/null +++ b/src/components/Button.tsx @@ -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 ( + + ); +}; + +export default Button; diff --git a/src/components/Input.tsx b/src/components/Input.tsx new file mode 100644 index 0000000..fec8e95 --- /dev/null +++ b/src/components/Input.tsx @@ -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( + ({ type, labelClassName, inputClasname, label, id, placeholder, error = '', ...rest }, ref) => { + return ( + + ); + } +); + +export default Input; diff --git a/src/components/Select.tsx b/src/components/Select.tsx new file mode 100644 index 0000000..42170a8 --- /dev/null +++ b/src/components/Select.tsx @@ -0,0 +1,24 @@ +import { forwardRef } from 'react'; + +interface SelectProps { + placeholder: string; + error?: string; + options: string[]; +} +const Select = forwardRef(({ placeholder, options,error,...rest }, ref) => { + return ( + <> + +

{error}

+ + ); +}); + +export default Select; diff --git a/src/components/navbar/Navbar.tsx b/src/components/navbar/Navbar.tsx index 4516326..b703b4d 100644 --- a/src/components/navbar/Navbar.tsx +++ b/src/components/navbar/Navbar.tsx @@ -37,7 +37,7 @@ function Navbar() { }, []); return ( -
+
diff --git a/src/components/register/RegisterSection.tsx b/src/components/register/RegisterSection.tsx new file mode 100644 index 0000000..6736205 --- /dev/null +++ b/src/components/register/RegisterSection.tsx @@ -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({ + resolver: zodResolver(extendedSchema), + }); + const [registerUser, { data, isLoading, isSuccess, isError, error }] = useRegisterUserMutation(); + let loginData: any; + + const onSubmit: SubmitHandler = 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 ( + <> +
+
+

New Customer?

+

Sign Up to continue

+
+
+ + +
+ + + + + +