diff --git a/package-lock.json b/package-lock.json index d3c8f3b..96e7dc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,11 +11,13 @@ "@hookform/resolvers": "^3.9.0", "@reduxjs/toolkit": "^2.2.7", "@types/react-router-dom": "^5.3.3", + "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.52.2", + "react-hot-toast": "^2.4.1", "react-icons": "^4.12.0", "react-redux": "^9.1.2", "react-router-dom": "^6.26.1", @@ -1282,6 +1284,12 @@ "node": ">=8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -1320,6 +1328,17 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1533,6 +1552,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1646,6 +1677,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2039,6 +2079,40 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -2150,6 +2224,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", + "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2455,6 +2538,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2846,6 +2950,12 @@ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2917,6 +3027,22 @@ "react": "^16.8.0 || ^17 || ^18 || ^19" } }, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "license": "MIT", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-icons": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz", diff --git a/package.json b/package.json index e284038..4cef548 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,13 @@ "@hookform/resolvers": "^3.9.0", "@reduxjs/toolkit": "^2.2.7", "@types/react-router-dom": "^5.3.3", + "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.52.2", + "react-hot-toast": "^2.4.1", "react-icons": "^4.12.0", "react-redux": "^9.1.2", "react-router-dom": "^6.26.1", diff --git a/src/App.tsx b/src/App.tsx index 6b9fee2..c22f870 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,42 +1,47 @@ -import { Footer, Navbar } from './components/layout' -import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; -import Home from './pages/Home' -import Login from './pages/auth/Login'; -import Register from './pages/auth/Register'; -import Auth from './pages/auth/Auth'; -import { ForgotPassword, ResetPassword } from './pages/auth/forgot-password'; -import About from './pages/About'; - - +import { Footer, Navbar } from "./components/layout"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import Home from "./pages/Home"; +import Login from "./pages/auth/Login"; +import Register from "./pages/auth/Register"; +import Auth from "./pages/auth/Auth"; +import { ForgotPassword, ResetPassword } from "./pages/auth/forgot-password"; +import About from "./pages/About"; +import { Toaster } from "react-hot-toast"; const App = () => { - - - - return ( - -
-
- -
- - }> - } /> - } /> - - } /> - } /> - } /> - } /> - - -
-
-
-
- ); -} - -export default App; \ No newline at end of file + return ( + <> + +
+
+ +
+ + }> + } /> + } /> + + } + /> + } + /> + } /> + } /> + + +
+
+
+
+ + + ); +}; + +export default App; diff --git a/src/apis/axios.ts b/src/apis/axios.ts index 424253c..d3dfbbf 100644 --- a/src/apis/axios.ts +++ b/src/apis/axios.ts @@ -1,20 +1,43 @@ -import axios, { AxiosError, InternalAxiosRequestConfig } from "axios"; +import axios, { + AxiosError, + AxiosResponse, + InternalAxiosRequestConfig, +} from "axios"; const baseURL = `${import.meta.env.VITE_PUBLIC_API_URL}/api/v1/`; // Create an axios instance with the base URL const axiosClient = axios.create({ - baseURL, + baseURL, }); axiosClient.interceptors.request.use( - (config: InternalAxiosRequestConfig) => { - // config.headers["access-control-allow-origin"] = "*"; - return config; - }, - (error: AxiosError) => { - return Promise.reject(error); - } + (config: InternalAxiosRequestConfig) => { + const resource = localStorage.getItem("TOKEN"); + if (resource) { + const token = JSON.parse(resource).access_token; + config.headers.Authorization = `Bearer ${token}`; + } + // config.headers["access-control-allow-origin"] = "*"; + return config; + }, + (error: AxiosError) => { + return Promise.reject(error); + } ); -export default axiosClient; \ No newline at end of file +// Response interceptor to handle errors +axiosClient.interceptors.response.use( + (response: AxiosResponse) => { + return response; + }, + (error: AxiosError) => { + if (error.response && error.response.status === 401) { + localStorage.removeItem("TOKEN"); + window.location.reload(); + } + return Promise.reject(error); + } +); + +export default axiosClient; diff --git a/src/apis/index.ts b/src/apis/index.ts index 88c63eb..e58509c 100644 --- a/src/apis/index.ts +++ b/src/apis/index.ts @@ -1 +1,79 @@ // This function contains the different API functions + +import { AxiosError } from "axios"; +import axiosClient from "./axios"; +import { ILoginForm, IRegisterForm } from "../models"; +import { toast } from "react-hot-toast"; + +type IResponse = { + message: string; + status_code: number; +} & ({ + status: false; + errors: string[]; +} | { + status: true; + data: T +}) + +type IUserResponse = { + access_token: string; + refresh_token: string; + expires_in: string; + user: { + id: string; + email: string; + username: string; + profile_image: string; + first_name: string; + last_name: string; + last_login?: Date; + }; +}; + +export const registerUser = async ( + body: IRegisterForm +): Promise => { + try { + const requestBody = { + email: body.email, + username: body.username, + password: body.password, + password_confirmation: body.passwordConfirmation, + first_name: body.name.split(" ")[0], + last_name: body.name.split(" ")[1], + }; + const { data } = await axiosClient.post( + "/auth/register/", + requestBody + ); + toast.success(data.message); + return data; + } catch (err) { + if (err instanceof AxiosError){ + const { data: { errors } } = err.response! + toast.error(errors[0]); + } + return null; + } +}; + +export const signinUser = async ( + body: ILoginForm +): Promise => { + try { + const requestBody = { + email_or_username: body.emailOrUsername, + password: body.password, + }; + const { data } = await axiosClient.post>("/auth/login/", requestBody); + toast.success(data.message); + if (data.status) return data.data; + } catch (err: unknown) { + if (err instanceof AxiosError){ + const { data: { errors } } = err.response! + toast.error(errors[0]); + } + } + return null; +}; diff --git a/src/components/layout/button/Button.tsx b/src/components/layout/button/Button.tsx index 5b26302..ab0515f 100644 --- a/src/components/layout/button/Button.tsx +++ b/src/components/layout/button/Button.tsx @@ -1,34 +1,46 @@ -import { ReactNode } from 'react'; -import { cn } from '../../../utils/constants'; +import { ReactNode } from "react"; +import { cn } from "../../../utils/constants"; interface ButtonProps { - backgroundColor?: string; - children: ReactNode; - onClick?: () => void; - outline?: boolean; - spacing?: boolean; - className?: string; + backgroundColor?: string; + children: ReactNode; + onClick?: () => void; + outline?: boolean; + spacing?: boolean; + className?: string; + type?: "submit" | "reset" | "button"; + disabled?: boolean; } -const Button = ({ outline=false, children, backgroundColor="bg-primary", spacing=true, className="" }: ButtonProps) => { - return ( - - ); +const Button = ({ + outline = false, + children, + backgroundColor = "bg-primary", + spacing = true, + className = "", + type, + disabled, +}: ButtonProps) => { + return ( + + ); }; -export default Button \ No newline at end of file +export default Button; diff --git a/src/models/login.ts b/src/models/login.ts index 2d13451..6d60ba2 100644 --- a/src/models/login.ts +++ b/src/models/login.ts @@ -1,4 +1,4 @@ export interface ILoginForm { - email:string + emailOrUsername:string password:string } \ No newline at end of file diff --git a/src/models/password.ts b/src/models/password.ts index 03dc22e..4872a39 100644 --- a/src/models/password.ts +++ b/src/models/password.ts @@ -1,9 +1,9 @@ export interface ForgotPasswordForm { - code :string email: string } export interface ResetPasswordForm { + // code :string password: string; confirmPassword: string; } \ No newline at end of file diff --git a/src/models/register.ts b/src/models/register.ts index 2c2c9ff..b45b512 100644 --- a/src/models/register.ts +++ b/src/models/register.ts @@ -3,6 +3,6 @@ export interface IRegisterForm { email: string; password: string; passwordConfirmation: string; - phone: number; + phone?: string; username: string; } \ No newline at end of file diff --git a/src/pages/auth/Login.tsx b/src/pages/auth/Login.tsx index 2dfb669..e00cb60 100644 --- a/src/pages/auth/Login.tsx +++ b/src/pages/auth/Login.tsx @@ -1,170 +1,176 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import {ILoginForm} from '../../models' -import * as yup from 'yup'; -import { yupResolver } from '@hookform/resolvers/yup'; -import { useForm } from "react-hook-form" -import { Button } from '../../components/layout'; -import { Link } from 'react-router-dom'; -import { useState } from 'react'; -import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'; +import { ILoginForm } from "../../models"; +import * as yup from "yup"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { useForm } from "react-hook-form"; +import { Button } from "../../components/layout"; +import { Link } from "react-router-dom"; +import { useState } from "react"; +import { AiOutlineEye, AiOutlineEyeInvisible } from "react-icons/ai"; // import {Carousel} from "../../components"; -// import { useNavigate } from 'react-router-dom'; -import { GoArrowUpRight } from 'react-icons/go'; -import AuthQuote from '../../components/pages/Auth-Page-Components/AuthQuote'; - +import { useNavigate } from "react-router-dom"; +import { GoArrowUpRight } from "react-icons/go"; +import AuthQuote from "../../components/pages/Auth-Page-Components/AuthQuote"; +import { signinUser } from "../../apis"; const Login = () => { - // const navigate = useNavigate(); - - const [showPassword, setShowPassword] = useState(false); + const navigate = useNavigate(); - const loginFormSchema = yup.object().shape({ - email: yup - .string() - .required('This field is required') - .matches( - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/, - `${'Enter a valid email'}` - ), - password: yup - .string() - .required('enter a password') - .min(8, 'Password must be atleast 8 characters long') - .matches( - /^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{8,}$/, - `${'Enter a correct password'}` - ), - }); - - - const { - handleSubmit, - register, - formState: { errors }, - } = useForm({ - resolver: yupResolver(loginFormSchema), - }); + const [showPassword, setShowPassword] = useState(false); + const loginFormSchema = yup.object().shape({ + emailOrUsername: yup + .string() + .required("You must provide a value for this field"), + password: yup + .string() + .required("You must provide a value for this field") + .min(8, "Password must be atleast 8 characters long") + .matches( + /^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{8,}$/, + `${"Enter a correct password"}` + ), + }); - const fieldHasErrors = (fieldName: keyof ILoginForm) => { - return Boolean(errors[fieldName]); - }; + const { + handleSubmit, + register, + formState: { errors, isSubmitting }, + reset, + } = useForm({ + resolver: yupResolver(loginFormSchema), + }); - const onSubmit = async (data: ILoginForm) => { - console.log(data) - }; + const onSubmit = async (data: ILoginForm) => { + console.log(data); + const res = await signinUser(data); + if (res) { + const { user, ...token } = res; + localStorage.setItem("TOKEN", JSON.stringify(token)); + localStorage.setItem("user", JSON.stringify(user)); + navigate("/"); + } + reset(); + }; - return ( -
- -
-
-

- Welcome Back Buddy! -

-

It's been a while here since you were gone.

-
-
-
- - -
- -
-
-
- -
- -
- {showPassword ? ( - setShowPassword(!showPassword)} - /> - ) : ( - setShowPassword(!showPassword)} - /> - ) - } -
-
-
- -
- -
-
- - Keep me logged in next time -
- - Forgot password? - - -
+ return ( +
+ + +
+

+ Welcome Back Buddy! +

+

+ It's been a while here since you were gone. +

+
+
+
+ + +
+ {errors.emailOrUsername && ( + + )} +
+
+
+ +
+ +
+ {showPassword ? ( + + setShowPassword(!showPassword) + } + /> + ) : ( + + setShowPassword(!showPassword) + } + /> + )} +
+
+
+ {errors.password && ( + + )} +
+
+
+
+ + + Keep me logged in next time + +
+ + Forgot password? + + +
- - -
- ); -} + +
+ +
+ ); +}; -export default Login \ No newline at end of file +export default Login; diff --git a/src/pages/auth/Register.tsx b/src/pages/auth/Register.tsx index ceaf634..f4dd3ae 100644 --- a/src/pages/auth/Register.tsx +++ b/src/pages/auth/Register.tsx @@ -1,300 +1,340 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { IRegisterForm } from '../../models'; -import * as yup from 'yup'; -import { yupResolver } from '@hookform/resolvers/yup'; -import { useForm } from 'react-hook-form'; -import { Button } from '../../components/layout'; -import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai'; -import { useState } from 'react'; +import { IRegisterForm } from "../../models"; +import * as yup from "yup"; +import { yupResolver } from "@hookform/resolvers/yup"; +import { useForm } from "react-hook-form"; +import { Button } from "../../components/layout"; +import { AiOutlineEye, AiOutlineEyeInvisible } from "react-icons/ai"; +import { useState } from "react"; // import {Carousel} from "../../components"; -// import {useNavigate} from "react-router-dom"; -import AuthQuote from '../../components/pages/Auth-Page-Components/AuthQuote'; +import { useNavigate } from "react-router-dom"; +import AuthQuote from "../../components/pages/Auth-Page-Components/AuthQuote"; +import { registerUser } from "../../apis"; const Register = () => { -// const navigate = useNavigate() + const navigate = useNavigate(); - const [showPassword, setShowPassword] = useState({ - password1: false, - password2: false - }); - const RegisterFormSchema = yup.object().shape({ - name: yup.string().required('this is required'), - username: yup.string().required('this is required'), - phone: yup.number().required('this is required'), - email: yup - .string() - .required('this is required') - .matches( - /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/, - `${'Enter a valid email'}` - ), - password: yup - .string() - .required('enter a password') - .min(8, 'Password must be atleast 8 characters long') - .matches( - /^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{8,}$/, - `${'Enter a password with numbers, letters and special characters'}` - ), + const [showPassword, setShowPassword] = useState({ + password1: false, + password2: false, + }); + const RegisterFormSchema = yup.object().shape({ + name: yup.string().required("This is required"), + username: yup.string().required("This is required"), + phone: yup + .string() + .matches( + /^(\+?(\d{1,3})?[-.\s]?(\(?\d{1,4}?\)?)[-.\s]?(\d{1,4})[-.\s]?(\d{1,4})[-.\s]?(\d{1,9})?)?$/, + "Enter a valid phone number" + ) + .optional(), + email: yup + .string() + .required("This is required") + .matches( + /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/, + `${"Enter a valid email"}` + ), + password: yup + .string() + .required("This is required") + .min(8, "Your password is weak") + .matches( + /^(?=.*?[A-Z])(?=(.*[a-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?!.*\s).{8,}$/, + `${"Enter a password with numbers, letters and special characters"}` + ), - passwordConfirmation: yup - .string() - .required('enter a password') - // .min(8, 'Password must be atleast 8 characters long') - .test(`${'passwords match'}`, `${'passwords do not match '}`, function (value) { - return this.parent.password === value; - }), - }); - + passwordConfirmation: yup + .string() + .required("This is required") + // .min(8, 'Password must be atleast 8 characters long') + .test( + `${"Passwords match"}`, + "Passwords do not match", + function (value) { + return this.parent.password === value; + } + ), + }); - const { - handleSubmit, - register, - formState: { errors }, - } = useForm({ - resolver: yupResolver(RegisterFormSchema), - }); + const { + handleSubmit, + register, + formState: { errors, isSubmitting }, + } = useForm({ + resolver: yupResolver(RegisterFormSchema), + }); - const fieldHasErrors = (fieldName: keyof IRegisterForm) => { - return Boolean(errors[fieldName]); - }; + // const fieldHasErrors = (fieldName: keyof IRegisterForm) => { + // return Boolean(errors[fieldName]); + // }; - const onSubmit = async (data: IRegisterForm) => { - console.log(data) - }; + const onSubmit = async (data: IRegisterForm) => { + console.log(data); + const res = await registerUser(data) + if (res && res.status) + navigate("/auth/login") + }; - return ( -
-
- -
-
-
-
-

- Good to have you here! -

-

- We are always warmed up on welcoming a new member. Feel home and safe. -

-
- -
-
-
- - -
- + return ( +
+
+ +
+ +
+
+

+ Good to have you here! +

+

+ We are always warmed up on welcoming a new member. + Feel home and safe. +

-
-
- - -
-