diff --git a/.env b/.env index b8d5625..187caec 100644 --- a/.env +++ b/.env @@ -6,4 +6,4 @@ TWITTER_URL=https://twitter.com INSTAGRAM_URL=https://www.instagram.com # BACKEND END POINTS -VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1' \ No newline at end of file +VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/employment/v1' \ No newline at end of file diff --git a/.env.development b/.env.development index 71ce632..9a43031 100644 --- a/.env.development +++ b/.env.development @@ -6,4 +6,4 @@ VITE_TWITTER_URL=https://twitter.com VITE_INSTAGRAM_URL=https://www.instagram.com # BACKEND END POINTS -VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1' \ No newline at end of file +VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/employment/v1' \ No newline at end of file diff --git a/.env.production b/.env.production index b8d5625..187caec 100644 --- a/.env.production +++ b/.env.production @@ -6,4 +6,4 @@ TWITTER_URL=https://twitter.com INSTAGRAM_URL=https://www.instagram.com # BACKEND END POINTS -VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1' \ No newline at end of file +VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/employment/v1' \ No newline at end of file diff --git a/src/components/auth/Login.tsx b/src/components/auth/Login.tsx index 9ed8354..d1b5cf4 100644 --- a/src/components/auth/Login.tsx +++ b/src/components/auth/Login.tsx @@ -1,8 +1,10 @@ import { useState } from "react"; -import { Button, FloatLabelInput } from ".."; +import { Button, CustomSpinner, FloatLabelInput } from ".."; import CustomModal from "../modal/CustomModal"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useLocation } from "react-router-dom"; import { RouteHandler } from "../../router/routes"; +import { RequestStatus } from "../../core/models"; +import { employerLogin } from "../../core/apiRequest"; type FormType = { @@ -16,7 +18,13 @@ type HandleChange = { }; export default function Login() { - const navigate = useNavigate() + + const navigate = useNavigate() + const {state} = useLocation() + + const [modal, setModal] = useState(false) + + const [requestStatus, setRequestStatus] = useState({loading:false, status:null, message:'', data:{}}) let [formDetails, setFormDetails] = useState({ email: "", @@ -28,16 +36,41 @@ export default function Login() { }: { target: HandleChange; }): any => { - setFormDetails((prev) => ({ ...prev, [name]: value })); + setFormDetails((prev:FormType) => ({ ...prev, [name]: value })); }; - const [modal, setModal] = useState(false) + const loginFxn = () => { + let reqData = { + application_uid: state?.application_uid, + password: formDetails?.password, + username: formDetails.email + } + + setRequestStatus((prev:RequestStatus) => ({...prev, loading:true})) + employerLogin(reqData).then(res => { + // console.log('RES', res) + if(!res?.data?.call_return){ + setRequestStatus({loading:false, status:false, message:'Email/Password is wrong', data:{}}) + return setTimeout(()=>{ + setRequestStatus({loading:false, status:null, message:'', data:{}}) + },4000) + } + setRequestStatus({loading:false, status:true, message:'login successful', data:res?.data}) + setModal(true) + }).catch(err =>{ + setRequestStatus({loading:false, status:false, message:'something went wrong', data:{}}) + console.log(err) + return setTimeout(()=>{ + setRequestStatus({loading:false, status:null, message:'', data:{}}) + },4000) + }) + } return ( <>
-
+
@@ -78,12 +111,16 @@ export default function Login() {
-
+
@@ -94,12 +131,12 @@ export default function Login() {
{ modal && -
-

We have sent you a verification code to complete this Login. Please check your phone number

-
+
+

We have sent you a verification code to complete this Login. Please check your phone number

+
diff --git a/src/components/auth/OTP.tsx b/src/components/auth/OTP.tsx index d75428c..a853dc8 100644 --- a/src/components/auth/OTP.tsx +++ b/src/components/auth/OTP.tsx @@ -1,11 +1,14 @@ import { useEffect, useState } from "react"; -import { Button, FloatLabelInput } from ".."; +import { Button, CustomSpinner } from ".."; import { useLocation, useNavigate } from "react-router-dom"; import { RouteHandler } from "../../router/routes"; +import { updateUserDetails } from "../../store/UserDetails"; +import { useDispatch } from "react-redux"; +import { verifyOTP } from "../../core/apiRequest"; +import { RequestStatus } from "../../core/models"; type FormType = { - email: string; - password: string; + [index: string] : string }; type HandleChange = { @@ -16,23 +19,51 @@ type HandleChange = { export default function Login() { const navigate = useNavigate() const { state } = useLocation(); + const dispatch = useDispatch() - let [formDetails, setFormDetails] = useState({ - email: "", - password: "", + const [requestStatus, setRequestStatus] = useState({loading:false, status:null, message:'', data:{}}) + + let [values, setValues] = useState({ + otp1: "", + otp2: "", + otp3: "", + otp4: "", }); - const handleFormChange = ({ + const handleChange = ({ target: { name, value }, }: { target: HandleChange; }): any => { - setFormDetails((prev) => ({ ...prev, [name]: value })); + setValues((prev:FormType) => ({ ...prev, [name]: value })); }; const handleSubmit = () => { - localStorage.setItem('token', 'dummy') - navigate(RouteHandler.homepage, {replace:true}) + let reqData = { + verify_uid: state?.verify_uid, + otp: values.otp1+values.otp2+values.otp3+values.otp4 + } + + setRequestStatus((prev:RequestStatus) => ({...prev, loading:true})) + verifyOTP(reqData).then(res => { + if(!res?.data?.call_return){ + setRequestStatus({loading:false, status:false, message:'OTP is wrong', data:{}}) + return setTimeout(()=>{ + setRequestStatus({loading:false, status:null, message:'', data:{}}) + },4000) + } + setRequestStatus({loading:false, status:true, message:'OTP Verified', data:res?.data}) + localStorage.setItem('token', state?.verify_uid) + let data = {firstname:'firstname', lastname:'lastname', uid:'28273737646466464'} + dispatch(updateUserDetails(data)); + navigate(`/${state?.application_uid}`, {replace:true}) + }).catch(err =>{ + setRequestStatus({loading:false, status:false, message:'something went wrong', data:{}}) + console.log(err) + return setTimeout(()=>{ + setRequestStatus({loading:false, status:null, message:'', data:{}}) + },4000) + }) } useEffect(() => { @@ -42,10 +73,20 @@ export default function Login() { } }, []); + useEffect(()=>{ + const formOTP = document.querySelectorAll('input') + for (const i of formOTP) { + if (i.value === '') { + i.focus(); + break; + } + } + },[values]) + return (
-
+
@@ -59,63 +100,62 @@ export default function Login() {
{/* INPUTS */} -
-
- -
-
- -
-
- -
-
- -
+
+ + + +
+ {requestStatus.loading ? +
+ +
+ :
diff --git a/src/components/shared/Button.tsx b/src/components/shared/Button.tsx index 245c3ac..5f79b34 100644 --- a/src/components/shared/Button.tsx +++ b/src/components/shared/Button.tsx @@ -5,6 +5,7 @@ interface ButtonProps { className?: string; type?: "button" | "submit" | "reset"; onClick?: React.MouseEventHandler; + disabled?: boolean } const Button: React.FC = ({ @@ -12,12 +13,14 @@ const Button: React.FC = ({ className, onClick, type = "button", + disabled = false }) => { return ( diff --git a/src/components/shared/CustomSpinner.tsx b/src/components/shared/CustomSpinner.tsx new file mode 100644 index 0000000..3d2ac44 --- /dev/null +++ b/src/components/shared/CustomSpinner.tsx @@ -0,0 +1,19 @@ +import React from 'react' + +type Props = { + size?: string +} + +export default function CustomSpinner({size='8'}:Props) { + let width = `w-${size}` + let height = `h-${size}` + return ( +
+ + Loading... +
+ ) +} diff --git a/src/components/shared/index.ts b/src/components/shared/index.ts index 7a3ffd4..1e028a9 100644 --- a/src/components/shared/index.ts +++ b/src/components/shared/index.ts @@ -2,5 +2,6 @@ import Button from "./Button"; import InputCompOne from "./InputCompOne"; import FloatLabelInput from "./FloatLabelInput"; import Stepper from "./Stepper"; +import CustomSpinner from "./CustomSpinner"; -export { Button, FloatLabelInput, InputCompOne, Stepper }; +export { Button, CustomSpinner, FloatLabelInput, InputCompOne, Stepper }; diff --git a/src/core/apiRequest.ts b/src/core/apiRequest.ts index 6ba6260..66a8439 100644 --- a/src/core/apiRequest.ts +++ b/src/core/apiRequest.ts @@ -1,18 +1,18 @@ import { postAuxEnd, getAuxEnd } from "./axiosCall"; -// FUNCTION TO START BVN VALIDATION -// export const validateBVN = (postData:any) => { -// let reqData = { -// ...postData -// } -// return postAuxEnd('/bvn', reqData) -// } +// FUNCTION TO LOGIN EMPLOYER +export const employerLogin = (postData:any) => { + let reqData = { + ...postData + } + return postAuxEnd('/auth', reqData) +} // FUNCTION TO VERIFY OTP AND LOGIN -// export const verifyOTP = (postData:any) => { -// let reqData = { -// ...postData -// } -// return postAuxEnd('/bvn/verify', reqData) -// } \ No newline at end of file +export const verifyOTP = (postData:any) => { + let reqData = { + ...postData + } + return postAuxEnd('/otp', reqData) +} \ No newline at end of file diff --git a/src/core/models.ts b/src/core/models.ts index 90a29f9..159dc69 100644 --- a/src/core/models.ts +++ b/src/core/models.ts @@ -1,27 +1,17 @@ export interface RequestStatus { - loading?:boolean - status?:boolean | undefined - message?:string - name?:string - data?:{}[] | [any] | {} + loading?: null | boolean + status?: null | boolean + message?: null | string + data? : {[index:string]: string | {[index:string]: string}} } -export interface User { - firstname?:string - lastname?:string - last_login?:string - message?:string - token?:string - customer_uid?:string - call_return?:string - } - - -export type PendingTableList = { - status?: string | boolean; - application_uid?: string - added?: string - loan_amount?: string - payment_month?: string -}[]; \ No newline at end of file +export interface APIResponse { + call_return: string + verify_uid: string + records: { + application_uid: string + password: string + username: string + } +} \ No newline at end of file diff --git a/src/layouts/DashboardLayout/DashboardAuth.tsx b/src/layouts/DashboardLayout/DashboardAuth.tsx index 950214e..ddfe27c 100644 --- a/src/layouts/DashboardLayout/DashboardAuth.tsx +++ b/src/layouts/DashboardLayout/DashboardAuth.tsx @@ -2,7 +2,7 @@ import {useState, useEffect} from 'react' import Layout from '../Layout'; // import DashboardLayout from "./DashboardLayout"; -import { Outlet, useNavigate } from "react-router-dom"; +import { Outlet, useNavigate, useParams } from "react-router-dom"; import { useSelector, useDispatch } from "react-redux"; import { updateUserDetails } from '../../store/UserDetails'; import { RouteHandler } from '../../router/routes'; @@ -13,6 +13,7 @@ export default function DashboardAuth() { const navigate = useNavigate() const dispatch = useDispatch() + const {application_uid} = useParams() const { userDetails } = useSelector((state:any) => state?.userDetails); // CHECKS IF USER Details are avaliable @@ -41,7 +42,7 @@ export default function DashboardAuth() { let token = localStorage.getItem('token') if(!token){ // IF NO TOKEN || UID RETURN TO LOGIN PAGE - navigate(RouteHandler.loginpage, {replace:true}) + navigate(RouteHandler.loginpage, {state:{application_uid}, replace:true}) return } const getUser = () => { // FUNCTION TO GET USER BY ID @@ -51,6 +52,8 @@ export default function DashboardAuth() { } if(!Object.keys(userDetails).length){ getUser() + }else{ + setLoading(false) } },[]) diff --git a/src/pages/StartValidationPage.tsx b/src/pages/StartValidationPage.tsx index 86246d6..400366d 100644 --- a/src/pages/StartValidationPage.tsx +++ b/src/pages/StartValidationPage.tsx @@ -4,7 +4,9 @@ import { StartValidation } from "../components"; const StartValidationPage: React.FC = () => { useEffect(()=>{ // remove this function later - localStorage.clear() + setTimeout(()=>{ + localStorage.clear() + },2000) },[]) return ( <> diff --git a/src/router/routes.tsx b/src/router/routes.tsx index e7e50ca..bcefa9e 100644 --- a/src/router/routes.tsx +++ b/src/router/routes.tsx @@ -1,5 +1,5 @@ export class RouteHandler { - static homepage = "/"; + static homepage = "/:application_uid"; static loginpage = "/auth/login"; static otppage = "/auth/otp"; } diff --git a/tailwind.config.js b/tailwind.config.js index d37737f..1c666d9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -5,7 +5,11 @@ export default { "./src/**/*.{js,ts,jsx,tsx}", ], theme: { - extend: {}, + extend: { + screens:{ + xs: "400px", + } + }, }, plugins: [], }