Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29538e3b6e | |||
| dd2df0d695 | |||
| a97db9a661 | |||
| 135cbce348 | |||
| 814bfe041a | |||
| d90d515f60 | |||
| e93a3dea68 | |||
| a50d5ec82d | |||
| 333ada0a1c | |||
| bb718953ad | |||
| a31b36686d | |||
| 00f4e1b565 | |||
| 6d302def04 | |||
| 82dd11a772 | |||
| 7e9c395f4a | |||
| 2cb5c471f6 | |||
| 4b008f6785 | |||
| f632099128 | |||
| 122eb31732 | |||
| 0207bf631a | |||
| 378ff4a625 | |||
| f88b6df24c | |||
| fe759c6d0a | |||
| 104295bdb2 | |||
| 44933d4362 | |||
| 9ce7110a5d | |||
| 085b2d4aaa | |||
| 747c945659 | |||
| 94f9803ec5 | |||
| 3998596fba | |||
| 886fd64347 | |||
| f95fd66c57 | |||
| 98b5d4bc4f | |||
| fd2b2245f5 | |||
| a7e97e1890 | |||
| 537d609117 | |||
| 5e0d21b5dd | |||
| ea4e6b7a59 | |||
| 07f7a90c0d | |||
| 2a2b8ee85d | |||
| e2b3978ab6 | |||
| b8f9958517 | |||
| 06cadbb742 | |||
| 067e7a395d | |||
| 5b6695c1f6 | |||
| 911c67e874 | |||
| a33784fc9e | |||
| b3efba09d6 | |||
| ff03282310 | |||
| 05dfb50f62 | |||
| 08af493d65 | |||
| e1bd0293f1 | |||
| a5b77abc92 | |||
| dd6d92654c | |||
| dd9652fe58 | |||
| 266627d941 | |||
| c4ffd49509 | |||
| 21b4bf5e8f | |||
| b71490aa8a | |||
| be9672991e | |||
| 97e6951685 | |||
| 1bd523c493 | |||
| 32f2a358b2 | |||
| ee94a59f75 | |||
| 4c24ce5903 | |||
| 86c0a236fe | |||
| 2daae9b0e0 | |||
| 2890677472 | |||
| 4a3f46c19b | |||
| 79f5af7692 | |||
| 2a59165054 | |||
| e3cf881e09 | |||
| dde4072593 | |||
| df6fe828e3 | |||
| db08d1201c | |||
| 32acf978c3 | |||
| f7ef9ff3a0 | |||
| 37c012461f | |||
| 0a295cc81c | |||
| e5c605560b | |||
| 26b95bab3d | |||
| cbbd23fde3 | |||
| 18c1a78d4c | |||
| f402efeb85 | |||
| 38becd42ac |
@@ -1 +1,9 @@
|
||||
DIGIFI_PORT=5173
|
||||
|
||||
# Social Links
|
||||
FACEBOOK_URL=https://www.facebook.com
|
||||
TWITTER_URL=https://twitter.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
@@ -1 +1,9 @@
|
||||
DIGIFI_PORT=5173
|
||||
|
||||
# Social Links
|
||||
VITE_FACEBOOK_URL=https://www.facebook.com
|
||||
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'
|
||||
@@ -1 +1,9 @@
|
||||
DIGIFI_PORT=5173
|
||||
|
||||
# Social Links
|
||||
FACEBOOK_URL=https://www.facebook.com
|
||||
TWITTER_URL=https://twitter.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
@@ -11,8 +11,13 @@ services:
|
||||
ports:
|
||||
- 6030:5173
|
||||
expose:
|
||||
- "5173"
|
||||
- "5173"
|
||||
extra_hosts:
|
||||
- digifi-apidev.chiefsoft.net:10.10.33.15
|
||||
- backend.wrenchboard.api.test:10.10.33.15
|
||||
environment:
|
||||
- PORT=${DIGIFI_PORT}
|
||||
tty: true
|
||||
stdin_open: true
|
||||
volumes:
|
||||
src:
|
||||
src:
|
||||
|
||||
@@ -11,10 +11,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"axios": "^1.6.8",
|
||||
"clsx": "2.1.0",
|
||||
"formik": "2.4.5",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-redux": "^8.0.5",
|
||||
"react-router-dom": "6.3.0",
|
||||
"react-select": "^5.8.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.btn-primary {
|
||||
background: #5A2C82;
|
||||
background: #5A2C82 !important;
|
||||
color: #FFFFFF;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
@@ -8,7 +8,34 @@
|
||||
}
|
||||
|
||||
.btn-active {
|
||||
background: #D10056;
|
||||
background: #D10056 !important;
|
||||
}
|
||||
|
||||
.btn-R {
|
||||
padding-inline: 3rem !important;
|
||||
font-weight: bold !important;
|
||||
font-size: 16px !important;
|
||||
background-color: #5A2C82;
|
||||
}
|
||||
|
||||
.btn-W {
|
||||
background: white !important;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #FBB700;
|
||||
line-height: 25px;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.btn-Y {
|
||||
background: #FBB700 !important;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
/* color: white; */
|
||||
line-height: 25px;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 262 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="50px" height="50px"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.12,5.12)"><path d="M32,11h5c0.552,0 1,-0.448 1,-1v-6.737c0,-0.524 -0.403,-0.96 -0.925,-0.997c-1.591,-0.113 -4.699,-0.266 -6.934,-0.266c-6.141,0 -10.141,3.68 -10.141,10.368v6.632h-7c-0.552,0 -1,0.448 -1,1v7c0,0.552 0.448,1 1,1h7v19c0,0.552 0.448,1 1,1h7c0.552,0 1,-0.448 1,-1v-19h7.222c0.51,0 0.938,-0.383 0.994,-0.89l0.778,-7c0.066,-0.592 -0.398,-1.11 -0.994,-1.11h-8v-5c0,-1.657 1.343,-3 3,-3z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 856 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="64px" height="64px"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(4,4)"><path d="M21.58008,7c-8.039,0 -14.58008,6.54494 -14.58008,14.58594v20.83203c0,8.04 6.54494,14.58203 14.58594,14.58203h20.83203c8.04,0 14.58203,-6.54494 14.58203,-14.58594v-20.83398c0,-8.039 -6.54494,-14.58008 -14.58594,-14.58008zM47,15c1.104,0 2,0.896 2,2c0,1.104 -0.896,2 -2,2c-1.104,0 -2,-0.896 -2,-2c0,-1.104 0.896,-2 2,-2zM32,19c7.17,0 13,5.83 13,13c0,7.17 -5.831,13 -13,13c-7.17,0 -13,-5.831 -13,-13c0,-7.169 5.83,-13 13,-13zM32,23c-4.971,0 -9,4.029 -9,9c0,4.971 4.029,9 9,9c4.971,0 9,-4.029 9,-9c0,-4.971 -4.029,-9 -9,-9z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 993 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="50px" height="50px"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.12,5.12)"><path d="M41,4h-32c-2.76,0 -5,2.24 -5,5v32c0,2.76 2.24,5 5,5h32c2.76,0 5,-2.24 5,-5v-32c0,-2.76 -2.24,-5 -5,-5zM17,20v19h-6v-19zM11,14.47c0,-1.4 1.2,-2.47 3,-2.47c1.8,0 2.93,1.07 3,2.47c0,1.4 -1.12,2.53 -3,2.53c-1.8,0 -3,-1.13 -3,-2.53zM39,39h-6c0,0 0,-9.26 0,-10c0,-2 -1,-4 -3.5,-4.04h-0.08c-2.42,0 -3.42,2.06 -3.42,4.04c0,0.91 0,10 0,10h-6v-19h6v2.56c0,0 1.93,-2.56 5.81,-2.56c3.97,0 7.19,2.73 7.19,8.26z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 878 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="50px" height="50px"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.12,5.12)"><path d="M6.91992,6l14.2168,20.72656l-14.9082,17.27344h3.17773l13.13867,-15.22266l10.44141,15.22266h10.01367l-14.87695,-21.6875l14.08008,-16.3125h-3.17578l-12.31055,14.26172l-9.7832,-14.26172z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 664 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="50px" height="50px"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.12,5.12)"><path d="M25,2c-12.682,0 -23,10.318 -23,23c0,3.96 1.023,7.854 2.963,11.29l-2.926,10.44c-0.096,0.343 -0.003,0.711 0.245,0.966c0.191,0.197 0.451,0.304 0.718,0.304c0.08,0 0.161,-0.01 0.24,-0.029l10.896,-2.699c3.327,1.786 7.074,2.728 10.864,2.728c12.682,0 23,-10.318 23,-23c0,-12.682 -10.318,-23 -23,-23zM36.57,33.116c-0.492,1.362 -2.852,2.605 -3.986,2.772c-1.018,0.149 -2.306,0.213 -3.72,-0.231c-0.857,-0.27 -1.957,-0.628 -3.366,-1.229c-5.923,-2.526 -9.791,-8.415 -10.087,-8.804c-0.295,-0.389 -2.411,-3.161 -2.411,-6.03c0,-2.869 1.525,-4.28 2.067,-4.864c0.542,-0.584 1.181,-0.73 1.575,-0.73c0.394,0 0.787,0.005 1.132,0.021c0.363,0.018 0.85,-0.137 1.329,1.001c0.492,1.168 1.673,4.037 1.819,4.33c0.148,0.292 0.246,0.633 0.05,1.022c-0.196,0.389 -0.294,0.632 -0.59,0.973c-0.296,0.341 -0.62,0.76 -0.886,1.022c-0.296,0.291 -0.603,0.606 -0.259,1.19c0.344,0.584 1.529,2.493 3.285,4.039c2.255,1.986 4.158,2.602 4.748,2.894c0.59,0.292 0.935,0.243 1.279,-0.146c0.344,-0.39 1.476,-1.703 1.869,-2.286c0.393,-0.583 0.787,-0.487 1.329,-0.292c0.542,0.194 3.445,1.604 4.035,1.896c0.59,0.292 0.984,0.438 1.132,0.681c0.148,0.242 0.148,1.41 -0.344,2.771z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0,0,256,256" width="50px" height="50px"><g fill="#ffffff" fill-rule="evenodd" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><g transform="scale(5.12,5.12)"><path d="M13,5l3,9v6h2v-6l3,-9h-2l-2,6l-2,-6zM24,9c-1.06641,0 -1.58984,0.16797 -2.24219,0.70313c-0.625,0.52734 -0.79687,0.93359 -0.75781,2.29688v5c0,0.99609 0.16406,1.65234 0.76563,2.23438c0.625,0.58203 1.21484,0.76563 2.23438,0.76563c1.06641,0 1.64844,-0.18359 2.25,-0.76562c0.625,-0.55859 0.75,-1.23828 0.75,-2.23437v-5c0,-0.88281 -0.15625,-1.71875 -0.76172,-2.27734c-0.625,-0.57422 -1.26953,-0.72266 -2.23828,-0.72266zM29,9v9c0,0.97266 0.98047,2 2,2c1.01953,0 1.55859,-0.51172 2,-1v1h2v-11h-2v8c-0.01172,0.68359 -0.81641,1 -1,1c-0.20703,0 -1,-0.04297 -1,-1v-8zM24,11c0.30078,0 1,-0.00391 1,1v5c0,0.96875 -0.67578,1 -1,1c-0.30078,0 -1,-0.01172 -1,-1v-5c0,-0.81641 0.43359,-1 1,-1zM10,22c-3.59375,0 -6,2.38281 -6,6v9.5c0,3.61719 2.40625,6.5 6,6.5h30c3.59375,0 6,-2.38281 6,-6v-10c0,-3.61719 -2.40625,-6 -6,-6zM12,26h6v2h-2v12h-2v-12h-2zM26,26h2v4c0.23047,-0.35937 0.57422,-0.64453 0.90234,-0.80469c0.32031,-0.16406 0.64453,-0.25781 0.97266,-0.25781c0.64844,0 1.15625,0.23438 1.50391,0.67188c0.34766,0.44141 0.62109,1.02734 0.62109,1.89063v6c0,0.74219 -0.25,1.20313 -0.57812,1.59766c-0.32031,0.39453 -0.80078,0.89453 -1.42187,0.90234c-1.05078,0.01172 -1.61328,-0.55078 -2,-1v1h-2zM18,29h2v8c0,0.23047 0.26953,1.00781 1,1c0.8125,-0.00781 0.82031,-0.76562 1,-1v-8h2v11h-2v-1c-0.37109,0.4375 -0.5625,0.57422 -0.98047,0.78125c-0.41406,0.23438 -0.83594,0.21875 -1.22656,0.21875c-0.48437,0 -1.03516,-0.4375 -1.29297,-0.76562c-0.23047,-0.30078 -0.5,-0.60937 -0.5,-1.23437zM36.19922,29c0.94922,0 1.61719,0.20313 2.12109,0.73438c0.51563,0.53125 0.67969,1.15234 0.67969,2.15234v3.11328h-4v1.54688c0,0.55859 0.07422,0.91406 0.21875,1.125c0.13672,0.23047 0.41406,0.33203 0.78125,0.32813c0.40625,-0.00391 0.66406,-0.08594 0.80078,-0.26953c0.14063,-0.16406 0.19922,-0.62891 0.19922,-1.23047v-0.5h2v0.59375c0,1.08984 -0.08594,1.90234 -0.625,2.43359c-0.50781,0.55859 -1.30078,0.81641 -2.33984,0.81641c-0.94922,0 -1.69141,-0.28125 -2.22266,-0.85937c-0.53125,-0.57812 -0.80859,-1.37109 -0.80859,-2.39062v-4.70703c0,-0.90625 0.31641,-1.57812 0.89844,-2.17578c0.46875,-0.48047 1.34766,-0.71094 2.29688,-0.71094zM29,30.5c-0.55078,0 -0.99219,0.49609 -1,1v6c0.00781,0.28906 0.44922,0.5 1,0.5c0.55078,0 1,-0.42578 1,-0.97656v-5.02344c0,-1 -0.44922,-1.5 -1,-1.5zM36,31c-0.55078,0 -0.99219,0.46484 -1,1v1h2v-1c0,-0.61328 -0.44922,-1 -1,-1z"></path></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 432 KiB |
@@ -0,0 +1,116 @@
|
||||
import { Button, InputCompOne, Stepper } from "..";
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:(value:{})=>any
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
loan_amount: "",
|
||||
payment_month: "",
|
||||
sales_agent: "",
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
payment_month: Yup.string()
|
||||
.required("Required"),
|
||||
loan_amount: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
sales_agent: Yup.string()
|
||||
});
|
||||
|
||||
export default function DashboardFormInit({handleNextStep}:Props) {
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:{}) => {
|
||||
handleNextStep(values)
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full flex justify-center">
|
||||
<Stepper step={0} />
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="mt-[3.25rem] flex flex-col gap-9">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="loan_amount"
|
||||
label="How Much Do You Want To Apply For?"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="350,000"
|
||||
value={props.values.loan_amount}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.loan_amount && props.touched.loan_amount) ? props.errors.loan_amount : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="payment_month"
|
||||
label="For How Many Months?"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={paymentMonth}
|
||||
selectValue={props.values.payment_month}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.payment_month && props.touched.payment_month) ? props.errors.payment_month : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="sales_agent"
|
||||
label="Direct sales agent ID ( Optional )"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
floatLabel='Enter agent ID'
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Agent ID"
|
||||
value={props.values.sales_agent}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.sales_agent && props.touched.sales_agent) ? props.errors.sales_agent : ''}
|
||||
/>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
|
||||
const paymentMonth: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "6", label: "6 Months" },
|
||||
{ value: "12", label: "12 Months" },
|
||||
{ value: "18", label: "18 Months" },
|
||||
{ value: "24", label: "24 Months" },
|
||||
]
|
||||
}
|
||||
@@ -1,58 +1,36 @@
|
||||
import { DefaultCard } from "../"
|
||||
import React, { FC } from "react";
|
||||
import DashboardHomeIntro from "./DashboardHomeIntro";
|
||||
import DashboardFormInit from "./DashboardFormInit";
|
||||
import DashboardHomeDetail from "./home/DashboardHomeDetail";
|
||||
import DashboardHomeEmploymentInfo from "./home/DashboardHomeEmploymentInfo";
|
||||
import DashboardHomeRefereeInfo from "./home/DashboardHomeRefereeInfo";
|
||||
import DashboardHomeAttestation from "./home/DashboardHomeAttestation";
|
||||
|
||||
interface DashboardHomeProps {}
|
||||
|
||||
const DashboardHome: FC<DashboardHomeProps> = () => {
|
||||
const [step, setStep] = React.useState(1);
|
||||
const [applicationDetails, setApplicationDetails] = React.useState({});
|
||||
|
||||
const handleNextStep = (values:{}={}) => {
|
||||
if (step < 7) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
setApplicationDetails((prev:{}) => ({...prev, ...values}))
|
||||
}
|
||||
|
||||
export default function DashboardHome() {
|
||||
return (
|
||||
<div className='w-full'>
|
||||
<div className='group w-full xxs:w-96 h-32'>
|
||||
<DefaultCard
|
||||
descText='You currently do not have any open application. Click on apply for a loan to get started.'
|
||||
iconName='arrow'
|
||||
iconColor='#FBB700'
|
||||
cardClass={`p-4 bg-[#FFFAFA] border border-[#EE4040]`}
|
||||
descTextClass='text-[#423131] leading-5'
|
||||
onClick={()=>{console.log('working')}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='w-full mt-20 flex gap-16 flex-wrap'>
|
||||
{/* cards display */}
|
||||
<div className='group h-40 w-full xxs:w-80'>
|
||||
<DefaultCard
|
||||
title='Apply for a loan'
|
||||
descText='You currently do not have any open application. Click on apply for a loan to get started.'
|
||||
iconName='greater-than'
|
||||
iconColor='#FFF'
|
||||
cardClass={`bg-[#5C2684] bg-[url('../../../src/assets/images/dashboard/card_bg.png')]`}
|
||||
titleClass='text-[#FFF]'
|
||||
descTextClass='text-[#EFEFEF] leading-5'
|
||||
onClick={()=>{console.log('working')}}
|
||||
/>
|
||||
</div>
|
||||
<div className='group h-40 w-full xxs:w-80'>
|
||||
<DefaultCard
|
||||
title='Loan history'
|
||||
descText='You currently do not have any open application. Click on apply for a loan to get started.'
|
||||
iconName='greater-than'
|
||||
iconColor='#FFF'
|
||||
cardClass={`bg-[#635D4D] bg-[url('../../../src/assets/images/dashboard/card_bg.png')]`}
|
||||
titleClass='text-[#FFF]'
|
||||
descTextClass='text-[#EFEFEF] leading-5'
|
||||
onClick={()=>{console.log('working')}}
|
||||
/>
|
||||
</div>
|
||||
<div className='group h-40 w-full xxs:w-80'>
|
||||
<DefaultCard
|
||||
title='How it works?'
|
||||
descText='Steps to follow to complete your loan application successfully.'
|
||||
iconName='greater-than'
|
||||
iconColor='#FFF'
|
||||
cardClass={`bg-[#635D4D] bg-[url('../../../src/assets/images/dashboard/card_bg.png')]`}
|
||||
titleClass='text-[#FFF]'
|
||||
descTextClass='text-[#EFEFEF] leading-5'
|
||||
onClick={()=>{console.log('working')}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
{step === 1 && <DashboardHomeIntro step={step} handleNextStep={handleNextStep} />}
|
||||
{step === 2 && <DashboardFormInit handleNextStep={handleNextStep} />}
|
||||
{step === 3 && <DashboardHomeDetail handleNextStep={handleNextStep} />}
|
||||
{step === 4 && <DashboardHomeEmploymentInfo handleNextStep={handleNextStep} />}
|
||||
{step === 5 && <DashboardHomeRefereeInfo handleNextStep={handleNextStep} />}
|
||||
{step === 6 && <DashboardHomeAttestation handleNextStep={handleNextStep} applicationDetails={applicationDetails} />}
|
||||
{step === 7 && <DashboardHomeIntro step={step} handleNextStep={handleNextStep} />}
|
||||
{/* <DashboardHomeAttestation handleNextStep={handleNextStep} applicationDetails={applicationDetails} /> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardHome;
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
import React, { FC } from "react";
|
||||
import NairaBag from "../../assets/images/dashboard/naira-bag.png";
|
||||
import { Button } from "../";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export interface DashBoardCardProps {
|
||||
title?: string;
|
||||
desc?: string;
|
||||
descSpan?: string;
|
||||
descSpanClass?: string;
|
||||
onClick?: any;
|
||||
cardClass?: string;
|
||||
titleClass?: string;
|
||||
descClass?: string;
|
||||
btnTitle?: string;
|
||||
btnTextClass?: string;
|
||||
image?: any;
|
||||
imgClass?: string;
|
||||
}
|
||||
|
||||
export const DashBoardCard: React.FC<DashBoardCardProps> = ({
|
||||
title,
|
||||
desc,
|
||||
onClick,
|
||||
cardClass,
|
||||
titleClass,
|
||||
descClass,
|
||||
descSpan,
|
||||
descSpanClass,
|
||||
btnTitle,
|
||||
btnTextClass,
|
||||
image,
|
||||
imgClass,
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={`h-full w-full rounded-lg p-5 shadow-lg hover:shadow-none bg-no-repeat bg-[90%] flex justify-between gap-4 items-center transition-all duration-300 ${
|
||||
cardClass && cardClass
|
||||
}`}
|
||||
// onClick={onClick}
|
||||
>
|
||||
<div className="w-3/4 flex flex-col gap-[2.3125rem]">
|
||||
{title && (
|
||||
<h1
|
||||
className={`mb-1 text-[#FFF] text-lg text-left font-bold ${
|
||||
titleClass && titleClass
|
||||
}`}
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
)}
|
||||
{desc && (
|
||||
<p className={`text-lg text-left ${descClass && descClass}`}>
|
||||
{desc}{" "}
|
||||
{descSpan && (
|
||||
<span className={`${descSpanClass && descSpanClass}`}>
|
||||
{descSpan}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{btnTitle && (
|
||||
<Button className={btnTextClass} text={btnTitle} onClick={onClick} />
|
||||
)}
|
||||
</div>
|
||||
{image && <img className={imgClass} src={image} alt="card-image" />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface DashboardHomeIntroProps {
|
||||
handleNextStep:(value:{})=>any
|
||||
step?:number|string
|
||||
}
|
||||
|
||||
const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step }) => {
|
||||
const { userDetails } = useSelector((state:any) => state?.userDetails); // CHECKS IF USER Details are avaliable
|
||||
return (
|
||||
<>
|
||||
{step == 1 ?
|
||||
<>
|
||||
<h1 className="font-bold my-5 text-2xl">Hello, {userDetails.firstname}</h1>
|
||||
<div className="group w-full lg:w-[27.8125rem] h-[12.75rem] mt-7 ">
|
||||
<DashBoardCard
|
||||
cardClass="bg-[#5C2684] relative"
|
||||
desc="Begin your application and get up to "
|
||||
descSpan="5 million naira loan."
|
||||
descClass="leading-[1.5625rem] text-lg text-white"
|
||||
descSpanClass="font-bold"
|
||||
btnTitle="Apply here"
|
||||
btnTextClass="w-[11.125rem] h-[2.8125rem] flex justify-center item-center btn-W text-[#FBB700]"
|
||||
image={NairaBag}
|
||||
imgClass="translate-y-4 -rotate-6"
|
||||
onClick={()=>handleNextStep({})}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<>
|
||||
<h1 className="font-bold my-5 text-2xl">Welcome Back, {userDetails.firstname}</h1>
|
||||
<div className="group w-full lg:w-[27.8125rem] h-[12.75rem] mt-7 ">
|
||||
<DashBoardCard
|
||||
cardClass="bg-[#5C2684] relative"
|
||||
desc="Your loan application has been reviewed and accepted, please confirm for disbursement."
|
||||
// descSpan="5 million naira loan."
|
||||
descClass="leading-[1.5625rem] text-lg text-white"
|
||||
// descSpanClass="font-bold"
|
||||
btnTitle="View and accept"
|
||||
btnTextClass="w-[11.125rem] h-[2.8125rem] flex justify-center item-center btn-W text-[#FBB700]"
|
||||
image={NairaBag}
|
||||
imgClass="translate-y-4 -rotate-6"
|
||||
// onClick={handleNextStep}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardHomeIntro;
|
||||
|
||||
// {/* <div className="group w-full lg:w-96 h-32">
|
||||
// <DefaultCard
|
||||
// descText="You currently do not have any open application. Click on apply for a loan to get started."
|
||||
// iconName="arrow"
|
||||
// iconColor="#FBB700"
|
||||
// cardClass={`p-4 bg-[#FFFAFA] border border-[#EE4040]`}
|
||||
// descTextClass="text-[#423131] leading-5"
|
||||
// onClick={() => {
|
||||
// console.log("working");
|
||||
// }}
|
||||
// />
|
||||
// </div> */}
|
||||
|
||||
// {/* <div className="w-full mt-20 flex gap-16 flex-wrap">
|
||||
// <div className="group h-40 w-full lg:w-80">
|
||||
// <DefaultCard
|
||||
// title="Apply for a loan"
|
||||
// descText="You currently do not have any open application. Click on apply for a loan to get started."
|
||||
// iconName="greater-than"
|
||||
// iconColor="#FFF"
|
||||
// cardClass={`bg-[#5C2684] bg-[url('../../../src/assets/images/dashboard/card_bg.png')]`}
|
||||
// titleClass="text-[#FFF]"
|
||||
// descTextClass="text-[#EFEFEF] leading-5"
|
||||
// onClick={() => {
|
||||
// console.log("working");
|
||||
// }}
|
||||
// />
|
||||
// </div>
|
||||
// <div className="group h-40 w-full lg:w-80">
|
||||
// <DefaultCard
|
||||
// title="Loan history"
|
||||
// descText="You currently do not have any open application. Click on apply for a loan to get started."
|
||||
// iconName="greater-than"
|
||||
// iconColor="#FFF"
|
||||
// cardClass={`bg-[#635D4D] bg-[url('../../../src/assets/images/dashboard/card_bg.png')]`}
|
||||
// titleClass="text-[#FFF]"
|
||||
// descTextClass="text-[#EFEFEF] leading-5"
|
||||
// onClick={() => {
|
||||
// console.log("working");
|
||||
// }}
|
||||
// />
|
||||
// </div>
|
||||
// <div className="group h-40 w-full lg:w-80">
|
||||
// <DefaultCard
|
||||
// title="How it works?"
|
||||
// descText="Steps to follow to complete your loan application successfully."
|
||||
// iconName="greater-than"
|
||||
// iconColor="#FFF"
|
||||
// cardClass={`bg-[#635D4D] bg-[url('../../../src/assets/images/dashboard/card_bg.png')]`}
|
||||
// titleClass="text-[#FFF]"
|
||||
// descTextClass="text-[#EFEFEF] leading-5"
|
||||
// onClick={() => {
|
||||
// console.log("working");
|
||||
// }}
|
||||
// />
|
||||
// </div>
|
||||
// </div> */}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { InputCompOne } from "..";
|
||||
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { RouteHandler } from "../../router/routes";
|
||||
|
||||
export default function DashboardProfile() {
|
||||
let navigate = useNavigate();
|
||||
const navigateToProfile = () => navigate(RouteHandler.dashboardHome);
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className='my-[2rem] flex items-center'>
|
||||
<button onClick={navigateToProfile} className='w-6 h-6 text-lg flex justify-center items-center rounded-full bg-gray-500'><</button>
|
||||
</div>
|
||||
<div className="max-w-[25.875rem] w-full p-4 rounded-xl flex flex-col gap-1 bg-[#FBB700]/30">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Full name"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="John James"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Phone number"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="07000000000"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Residential address"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Somewhere in lagos"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Select your state"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Lagos"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Email address"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="johndoe@gmail.com"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Date of birth"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="12/10/1994"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
import { applyForLoan } from '../../../core/apiRequest';
|
||||
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
// import { RouteHandler } from '../../../router/routes';
|
||||
|
||||
type Props = {
|
||||
handleNextStep:(value:{})=>any
|
||||
applicationDetails: {}
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
account: "",
|
||||
checked: false
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
account: Yup.string()
|
||||
.required("Required"),
|
||||
checked: Yup.bool() // use bool instead of boolean
|
||||
.oneOf([true], "You must accept the terms and conditions")
|
||||
});
|
||||
|
||||
export default function DashboardHomeAttestation({handleNextStep, applicationDetails}:Props) {
|
||||
// let navigate = useNavigate();
|
||||
// const navigateToProfile = () => navigate(RouteHandler.dashboardProfile);
|
||||
|
||||
//FUNCTION TO HANDLE LOAN APPLICATION
|
||||
const handleSubmit = (values:any) => {
|
||||
delete values.checked
|
||||
applyForLoan({...applicationDetails, disbursement: values}).then(res=>{
|
||||
console.log('APPLY FOR LOAN', res)
|
||||
handleNextStep({disbursement: values})
|
||||
console.log('ApplicationDetails', {...applicationDetails, disbursement: values})
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
// applyForLoan(payload).then(res=>{
|
||||
// console.log('APPLY FOR LOAN', res)
|
||||
// // handleNextStep({disbursement: values})
|
||||
// }).catch(err=>{
|
||||
// console.log(err)
|
||||
// })
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full flex justify-center">
|
||||
<Stepper step={4} />
|
||||
</div>
|
||||
<p className='my-10 text-red-500 text-lg md:text-2xl'>Applicant's Attestation and Debit Instruction</p>
|
||||
<p className='text-red-500 text-base'>NB: Must be your FCMB account number</p>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="flex flex-col gap-9">
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="account"
|
||||
floatLabel="Disbursement account number"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="0102547896"
|
||||
value={props.values.account}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.account && props.touched.account) ? props.errors.account : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className='max-w-[25.875rem]'>
|
||||
<div className='flex gap-4 items-start'>
|
||||
<input
|
||||
type='checkbox'
|
||||
name="checked"
|
||||
className='w-4 h-4 p-2 accent-purple-600 text-purple-600 bg-gray-100 border-gray-300 rounded focus:ring-purple-500'
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
<p className='text-[12px] text-justify'>By pressing, you agree that you have read, understood and accept the <span className='text-blue-600'>applicatant's attestation</span> and <span className='text-blue-600'>terms and conditions</span> for FCMB
|
||||
premium salary loan. You also give us permission to collect financial information and run credit checks on the account provided through our partners
|
||||
</p>
|
||||
</div>
|
||||
{props.errors.checked && props.touched.checked && <span className='text-[10px] text-red-500'>{props.errors.checked}</span>}
|
||||
</div>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Apply"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// const payload = {
|
||||
// "loan_amount": "100000",
|
||||
// "payment_month": "18",
|
||||
// "sales_agent": "Testing1234",
|
||||
// "gender": "male",
|
||||
// "address": "World bank housing Estate, Umuahia",
|
||||
// "marital_status": "single",
|
||||
// "state": "abia",
|
||||
// "email": "test5070@gmail.com",
|
||||
// "country": "NG",
|
||||
// "employment": {
|
||||
// "job_title": "Information Officer",
|
||||
// "name": "Testing Testing",
|
||||
// "sector": "private (non academic)",
|
||||
// "industry": "engineering",
|
||||
// "resumption_date": "2024-04-05",
|
||||
// "email": "test50700@gmail.com",
|
||||
// "annual_income": "600000",
|
||||
// "monthly_salary": "50000",
|
||||
// "salary_payment_date": "2024-04-19",
|
||||
// "employment_id": "2555566",
|
||||
// "highest_eductaion": "b.sc + professional qualification"
|
||||
// },
|
||||
// "loan_reference": [
|
||||
// {
|
||||
// "fullname": "John Mike",
|
||||
// "relationship": "Brother",
|
||||
// "phone_number": "07055566611",
|
||||
// "email": "refone@gmail.com",
|
||||
// "bvn": "11111111111"
|
||||
// },
|
||||
// {
|
||||
// "fullname": "Mary Paul",
|
||||
// "relationship": "Brother",
|
||||
// "phone_number": "07055577711",
|
||||
// "email": "reftwo@gmail.com",
|
||||
// "bvn": "22222222222"
|
||||
// }
|
||||
// ],
|
||||
// disbursement:{account: '1122334456'}
|
||||
// }
|
||||
@@ -0,0 +1,190 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:(value:{})=>any
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
gender: "",
|
||||
address: "",
|
||||
marital_status: "",
|
||||
state: "",
|
||||
email:"",
|
||||
country:""
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
gender: Yup.string()
|
||||
.required("Required"),
|
||||
address: Yup.string()
|
||||
.required("Required"),
|
||||
marital_status: Yup.string()
|
||||
.required("Required"),
|
||||
state: Yup.string()
|
||||
.required("Required"),
|
||||
email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
country: Yup.string()
|
||||
.required("Required"),
|
||||
});
|
||||
|
||||
export default function DashboardHomeDetail({handleNextStep}:Props) {
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
handleNextStep(values)
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full flex justify-center">
|
||||
<Stepper step={1} />
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="mt-[3.25rem] flex flex-col gap-9">
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="gender"
|
||||
label="Select your gender"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={gender}
|
||||
selectValue={props.values.gender}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.gender && props.touched.gender) ? props.errors.gender : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="address"
|
||||
label="Residential address"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Somewhere in lagos"
|
||||
value={props.values.address}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.address && props.touched.address) ? props.errors.address : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="marital_status"
|
||||
label="Marital status"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={maritalStatus}
|
||||
selectValue={props.values.marital_status}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.marital_status && props.touched.marital_status) ? props.errors.marital_status : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="state"
|
||||
label="Select your state"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={state}
|
||||
selectValue={props.values.state}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.state && props.touched.state) ? props.errors.state : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="email"
|
||||
label="Email address"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="johndoe@gmail.com"
|
||||
value={props.values.email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.email && props.touched.email) ? props.errors.email : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="country"
|
||||
label="Select your country"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={country}
|
||||
selectValue={props.values.country}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.country && props.touched.country) ? props.errors.country : ''}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
|
||||
const gender: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "male", label: "Male" },
|
||||
{ value: "female", label: "Female" },
|
||||
{ value: "others", label: "Prefer not to say" },
|
||||
]
|
||||
}
|
||||
|
||||
const maritalStatus: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "single", label: "Single" },
|
||||
{ value: "married", label: "Married" },
|
||||
{ value: "divorced", label: "Divorced" },
|
||||
]
|
||||
}
|
||||
|
||||
const state: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "abia", label: "Abia" },
|
||||
{ value: "imo", label: "Imo" },
|
||||
{ value: "lagos", label: "Lagos" },
|
||||
]
|
||||
}
|
||||
|
||||
const country: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "NG", label: "Nigeria" },
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:(value:{})=>any
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
job_title: "",
|
||||
name: "",
|
||||
sector: "",
|
||||
industry: "",
|
||||
resumption_date: "",
|
||||
email:"",
|
||||
annual_income: "",
|
||||
monthly_salary: "",
|
||||
salary_payment_date: "",
|
||||
employment_id: "",
|
||||
highest_eductaion: ""
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
job_title: Yup.string()
|
||||
.required("Required"),
|
||||
name: Yup.string()
|
||||
.required("Required"),
|
||||
sector: Yup.string()
|
||||
.required("Required"),
|
||||
industry: Yup.string()
|
||||
.required("Required"),
|
||||
resumption_date: Yup.string()
|
||||
.required("Required"),
|
||||
email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
annual_income: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
monthly_salary: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
salary_payment_date: Yup.string()
|
||||
.required("Required"),
|
||||
employment_id: Yup.string()
|
||||
.required("Required"),
|
||||
highest_eductaion: Yup.string()
|
||||
.required("Required"),
|
||||
});
|
||||
|
||||
export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
|
||||
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
handleNextStep({employment: values})
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full flex justify-center">
|
||||
<Stepper step={2} />
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="mt-[3.25rem] flex flex-col gap-9">
|
||||
<p className='text-red-500 text-lg md:text-2xl'>Employment Informaton</p>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="job_title"
|
||||
floatLabel="Job Title"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Software Engineer"
|
||||
value={props.values.job_title}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.job_title && props.touched.job_title) ? props.errors.job_title : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="name"
|
||||
floatLabel="Employer name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Mr. Mark John"
|
||||
value={props.values.name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.name && props.touched.name) ? props.errors.name : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="sector"
|
||||
floatLabel="Job Sector"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={jobSector}
|
||||
selectValue={props.values.sector}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.sector && props.touched.sector) ? props.errors.sector : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="industry"
|
||||
floatLabel="Select your industry"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={industry}
|
||||
selectValue={props.values.industry}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.industry && props.touched.industry) ? props.errors.industry : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="resumption_date"
|
||||
floatLabel="Date of resumption"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="12/12/2015"
|
||||
value={props.values.resumption_date}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.resumption_date && props.touched.resumption_date) ? props.errors.resumption_date : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="email"
|
||||
floatLabel="Employers official email"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="example@gmail.com"
|
||||
value={props.values.email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.email && props.touched.email) ? props.errors.email : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="annual_income"
|
||||
floatLabel="Annual Income"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="1,200,000"
|
||||
value={props.values.annual_income}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.annual_income && props.touched.annual_income) ? props.errors.annual_income : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="monthly_salary"
|
||||
floatLabel="Net monthly salary"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="100,000"
|
||||
value={props.values.monthly_salary}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.monthly_salary && props.touched.monthly_salary) ? props.errors.monthly_salary : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="salary_payment_date"
|
||||
floatLabel="Salary payment date"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="30th of every month"
|
||||
value={props.values.salary_payment_date}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.salary_payment_date && props.touched.salary_payment_date) ? props.errors.salary_payment_date : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="employment_id"
|
||||
floatLabel="Employee ID"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="LS/001/005"
|
||||
value={props.values.employment_id}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employment_id && props.touched.employment_id) ? props.errors.employment_id : ''}
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="highest_eductaion"
|
||||
floatLabel="Highest level of education"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={highestEductaion}
|
||||
selectValue={props.values.highest_eductaion}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.highest_eductaion && props.touched.highest_eductaion) ? props.errors.highest_eductaion : ''}
|
||||
/>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
|
||||
const jobSector: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "private (non academic)", label: "Private (non academic)" },
|
||||
]
|
||||
}
|
||||
|
||||
const industry: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "engineering", label: "Engineering" },
|
||||
]
|
||||
}
|
||||
|
||||
const highestEductaion: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "b.sc + professional qualification", label: "B.Sc + Professional Qualification" },
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:(value:{})=>any
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
ref_name: "",
|
||||
ref_email: "",
|
||||
ref_phone_number: "",
|
||||
ref_relationship: "",
|
||||
ref_bvn: "",
|
||||
ref_two_name: "",
|
||||
ref_two_email: "",
|
||||
ref_two_phone_number: "",
|
||||
ref_two_relationship: "",
|
||||
ref_two_bvn: "",
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
ref_name: Yup.string()
|
||||
.required("Required"),
|
||||
ref_email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
ref_phone_number: Yup.string()
|
||||
.required("Required"),
|
||||
ref_relationship: Yup.string()
|
||||
.required("Required"),
|
||||
ref_bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits"),
|
||||
ref_two_name: Yup.string()
|
||||
.required("Required"),
|
||||
ref_two_email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
ref_two_phone_number: Yup.string()
|
||||
.required("Required"),
|
||||
ref_two_relationship: Yup.string()
|
||||
.required("Required"),
|
||||
ref_two_bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits"),
|
||||
});
|
||||
|
||||
export default function DashboardHomeRefereeInfo({handleNextStep}:Props) {
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
let refOne = {
|
||||
fullname: values.ref_name,
|
||||
relationship: values.ref_relationship,
|
||||
phone_number: values.ref_phone_number,
|
||||
email: values.ref_email,
|
||||
bvn: values.ref_bvn
|
||||
}
|
||||
let refTwo = {
|
||||
fullname: values.ref_two_name,
|
||||
relationship: values.ref_two_relationship,
|
||||
phone_number: values.ref_two_phone_number,
|
||||
email: values.ref_two_email,
|
||||
bvn: values.ref_two_bvn
|
||||
}
|
||||
handleNextStep({loan_reference:[refOne, refTwo]})
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full flex justify-center">
|
||||
<Stepper step={3} />
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="mt-[3.25rem] flex flex-col gap-9">
|
||||
<p className='text-red-500 text-lg md:text-2xl'>Reference Details <span className='text-base'>(Must be 18 years and above)</span></p>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<div className='w-full max-w-[25.875rem]'>
|
||||
<p className='text-red-500 text-base'>Reference one</p>
|
||||
<div className='w-full flex flex-col gap-9'>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_name"
|
||||
floatLabel="Full name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="John James"
|
||||
value={props.values.ref_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_name && props.touched.ref_name) ? props.errors.ref_name : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_relationship"
|
||||
floatLabel="Relationship"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Sister"
|
||||
value={props.values.ref_relationship}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_relationship && props.touched.ref_relationship) ? props.errors.ref_relationship : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_phone_number"
|
||||
floatLabel="Phone number"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="07000000000"
|
||||
value={props.values.ref_phone_number}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_phone_number && props.touched.ref_phone_number) ? props.errors.ref_phone_number : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_email"
|
||||
floatLabel="Email address"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="demo@gamil.com"
|
||||
value={props.values.ref_email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_email && props.touched.ref_email) ? props.errors.ref_email : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_bvn"
|
||||
floatLabel="BVN"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="2228457896"
|
||||
value={props.values.ref_bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_bvn && props.touched.ref_bvn) ? props.errors.ref_bvn : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='w-full max-w-[25.875rem]'>
|
||||
<p className='text-red-500 text-base'>Reference two</p>
|
||||
<div className='w-full flex flex-col gap-9'>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_two_name"
|
||||
floatLabel="Full name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="John James"
|
||||
value={props.values.ref_two_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_name && props.touched.ref_two_name) ? props.errors.ref_two_name : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_two_relationship"
|
||||
floatLabel="Relationship"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Sister"
|
||||
value={props.values.ref_two_relationship}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_relationship && props.touched.ref_two_relationship) ? props.errors.ref_two_relationship : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_two_phone_number"
|
||||
floatLabel="Phone number"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="07000000000"
|
||||
value={props.values.ref_two_phone_number}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_phone_number && props.touched.ref_two_phone_number) ? props.errors.ref_two_phone_number : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_two_email"
|
||||
floatLabel="Email address"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="demo@gamil.com"
|
||||
value={props.values.ref_two_email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_email && props.touched.ref_two_email) ? props.errors.ref_two_email : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="ref_two_bvn"
|
||||
floatLabel="BVN"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="2228457896"
|
||||
value={props.values.ref_two_bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_bvn && props.touched.ref_two_bvn) ? props.errors.ref_two_bvn : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import DashboardHome from './DashboardHome'
|
||||
import DashboardProfile from './DashboardProfile';
|
||||
|
||||
export { DashboardHome };
|
||||
export { DashboardHome, DashboardProfile };
|
||||
@@ -1,116 +0,0 @@
|
||||
import {useState} from 'react'
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
import { Icons } from "../index";
|
||||
|
||||
type Props = {
|
||||
asideDisplay?: () => void
|
||||
}
|
||||
|
||||
export default function Aside({asideDisplay}:Props) {
|
||||
|
||||
const {pathname} = useLocation()
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const [openNestedLink, setOpenNestedLink] = useState<{name:string|null}>({name: ''})
|
||||
|
||||
const handleOpenNestedLink = (e:any) => {
|
||||
if(!e || !e.target){
|
||||
return setOpenNestedLink({name: ''})
|
||||
}
|
||||
if(openNestedLink.name && openNestedLink.name == e.target.name){
|
||||
setOpenNestedLink({name: ''})
|
||||
}else{
|
||||
setOpenNestedLink({name: e.target.name})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="py-5 px-10 flex flex-col h-full bg-inherit">
|
||||
<div className="flex justify-center items-center text-sm">
|
||||
<p className="w-14 h-14 rounded-full bg-[#5C2684]/50 flex items-center justify-center">
|
||||
AC
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-10 h-full overflow-y-auto bg-inherit">
|
||||
{asideLinks.map((link, index) => {
|
||||
if(link.nestedLink?.length){
|
||||
let allNestedLinks = link.nestedLink.map(item => item.link)
|
||||
return (
|
||||
<div key={index} className='w-full relative bg-inherit overflow-hidden'>
|
||||
<button
|
||||
name={link.name}
|
||||
onClick={(e)=>handleOpenNestedLink(e)}
|
||||
className={`py-2 pl-2 text-left relative w-full overflow-hidden rounded-lg border-2 flex justify-between items-center z-10 bg-inherit ${allNestedLinks.includes(pathname) ? 'border-[#5C2684] text-[#5C2684]' : 'border-transparent text-[#585858]'}`}
|
||||
>
|
||||
{link.name}
|
||||
<div className={`mr-2 ${openNestedLink.name == link.name ? '-rotate-90' : 'rotate-90'} transition-all duration-300`}>
|
||||
<Icons
|
||||
name='greater-than'
|
||||
fillColor={`${openNestedLink.name == link.name ? '#5C2684' : '#585858'}`}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
<div className={`transition-all duration-300 w-full z-1 ${openNestedLink.name == link.name ? 'relative top-0' : 'absolute -top-[500px]'}`}>
|
||||
{link.nestedLink.map((nextLink, index) => (
|
||||
<Link
|
||||
onClick={()=>{asideDisplay && asideDisplay()}}
|
||||
key={index}
|
||||
to={nextLink.link ? nextLink.link : '#'}
|
||||
className={`w-full my-1 flex items-center gap-2 py-2 pl-5 text-base font-medium border-l-2 ${pathname == nextLink.link ? 'border-[#5C2684] text-[#5C2684]' : 'border-transparent text-[#585858]'}`}
|
||||
>
|
||||
<Icons name={nextLink.icon} fillColor={`${pathname == nextLink.link ? '#5C2684' : '#585858'}`} />
|
||||
{nextLink.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}else{
|
||||
return(
|
||||
<Link
|
||||
onClick={()=>{asideDisplay && asideDisplay()}}
|
||||
key={index}
|
||||
to={link.link ? link.link : '#'}
|
||||
className={`w-full my-4 flex items-center gap-2 py-2 pl-5 rounded-lg text-base font-medium border-2 ${pathname == link.link ? 'border-[#5C2684] text-[#5C2684]' : 'border-transparent text-[#585858]'}`}
|
||||
>
|
||||
<Icons name={link.icon} fillColor={`${pathname == link.link ? '#5C2684' : '#585858'}`} />
|
||||
{link.name}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<div className="w-full flex justify-center items-center">
|
||||
<button className="py-3 px-6 bg-red-100 text-red-500 font-medium rounded-md" onClick={()=>navigate('/login', {replace:true})}>
|
||||
Log out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
type AsideLinksType = {
|
||||
name: string,
|
||||
link?: string,
|
||||
icon: string,
|
||||
nestedLink:{
|
||||
name: string,
|
||||
link: string,
|
||||
icon: string,
|
||||
}[]
|
||||
}[]
|
||||
const asideLinks:AsideLinksType = [
|
||||
{name: 'Home', link: '/dashboard/home', icon: 'home', nestedLink:[]},
|
||||
{name: 'My Profile', link: '/dashboard/profile', icon: 'profile', nestedLink:[]},
|
||||
{name: 'Verification', link: '/dashboard/verification', icon: 'verification', nestedLink:[]},
|
||||
{name: 'Payments', link: '/dashboard/payments', icon: 'payments', nestedLink:[]},
|
||||
{name: 'Legals', link: '/dashboard/legals', icon: 'legals', nestedLink:[]},
|
||||
{name: 'Nested Link', icon: 'home', nestedLink:[
|
||||
{name: 'Link 2', link: '/dashboard/not-found', icon: 'legals'},
|
||||
{name: 'Link 1', link: '/dashboard/not-found', icon: 'home'}
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -1,10 +0,0 @@
|
||||
import DashboardLayout from "./DashboardLayout";
|
||||
import { Outlet } from "react-router-dom";
|
||||
|
||||
export default function DashboardAuth() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<Outlet />
|
||||
</DashboardLayout>
|
||||
)
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
import { ReactNode, useState, useEffect } from 'react'
|
||||
|
||||
import Aside from './Aside'
|
||||
|
||||
export default function DashboardLayout({children}:{children: ReactNode}) {
|
||||
|
||||
const [showAside, setShowAside] = useState<boolean>(false)
|
||||
|
||||
const asideDisplay = ():void => {
|
||||
setShowAside(prev => !prev)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
return setShowAside(false)
|
||||
// setWidthSize(window.innerWidth)
|
||||
}
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
// return () => {
|
||||
// window.removeEventListener('resize', screenResized)
|
||||
// }
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<div className='w-full max-w-[2000px] mx-auto h-screen flex bg-[#020202] text-black'>
|
||||
<aside className='w-[300px] bg-white hidden md:block border-r-2 border-[#E6E6E6]'>
|
||||
<Aside />
|
||||
</aside>
|
||||
|
||||
<aside className={`w-[300px] md:hidden bg-white border-r-2 border-[#E6E6E6] fixed top-0 bottom-0 z-50 transition-all duration-500 ${showAside ? 'left-0' : '-left-[200%]'}`}>
|
||||
<Aside asideDisplay={asideDisplay}/>
|
||||
</aside>
|
||||
|
||||
<main className={`dash-bg-image bg-[#F9F9F9] relative w-full overflow-y-auto overflow-x-hidden`}>
|
||||
<header className={`p-5 sticky z-10 top-0 w-full bg-[#F9F9F9] border-b-2 border-[#E6E6E6] bg-[url('../../../src/assets/images/dashboard/bg_ellipse1.png')] bg-no-repeat bg-[top_right]`}>
|
||||
<div className='h-14 w-full flex justify-end items-center gap-5'>
|
||||
{/* <div className=''>
|
||||
<button className='px-4 py-2 rounded-lg shadow-lg bg-white/50'>DarkMode</button>
|
||||
</div> */}
|
||||
{/* MENU HAND BURGER */}
|
||||
<div className='w-full'>Welcome Austin Catherine</div>
|
||||
<div
|
||||
className="relative md:hidden w-5 h-[20px] flex flex-col items-center justify-between"
|
||||
onClick={asideDisplay}
|
||||
>
|
||||
<div
|
||||
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
|
||||
showAside ? "top-1/2 -translate-y-1/2 rotate-45" : "top-0"
|
||||
}`}
|
||||
></div>
|
||||
<div
|
||||
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-300 ${
|
||||
showAside
|
||||
? "top-1/2 -translate-y-1/2 rotate-[2000deg] opacity-0"
|
||||
: "top-1/2 -translate-y-1/2"
|
||||
}`}
|
||||
></div>
|
||||
<div
|
||||
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
|
||||
showAside
|
||||
? "top-1/2 -translate-y-1/2 -rotate-45"
|
||||
: "bottom-0"
|
||||
}`}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className='flex p-5 relative'>
|
||||
<div className='w-full p-5'>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{/* <div className={`pl-5 w-[300px] min-w-[300px] hidden lg:block`}>
|
||||
<div className='sticky top-16'>
|
||||
<div className='w-full min-h-72 bg-white/50 shadow-lg rounded-lg p-5'>
|
||||
<p className='text-base font-semibold tracking-wide pb-2' title='Answered question is marked green'>Answered Question</p>
|
||||
<div className='grid grid-cols-8 gap-2'>
|
||||
{Array.from({length: 50}, (_, i) => i + 1).map((item, index) => (
|
||||
<span key={index} className={`w-6 h-6 text-sm rounded-full flex justify-center items-center shadow-lg cursor-pointer ${index%2 == 0 ? 'bg-emerald-600' : ''}`}>{item}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { footerCustomerLinks, footerSocialLinks } from "../../utils/data";
|
||||
|
||||
interface FooterLinksProps {
|
||||
href: string;
|
||||
icon?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
const BottomFooterOne = () => {
|
||||
const date: number = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<footer className="pt-[1.25rem] pb-[1.875rem]">
|
||||
<div className="containerMode flex flex-col gap-2 w-full">
|
||||
<div className="flex flex-wrap flex-[100] justify-between w-full gap-2">
|
||||
<SocialIconButtons />
|
||||
<CustomerLinks />
|
||||
</div>
|
||||
<p className="text-[.8125rem] text-[#333] leading-[1.42857]">
|
||||
© <span>{date}</span> First City Monument Bank (Licensed by the
|
||||
Central Bank of Nigeria)
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default BottomFooterOne;
|
||||
|
||||
const SocialIconButtons = () => {
|
||||
const icons = footerSocialLinks.map(
|
||||
({ href, icon }: FooterLinksProps, idx: number) => (
|
||||
<li key={idx}>
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="bg-[#592B81] py-[.3125rem] px-[.625rem] text-white w-[2.625rem] h-[2.625rem] flex items-center justify-center rounded-[3.125rem]"
|
||||
>
|
||||
{icon && <img src={icon} alt="icon" />}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
|
||||
return <ul className="flex flex-[33.333] items-center gap-1">{icons}</ul>;
|
||||
};
|
||||
|
||||
const CustomerLinks = () => {
|
||||
const links = footerCustomerLinks.map(
|
||||
({ href, text }: FooterLinksProps, idx: number) => (
|
||||
<li key={idx} className="list-none">
|
||||
<a
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="py-[.75rem] text-[.8125rem] uppercase text-[#606161] flex items-center justify-center"
|
||||
>
|
||||
{text}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
return (
|
||||
<div className="flex-[66.667] flex items-center flex-nowrap md:flex-wrap gap-2">
|
||||
{links}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,22 +1,33 @@
|
||||
import { Link } from "react-router-dom";
|
||||
// import { Link } from "react-router-dom";
|
||||
import { socialsIcons } from "../../utils/data";
|
||||
|
||||
export default function Footer() {
|
||||
const date = new Date().getFullYear();
|
||||
|
||||
return (
|
||||
<div className="w-full h-[5.4375rem] bg-[F7F7F7] flex items-center">
|
||||
<div className="containerMode flex justify-between items-center flex-wrap gap-2">
|
||||
<div className="containerMode flex justify-center md:justify-between items-center flex-wrap gap-2">
|
||||
<p className="text-[.9375rem] tracking-[2%] font-semibold text-[#969696]">
|
||||
{date} @ First City Monument Bank Limited
|
||||
</p>
|
||||
<div className="footer-social-icons flex justify-end items-center gap-2">
|
||||
{socialsIcons.map((icon, index) => (
|
||||
<Link key={index} className="w-[1.875rem] h-[1.875rem]" to="#">
|
||||
<img src={icon.image} alt={icon.name} />
|
||||
</Link>
|
||||
))}
|
||||
{renderSocialLinks()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderSocialLinks(): JSX.Element {
|
||||
const link = socialsIcons.map(function (item, index) {
|
||||
let { name, image, link } = item;
|
||||
|
||||
return (
|
||||
<a href={link} key={index} className="w-[1.875rem] h-[1.875rem]">
|
||||
<img src={image} alt={name} />
|
||||
</a>
|
||||
);
|
||||
});
|
||||
|
||||
return <ul className="flex items-center gap-2">{link}</ul>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import styles from "./footer.module.css"
|
||||
|
||||
const MidFooter = () => {
|
||||
return (
|
||||
<div className={`h-[2.3125rem] text-[1.25rem] ${styles.lower_footer}`}>
|
||||
<div className="containerMode flex justify-end p-[.375rem] w-full text-white font-medium text-[.6875rem] md:text-[1.25rem]">
|
||||
<div className="flex gap-2 items-center justify-end px-2 text-[11px] md:text-[13px]">
|
||||
<p className="text-[20px] font-extralight">my bank and I</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MidFooter
|
||||
@@ -0,0 +1,35 @@
|
||||
import { footerItems } from "../../utils/data";
|
||||
import TopFooterOneMenu from "./TopFooterOneMenu";
|
||||
|
||||
export interface TopFooterOneMenuProps {
|
||||
category: string;
|
||||
subItems: {
|
||||
text: string;
|
||||
href?: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
const TopFooterOne = () => {
|
||||
const footerListItems: TopFooterOneMenuProps[] = footerItems;
|
||||
|
||||
return (
|
||||
<footer className="bg-[#f7f7f7] text-[#898B8B] border border-[#ececec] p-5">
|
||||
<div className="containerMode w-full flex flex-col gap-[1.875rem]">
|
||||
<h4 className="uppercase text-[1.3125rem] font-bold my-[.625rem] cursor-default">
|
||||
sitemap
|
||||
</h4>
|
||||
<div className="grid grid-cols-2 md:grid-cols-6 gap-2 md:gap-0">
|
||||
{footerListItems.map(({ category, subItems }, index) => (
|
||||
<TopFooterOneMenu
|
||||
key={`${category}-${index}`}
|
||||
category={category}
|
||||
subItems={subItems}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopFooterOne;
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { TopFooterOneMenuProps } from "./TopFooterOne";
|
||||
|
||||
|
||||
const TopFooterOneMenu: React.FC<TopFooterOneMenuProps> = ({
|
||||
category,
|
||||
subItems,
|
||||
}) => {
|
||||
return (
|
||||
<ul className="flex gap-2 flex-col">
|
||||
<li className="text-[.6875rem] font-bold text-[#5e2785] cursor-default">
|
||||
{category}
|
||||
</li>
|
||||
<ul className="flex flex-col gap-1">
|
||||
{subItems.map(({ href = "#", text }) => (
|
||||
<li
|
||||
key={text}
|
||||
className="text-[.6875rem] text-[#5e2785] hover:underline w-fit"
|
||||
>
|
||||
{href ? <Link to={href}>{text}</Link> : <span>{text}</span>}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopFooterOneMenu;
|
||||
@@ -0,0 +1,8 @@
|
||||
.lower_footer{
|
||||
background: url(../../assets/images/footer_back.jpg) no-repeat;
|
||||
background-size: cover;
|
||||
/* padding: 0.4rem 0; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
import Footer from "./Footer";
|
||||
import TopFooterOne from "./TopFooterOne";
|
||||
import MidFooter from "./MidFooter";
|
||||
import BottomFooterOne from "./BottomFooterOne";
|
||||
|
||||
export { Footer };
|
||||
export { Footer, TopFooterOne, MidFooter, BottomFooterOne };
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from "react";
|
||||
import DebitAccount from "./DebitAccount";
|
||||
|
||||
|
||||
const ApplicantsAttestation: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-between items-center w-full mt-8 mb-[45px]">
|
||||
<h1 className="font-semibold text-[2.375rem] text-[#5C2684] my-[.5rem] max-w-[34rem]">
|
||||
Applicant’s Attestation and Debit Instruction
|
||||
</h1>
|
||||
<div className="flex flex-col gap-[.4375rem]">
|
||||
<p className="font-extrabold tracking-[3%] text-[#FBB700] underline">
|
||||
For more enquiries and support
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Call: 09099000000
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Email: fcmbloan@support.com
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<DebitAccount />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApplicantsAttestation;
|
||||
@@ -0,0 +1,89 @@
|
||||
import React from "react";
|
||||
import * as Yup from "yup";
|
||||
import { Form, Formik } from "formik";
|
||||
import { InputCompOne } from "../shared";
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits")
|
||||
});
|
||||
|
||||
// initial values for formik
|
||||
let initialValues = {
|
||||
bvn: ''
|
||||
};
|
||||
|
||||
type Props = {
|
||||
handleNextStep:()=>any
|
||||
}
|
||||
|
||||
const BVN = ({handleNextStep}:Props) => {
|
||||
|
||||
const firstInputRef = React.useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log('values', values)
|
||||
handleNextStep()
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props:any) => (
|
||||
<Form className="">
|
||||
<div className="w-full">
|
||||
<div className="containerMode flex justify-between gap-1 xl:gap-8 flex-col">
|
||||
<div className="my-[4rem] flex items-center justify-center w-full">
|
||||
<h1 className="font-bold text-[2.375rem] text-[#5C2684] my-[.5rem] text-center">
|
||||
Let’s Get You Started
|
||||
</h1>
|
||||
</div>
|
||||
<div className="mx-auto flex flex-col gap-8 max-w-[31.625rem]">
|
||||
<InputCompOne
|
||||
parentClass="flex flex-col gap-2"
|
||||
label="Enter Your BVN "
|
||||
name="bvn"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( To get your BVN, dial *565*0# )"
|
||||
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
|
||||
placeholder="Enter your BVN"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
|
||||
value={props.values.bvn}
|
||||
onChange={props.handleChange}
|
||||
ref={firstInputRef}
|
||||
maxLength={11}
|
||||
error={(props.errors.bvn && props.touched.bvn) && props.errors.bvn}
|
||||
/>
|
||||
<button
|
||||
type='submit'
|
||||
className="w-full h-[3.625rem] rounded bg-[#FBB700] rounded-2 px-4 text-[18px] text-[#282828] font-semibold disabled:text-[#282828] disabled:text-opacity-50"
|
||||
>
|
||||
Enter
|
||||
</button>
|
||||
<p className="text-[#5C2684] mt-[1.5625rem] max-w-[31.625rem]">
|
||||
***Every personal information attached to your BVN is safe and secured. It is only inportant for us to verify your information and also give you access to your application profile/account
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
};
|
||||
|
||||
export default BVN;
|
||||
@@ -0,0 +1,311 @@
|
||||
import React from "react";
|
||||
|
||||
import { Button, InputCompOne } from "..";
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
const initialValues = {
|
||||
title: "",
|
||||
marital_status: "",
|
||||
agent_id: "",
|
||||
bvn: "",
|
||||
first_name: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
surname: "",
|
||||
dob: "",
|
||||
second_name: "",
|
||||
spouse_bvn: "",
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
title: Yup.string()
|
||||
.required("Required"),
|
||||
marital_status: Yup.string()
|
||||
.required("Required"),
|
||||
agent_id: Yup.string()
|
||||
.required("Required"),
|
||||
bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits"),
|
||||
first_name: Yup.string()
|
||||
.required("Required"),
|
||||
phone: Yup.string()
|
||||
.required("Required"),
|
||||
email: Yup.string()
|
||||
.required("Required")
|
||||
.email("Wrong email format"),
|
||||
surname: Yup.string()
|
||||
.required("Required"),
|
||||
dob: Yup.string()
|
||||
.required("Required"),
|
||||
});
|
||||
|
||||
interface BasicInfoProps {
|
||||
handleNextStep: any;
|
||||
}
|
||||
|
||||
const BasicInfo: React.FC<BasicInfoProps> = ({
|
||||
handleNextStep,
|
||||
}) => {
|
||||
// const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// const handleInput = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
// const { name, value } = e.target as HTMLInputElement;
|
||||
|
||||
// if (name === "bvn") {
|
||||
// const isNumeric = /^[0-9]+$/.test(value);
|
||||
|
||||
// if (isNumeric) {
|
||||
// if (value.length === 10) {
|
||||
// setHideOTPComponent(false);
|
||||
// } else {
|
||||
// setHideOTPComponent(true);
|
||||
// }
|
||||
// } else {
|
||||
// console.log("Invalid BVN");
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log(values)
|
||||
handleNextStep()
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Header */}
|
||||
<h1 className="font-semibold text-[2.375rem] text-[#5C2684] my-[.5rem]">
|
||||
Let’s Get You Started
|
||||
</h1>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
BASIC INFORMATION
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-8 grid grid-cols-2">
|
||||
<div className="flex flex-col gap-4 max-w-[15.6875rem]">
|
||||
<InputCompOne
|
||||
parentInputClass="max-w-[224px] w-full"
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="title"
|
||||
label="Title"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
select={true}
|
||||
selectClass="w-full h-[36px] rounded-[6px]"
|
||||
selectOptions={titleOptions}
|
||||
selectValue={props.values.title}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.title && props.touched.title) ? props.errors.title : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentInputClass="max-w-[224px] w-full"
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="marital_status"
|
||||
label="Marital Status"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
select={true}
|
||||
selectClass="w-full h-[36px] rounded-[6px]"
|
||||
selectOptions={maritalStatusOptions}
|
||||
selectValue={props.values.marital_status}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.marital_status && props.touched.marital_status) ? props.errors.marital_status : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentInputClass="max-w-[224px] w-full"
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="agent_id"
|
||||
label="Direct Sales Agent ID"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
select={true}
|
||||
selectClass="w-full h-[36px] rounded-[6px]"
|
||||
selectOptions={{loading: false, data:[{ value: "", label: "Select" }, { value: "dd", label: "AB001" }]}}
|
||||
selectValue={props.values.agent_id}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.agent_id && props.touched.agent_id) ? props.errors.agent_id : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
label="BVN"
|
||||
name="bvn"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( To get your BVN, dial *565*0# )"
|
||||
labelSpanClass="text-[11px] text-[#7a7373]"
|
||||
placeholder="Enter your BVN"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#5C2684] mb-[2px] gap-[2px]"
|
||||
input={true}
|
||||
inputClass="w-full h-[36px] bg-[#EFEFEF] rounded-[6px]"
|
||||
value={props.values.bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.bvn && props.touched.bvn) ? props.errors.bvn : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="First Name"
|
||||
name="first_name"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.first_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.first_name && props.touched.first_name) ? props.errors.first_name : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Phone Number"
|
||||
name="phone"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.phone}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.phone && props.touched.phone) ? props.errors.phone : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Email Address"
|
||||
name="email"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.email && props.touched.email) ? props.errors.email : ''}
|
||||
/>
|
||||
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Surname"
|
||||
name="surname"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem] px-3"
|
||||
value={props.values.surname}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.surname && props.touched.surname) ? props.errors.surname : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Date of Birth"
|
||||
name="dob"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem] px-3"
|
||||
value={props.values.dob}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.dob && props.touched.dob) ? props.errors.dob : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Second Name"
|
||||
name="second_name"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem] px-3"
|
||||
value={props.values.second_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.second_name && props.touched.second_name) ? props.errors.second_name : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-full'>
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5 mt-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
SPOUSE DETAILS ( If not applicable, please move to the next stage )
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-8 grid grid-cols-2">
|
||||
<div className="flex flex-col gap-4 max-w-[15.6875rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="BVN"
|
||||
name="spouse_bvn"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( To get your BVN, dial *565*0# )"
|
||||
labelSpanClass="text-[11px] text-[#7a7373]"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.spouse_bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.spouse_bvn && props.touched.spouse_bvn) ? props.errors.spouse_bvn : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<>
|
||||
<Button
|
||||
className="mt-8 btn-R bg-[#5A2C82]"
|
||||
text="Enter"
|
||||
type="submit"
|
||||
/>
|
||||
</>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default BasicInfo;
|
||||
|
||||
|
||||
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
const maritalStatusOptions: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Select" },
|
||||
{ value: "single", label: "Single" },
|
||||
{ value: "married", label: "Married" },
|
||||
{ value: "divorced", label: "Divorced" },
|
||||
{ value: "widowed", label: "Widowed" },
|
||||
]
|
||||
}
|
||||
|
||||
const titleOptions: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Select" },
|
||||
{ value: "ms", label: "Ms" },
|
||||
{ value: "mr", label: "Mr" },
|
||||
{ value: "miss", label: "Miss" },
|
||||
{ value: "mrs", label: "Mrs" },
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
import { InputCompOne } from "..";
|
||||
|
||||
const CreditAccount: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
CREDIT ACCOUNT ( Your account to receive your loan )
|
||||
</p>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[29.4375rem] w-full my-5 ml-5"
|
||||
label="Disbursement Account Number "
|
||||
name="disbursementAccountNumber"
|
||||
labelSpan="( Your FCMB Account )"
|
||||
labelSpanClass="text-[12px] text-[#5C2684] ml-1"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreditAccount;
|
||||
@@ -0,0 +1,146 @@
|
||||
import React from "react";
|
||||
import {useNavigate} from 'react-router-dom'
|
||||
import { Button, InputCompOne } from "..";
|
||||
import { RouteHandler } from "../../router/routes";
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
const initialValues = {
|
||||
disburse_account: "",
|
||||
bank_name: "",
|
||||
account_name: "",
|
||||
account_number: "",
|
||||
checked: false
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
disburse_account: Yup.string()
|
||||
.required("Required"),
|
||||
bank_name: Yup.string()
|
||||
.required("Required"),
|
||||
account_name: Yup.string()
|
||||
.required("Required"),
|
||||
account_number: Yup.string()
|
||||
.required("Required"),
|
||||
checked: Yup.bool() // use bool instead of boolean
|
||||
.oneOf([true], "You must accept the terms and conditions")
|
||||
});
|
||||
|
||||
const DebitAccount: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log(values)
|
||||
navigate(RouteHandler.letsGetStarted, {replace:true})
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="w-full rounded py-3 mb-9 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
CREDIT ACCOUNT ( Your account to receive your loan )
|
||||
</p>
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[29.4375rem] w-full my-5 ml-5"
|
||||
label="Disbursement Account Number "
|
||||
name="disburse_account"
|
||||
labelSpan="( Your FCMB Account )"
|
||||
labelSpanClass="text-[12px] text-[#5C2684] ml-1"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[36px] bg-[#EFEFEF] rounded-[6px]"
|
||||
value={props.values.disburse_account}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.disburse_account && props.touched.disburse_account) ? props.errors.disburse_account : ''}
|
||||
/>
|
||||
|
||||
<div className="mt-9 flex flex-col gap-9">
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
DEBIT ACCOUNT ( Your salary account for monthly repayment )
|
||||
</p>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[471px] w-full ml-5"
|
||||
label="Bank Name"
|
||||
name="bank_name"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[36px] bg-[#EFEFEF] rounded-[6px]"
|
||||
value={props.values.bank_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.bank_name && props.touched.bank_name) ? props.errors.bank_name : ''}
|
||||
/>
|
||||
|
||||
<div className="flex items-center gap-[59px]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[471px] w-full ml-5"
|
||||
label="Account Number"
|
||||
name="account_number"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[36px] bg-[#EFEFEF] rounded-[6px]"
|
||||
value={props.values.account_number}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.account_number && props.touched.account_number) ? props.errors.account_number : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[471px] w-full ml-5"
|
||||
label="Account Name"
|
||||
name="account_name"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[36px] bg-[#EFEFEF] rounded-[6px]"
|
||||
value={props.values.account_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.account_name && props.touched.account_name) ? props.errors.account_name : ''}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="max-w-[578px] flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
// checked={true}
|
||||
|
||||
name='checked'
|
||||
onChange={props.handleChange}
|
||||
className="form-checkbox h-[25px] w-[25px] rounded-sm text-[#5c2684] "
|
||||
style={{ backgroundColor: "#5C2684" }}
|
||||
/>
|
||||
<label className="ml-2 text-gray-700">
|
||||
I have read, understood and accept the{" "}
|
||||
<span className="text-[#4545CB]">applicant's attestation</span> and
|
||||
all the <span className="text-[#4545CB]">terms and conditions</span>{" "}
|
||||
for FCMB premium salary loan.
|
||||
</label>
|
||||
{props.errors.checked && props.touched.checked && <span className='text-[10px] text-red-500'>{props.errors.checked}</span>}
|
||||
</div>
|
||||
<Button
|
||||
className="my-8 max-w-[33.875rem] btn-R bg-[#5A2C82] w-full h-11"
|
||||
text="Apply"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DebitAccount;
|
||||
@@ -1,17 +1,24 @@
|
||||
import { FC } from "react";
|
||||
import BasicInfo from "./BasicInfo";
|
||||
import YourAreAlmostThere from "./YourAreAlmostThere";
|
||||
import LoanAmountComp from "./LoanAmountComp";
|
||||
import ApplicantsAttestation from "./ApplicantsAttestation";
|
||||
|
||||
const GetStarted = ({handleNextStep, step}:{handleNextStep:any, step:string|number|any}) => {
|
||||
|
||||
const GetStarted: FC = () => {
|
||||
return (
|
||||
<div className="w-full flex items-center justify-center">
|
||||
<div className="containerMode">
|
||||
<h1 className="font-semibold text-[2.375rem] text-[#5C2684] my-[.5rem]">
|
||||
Let’s Get You Started
|
||||
</h1>
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
BASIC INFORMATION
|
||||
</p>
|
||||
</div>
|
||||
{/* Main */}
|
||||
<main>
|
||||
{step === 2 && (
|
||||
<BasicInfo
|
||||
handleNextStep={handleNextStep}
|
||||
/>
|
||||
)}
|
||||
{step === 3 && <YourAreAlmostThere handleNextStep={handleNextStep} />}
|
||||
{step === 4 && <LoanAmountComp handleNextStep={handleNextStep} />}
|
||||
{step === 5 && <ApplicantsAttestation />}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
import { Button, InputCompOne } from "..";
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
const initialValues = {
|
||||
monthly_salary: "",
|
||||
loan_amount: "",
|
||||
duration: 6
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
duration: Yup.number()
|
||||
.required("Required"),
|
||||
monthly_salary: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
loan_amount: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
});
|
||||
|
||||
// interface SliderProps {
|
||||
// handleSliderChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
// value: number;
|
||||
// }
|
||||
|
||||
interface LoanAmountProps {
|
||||
handleNextStep: any;
|
||||
}
|
||||
|
||||
const LoanAmountComp: React.FC<LoanAmountProps> = ({ handleNextStep }) => {
|
||||
// const [value, setValue] = React.useState(6);
|
||||
|
||||
// const handleSliderChange = (e: any) => {
|
||||
// setValue(e.target.value);
|
||||
// };
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log(values)
|
||||
handleNextStep()
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-between items-center w-full mt-8 mb-[2.8125rem]">
|
||||
<h1 className="font-semibold text-[38px] text-[#5C2684] my-[8px]">
|
||||
Loan Amount
|
||||
</h1>
|
||||
<div className="flex flex-col gap-[7px]">
|
||||
<p className="font-extrabold tracking-[3%] text-[#FBB700] underline">
|
||||
For more enquiries and support
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Call: 09099000000
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Email: fcmbloan@support.com
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="flex flex-col gap-[45px] justify-center ml-[40px] mb-[40px]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[29.4375rem] w-full"
|
||||
label="Your Monthly Salary*"
|
||||
name="monthly_salary"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[51px] bg-[#EFEFEF] rounded-[6px] placeholder:text-green-600 placeholder:font-bold px-4"
|
||||
placeholder="150,000"
|
||||
value={props.values.monthly_salary}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.monthly_salary && props.touched.monthly_salary) ? props.errors.monthly_salary : ''}
|
||||
/>
|
||||
|
||||
<div className="w-full border-[.1875rem] rounded-xl border-black min-h-[884px] py-4 px-8 max-w-[784px]">
|
||||
<p className="leading-[22px] tracking-[3%] text-[#5C2684] w-[729px] mb-[2.625rem]">
|
||||
The maximum amount you can apply for on this offer is based on the
|
||||
information you shared with us in your loan application. We have
|
||||
made this offer to suit your monthly remuneration and to enable you
|
||||
pay your loan on-time
|
||||
</p>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[45.8125rem] w-full mb-3"
|
||||
label="How much do you want to apply for?"
|
||||
name="loan_amount"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
|
||||
input
|
||||
inputClass="w-full h-[51px] bg-[#EFEFEF] rounded-[6px] placeholder:text-green-600 placeholder:font-bold px-9"
|
||||
placeholder="350,000"
|
||||
value={props.values.loan_amount}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.loan_amount && props.touched.loan_amount) ? props.errors.loan_amount : ''}
|
||||
/>
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<div className=" h-[68px] flex flex-col py-1 px-[13px] shadow-md text-[#5C2684]">
|
||||
<span>Minimum Offer:</span>
|
||||
<p>
|
||||
<b>N</b>100,000
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="h-[68px] flex flex-col py-1 px-[13px] shadow-md text-[#5C2684]">
|
||||
<span>Maximum Offer:</span>
|
||||
<p>
|
||||
<b>N</b>500,000
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<>
|
||||
<div className="flex flex-col items-start mt-11 mb-16">
|
||||
<p className="text-lg font-semibold">For how many months? <span className='text-[10px] text-red-500'>{(props.errors.duration && props.touched.duration) ? props.errors.duration : ''}</span></p>
|
||||
<div className="w-full">
|
||||
<input
|
||||
type="range"
|
||||
min="6"
|
||||
max="24"
|
||||
value={props.values.duration}
|
||||
onChange={props.handleChange}
|
||||
className="slider w-full h-2 bg-gray-300 rounded-lg appearance-none cursor-pointer"
|
||||
style={{
|
||||
background: `linear-gradient(90deg, #6B21A8 ${
|
||||
((props.values.duration - 6) / 18) * 100
|
||||
}%, #D1D5DB ${((props.values.duration - 6) / 18) * 100}%)`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-4 text-lg font-semibold text-gray-700 w-full flex items-center text-center justify-center">
|
||||
{props.values.duration} months
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<div className="w-full flex items-center justify-center flex-col">
|
||||
<div className="w-[279px] h-[130px] mb-[76px] flex items-center justify-center flex-col">
|
||||
<p className="text-[#FBB700]">Your Monthly Repayment</p>
|
||||
<p>N</p>
|
||||
</div>
|
||||
<Button
|
||||
className="max-w-[462px] w-full bg-[#5C2684] rounded h-[2.75rem]"
|
||||
text="Submit"
|
||||
type='submit'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoanAmountComp;
|
||||
|
||||
// const Slider: React.FC<SliderProps> = ({ handleSliderChange, value }) => {
|
||||
// return (
|
||||
// <div className="flex flex-col items-start mt-11 mb-16">
|
||||
// <p className="text-lg font-semibold">For how many months?</p>
|
||||
// <div className="w-full">
|
||||
// <input
|
||||
// type="range"
|
||||
// min="6"
|
||||
// max="24"
|
||||
// value={value}
|
||||
// onChange={handleSliderChange}
|
||||
// className="slider w-full h-2 bg-gray-300 rounded-lg appearance-none cursor-pointer"
|
||||
// style={{
|
||||
// background: `linear-gradient(90deg, #6B21A8 ${
|
||||
// ((value - 6) / 18) * 100
|
||||
// }%, #D1D5DB ${((value - 6) / 18) * 100}%)`,
|
||||
// }}
|
||||
// />
|
||||
// </div>
|
||||
// <div className="mt-4 text-lg font-semibold text-gray-700 w-full flex items-center text-center justify-center">
|
||||
// {value} months
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
@@ -0,0 +1,402 @@
|
||||
import React from "react";
|
||||
import { Button, InputCompOne } from "..";
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
const initialValues = {
|
||||
job_title: "",
|
||||
employer_name: "",
|
||||
employer_email:"",
|
||||
date_of_resumption: "",
|
||||
employee_id: "",
|
||||
annual_income: "",
|
||||
monthly_salary: "",
|
||||
salary_payment_date: "",
|
||||
ref_name: "",
|
||||
ref_email: "",
|
||||
ref_number: "",
|
||||
ref_relationship: "",
|
||||
ref_bvn: "",
|
||||
ref_two_name: "",
|
||||
ref_two_email: "",
|
||||
ref_two_number: "",
|
||||
ref_two_relationship: "",
|
||||
ref_two_bvn: "",
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
job_title: Yup.string()
|
||||
.required("Required"),
|
||||
employer_name: Yup.string()
|
||||
.required("Required"),
|
||||
date_of_resumption: Yup.string()
|
||||
.required("Required"),
|
||||
employer_email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
annual_income: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
monthly_salary: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
salary_payment_date: Yup.string()
|
||||
.required("Required"),
|
||||
employee_id: Yup.string()
|
||||
.required("Required"),
|
||||
ref_name: Yup.string()
|
||||
.required("Required"),
|
||||
ref_email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
ref_number: Yup.string()
|
||||
.required("Required"),
|
||||
ref_relationship: Yup.string()
|
||||
.required("Required"),
|
||||
ref_bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits"),
|
||||
ref_two_name: Yup.string()
|
||||
.required("Required"),
|
||||
ref_two_email: Yup.string()
|
||||
.email("Invalid")
|
||||
.required("Required"),
|
||||
ref_two_number: Yup.string()
|
||||
.required("Required"),
|
||||
ref_two_relationship: Yup.string()
|
||||
.required("Required"),
|
||||
ref_two_bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits"),
|
||||
});
|
||||
|
||||
interface YourAreAlmostThereProps {
|
||||
handleNextStep: any;
|
||||
}
|
||||
|
||||
const YourAreAlmostThere: React.FC<YourAreAlmostThereProps> = ({ handleNextStep }) => {
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log(values)
|
||||
handleNextStep()
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="font-semibold text-[2.375rem] text-[#5C2684] my-[.5rem]">
|
||||
You’re almost there
|
||||
</h1>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props)=>(
|
||||
<Form>
|
||||
<div className="flex flex-col gap-6">
|
||||
<>
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
EMPLOYMENT DETAILS
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[17.9375rem] w-full"
|
||||
label="Job Title"
|
||||
name="job_title"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.job_title}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.job_title && props.touched.job_title) ? props.errors.job_title : ''}
|
||||
/>
|
||||
<div className="flex items-center gap-[3.6875rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Employer’s Name"
|
||||
name="employer_name"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.employer_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employer_name && props.touched.employer_name) ? props.errors.employer_name : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Employer’s Official Email"
|
||||
name="employer_email"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.employer_email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employer_email && props.touched.employer_email) ? props.errors.employer_email : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[9rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[17.9375rem] w-full"
|
||||
label="Resumption Date"
|
||||
name="date_of_resumption"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.date_of_resumption}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.date_of_resumption && props.touched.date_of_resumption) ? props.errors.date_of_resumption : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[17.9375rem] w-full"
|
||||
label="Employee ID."
|
||||
name="employee_id"
|
||||
labelSpan="Upload your work ID"
|
||||
labelSpanClass="text-[11px] text-[#7a7373]"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.employee_id}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employee_id && props.touched.employee_id) ? props.errors.employee_id : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[3.6875rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Salary ( Gross annual income )"
|
||||
name="annual_income"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.annual_income}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.annual_income && props.touched.annual_income) ? props.errors.annual_income : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Salary ( Net monthly Income )"
|
||||
name="monthly_salary"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.monthly_salary}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.monthly_salary && props.touched.monthly_salary) ? props.errors.monthly_salary : ''}
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Salary Payment Date"
|
||||
name="salary_payment_date"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.salary_payment_date}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.salary_payment_date && props.touched.salary_payment_date) ? props.errors.salary_payment_date : ''}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<>
|
||||
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
|
||||
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
|
||||
REFERENCE DETAILS ( Must be 18 years and above )
|
||||
</p>
|
||||
</div>
|
||||
<div className="">
|
||||
<div className="flex flex-col gap-[3.4375rem]">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center gap-[6.5625rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Name"
|
||||
name="ref_name"
|
||||
labelSpan="1st reference"
|
||||
labelSpanClass="text-[12px] text-[#5C2684] ml-1"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] px-[.125rem] rounded-[.375rem]"
|
||||
value={props.values.ref_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_name && props.touched.ref_name) ? props.errors.ref_name : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Relationship with He/She"
|
||||
name="ref_relationship"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] px-[.125rem] rounded-[.375rem]"
|
||||
value={props.values.ref_relationship}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_relationship && props.touched.ref_relationship) ? props.errors.ref_relationship : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[6.5625rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Phone Number"
|
||||
name="ref_number"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_number}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_number && props.touched.ref_number) ? props.errors.ref_number : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Email Address"
|
||||
name="ref_email"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_email && props.touched.ref_email) ? props.errors.ref_email : ''}
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="BVN"
|
||||
name="ref_bvn"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_bvn && props.touched.ref_bvn) ? props.errors.ref_bvn : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center gap-[6.5625rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Name"
|
||||
name="ref_two_name"
|
||||
labelSpan="2nd reference"
|
||||
labelSpanClass="text-[12px] text-[#5C2684] ml-[4px]"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_two_name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_name && props.touched.ref_two_name) ? props.errors.ref_two_name : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Relationship with He/She"
|
||||
name="ref_two_relationship"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_two_relationship}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_relationship && props.touched.ref_two_relationship) ? props.errors.ref_two_relationship : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[6.5625rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Phone Number"
|
||||
name="ref_two_number"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_two_number}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_number && props.touched.ref_two_number) ? props.errors.ref_two_number : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Email Address"
|
||||
name="ref_two_email"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_two_email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_email && props.touched.ref_two_email) ? props.errors.ref_two_email : ''}
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="BVN"
|
||||
name="ref_two_bvn"
|
||||
parentInputClass="w-full"
|
||||
labelClass="font-bold text-[1.125rem] leading-[1.3613rem] tracking-[2%] text-[#5C2684] mb-[.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] rounded-[.375rem]"
|
||||
value={props.values.ref_two_bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.ref_two_bvn && props.touched.ref_two_bvn) ? props.errors.ref_two_bvn : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<Button
|
||||
className="my-8 max-w-[20.3125rem] btn-R bg-[#5A2C82]"
|
||||
text="Continue"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default YourAreAlmostThere;
|
||||
@@ -1,13 +1,16 @@
|
||||
import { useState, ChangeEvent, FC } from "react";
|
||||
import React, { useState, ChangeEvent } from "react";
|
||||
import Logo from "../../assets/icons/logo.svg";
|
||||
import Button from "../shared/Button";
|
||||
import { lowerMenuItems } from "../../utils/data";
|
||||
import { _lowerMenuItems } from "../../utils/data";
|
||||
import Sidebar from "./Sidebar";
|
||||
import { Link } from "react-router-dom";
|
||||
import HeaderMenuItem from "./HeaderMenuItem";
|
||||
import { RouteHandler } from "../../router/routes";
|
||||
|
||||
type LowerMenuItem = {
|
||||
id: string | number;
|
||||
export type LowerMenuItem = {
|
||||
name: string;
|
||||
linkPath: string;
|
||||
subItems?: LowerMenuItem[];
|
||||
};
|
||||
|
||||
type HiddenMenuItems = {
|
||||
@@ -15,7 +18,7 @@ type HiddenMenuItems = {
|
||||
hideMenu?: boolean;
|
||||
};
|
||||
|
||||
const Header: FC<HiddenMenuItems> = ({
|
||||
const Header: React.FC<HiddenMenuItems> = ({
|
||||
hideSidebar = false,
|
||||
hideMenu = false,
|
||||
}) => {
|
||||
@@ -31,7 +34,7 @@ const Header: FC<HiddenMenuItems> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative my-2 py-2 flex items-center justify-center border-b-2 border-[#E3DEDA]">
|
||||
<div className="relative mt-2 py-2 flex items-center justify-center border-b-2 border-[#E3DEDA]">
|
||||
{!hideSidebar && (
|
||||
<Sidebar toggleSidebar={toggleSidebar} isSidebarOpen={isSidebarOpen} />
|
||||
)}
|
||||
@@ -48,20 +51,25 @@ const Header: FC<HiddenMenuItems> = ({
|
||||
{!hideMenu && (
|
||||
<div className="flex flex-col-reverse lg:flex-col grow lg:grow-0 justify-between items-end">
|
||||
<ul className="flex gap-0 lg:gap-[10px] items-center justify-end w-full flex-wrap">
|
||||
{["Open An Account", "Internet Banking", "Contact Us"].map(
|
||||
(text: string) => (
|
||||
<li key={text} className="hidden sm:flex">
|
||||
<a href="#">
|
||||
<Button
|
||||
className={
|
||||
text === "Open An Account" ? "btn-active" : ""
|
||||
}
|
||||
text={text}
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
{[
|
||||
{ text: "Open An Account", href: RouteHandler.getStarted },
|
||||
{
|
||||
text: "Internet Banking",
|
||||
href: RouteHandler.businessBanking,
|
||||
},
|
||||
{ text: "Contact Us", href: RouteHandler.cooperateBanking },
|
||||
].map((item: { text: string; href: string }) => (
|
||||
<li key={item.text} className="hidden sm:flex">
|
||||
<a href={item.href}>
|
||||
<Button
|
||||
className={
|
||||
item.text === "Open An Account" ? "btn-active" : ""
|
||||
}
|
||||
text={item.text}
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
<li className="w-full lg:w-fit">
|
||||
<SearchInput
|
||||
onChange={handleSearchChange}
|
||||
@@ -69,6 +77,7 @@ const Header: FC<HiddenMenuItems> = ({
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="flex lg:hidden">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -88,14 +97,9 @@ const Header: FC<HiddenMenuItems> = ({
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<ul className="hidden lg:flex gap-[10px] items-center justify-end flex-wrap">
|
||||
{lowerMenuItems.map((item: LowerMenuItem) => (
|
||||
<li
|
||||
key={item.id}
|
||||
className="cursor-pointer text-[13.5px] font-medium text-[#525252] tracking-[1px] leading-[-0.3pt]"
|
||||
>
|
||||
{item.name}
|
||||
</li>
|
||||
<ul className="hidden lg:flex gap-[10px] items-center justify-end flex-wrap relative">
|
||||
{_lowerMenuItems.map((item: LowerMenuItem, idx: number) => (
|
||||
<HeaderMenuItem key={idx} item={item} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import React, { useState } from "react";
|
||||
import { LowerMenuItem } from "./Header";
|
||||
|
||||
interface MenuItemProps {
|
||||
item: LowerMenuItem;
|
||||
}
|
||||
|
||||
const HeaderMenuItem: React.FC<MenuItemProps> = ({ item }) => {
|
||||
const [showSubMenu, setShowSubMenu] = useState<boolean>(false);
|
||||
|
||||
const toggleSubMenu = () => {
|
||||
setShowSubMenu(!showSubMenu);
|
||||
};
|
||||
|
||||
return (
|
||||
<li
|
||||
className={`cursor-pointer text-[13.5px] font-medium text-[#525252] tracking-[1px] leading-[-0.3pt]`}
|
||||
onMouseEnter={toggleSubMenu}
|
||||
onMouseLeave={toggleSubMenu}
|
||||
>
|
||||
<a href={item.linkPath}>{item.name}</a>
|
||||
{showSubMenu && item.subItems && (
|
||||
<ul
|
||||
className={`absolute bg-white shadow-md p-4 z-20 `}
|
||||
>
|
||||
{item.subItems.map((subItem, index) => (
|
||||
<HeaderMenuItem key={index} item={subItem} />
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeaderMenuItem;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { top_header_data } from "../../utils/data";
|
||||
import { Link } from "react-router-dom";
|
||||
import styles from "./header.module.css";
|
||||
|
||||
const TopHeader = () => {
|
||||
@@ -7,28 +8,36 @@ const TopHeader = () => {
|
||||
<div className="flex flex-col sm:hidden bg-[#5c2684]">
|
||||
<ul className="flex flex-col justify-center items-center pt-[0.4rem] text-[13px] font-light">
|
||||
{["Open An Account", "Internet Banking", "Contact Us"].map((text) => (
|
||||
<li key={text} className="w-full">
|
||||
<a href="#" className={`p-2 cursor-pointer text-white w-full items-center justify-center flex`}>
|
||||
<li key={text} className="w-full">
|
||||
<a
|
||||
href="#"
|
||||
className={`p-2 cursor-pointer text-white w-full items-center justify-center flex`}
|
||||
>
|
||||
{text}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
<li className="w-full flex items-center justify-center">
|
||||
<a href="#" className={`p-2 mt-2 flex gap-2 bg-[#74449E] cursor-pointer text-white w-full items-center justify-center`}>
|
||||
<a
|
||||
href="#"
|
||||
className={`p-2 mt-2 flex gap-2 bg-[#74449E] cursor-pointer text-white w-full items-center justify-center`}
|
||||
>
|
||||
<p className="uppercase">Today's Share price:</p>
|
||||
<span className="text-[#F8B51F] text-base md:text-lg">$ 4.00</span>
|
||||
</a>
|
||||
</li>
|
||||
<span className="text-[#F8B51F] text-base md:text-lg">
|
||||
$ 4.00
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className={styles.top_header}>
|
||||
<div className="containerMode flex justify-between w-full text-white font-medium text-[11px] md:text-[13px]">
|
||||
<ul className="flex items-center py-[0.4rem] flex-wrap">
|
||||
{top_header_data.map(({ id, name }) => (
|
||||
{top_header_data.map(({ id, name, href }) => (
|
||||
<li key={id}>
|
||||
<a href="#" className={`py-[11px] px-[15px]`}>
|
||||
<Link to={href} className={`py-[11px] px-[15px]`}>
|
||||
{name}
|
||||
</a>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -2,10 +2,10 @@ import styles from "./hero.module.css";
|
||||
const Hero = () => {
|
||||
return (
|
||||
<div
|
||||
className={`w-full relative mt-[.9375rem] mb-0 sm:mb-[2.25rem] regLap:h-[30rem] xl:h-[26.875rem] lg:h-[25rem] md:h-[21.875rem] sm:h-[18.75rem] h-[15.625rem] object-cover ${styles.heroBg}`}
|
||||
className={`w-full relative mb-0 sm:mb-[2.25rem] regLap:h-[30rem] xl:h-[26.875rem] lg:h-[25rem] md:h-[21.875rem] sm:h-[18.75rem] h-[15.625rem] object-cover ${styles.heroBg}`}
|
||||
>
|
||||
<div className="containerMode flex justify-between gap-1 xl:gap-8">
|
||||
<h1 className="max-w-[32.9375rem] font-extrabold text-[1.3rem] leading-[2.5rem] sm:text-[3.625rem] sm:leading-[4.3869rem] text-[#5C2684]">
|
||||
<h1 className="max-w-[32.9375rem] font-extrabold text-[1.3rem] leading-[2.5rem] sm:text-[3.625rem] sm:leading-[4.3869rem] text-[#5C2684] cursor-default">
|
||||
PREMIUM SALARY LOAN
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import React from "react";
|
||||
import styles from "./hero.module.css";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
interface PersonalHeroProps {
|
||||
heading?: string;
|
||||
body?: string;
|
||||
buttonLink?: string;
|
||||
buttonText?: string;
|
||||
}
|
||||
const PersonalHero: React.FC<PersonalHeroProps> = ({
|
||||
heading,
|
||||
body,
|
||||
buttonLink = "#",
|
||||
buttonText,
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={`w-full max-[28.125rem] relative mb-0 sm:mb-[2.25rem] regLap:h-[30rem] xl:h-[26.875rem] lg:h-[25rem] md:h-[21.875rem] sm:h-[18.75rem] h-[15.625rem] object-cover ${styles.personalHeroBg}`}
|
||||
>
|
||||
<div className="containerMode flex justify-between gap-1 xl:gap-8 flex-col">
|
||||
<h1 className="max-w-[32.9375rem] font-extrabold text-[1.3rem] leading-[2.5rem] sm:text-[3.625rem] sm:leading-[4.3869rem] text-[#5C2684] cursor-default">
|
||||
{heading}
|
||||
</h1>
|
||||
<p className="p-[.3125rem] pr-5 font-medium table w-[25.375rem]">{body}</p>
|
||||
<Link to={buttonLink}>
|
||||
<button className="bg-[#A6368C] text-white text-[.9375rem] w-[10.9375rem] py-[.4375rem] px-[.625rem]">
|
||||
{buttonText}
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PersonalHero;
|
||||
@@ -6,4 +6,14 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.personalHeroBg{
|
||||
background: url(../../../assets/images/personal-page.jpg) no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
/* padding: 0.4rem 0; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import Hero from "./Hero";
|
||||
import PersonalHero from "./PersonalHero";
|
||||
|
||||
export { Hero };
|
||||
export { Hero, PersonalHero };
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { FC } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { RouteHandler } from "../../../router/routes";
|
||||
|
||||
const FeatureText: FC = () => {
|
||||
const FeatureText = () => {
|
||||
return (
|
||||
<div className="w-full sm:w-2/3 px-0 sm:px-[15px] flex flex-col">
|
||||
<div className="mt-5 text-[.9375rem] text-[#454545] leading-[1.4375rem]">
|
||||
<div className="mt-5 text-[.9375rem] text-[#454545] leading-[1.4375rem] cursor-default">
|
||||
<p className="mb-[.9375rem] text-justify sm:text-left">
|
||||
Premium Salary Plus loan provides confirmed staff of commercial
|
||||
organizations more usable funds. The employee’s organization must have
|
||||
@@ -28,14 +27,17 @@ const FeatureText: FC = () => {
|
||||
</ul>
|
||||
</div>
|
||||
<Link
|
||||
to={RouteHandler.getStarted}
|
||||
className="text-[#5C2684] hover:underline mt-[1.5625rem] w-fit"
|
||||
to={RouteHandler.letsGetStarted}
|
||||
className="text-[#5C2684] mt-[1.5625rem] w-fit"
|
||||
>
|
||||
***Click here to apply
|
||||
*** <span className="hover:underline">Click here to apply</span>
|
||||
</Link>
|
||||
<p className="mt-[.5625rem] font-bold cursor-default">
|
||||
<Link
|
||||
to={RouteHandler.termsAndConditions}
|
||||
className="mt-[.5625rem] font-bold"
|
||||
>
|
||||
Terms and conditions apply
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Hero } from "./Hero";
|
||||
import { Hero, PersonalHero } from "./Hero";
|
||||
import { Requirements } from "./Requirements";
|
||||
|
||||
export {Hero, Requirements}
|
||||
export {Hero, Requirements, PersonalHero}
|
||||
@@ -1,45 +1,119 @@
|
||||
type Props = {
|
||||
name:string,
|
||||
fillColor?:string
|
||||
}
|
||||
import { FaCaretDown } from "react-icons/fa";
|
||||
|
||||
export default function Icons({name, fillColor}:Props) {
|
||||
import dashIcon from "../../assets/images/dashboard/dashDefault.svg";
|
||||
type Props = {
|
||||
name: string;
|
||||
fillColor?: string;
|
||||
className?:string;
|
||||
};
|
||||
|
||||
export default function Icons({ name, fillColor, className }: Props) {
|
||||
return (
|
||||
<>
|
||||
{name == 'home' ?
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.1667 14.9875V19.9875H17.5C18.8807 19.9875 20 18.8682 20 17.4875V9.88673C20.0002 9.4538 19.832 9.03778 19.5308 8.72673L12.4492 1.07087C11.1996 -0.281086 9.09074 -0.364094 7.73879 0.885437C7.67457 0.944812 7.6127 1.00665 7.55336 1.07087L0.48418 8.72423C0.173945 9.03657 -0.000117128 9.45899 5.9134e-08 9.89923V17.4875C5.9134e-08 18.8682 1.1193 19.9875 2.5 19.9875H5.83332V14.9875C5.84891 12.7152 7.68355 10.8596 9.89867 10.8061C12.1879 10.7509 14.1492 12.6381 14.1667 14.9875Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
<path d="M10 12.4875C8.6193 12.4875 7.5 13.6068 7.5 14.9875V19.9875H12.5V14.9875C12.5 13.6068 11.3807 12.4875 10 12.4875Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
</svg>
|
||||
:name == 'profile'?
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 10C12.7614 10 15 7.76142 15 5C15 2.23858 12.7614 0 10 0C7.23858 0 5 2.23858 5 5C5 7.76142 7.23858 10 10 10Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
<path d="M10 11.6667C5.85977 11.6713 2.50461 15.0265 2.5 19.1667C2.5 19.6269 2.87309 20 3.33332 20H16.6666C17.1269 20 17.5 19.6269 17.5 19.1667C17.4954 15.0265 14.1402 11.6713 10 11.6667Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
</svg>
|
||||
:name == 'verification'?
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.728 6.8281L18.1812 5.28145C17.814 4.91432 17.2203 4.91432 16.857 5.28145L7.50177 14.6356L3.15031 10.2807C2.78313 9.91359 2.1894 9.91359 1.82613 10.2807L0.275384 11.8313C-0.0917946 12.1984 -0.0917946 12.7921 0.275384 13.1592L6.83772 19.7246C7.2049 20.0918 7.79864 20.0918 8.16191 19.7246L19.7241 8.15603C20.0913 7.78499 20.0913 7.19133 19.728 6.8281ZM7.06037 10.9681C7.30256 11.2142 7.70098 11.2142 7.94316 10.9681L16.068 2.8365C16.3101 2.59044 16.3101 2.19597 16.068 1.95382L14.3024 0.184543C14.0602 -0.0615144 13.6618 -0.0615144 13.4196 0.184543L7.50177 6.10164L5.33776 3.93399C5.09558 3.68794 4.69715 3.68794 4.45497 3.93399L2.68548 5.70327C2.4433 5.94932 2.4433 6.3438 2.68548 6.58595L7.06037 10.9681Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
</svg>
|
||||
:name == 'payments'?
|
||||
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 14.2857C0 15.2321 0.746528 16 1.66667 16H18.3333C19.2535 16 20 15.2321 20 14.2857V8H0V14.2857ZM6.66667 11.8571C6.66667 11.6214 6.85417 11.4286 7.08333 11.4286H11.8056C12.0347 11.4286 12.2222 11.6214 12.2222 11.8571V13.2857C12.2222 13.5214 12.0347 13.7143 11.8056 13.7143H7.08333C6.85417 13.7143 6.66667 13.5214 6.66667 13.2857V11.8571ZM2.22222 11.8571C2.22222 11.6214 2.40972 11.4286 2.63889 11.4286H5.13889C5.36806 11.4286 5.55556 11.6214 5.55556 11.8571V13.2857C5.55556 13.5214 5.36806 13.7143 5.13889 13.7143H2.63889C2.40972 13.7143 2.22222 13.5214 2.22222 13.2857V11.8571ZM20 1.71429V3.42857H0V1.71429C0 0.767857 0.746528 0 1.66667 0H18.3333C19.2535 0 20 0.767857 20 1.71429Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
</svg>
|
||||
:name == 'legals'?
|
||||
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 10.5H7.99937C7.99937 9.99438 8.04125 10.2272 5.34156 4.82781C4.79 3.725 3.21062 3.72281 2.65812 4.82781C-0.0643752 10.2734 0.000625 10.0103 0.000625 10.5H0C0 11.8806 1.79094 13 4 13C6.20906 13 8 11.8806 8 10.5ZM4 5.5L6.25 10H1.75L4 5.5ZM19.9994 10.5C19.9994 9.99438 20.0413 10.2272 17.3416 4.82781C16.79 3.725 15.2106 3.72281 14.6581 4.82781C11.9356 10.2734 12.0006 10.0103 12.0006 10.5H12C12 11.8806 13.7909 13 16 13C18.2091 13 20 11.8806 20 10.5H19.9994ZM13.75 10L16 5.5L18.25 10H13.75ZM16.5 14H11V4.78906C11.7347 4.4675 12.2863 3.80531 12.4497 3H16.5C16.7763 3 17 2.77625 17 2.5V1.5C17 1.22375 16.7763 1 16.5 1H11.9888C11.5325 0.39625 10.8153 0 10 0C9.18469 0 8.4675 0.39625 8.01125 1H3.5C3.22375 1 3 1.22375 3 1.5V2.5C3 2.77625 3.22375 3 3.5 3H7.55031C7.71375 3.805 8.265 4.4675 9 4.78906V14H3.5C3.22375 14 3 14.2238 3 14.5V15.5C3 15.7762 3.22375 16 3.5 16H16.5C16.7763 16 17 15.7762 17 15.5V14.5C17 14.2238 16.7763 14 16.5 14Z" fill={fillColor ? fillColor : '#5C2684'}/>
|
||||
</svg>
|
||||
:name == 'arrow'?
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.3072 1.05822L7.03885 0.34847C7.34865 0.0479466 7.8496 0.0479466 8.15611 0.34847L14.563 6.56035C14.8728 6.86087 14.8728 7.34682 14.563 7.64415L8.15611 13.8592C7.84631 14.1597 7.34536 14.1597 7.03885 13.8592L6.3072 13.1495C5.9941 12.8458 6.00069 12.3502 6.32038 12.0529L10.2917 8.38267H0.819787C0.381453 8.38267 0.0288086 8.04058 0.0288086 7.61538V6.59232C0.0288086 6.16711 0.381453 5.82503 0.819787 5.82503H10.2917L6.32038 2.15481C5.9974 1.85748 5.99081 1.36194 6.3072 1.05822Z" fill={fillColor ? fillColor : '#FBB700'}/>
|
||||
</svg>
|
||||
:name == 'greater-than'?
|
||||
<svg width="11" height="16" viewBox="0 0 11 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.74365 8.64502L3.10303 15.2856C2.64404 15.7446 1.90186 15.7446 1.44775 15.2856L0.344238 14.1821C-0.114746 13.7231 -0.114746 12.981 0.344238 12.5269L5.05127 7.81982L0.344238 3.11279C-0.114746 2.65381 -0.114746 1.91162 0.344238 1.45752L1.44287 0.344238C1.90186 -0.114746 2.64404 -0.114746 3.09814 0.344238L9.73877 6.98486C10.2026 7.44385 10.2026 8.18604 9.74365 8.64502Z" fill={fillColor ? fillColor : '#FFF'}/>
|
||||
</svg>
|
||||
:
|
||||
null
|
||||
}
|
||||
{name == "home" ? (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14.1667 14.9875V19.9875H17.5C18.8807 19.9875 20 18.8682 20 17.4875V9.88673C20.0002 9.4538 19.832 9.03778 19.5308 8.72673L12.4492 1.07087C11.1996 -0.281086 9.09074 -0.364094 7.73879 0.885437C7.67457 0.944812 7.6127 1.00665 7.55336 1.07087L0.48418 8.72423C0.173945 9.03657 -0.000117128 9.45899 5.9134e-08 9.89923V17.4875C5.9134e-08 18.8682 1.1193 19.9875 2.5 19.9875H5.83332V14.9875C5.84891 12.7152 7.68355 10.8596 9.89867 10.8061C12.1879 10.7509 14.1492 12.6381 14.1667 14.9875Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
<path
|
||||
d="M10 12.4875C8.6193 12.4875 7.5 13.6068 7.5 14.9875V19.9875H12.5V14.9875C12.5 13.6068 11.3807 12.4875 10 12.4875Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
</svg>
|
||||
) : name == "profile" ? (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10 10C12.7614 10 15 7.76142 15 5C15 2.23858 12.7614 0 10 0C7.23858 0 5 2.23858 5 5C5 7.76142 7.23858 10 10 10Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
<path
|
||||
d="M10 11.6667C5.85977 11.6713 2.50461 15.0265 2.5 19.1667C2.5 19.6269 2.87309 20 3.33332 20H16.6666C17.1269 20 17.5 19.6269 17.5 19.1667C17.4954 15.0265 14.1402 11.6713 10 11.6667Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
</svg>
|
||||
) : name == "verification" ? (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19.728 6.8281L18.1812 5.28145C17.814 4.91432 17.2203 4.91432 16.857 5.28145L7.50177 14.6356L3.15031 10.2807C2.78313 9.91359 2.1894 9.91359 1.82613 10.2807L0.275384 11.8313C-0.0917946 12.1984 -0.0917946 12.7921 0.275384 13.1592L6.83772 19.7246C7.2049 20.0918 7.79864 20.0918 8.16191 19.7246L19.7241 8.15603C20.0913 7.78499 20.0913 7.19133 19.728 6.8281ZM7.06037 10.9681C7.30256 11.2142 7.70098 11.2142 7.94316 10.9681L16.068 2.8365C16.3101 2.59044 16.3101 2.19597 16.068 1.95382L14.3024 0.184543C14.0602 -0.0615144 13.6618 -0.0615144 13.4196 0.184543L7.50177 6.10164L5.33776 3.93399C5.09558 3.68794 4.69715 3.68794 4.45497 3.93399L2.68548 5.70327C2.4433 5.94932 2.4433 6.3438 2.68548 6.58595L7.06037 10.9681Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
</svg>
|
||||
) : name == "payments" ? (
|
||||
<svg
|
||||
width="20"
|
||||
height="16"
|
||||
viewBox="0 0 20 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 14.2857C0 15.2321 0.746528 16 1.66667 16H18.3333C19.2535 16 20 15.2321 20 14.2857V8H0V14.2857ZM6.66667 11.8571C6.66667 11.6214 6.85417 11.4286 7.08333 11.4286H11.8056C12.0347 11.4286 12.2222 11.6214 12.2222 11.8571V13.2857C12.2222 13.5214 12.0347 13.7143 11.8056 13.7143H7.08333C6.85417 13.7143 6.66667 13.5214 6.66667 13.2857V11.8571ZM2.22222 11.8571C2.22222 11.6214 2.40972 11.4286 2.63889 11.4286H5.13889C5.36806 11.4286 5.55556 11.6214 5.55556 11.8571V13.2857C5.55556 13.5214 5.36806 13.7143 5.13889 13.7143H2.63889C2.40972 13.7143 2.22222 13.5214 2.22222 13.2857V11.8571ZM20 1.71429V3.42857H0V1.71429C0 0.767857 0.746528 0 1.66667 0H18.3333C19.2535 0 20 0.767857 20 1.71429Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
</svg>
|
||||
) : name == "legals" ? (
|
||||
<svg
|
||||
width="20"
|
||||
height="16"
|
||||
viewBox="0 0 20 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 10.5H7.99937C7.99937 9.99438 8.04125 10.2272 5.34156 4.82781C4.79 3.725 3.21062 3.72281 2.65812 4.82781C-0.0643752 10.2734 0.000625 10.0103 0.000625 10.5H0C0 11.8806 1.79094 13 4 13C6.20906 13 8 11.8806 8 10.5ZM4 5.5L6.25 10H1.75L4 5.5ZM19.9994 10.5C19.9994 9.99438 20.0413 10.2272 17.3416 4.82781C16.79 3.725 15.2106 3.72281 14.6581 4.82781C11.9356 10.2734 12.0006 10.0103 12.0006 10.5H12C12 11.8806 13.7909 13 16 13C18.2091 13 20 11.8806 20 10.5H19.9994ZM13.75 10L16 5.5L18.25 10H13.75ZM16.5 14H11V4.78906C11.7347 4.4675 12.2863 3.80531 12.4497 3H16.5C16.7763 3 17 2.77625 17 2.5V1.5C17 1.22375 16.7763 1 16.5 1H11.9888C11.5325 0.39625 10.8153 0 10 0C9.18469 0 8.4675 0.39625 8.01125 1H3.5C3.22375 1 3 1.22375 3 1.5V2.5C3 2.77625 3.22375 3 3.5 3H7.55031C7.71375 3.805 8.265 4.4675 9 4.78906V14H3.5C3.22375 14 3 14.2238 3 14.5V15.5C3 15.7762 3.22375 16 3.5 16H16.5C16.7763 16 17 15.7762 17 15.5V14.5C17 14.2238 16.7763 14 16.5 14Z"
|
||||
fill={fillColor ? fillColor : "#5C2684"}
|
||||
/>
|
||||
</svg>
|
||||
) : name == "arrow" ? (
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.3072 1.05822L7.03885 0.34847C7.34865 0.0479466 7.8496 0.0479466 8.15611 0.34847L14.563 6.56035C14.8728 6.86087 14.8728 7.34682 14.563 7.64415L8.15611 13.8592C7.84631 14.1597 7.34536 14.1597 7.03885 13.8592L6.3072 13.1495C5.9941 12.8458 6.00069 12.3502 6.32038 12.0529L10.2917 8.38267H0.819787C0.381453 8.38267 0.0288086 8.04058 0.0288086 7.61538V6.59232C0.0288086 6.16711 0.381453 5.82503 0.819787 5.82503H10.2917L6.32038 2.15481C5.9974 1.85748 5.99081 1.36194 6.3072 1.05822Z"
|
||||
fill={fillColor ? fillColor : "#FBB700"}
|
||||
/>
|
||||
</svg>
|
||||
) : name == "greater-than" ? (
|
||||
<svg
|
||||
width="11"
|
||||
height="16"
|
||||
viewBox="0 0 11 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.74365 8.64502L3.10303 15.2856C2.64404 15.7446 1.90186 15.7446 1.44775 15.2856L0.344238 14.1821C-0.114746 13.7231 -0.114746 12.981 0.344238 12.5269L5.05127 7.81982L0.344238 3.11279C-0.114746 2.65381 -0.114746 1.91162 0.344238 1.45752L1.44287 0.344238C1.90186 -0.114746 2.64404 -0.114746 3.09814 0.344238L9.73877 6.98486C10.2026 7.44385 10.2026 8.18604 9.74365 8.64502Z"
|
||||
fill={fillColor ? fillColor : "#FFF"}
|
||||
/>
|
||||
</svg>
|
||||
) :name == 'arrow-down'?
|
||||
<FaCaretDown className={`text-xl ${className && className}`} />
|
||||
:name == "dash-icon" ? (
|
||||
<img src={dashIcon} alt="dash-icon" />
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
|
||||
const InternetBanking: React.FC = () => {
|
||||
return (
|
||||
<div>InternetBanking</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default InternetBanking
|
||||
@@ -0,0 +1,3 @@
|
||||
import InternetBanking from "./InternetBanking";
|
||||
|
||||
export { InternetBanking };
|
||||
@@ -0,0 +1,204 @@
|
||||
import React from "react";
|
||||
import * as Yup from "yup";
|
||||
import { Form, Formik } from "formik";
|
||||
import { InputCompOne } from "..";
|
||||
import {useNavigate} from 'react-router-dom'
|
||||
import { RouteHandler } from "../../router/routes";
|
||||
|
||||
import { useDispatch } from "react-redux";
|
||||
import { updateUserDetails } from "../../store/UserDetails";
|
||||
|
||||
import { validateBVN, verifyOTP } from "../../core/apiRequest";
|
||||
import { RequestStatus } from "../../core/models";
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
bvn: Yup.string()
|
||||
.required("BVN is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(11, "must be 11 digits")
|
||||
.max(11, "must be 11 digits"),
|
||||
otp: Yup.string()
|
||||
// .when('require_otp', {
|
||||
// is: true,
|
||||
// then: Yup.string().required("OTP is required")
|
||||
// })
|
||||
// .required("OTP is required")
|
||||
.test("no-e", "Invalid number", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.min(5, "must be 5 digits")
|
||||
.max(5, "must be 5 digits"),
|
||||
// .test("no-e", "must be 11 characters", (value:any) => {
|
||||
// if (value.length < 11) {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// })
|
||||
});
|
||||
|
||||
// initial values for formik
|
||||
let initialValues = {
|
||||
bvn: '',
|
||||
otp: '',
|
||||
};
|
||||
|
||||
type ValidBVN = {
|
||||
verification_id:string
|
||||
valid: undefined | boolean
|
||||
}
|
||||
|
||||
const LetsGetStarted: React.FC = () => {
|
||||
const dispatch = useDispatch()
|
||||
const navigate = useNavigate()
|
||||
// const [pinValues, setPinValues] = React.useState({
|
||||
// bvn: "",
|
||||
// otp: "",
|
||||
// });
|
||||
// const otpInputRef = React.useRef<HTMLInputElement>(null);
|
||||
|
||||
const [requestStatusBVN, setRequestStatusBVN] = React.useState<RequestStatus>({loading:false, status:undefined, message:''});
|
||||
|
||||
const [requestStatusOTP, setRequestStatusOTP] = React.useState<RequestStatus>({loading:false, status:undefined, message:''});
|
||||
|
||||
const [bvnIsValid, setBvnIsValid] = React.useState<ValidBVN>({
|
||||
verification_id: '',
|
||||
valid: undefined
|
||||
});
|
||||
|
||||
|
||||
// e: React.FormEvent<HTMLInputElement>
|
||||
// let { value } = e.target as HTMLInputElement;
|
||||
const bvnValidation = (values:any) => { // Function to Validate BVN
|
||||
let bvn = values.bvn
|
||||
setRequestStatusBVN({loading:true, status:false, message:''})
|
||||
validateBVN({bvn}).then(res => {
|
||||
if(!res || !res.data.call_return){
|
||||
setBvnIsValid({verification_id:'', valid: false})
|
||||
setRequestStatusBVN({loading:false, status:false, message:'unable to verify BVN'})
|
||||
return setTimeout(()=>{
|
||||
setRequestStatusBVN({loading:false, status:false, message:''})
|
||||
}, 4000)
|
||||
}
|
||||
setBvnIsValid({verification_id:res.data.verification_id, valid: true})
|
||||
setRequestStatusBVN({loading:false, status:true, message:'verified'})
|
||||
}).catch(err => {
|
||||
setBvnIsValid({verification_id:'', valid: false})
|
||||
console.log(err)
|
||||
})
|
||||
};
|
||||
|
||||
const handleSubmit = (values:any) => { // Function to VERIFY OTP AND LOGIN USER
|
||||
setRequestStatusOTP({loading:true, status:false, message:''})
|
||||
// console.log('values', values)
|
||||
verifyOTP({...values, verification_id:bvnIsValid.verification_id}).then(res=>{
|
||||
if(!res || !res.data.call_return){
|
||||
setRequestStatusOTP({loading:false, status:false, message:'wrong otp'})
|
||||
return setTimeout(()=>{
|
||||
setRequestStatusOTP({loading:false, status:false, message:''})
|
||||
},4000)
|
||||
}
|
||||
// console.log(res.data)
|
||||
localStorage.setItem('token', res.data?.token)
|
||||
localStorage.setItem('uid', res?.data?.customer[0]?.uid)
|
||||
dispatch(updateUserDetails({ ...res?.data?.customer[0] }));
|
||||
navigate(RouteHandler.dashboardHome, {replace:true})
|
||||
}).catch(err => {
|
||||
setRequestStatusOTP({loading:false, status:false, message:'something went wrong, try again'})
|
||||
console.log(err)
|
||||
return setTimeout(()=>{
|
||||
setRequestStatusOTP({loading:false, status:false, message:''})
|
||||
},4000)
|
||||
})
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={bvnIsValid.valid ? handleSubmit : bvnValidation}
|
||||
>
|
||||
{(props:any) => (
|
||||
<Form className="">
|
||||
<div className="w-full">
|
||||
<div className="containerMode flex justify-between gap-1 xl:gap-8 flex-col">
|
||||
<div className="my-[4rem] flex items-center justify-center w-full">
|
||||
<h1 className="font-bold text-[2.375rem] text-[#5C2684] my-[.5rem] text-center">
|
||||
Let’s Get You Started
|
||||
</h1>
|
||||
</div>
|
||||
<div className="mx-auto flex flex-col gap-8 max-w-[31.625rem] ">
|
||||
<div className='w-full'>
|
||||
<InputCompOne
|
||||
parentClass="flex flex-col gap-2"
|
||||
label="Enter Your BVN "
|
||||
name="bvn"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( To get your BVN, dial *565*0# )"
|
||||
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
|
||||
placeholder="Enter your BVN"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
|
||||
value={props.values.bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.bvn && props.touched.bvn) && props.errors.bvn}
|
||||
/>
|
||||
<p className={`p-2 ${!requestStatusBVN.status ? 'text-red-500' : 'text-emerald-500'}`}>{requestStatusBVN.loading ? 'verifying...' : requestStatusBVN.message}</p>
|
||||
</div>
|
||||
{bvnIsValid.valid && (
|
||||
<InputCompOne
|
||||
parentClass="flex flex-col gap-2"
|
||||
label="Enter OTP "
|
||||
name="otp"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( Please check your BVN phone number for verification pin )"
|
||||
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
|
||||
placeholder="Enter your OTP"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
|
||||
value={props.values.otp}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.otp && props.touched.otp) && props.errors.otp}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
type='submit'
|
||||
className="w-full h-[3.625rem] rounded bg-[#FBB700] rounded-2 px-4 text-[18px] text-[#282828] font-semibold disabled:text-[#282828] disabled:text-opacity-50"
|
||||
disabled={requestStatusBVN.loading || (!props.values.otp && bvnIsValid.valid)}
|
||||
>
|
||||
Enter
|
||||
</button>
|
||||
|
||||
<p className={`p-2 ${!requestStatusOTP.status ? 'text-red-500' : 'text-emerald-500'}`}>{requestStatusOTP.message}</p>
|
||||
|
||||
{bvnIsValid.valid || bvnIsValid.valid == undefined ? (
|
||||
<p className="text-[#5C2684] mt-[1.5625rem] w-fit">
|
||||
***Every personal information attached to your BVN is safe and
|
||||
secure. It is only important for us to verify your information and
|
||||
also give you access to your application profile/account.
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-[#5C2684] mt-[1.5625rem] w-fit">
|
||||
***Did not receive OTP? Click to resend
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
};
|
||||
|
||||
export default LetsGetStarted;
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import Logo from "../../assets/icons/logo.svg";
|
||||
|
||||
|
||||
const LetsGetStartedNav: React.FC = () => {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="containerMode flex justify-between gap-1 xl:gap-8">
|
||||
<Link to="/">
|
||||
<img
|
||||
src={Logo}
|
||||
alt="Logo"
|
||||
className="w-[52px] h-[43px] xl:w-[72px] xl:h-[63px]"
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LetsGetStartedNav;
|
||||
@@ -0,0 +1,4 @@
|
||||
import LetsGetStarted from "./LetsGetStarted";
|
||||
import LetsGetStartedNav from "./LetsGetStartedNav";
|
||||
|
||||
export { LetsGetStarted, LetsGetStartedNav };
|
||||
@@ -0,0 +1,428 @@
|
||||
import React from "react";
|
||||
|
||||
const Main: React.FC = () => {
|
||||
return (
|
||||
<div className="w-full my-3">
|
||||
<div className="containerMode">
|
||||
<p className="mb-[15px]">
|
||||
<strong>PRIVACY POLICY</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>1.Your Privacy is important to us.</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
This privacy statement sets out the privacy policy of
|
||||
fcmbgroupplc.com, which provides a portal, or gateway, to the
|
||||
financial services offered by the First City Monument Bank Limited and
|
||||
the other members of the FCMB Group Plc (Collectively, “FCMB”).
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
This policy explains how we collect, share, use, and protect
|
||||
information when you visit or use this website and any other online
|
||||
services, platforms, or products offered by FCMB or any of its banking
|
||||
and non-banking affiliates and subsidiaries that link to or reference
|
||||
this policy (collectively, our “services”).
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>1.1 FCMB and You</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
First City Monument Bank Limited is a private limited liability
|
||||
company registered in the Federal Republic of Nigeria under RC No.
|
||||
46713. Its head-office is at Primrose Tower, 17A Tinubu Street, Lagos
|
||||
State, Nigeria.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
FCMB Group Plc hosts the fcmbgroupplc.com website and provides
|
||||
technical support, access and links to the Local Sites of First City
|
||||
Group members. fcmbgroupplc.com does not offer financial services or
|
||||
products. Financial services and products may only be obtained by
|
||||
registering with a Local Site. The First City Group provides financial
|
||||
products and services to a global clientele through its affiliated
|
||||
companies and branches located in 36 states and the Federal Capital
|
||||
Territory in Nigeria, and in the UK. Privacy and personal data
|
||||
protection principles vary from one country to another. When you
|
||||
access or link to a Local Site, please read the privacy statement
|
||||
issued by the Local Site to determine the policies that apply to
|
||||
information or data maintained by the Local Site.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>2. Information we may collect about you </span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>2.1 Your Personal Information</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
At FCMB, we strive to meet your needs and provide you with exceptional
|
||||
services. In the course of consuming our services through various
|
||||
channels, such as forms, phone calls, correspondence, service point
|
||||
interfaces, and other available channels, we collect information that
|
||||
you provide to us. This information may include, but is not limited
|
||||
to, contact data, log/Technical information, Financial Data, Marketing
|
||||
and Communications Data, identity verification details (this includes
|
||||
Personally Identifiable Information (PII), otherwise known as Personal
|
||||
Information or Personal Data, which includes email address, phone
|
||||
number, contact address, limited financial information, location data,
|
||||
device data etc.) and documents, services consumed or desired, mode of
|
||||
consumption, preferences, location, general events, and instructions
|
||||
and transactions relating to the services.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
The lawful basis we rely on for processing your Personal Information
|
||||
are:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Your Consent: Where you agree to us collecting your Personal
|
||||
Information by using our Services.
|
||||
</li>
|
||||
<li>
|
||||
We have a contractual obligation: Without your Personal Information,
|
||||
we cannot provide our Services to you.
|
||||
</li>
|
||||
<li>
|
||||
We have a legal obligation: To ensure we are fully compliant with
|
||||
all applicable financial legislations such as Anti-Money Laundering
|
||||
and Countering the Financing of Terrorism (AML/CFT) Laws, we must
|
||||
collect and store your Personal Information. We protect against
|
||||
fraud by checking your identity with your Personal Information.
|
||||
</li>
|
||||
</ol>
|
||||
<p className="mb-[15px]">
|
||||
Additionally, to better serve your needs, we may utilize information
|
||||
about you collected from third parties and service partners. It is
|
||||
important to note that these third-party sources are not under the
|
||||
control of FCMB, and we are not responsible for how they use the
|
||||
information.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>2.2 Usage and other information</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
In addition to the personal information described above, we may
|
||||
collect certain information about your use of our online services. For
|
||||
example, we may capture the IP address of the device you use to
|
||||
connect to the online service, the type of operating system and
|
||||
browser you use, and information about the site you came from, the
|
||||
parts of our online service you access, and the site you visit next.
|
||||
FCMB or our third-party partners may also use cookies, web beacons or
|
||||
other technologies to collect and store other information about your
|
||||
visit to, or use of, our online services. In addition, we may later
|
||||
associate the usage and other information we collect online with
|
||||
personal information about you.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>2.3 FCMB Mobile</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
For the convenience of our FCMB customers, we provide access to our
|
||||
products and services through our mobile applications and
|
||||
mobile-optimized websites ("FCMB Mobile"). When you engage with us
|
||||
through FCMB Mobile, we may collect certain information to enhance
|
||||
your experience. This information may include unique device
|
||||
identifiers for your mobile device, screen resolution, device
|
||||
settings, location information, and analytical data regarding your
|
||||
mobile device usage. Please note that we may request your permission
|
||||
before collecting specific information, such as precise geo-location
|
||||
data,- contact or image data and other personal identifiable
|
||||
information through FCMB Mobile. Rest assured that any information
|
||||
collected is handled with the utmost care and in accordance with our
|
||||
privacy policy.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>2.4 Additional sources of information</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
We may also collect information about you from additional online and
|
||||
offline sources including from co-branded partner sites or
|
||||
commercially available third-party sources, such as credit reporting
|
||||
agencies. We may combine this information with the personal and other
|
||||
information we have collected about you under this Privacy Policy.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>2.5 Non-Personal Information</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
In order to achieve our goal of providing you with the best-in-class
|
||||
service, we may also collect, store, use and transfer non-personal
|
||||
information or anonymized data such as statistical or demographic
|
||||
data. These may be collected or sourced during your visits to perform
|
||||
certain tasks such as grant you access to some parts of our web site
|
||||
or conduct research on your behaviour on our site in order to improve
|
||||
our services. We will not disclose your information to any person
|
||||
outside our organization except as described in this Privacy Policy.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>3. Our Use of Information</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
FCMB and/or subsidiaries may use or process the information discussed
|
||||
above in a number of ways, such as to:
|
||||
</p>
|
||||
<ol>
|
||||
<li>Manage your preferences;</li>
|
||||
<li>
|
||||
Create and manage any accounts or transactions you may have with us,
|
||||
verify your identity, provide our services, and respond to your
|
||||
inquiries;
|
||||
</li>
|
||||
<li>
|
||||
Process your applications and transactions (including authorization,
|
||||
clearing, chargebacks and other related dispute resolution
|
||||
activities);
|
||||
</li>
|
||||
<li>
|
||||
Protect against and prevent fraud, unauthorized transactions, claims
|
||||
and other liabilities as well as enhance the security of your
|
||||
account or our online services;
|
||||
</li>
|
||||
<li>
|
||||
Provide, administer and communicate with you about our products,
|
||||
services, offers, programs and promotions as well as those of our
|
||||
merchants and partners;
|
||||
</li>
|
||||
<li>
|
||||
Evaluate your interest in employment and contact you regarding
|
||||
possible employment with FCMB;
|
||||
</li>
|
||||
<li>
|
||||
Evaluate and improve our business, including developing new products
|
||||
and services;
|
||||
</li>
|
||||
<li>To target advertisements, newsletters, and service updates;</li>
|
||||
<li>As necessary to establish, exercise and defend legal rights;</li>
|
||||
<li>
|
||||
Perform analytics concerning your use of our online services,
|
||||
including your responses to our emails and the pages and
|
||||
advertisements you view;
|
||||
</li>
|
||||
<li>
|
||||
As may be required by applicable laws and regulations, including for
|
||||
compliance with Know Your Customers and risk assessment, Anti-Money
|
||||
Laundering, anti-corruption and sanctions screening requirements, or
|
||||
as requested by any judicial process, law enforcement or
|
||||
governmental agency having or claiming jurisdiction over FCMB or
|
||||
affiliates;
|
||||
</li>
|
||||
<li>
|
||||
To use data analytics to improve our Website, products, or services,
|
||||
and user experiences;
|
||||
</li>
|
||||
<li>
|
||||
For other purposes for which we provide specific notice at the time
|
||||
you provide or we collect your information.
|
||||
</li>
|
||||
</ol>
|
||||
<p className="mb-[15px]">
|
||||
We may also use data that we collect on an aggregate or anonymous
|
||||
basis (such that it does not identify any individual customers) for
|
||||
various business purposes, where permissible under applicable laws and
|
||||
regulations.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>4. Cookies</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
This website, along with most other major websites, uses cookies.
|
||||
Cookies are pieces of information that a website transfers to the
|
||||
cookie file on your computer’s hard disk. Cookies enable users to
|
||||
navigate around the website and (where appropriate) enable us to
|
||||
tailor the content to fit the needs of visitors who have accessed the
|
||||
site.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Firstcitygroup.com uses two types of cookies on this website:
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
Session cookies, which are temporary cookies that remain in the
|
||||
cookie file of your computer until you close your browser (at which
|
||||
point they are deleted).
|
||||
</li>
|
||||
<li>
|
||||
Persistent or stored cookies that remain permanently on the cookie
|
||||
file of your computer.
|
||||
</li>
|
||||
</ol>
|
||||
<p className="mb-[15px]">
|
||||
Cookies cannot look into your computer and obtain information about
|
||||
you or your family or read any material kept on your hard drive and,
|
||||
unless you have logged onto an authenticated page, cookies cannot be
|
||||
used to identify who you are.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Cookies cannot be used by anyone else who has access to the computer
|
||||
to find out anything about you, other than the fact that someone using
|
||||
the computer has visited a certain website. Cookies do not in any way
|
||||
compromise the security of your computer.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Cookies will not be used to contact you for marketing purposes other
|
||||
than by means of advertisements offered within this website.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Cookies may be used to record details of pages relating to particular
|
||||
products and services that you have visited on this website. This is
|
||||
to provide fcmb.com with generic usage statistics to allow the company
|
||||
to improve this website and to provide you with information that may
|
||||
interest you.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
The web browsers of most computers are initially set up to accept
|
||||
cookies. If you prefer, you can set your web browser to disable
|
||||
cookies or to inform you when a website is attempting to add a cookie.
|
||||
You can also delete cookies that have previously been added to your
|
||||
computer’s cookie file.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
You can set your browser to disable persistent cookies and/or session
|
||||
cookies but if you disable session cookies, although you will be able
|
||||
to view this website’s unsecured pages, you may not be able to log
|
||||
onto any authenticated pages.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Please visit{" "}
|
||||
<a href="http://www.allaboutcookies.org/manage-cookies/">
|
||||
http://www.allaboutcookies.org/manage-cookies/
|
||||
</a>{" "}
|
||||
to discover how to disable and delete cookies.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>5. Disclosures</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>5.1 Disclosures</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
We may divulge individual data to any individual performing review,
|
||||
lawful, operational, or different services for us. We will utilize
|
||||
data which does not identify the person for these exercises at
|
||||
whatever point achievable. Data divulged to vendors or contractors for
|
||||
operational purposes may not be re-disclosed to others by such a
|
||||
vendor or contractor. We may reveal individual data when needed to do
|
||||
as such by a court request, or court order. We may divulge individual
|
||||
data as we esteem it proper to secure the wellbeing of our customers
|
||||
or for an investigation identified with open security or to report an
|
||||
action that has all the earmarks of being disregarding law. We may
|
||||
divulge individual data to ensure the security and dependability of
|
||||
this site and to take safety measures against accountability.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>5.2 Disclosures to Third Parties</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Data about you that is accessible to you by means of fcmb.com,
|
||||
including your personal data, can become subject to the legal systems
|
||||
and laws in force in the country where the data is held, received or
|
||||
stored by you or us. Such data can become subject to disclosure
|
||||
pursuant to the laws of the country.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
We may reveal your name and other personal data and other monetary
|
||||
data about you at the request of regulatory agency or in connection
|
||||
with an examination of us as a bank. This information could be
|
||||
revealed to internal and external attorneys or auditors, and to others
|
||||
whom we are required to make such revelations.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>6. Information Security and Retention</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
At FCMB, we are fully committed to protecting the information we
|
||||
collect. We maintain administrative, technical, and physical controls
|
||||
to actively safeguard the Personal Information you provide or we
|
||||
collect. These controls are designed to protect against loss, theft,
|
||||
unauthorized access, disclosure, copying, misuse, or modification.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Our security measures actively include secure servers, firewalls, data
|
||||
encryption, and restricted access granted only to employees for
|
||||
fulfilling their job responsibilities.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
When using a password for any of your accounts, it is essential that
|
||||
you actively ensure its confidentiality and refrain from sharing it
|
||||
with anyone.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
We actively conduct our business in accordance with these principles
|
||||
to actively ensure the confidentiality and protection of your Personal
|
||||
Information. While transmitting information online may not be entirely
|
||||
secure, we actively take all reasonable steps to ensure the security
|
||||
and protection of your Personal Information.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
We will only retain personal information on our servers for as long as
|
||||
it is actively necessary while providing services to you. In the event
|
||||
you close your account, we actively store your information on our
|
||||
servers to comply with regulatory obligations and actively monitor,
|
||||
detect, and prevent fraud. Any retention of your Personal Data is
|
||||
solely for such length of time as may be required by law, regulation,
|
||||
and the internal policies of FCMB, her members and/or affiliates.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>6.1 Data Protection on the Internet</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
At FCMB we utilize encryption innovation to ensure the transmission of
|
||||
data to or from you by means of fcmb.com. For security reasons and to
|
||||
protect the security of your information, access to fcmb.com is
|
||||
restricted to authorized users only. However, because information
|
||||
about you, your account data and other transactions can be accessed
|
||||
through a public network, the Internet, there can be no guarantee that
|
||||
your account information will remain secure and you accept the risk
|
||||
that unauthorized persons may view such information. If you believe
|
||||
that an unauthorized person has accessed your information, please
|
||||
contact the Bank immediately.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>7. Updates to this Policy</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
From time to time, we may change, amend or review this Privacy Policy
|
||||
from time to time to reflect new services or changes in our Privacy
|
||||
Policy and place any updates on this page. All changes made will be
|
||||
posted on this page and where changes will materially affect you, we
|
||||
will notify you of this change by placing a notice online or via mail.
|
||||
If you keep using our Services, you consent to all amendments of this
|
||||
Privacy Policy.
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
<strong>
|
||||
<span>8. Contact us</span>
|
||||
</strong>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
For issues relating to personal data, please contact us via any of the
|
||||
below:
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Corporate Address: Primrose Tower, 17A, Tinubu Street, Marina, Lagos
|
||||
</p>
|
||||
<p className="mb-[15px]">Telephone: 07003290000, 01-2798800</p>
|
||||
<p className="mb-[15px]">
|
||||
Email: <a href="#">customerservice@fcmb.com</a>
|
||||
</p>
|
||||
<p className="mb-[15px]">
|
||||
Whatsapp: (+234) 09099999814 or (+234) 09099999815
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Main;
|
||||
@@ -0,0 +1,3 @@
|
||||
import Main from "./Main";
|
||||
|
||||
export { Main as TsAndCs };
|
||||
@@ -3,7 +3,9 @@ export * from "./Home";
|
||||
export * from "./GetStarted";
|
||||
export * from "./shared";
|
||||
export * from "./Footer";
|
||||
export * from "./DashboardLayout";
|
||||
// export * from "./DashboardLayout";
|
||||
export * from "./Icons";
|
||||
export * from './Dashboard'
|
||||
export * from './Cards'
|
||||
export * from "./Dashboard";
|
||||
export * from "./Cards";
|
||||
export * from "./LetsGetStated";
|
||||
export * from "./TsAndCs";
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
import React from "react";
|
||||
|
||||
type ButtonProps = {
|
||||
className?: string;
|
||||
interface ButtonProps {
|
||||
text: string;
|
||||
};
|
||||
className?: string;
|
||||
type?: "button" | "submit" | "reset";
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
}
|
||||
|
||||
const Button = ({ text, className }: ButtonProps) => {
|
||||
return <button className={`btn-primary uppercase text-[11px] lg:text-[13px] p-[6px] lg:px-[10px] ${className}`}>{text}</button>;
|
||||
const Button: React.FC<ButtonProps> = ({
|
||||
text,
|
||||
className,
|
||||
onClick,
|
||||
type = "button",
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
className={`btn-primary uppercase text-[11px] lg:text-[13px] p-[6px] lg:px-[10px] ${className}`}
|
||||
onClick={onClick}
|
||||
type={type}
|
||||
>
|
||||
{text}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { Icons } from "../Icons";
|
||||
|
||||
export interface InputCompOneProps {
|
||||
label?: string;
|
||||
labelClass?: string;
|
||||
labelSpan?: string;
|
||||
labelSpanClass?: string;
|
||||
floatLabel?: string;
|
||||
placeholder?: string;
|
||||
value?: string | any;
|
||||
onChange?: (e:any) => any;
|
||||
onInput?: (e:any) => any;
|
||||
name: string;
|
||||
tabIndex?: number;
|
||||
ref?: React.RefObject<HTMLInputElement>;
|
||||
selectValue?: string;
|
||||
input?: boolean;
|
||||
select?: boolean;
|
||||
selectOptions?: {loading:boolean, data:{ value: string; label: string }[]};
|
||||
inputType?: string;
|
||||
inputClass?: string;
|
||||
parentInputClass?: string;
|
||||
selectClass?: string;
|
||||
parentClass?: string;
|
||||
maxLength?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
(
|
||||
{
|
||||
label,
|
||||
labelClass,
|
||||
labelSpan,
|
||||
labelSpanClass,
|
||||
floatLabel,
|
||||
placeholder,
|
||||
value,
|
||||
onChange,
|
||||
onInput,
|
||||
name,
|
||||
tabIndex,
|
||||
selectValue,
|
||||
input = false,
|
||||
select = false,
|
||||
selectOptions = {loading:false, data:[]},
|
||||
inputType = "text",
|
||||
inputClass,
|
||||
parentInputClass,
|
||||
selectClass,
|
||||
parentClass,
|
||||
maxLength,
|
||||
error,
|
||||
},
|
||||
forwardedRef
|
||||
) => {
|
||||
return (
|
||||
<div className={parentClass}>
|
||||
{label && (
|
||||
<label htmlFor={label ? label : floatLabel} className={`flex gap-2 items-center flex-wrap ${labelClass}`}>
|
||||
{label}
|
||||
{labelSpan && <span className={labelSpanClass}>{labelSpan}</span>}
|
||||
{error && label && <span className='text-[10px] text-red-500'>{error}</span>}
|
||||
</label>
|
||||
)}
|
||||
{input && (
|
||||
<div className={`relative ${parentInputClass}`}>
|
||||
<input
|
||||
type={inputType}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onInput={onInput}
|
||||
name={name}
|
||||
tabIndex={tabIndex}
|
||||
ref={forwardedRef}
|
||||
className={`px-4 ${floatLabel && 'peer pt-4 placeholder:text-transparent'} ${inputClass}`}
|
||||
maxLength={maxLength}
|
||||
id={label ? label : floatLabel}
|
||||
/>
|
||||
{floatLabel &&
|
||||
<label
|
||||
htmlFor={label ? label : floatLabel}
|
||||
className={`flex items-center gap-2 cursor-pointer text-sm text-black/70 dark:text-white absolute left-4 top-0 translate-y-0 peer-focus:top-0 peer-focus:translate-y-0 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 transition-all duration-500`}
|
||||
>
|
||||
{floatLabel}
|
||||
{error && floatLabel && !label && <span className='text-[10px] text-red-500'>{error}</span>}
|
||||
</label>
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
{select && (
|
||||
<div className={`relative ${parentInputClass}`}>
|
||||
<select
|
||||
name={name}
|
||||
id={label ? label : floatLabel}
|
||||
value={selectValue}
|
||||
className={`px-4 appearance-none ${floatLabel && 'peer pt-4'} ${selectClass}`}
|
||||
onChange={onChange}
|
||||
>
|
||||
{selectOptions.loading ?
|
||||
<option value=''>Loading</option>
|
||||
: selectOptions.data.length ?
|
||||
selectOptions.data.map(({ value, label }) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
</option>
|
||||
))
|
||||
:
|
||||
<option value=''>Not Found</option>
|
||||
}
|
||||
{/* {selectOptions.map(({ value, label }) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
</option>
|
||||
))} */}
|
||||
</select>
|
||||
{floatLabel &&
|
||||
<label
|
||||
htmlFor={label ? label : floatLabel}
|
||||
className={`flex items-center gap-2 cursor-pointer text-sm text-black/70 dark:text-white absolute left-4 top-0 translate-y-0 peer-focus:top-0 peer-focus:translate-y-0 transition-all duration-500`}
|
||||
>
|
||||
{floatLabel}
|
||||
{error && floatLabel && !label && <span className='text-[10px] text-red-500'>{error}</span>}
|
||||
</label>
|
||||
}
|
||||
{/* select custon arrow */}
|
||||
<div className='absolute right-4 top-1/2 -translate-y-1/2'>
|
||||
<Icons name='arrow-down' />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default InputCompOne;
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
|
||||
interface StepperProps {
|
||||
step: number;
|
||||
}
|
||||
|
||||
const Stepper: React.FC<StepperProps> = ({ step = 0 }) => {
|
||||
// const [activeStep, setActiveStep] = useState(step);
|
||||
|
||||
return (
|
||||
<div className="flex justify-between items-center gap-5">
|
||||
{[...Array(5)].map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`w-[1.875rem] border-[.1875rem] rounded-sm ${(step === index
|
||||
? "border-[#E8B4FF]"
|
||||
: "border-[#5C2684]")}`}
|
||||
// onClick={() => setActiveStep(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Stepper;
|
||||
@@ -1,4 +1,6 @@
|
||||
import Button from "./Button";
|
||||
import InputCompOne from "./InputCompOne";
|
||||
import FloatLabelInput from "./FloatLabelInput";
|
||||
import Stepper from "./Stepper";
|
||||
|
||||
export {Button, FloatLabelInput}
|
||||
export { Button, FloatLabelInput, InputCompOne, Stepper };
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { postAuxEnd, getAuxEnd } from "./axiosCall";
|
||||
|
||||
// FUNCTION TO START BVN VALIDATION
|
||||
export const validateBVN = (postData:any) => {
|
||||
let reqData = {
|
||||
...postData
|
||||
}
|
||||
return postAuxEnd('/bvn', reqData)
|
||||
}
|
||||
|
||||
|
||||
// FUNCTION TO VERIFY OTP AND LOGIN
|
||||
export const verifyOTP = (postData:any) => {
|
||||
let reqData = {
|
||||
...postData
|
||||
}
|
||||
return postAuxEnd('/bvn/verify', reqData)
|
||||
}
|
||||
|
||||
// FUNCTION TO APPLY FOR LOAN
|
||||
export const applyForLoan = (postData:any) => {
|
||||
let reqData = {
|
||||
customer_uid: localStorage.getItem('uid'),
|
||||
...postData
|
||||
}
|
||||
return postAuxEnd('/loan/apply', reqData)
|
||||
}
|
||||
|
||||
|
||||
// FUNCTION TO GET USER BY CUSTOMER UID
|
||||
export const getUserByID = () => {
|
||||
let reqData = {
|
||||
customer_uid: localStorage.getItem('uid'),
|
||||
}
|
||||
return getAuxEnd(`/profile?uid=${reqData.customer_uid}`, reqData)
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import axios from "axios";
|
||||
|
||||
export function postAuxEnd(uri: string, reqData: any): Promise<any> {
|
||||
const endPoint = import.meta.env.VITE_USERS_ENDPOINT + uri;
|
||||
const formData = new FormData();
|
||||
for (let value in reqData) {
|
||||
if (typeof reqData[value] === "object") {
|
||||
// for (let innerValue in reqData[value]) {
|
||||
// let innerReqData = reqData[value]
|
||||
// console.log('SAMPLE',innerReqData)
|
||||
// formData.append(reqData[value][innerValue], reqData[value][innerValue]);
|
||||
// }
|
||||
// formData.append(value, JSON.stringify(reqData[value]));
|
||||
formData.append(value, reqData[value]);
|
||||
} else {
|
||||
formData.append(value, reqData[value]);
|
||||
}
|
||||
}
|
||||
return axios
|
||||
.post(endPoint, formData)
|
||||
.then((response: {}) => {
|
||||
// if (response.data.internal_return == "-9999") {
|
||||
// localStorage.clear();
|
||||
// window.location.href = `/login?sessionExpired=true`;
|
||||
// }
|
||||
return response;
|
||||
})
|
||||
.catch((error: any) => {
|
||||
if (error.response) {
|
||||
//response status is an error code
|
||||
console.log(
|
||||
"ERROR-------------------------------------------------------"
|
||||
);
|
||||
console.log(error.response.status);
|
||||
console.log(
|
||||
"ERROR-------------------------------------------------------"
|
||||
);
|
||||
} else if (error.request) {
|
||||
//response not received though the request was sent
|
||||
console.log(
|
||||
"ERROR2-------------------------------------------------------"
|
||||
);
|
||||
console.log(error?.request);
|
||||
console.log(
|
||||
"ERROR2-------------------------------------------------------"
|
||||
);
|
||||
} else {
|
||||
//an error occurred when setting up the request
|
||||
console.log(
|
||||
"ERROR3-------------------------------------------------------"
|
||||
);
|
||||
console.log(error);
|
||||
console.log(
|
||||
"ERROR3-------------------------------------------------------"
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function getAuxEnd(uri: string, reqData: any): Promise<any> {
|
||||
const endPoint = import.meta.env.VITE_USERS_ENDPOINT + uri;
|
||||
const formData = new FormData();
|
||||
for (let value in reqData) {
|
||||
formData.append(value, reqData[value]);
|
||||
}
|
||||
return axios
|
||||
.get(endPoint, reqData)
|
||||
.then((response: {}) => {
|
||||
// if (response.data.internal_return == "-9999") {
|
||||
// localStorage.clear();
|
||||
// window.location.href = `/login?sessionExpired=true`;
|
||||
// }
|
||||
return response;
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.log(
|
||||
"ERROR3-------------------------------------------------------", error
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export interface RequestStatus {
|
||||
loading?:boolean
|
||||
status?:boolean | undefined
|
||||
message?:string
|
||||
name?:string
|
||||
data?:{}[] | [any] | {}
|
||||
}
|
||||
|
||||
|
||||
export interface User {
|
||||
firstname?:string
|
||||
lastname?:string
|
||||
last_login?:string
|
||||
message?:string
|
||||
token?:string
|
||||
customer_uid?:string
|
||||
call_return?:string
|
||||
}
|
||||
@@ -14,9 +14,7 @@ body {
|
||||
|
||||
@layer components {
|
||||
.containerMode {
|
||||
@apply container mx-auto px-5 xxs:max-w-full sm:max-w-[98%] lg:max-w-[1100px];
|
||||
}
|
||||
.dash-bg-image{
|
||||
background: url('../src/assets/images/dashboard/bg_ellipse1.png') right top no-repeat, url('../src/assets/images/dashboard/bg_ellipse2.png') -8% bottom no-repeat;;
|
||||
/* @apply container mx-auto px-5 xxs:max-w-full sm:max-w-[98%] lg:max-w-[1100px]; */
|
||||
@apply container mx-auto px-5 max-w-[1500px]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
import { useState } from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import Logo from "../../assets/icons/logo.svg";
|
||||
import { Icons } from "../../components";
|
||||
|
||||
type Props = {
|
||||
asideDisplay?: () => void;
|
||||
logoutUser: () => void
|
||||
};
|
||||
|
||||
export default function Aside({ asideDisplay, logoutUser }: Props) {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const [openNestedLink, setOpenNestedLink] = useState<{ name: string | null }>(
|
||||
{ name: "" }
|
||||
);
|
||||
|
||||
const handleOpenNestedLink = (e: any) => {
|
||||
if (!e || !e.target) {
|
||||
return setOpenNestedLink({ name: "" });
|
||||
}
|
||||
if (openNestedLink.name && openNestedLink.name == e.target.name) {
|
||||
setOpenNestedLink({ name: "" });
|
||||
} else {
|
||||
setOpenNestedLink({ name: e.target.name });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="py-5 px-10 flex flex-col h-full bg-inherit">
|
||||
<Link to="/">
|
||||
<img src={Logo} alt="Logo" className="w-[72px] h-[63px]" />
|
||||
</Link>
|
||||
<div className="mt-10 h-full overflow-y-auto bg-inherit">
|
||||
{asideLinks.map((link, index) => {
|
||||
if (link.nestedLink?.length) {
|
||||
let allNestedLinks = link.nestedLink.map((item) => item.link);
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="w-full relative bg-inherit overflow-hidden"
|
||||
>
|
||||
<button
|
||||
name={link.name}
|
||||
onClick={(e) => handleOpenNestedLink(e)}
|
||||
className={`py-2 pl-2 text-left relative w-full overflow-hidden rounded-lg flex justify-between items-center z-10 bg-inherit ${
|
||||
allNestedLinks.includes(pathname)
|
||||
? " text-[#5C2684]"
|
||||
: " text-[#585858]"
|
||||
}`}
|
||||
>
|
||||
{link.name}
|
||||
{/* <div className={`mr-2 ${openNestedLink.name == link.name ? '-rotate-90' : 'rotate-90'} transition-all duration-300`}>
|
||||
<Icons
|
||||
name='greater-than'
|
||||
fillColor={`${openNestedLink.name == link.name ? '#5C2684' : '#585858'}`}
|
||||
/>
|
||||
</div> */}
|
||||
</button>
|
||||
<div
|
||||
className={`transition-all duration-300 w-full z-1 ${
|
||||
openNestedLink.name == link.name
|
||||
? "relative top-0"
|
||||
: "absolute -top-[500px]"
|
||||
}`}
|
||||
>
|
||||
{link.nestedLink.map((nextLink, index) => (
|
||||
<Link
|
||||
onClick={() => {
|
||||
asideDisplay && asideDisplay();
|
||||
}}
|
||||
key={index}
|
||||
to={nextLink.link ? nextLink.link : "#"}
|
||||
className={`w-full my-1 flex items-center gap-2 py-2 pl-5 text-base font-medium ${
|
||||
pathname == nextLink.link
|
||||
? " text-[#5C2684]"
|
||||
: "text-[#585858]"
|
||||
}`}
|
||||
>
|
||||
<Icons
|
||||
name={nextLink.icon}
|
||||
fillColor={`${
|
||||
pathname == nextLink.link ? "#5C2684" : "#585858"
|
||||
}`}
|
||||
/>
|
||||
{nextLink.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Link
|
||||
onClick={() => {
|
||||
asideDisplay && asideDisplay();
|
||||
}}
|
||||
key={index}
|
||||
to={link.link ? link.link : "#"}
|
||||
className={`w-full my-4 flex items-center gap-2 py-2 pl-5 rounded-lg text-base font-medium ${
|
||||
pathname == link.link ? "text-[#5C2684]" : "text-[#585858]"
|
||||
}`}
|
||||
>
|
||||
<Icons
|
||||
name={link.icon}
|
||||
fillColor={`${pathname == link.link ? "#5C2684" : "#585858"}`}
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<div className="w-full flex justify-center items-center flex-col gap-3">
|
||||
<button
|
||||
className="py-3 px-6 bg-red-100 text-red-500 font-medium rounded-md w-full"
|
||||
onClick={() => logoutUser()}
|
||||
>
|
||||
Log out
|
||||
</button>
|
||||
|
||||
|
||||
<div className="flex flex-col gap-[.4375rem] text-[.75rem]">
|
||||
<p className="font-extrabold tracking-[3%] text-[#FBB700] underline">
|
||||
For more enquiries and support
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Call: 09099000000
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Email: fcmbloan@support.com
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type AsideLinksType = {
|
||||
name: string;
|
||||
link?: string;
|
||||
icon: string;
|
||||
nestedLink?: {
|
||||
name: string;
|
||||
link: string;
|
||||
icon: string;
|
||||
}[];
|
||||
}[];
|
||||
|
||||
const asideLinks: AsideLinksType = [
|
||||
{ name: "Dashboard", link: "/dashboard/home", icon: "dash-icon", nestedLink: [] },
|
||||
{
|
||||
name: "Your Profile",
|
||||
link: "/dashboard/profile",
|
||||
icon: "dash-icon",
|
||||
nestedLink: [],
|
||||
},
|
||||
{
|
||||
name: "Employment Details",
|
||||
link: "/dashboard/verification",
|
||||
icon: "dash-icon",
|
||||
nestedLink: [],
|
||||
},
|
||||
{
|
||||
name: "Reference Details",
|
||||
link: "/dashboard/payments",
|
||||
icon: "dash-icon",
|
||||
nestedLink: [],
|
||||
},
|
||||
{
|
||||
name: "Agreements",
|
||||
link: "/dashboard/legals",
|
||||
icon: "dash-icon",
|
||||
nestedLink: [],
|
||||
},
|
||||
// {name: 'Nested Link', icon: 'home', nestedLink:[
|
||||
// {name: 'Link 2', link: '/dashboard/not-found', icon: 'legals'},
|
||||
// {name: 'Link 1', link: '/dashboard/not-found', icon: 'home'}
|
||||
// ]
|
||||
// },
|
||||
];
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
import {useState, useEffect} from 'react'
|
||||
import DashboardLayout from "./DashboardLayout";
|
||||
import { Outlet, useNavigate } from "react-router-dom";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { RouteHandler } from '../../router/routes';
|
||||
import { updateUserDetails } from '../../store/UserDetails';
|
||||
import { getUserByID } from '../../core/apiRequest';
|
||||
|
||||
import Logo from '../../assets/images/logo.png'
|
||||
|
||||
export default function DashboardAuth() {
|
||||
|
||||
const navigate = useNavigate()
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const { userDetails } = useSelector((state:any) => state?.userDetails); // CHECKS IF USER Details are avaliable
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(()=>{
|
||||
let token = localStorage.getItem('token')
|
||||
if(!token){
|
||||
navigate(RouteHandler.letsGetStarted, {replace:true})
|
||||
return
|
||||
}
|
||||
const getUser = () => { // FUNCTION TO GET USER BY ID
|
||||
// let data = {firstname:'firstname', lastname:'lastname', uid:'28273737646466464'}
|
||||
getUserByID().then(res=>{
|
||||
if(!res.data.call_return || !Object.keys(res.data.customer).length){
|
||||
navigate(RouteHandler.letsGetStarted, {replace:true})
|
||||
return
|
||||
}
|
||||
setLoading(false)
|
||||
dispatch(updateUserDetails(res.data.customer));
|
||||
}).catch(err=>{
|
||||
console.log('USER ERROR', err)
|
||||
})
|
||||
}
|
||||
if(!Object.keys(userDetails).length){
|
||||
getUser()
|
||||
}
|
||||
},[])
|
||||
|
||||
return (
|
||||
<>
|
||||
{loading && !Object.keys(userDetails).length ?
|
||||
<div className='w-full h-screen flex flex-col justify-center items-center gap-4'>
|
||||
<img className='animate-pulse' src={Logo} alt='Logo' />
|
||||
<p className='animate-pulse'>loading...</p>
|
||||
</div>
|
||||
:
|
||||
<DashboardLayout>
|
||||
<Outlet />
|
||||
</DashboardLayout>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import { ReactNode, useState, useEffect } from "react";
|
||||
import { RouteHandler } from "../../router/routes";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import Aside from "./Aside";
|
||||
|
||||
export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [showAside, setShowAside] = useState<boolean>(false);
|
||||
const asideDisplay = (): void => {
|
||||
setShowAside((prev) => !prev);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
return setShowAside(false);
|
||||
};
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Assume this interface for ChildProps
|
||||
// interface ChildProps {
|
||||
// customProp?: string;
|
||||
// }
|
||||
|
||||
// const enhanceChildren = React.Children.map(children, (child) => {
|
||||
// if (React.isValidElement<ChildProps>(child)) {
|
||||
// return React.cloneElement(child, { customProp: "Hello, World!" });
|
||||
// }
|
||||
// return child;
|
||||
// });
|
||||
|
||||
const logoutUser = () => {
|
||||
localStorage.clear()
|
||||
navigate(RouteHandler.letsGetStarted, {replace:true})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-[2000px] mx-auto h-screen flex bg-[#020202] text-black">
|
||||
<aside className="max-w-[18.75rem] w-full bg-white hidden md:block border-r-2 border-[#E6E6E6]">
|
||||
<Aside logoutUser={logoutUser} />
|
||||
</aside>
|
||||
<aside
|
||||
className={`max-w-[18.75rem] w-full md:hidden bg-white border-r-2 border-[#E6E6E6] fixed top-0 bottom-0 z-50 transition-all duration-500 ${
|
||||
showAside ? "left-0" : "-left-[200%]"
|
||||
}`}
|
||||
>
|
||||
<Aside logoutUser={logoutUser} asideDisplay={asideDisplay} />
|
||||
</aside>
|
||||
<main className="dash-bg-image bg-[#F9F9F9] relative w-full overflow-y-auto overflow-x-hidden">
|
||||
|
||||
<header className={`p-5 md:hidden sticky z-10 top-0 w-full bg-[#F9F9F9] border-b-2 border-[#E6E6E6]`}>
|
||||
<div className='h-14 w-full flex justify-end items-center gap-5'>
|
||||
{/* MENU HAND BURGER */}
|
||||
{/* <div className='w-full'>Welcome Austin Catherine</div> */}
|
||||
<div
|
||||
className="relative md:hidden w-5 h-[20px] flex flex-col items-center justify-between"
|
||||
onClick={asideDisplay}
|
||||
>
|
||||
<div
|
||||
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
|
||||
showAside ? "top-1/2 -translate-y-1/2 rotate-45" : "top-0"
|
||||
}`}
|
||||
></div>
|
||||
<div
|
||||
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-300 ${
|
||||
showAside
|
||||
? "top-1/2 -translate-y-1/2 rotate-[2000deg] opacity-0"
|
||||
: "top-1/2 -translate-y-1/2"
|
||||
}`}
|
||||
></div>
|
||||
<div
|
||||
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
|
||||
showAside
|
||||
? "top-1/2 -translate-y-1/2 -rotate-45"
|
||||
: "bottom-0"
|
||||
}`}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="flex p-5 relative">
|
||||
<div className="w-full p-5">{children}</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// {/* <header className={`p-5 sticky z-10 top-0 w-full bg-[#F9F9F9] border-b-2 border-[#E6E6E6]`}>
|
||||
// <div className='h-14 w-full flex justify-end items-center gap-5'>
|
||||
|
||||
// {/* MENU HAND BURGER */}
|
||||
// <div className='w-full'>Welcome Austin Catherine</div>
|
||||
// <div
|
||||
// className="relative md:hidden w-5 h-[20px] flex flex-col items-center justify-between"
|
||||
// onClick={asideDisplay}
|
||||
// >
|
||||
// <div
|
||||
// className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
|
||||
// showAside ? "top-1/2 -translate-y-1/2 rotate-45" : "top-0"
|
||||
// }`}
|
||||
// ></div>
|
||||
// <div
|
||||
// className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-300 ${
|
||||
// showAside
|
||||
// ? "top-1/2 -translate-y-1/2 rotate-[2000deg] opacity-0"
|
||||
// : "top-1/2 -translate-y-1/2"
|
||||
// }`}
|
||||
// ></div>
|
||||
// <div
|
||||
// className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
|
||||
// showAside
|
||||
// ? "top-1/2 -translate-y-1/2 -rotate-45"
|
||||
// : "bottom-0"
|
||||
// }`}
|
||||
// ></div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </header> */}
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import { Footer, Header } from "../components";
|
||||
|
||||
interface GetStartedLayoutProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const GetStartedLayout: React.FC<GetStartedLayoutProps> = ({ children }) => {
|
||||
return (
|
||||
<div className="containerMode mb-[5.4375rem]">
|
||||
<div className='sticky z-50 top-0 bg-white'>
|
||||
<Header hideSidebar={true} hideMenu={true} />
|
||||
</div>
|
||||
<div className="flex flex-col min-h-[70vh] justify-between">
|
||||
{children}
|
||||
</div>
|
||||
<div className="fixed bottom-0 left-0 bg-white w-full">
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GetStartedLayout;
|
||||
@@ -0,0 +1,27 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import {
|
||||
BottomFooterOne,
|
||||
Header,
|
||||
MidFooter,
|
||||
TopFooterOne,
|
||||
TopHeader,
|
||||
} from "../components";
|
||||
|
||||
interface HomeLayoutProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const HomeLayout: React.FC<HomeLayoutProps> = ({ children }) => {
|
||||
return (
|
||||
<>
|
||||
<TopHeader />
|
||||
<Header />
|
||||
{children}
|
||||
<TopFooterOne />
|
||||
<MidFooter />
|
||||
<BottomFooterOne />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HomeLayout;
|
||||
@@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import { Footer, LetsGetStartedNav } from "../components";
|
||||
// import layoutImage from "../assets/images/test1-reverse.png";
|
||||
|
||||
const LetsGetStartedLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<div className='containerMode mb-[5.4375rem]'>
|
||||
<div className="w-full min-h-[90vh] grid lg:grid-cols-2">
|
||||
<div className="w-full flex flex-col my-3">
|
||||
<LetsGetStartedNav />
|
||||
{children}
|
||||
</div>
|
||||
<div className="w-full h-96 lg:h-full bg-[url(../src/assets/images/test1-reverse.png)] bg-cover bg-no-repeat">
|
||||
{/* <img src={layoutImage} alt="" className="w-full h-full object-cover" /> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="fixed bottom-0 left-0 bg-[#F7F7F7] w-full">
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LetsGetStartedLayout;
|
||||
@@ -0,0 +1,7 @@
|
||||
import HomeLayout from "./HomeLayout";
|
||||
import LetsGetStartedLayout from "./LetsGetStartedLayout";
|
||||
import GetStartedLayout from "./GetStartedLayout";
|
||||
import DashboardLayout from "./DashboardLayout/DashboardLayout";
|
||||
import { DashboardAuth } from "./DashboardLayout";
|
||||
|
||||
export { HomeLayout, LetsGetStartedLayout, GetStartedLayout, DashboardLayout, DashboardAuth };
|
||||
@@ -4,10 +4,15 @@ import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
|
||||
import { Provider } from "react-redux";
|
||||
import store from "./store/store";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { HomeLayout } from "../layouts";
|
||||
import { PersonalHero } from "../components";
|
||||
|
||||
const BusinessBankingPage: React.FC = () => {
|
||||
return (
|
||||
<HomeLayout>
|
||||
<PersonalHero
|
||||
heading="Business Account"
|
||||
body="Open a personal or business account in minutes, tailored to your unique needs."
|
||||
buttonLink="#"
|
||||
buttonText="Click here"
|
||||
/>
|
||||
Business Banking
|
||||
</HomeLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default BusinessBankingPage;
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { HomeLayout } from "../layouts";
|
||||
import { PersonalHero } from "../components";
|
||||
|
||||
const CooperateBankingPage: React.FC = () => {
|
||||
return (
|
||||
<HomeLayout>
|
||||
<PersonalHero
|
||||
heading="Cooperate Account"
|
||||
body="Open a personal or business account in minutes, tailored to your unique needs."
|
||||
buttonLink="#"
|
||||
buttonText="Click here"
|
||||
/>
|
||||
Cooperate Banking
|
||||
</HomeLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default CooperateBankingPage;
|
||||
@@ -1,5 +1,9 @@
|
||||
import { DashboardProfile } from "../components";
|
||||
|
||||
export default function DashboardProfilePage() {
|
||||
return (
|
||||
<div>DashboardProfile</div>
|
||||
)
|
||||
<>
|
||||
<DashboardProfile />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
import React from "react";
|
||||
import { GetStarted as Main, Header, Footer } from "../components";
|
||||
import { GetStarted as Main } from "../components";
|
||||
import { GetStartedLayout, LetsGetStartedLayout } from "../layouts";
|
||||
import BVN from "../components/GetStarted/BVN";
|
||||
|
||||
const GetStartedPage: React.FC = () => {
|
||||
const [step, setStep] = React.useState(1);
|
||||
|
||||
const handleNextStep = () => {
|
||||
if (step < 5) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Header hideSidebar={true} hideMenu={true} />
|
||||
<Main />
|
||||
<Footer />
|
||||
{step == 1 ?
|
||||
<LetsGetStartedLayout>
|
||||
<BVN handleNextStep={handleNextStep} />
|
||||
</LetsGetStartedLayout>
|
||||
:
|
||||
<GetStartedLayout>
|
||||
<Main step={step} handleNextStep={handleNextStep} />
|
||||
</GetStartedLayout>
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { FC } from "react";
|
||||
import { Hero, Header, TopHeader, Requirements } from "../components";
|
||||
import React from "react";
|
||||
import { Hero, Requirements } from "../components";
|
||||
import { HomeLayout } from "../layouts";
|
||||
|
||||
const HomePage: FC = () => {
|
||||
const HomePage: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<TopHeader />
|
||||
<Header />
|
||||
<HomeLayout>
|
||||
<Hero />
|
||||
<Requirements />
|
||||
</>
|
||||
</HomeLayout>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import { HomeLayout } from '../layouts'
|
||||
|
||||
const InternetBankingPage: React.FC = () => {
|
||||
return (
|
||||
<HomeLayout>InternetBankingPage</HomeLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default InternetBankingPage
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { LetsGetStartedLayout } from "../layouts";
|
||||
import { LetsGetStarted } from "../components";
|
||||
|
||||
const LetsGetStatedPage: React.FC = () => {
|
||||
return (
|
||||
<LetsGetStartedLayout>
|
||||
<LetsGetStarted />
|
||||
</LetsGetStartedLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default LetsGetStatedPage;
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { HomeLayout } from "../layouts";
|
||||
import { PersonalHero } from "../components";
|
||||
|
||||
const PersonalBankingPage: React.FC = () => {
|
||||
return (
|
||||
<HomeLayout>
|
||||
<PersonalHero
|
||||
heading="Personal Or Business Account"
|
||||
body="Open a personal or business account in minutes, tailored to your unique needs."
|
||||
buttonLink="#"
|
||||
buttonText="Click here"
|
||||
/>
|
||||
Personal Banking
|
||||
</HomeLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default PersonalBankingPage;
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { HomeLayout } from "../layouts";
|
||||
import { TsAndCs } from "../components";
|
||||
|
||||
const TermsAndConditionPage: React.FC = () => {
|
||||
return (
|
||||
<HomeLayout>
|
||||
<TsAndCs />
|
||||
</HomeLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export default TermsAndConditionPage;
|
||||
@@ -6,5 +6,24 @@ import DashboardLegalsPage from "./DashboardLegalsPage";
|
||||
import DashboardProfilePage from "./DashboardProfilePage";
|
||||
import DashboardVerificationPage from "./DashboardVerificationPage";
|
||||
import DashboardpaymentsPage from "./DashboardPaymentsPage";
|
||||
import TermsAndConditionPage from "./TermsAndConditionPage";
|
||||
import PersonalBankingPage from "./PersonalBankingPage";
|
||||
import BusinessBankingPage from "./BusinessBankingPage";
|
||||
import CooperateBankingPage from "./CooperateBankingPage";
|
||||
import LetsGetStatedPage from "./LetsGetStatedPage";
|
||||
|
||||
export {HomePage, LoginPage, GetStartedPage, DashboardHomePage, DashboardLegalsPage, DashboardProfilePage, DashboardVerificationPage, DashboardpaymentsPage}
|
||||
export {
|
||||
HomePage,
|
||||
LoginPage,
|
||||
GetStartedPage,
|
||||
DashboardHomePage,
|
||||
DashboardLegalsPage,
|
||||
DashboardProfilePage,
|
||||
DashboardVerificationPage,
|
||||
DashboardpaymentsPage,
|
||||
TermsAndConditionPage,
|
||||
PersonalBankingPage,
|
||||
BusinessBankingPage,
|
||||
CooperateBankingPage,
|
||||
LetsGetStatedPage
|
||||
};
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import { RouteHandler } from "./routes";
|
||||
import { GetStartedPage, HomePage, LoginPage, DashboardHomePage, DashboardLegalsPage, DashboardProfilePage, DashboardVerificationPage, DashboardpaymentsPage } from "../pages";
|
||||
import { DashboardAuth } from "../components";
|
||||
import {
|
||||
GetStartedPage,
|
||||
HomePage,
|
||||
LoginPage,
|
||||
DashboardHomePage,
|
||||
DashboardLegalsPage,
|
||||
DashboardProfilePage,
|
||||
DashboardVerificationPage,
|
||||
DashboardpaymentsPage,
|
||||
TermsAndConditionPage,
|
||||
BusinessBankingPage,
|
||||
CooperateBankingPage,
|
||||
PersonalBankingPage,
|
||||
LetsGetStatedPage,
|
||||
} from "../pages";
|
||||
import { DashboardAuth } from "../layouts";
|
||||
|
||||
const Routers = () => {
|
||||
return (
|
||||
@@ -9,14 +23,51 @@ const Routers = () => {
|
||||
<Route path={RouteHandler.homepage} element={<HomePage />} />
|
||||
<Route path={RouteHandler.loginpage} element={<LoginPage />} />
|
||||
<Route path={RouteHandler.getStarted} element={<GetStartedPage />} />
|
||||
<Route
|
||||
path={RouteHandler.termsAndConditions}
|
||||
element={<TermsAndConditionPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.businessBanking}
|
||||
element={<BusinessBankingPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.cooperateBanking}
|
||||
element={<CooperateBankingPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.personalBanking}
|
||||
element={<PersonalBankingPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.letsGetStarted}
|
||||
element={<LetsGetStatedPage />}
|
||||
/>
|
||||
|
||||
{/* Dashboard */}
|
||||
<Route element={<DashboardAuth />}>
|
||||
<Route path={RouteHandler.dashboardHome} element={<DashboardHomePage />} />
|
||||
<Route path={RouteHandler.dashboardProfile} element={<DashboardProfilePage />} />
|
||||
<Route path={RouteHandler.dashboardVerification} element={<DashboardVerificationPage />} />
|
||||
<Route path={RouteHandler.dashboardPayments} element={<DashboardpaymentsPage />} />
|
||||
<Route path={RouteHandler.dashboardLegals} element={<DashboardLegalsPage />} />
|
||||
<Route
|
||||
path={RouteHandler.dashboardHome}
|
||||
element={<DashboardHomePage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.dashboardProfile}
|
||||
element={<DashboardProfilePage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.dashboardVerification}
|
||||
element={<DashboardVerificationPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.dashboardPayments}
|
||||
element={<DashboardpaymentsPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.dashboardLegals}
|
||||
element={<DashboardLegalsPage />}
|
||||
/>
|
||||
</Route>
|
||||
<Route path='*'element={<>Error Page</>} />
|
||||
<Route path="*" element={<>Error Page</>} />
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
export class RouteHandler {
|
||||
static homepage = "/"
|
||||
static loginpage = '/login'
|
||||
static getStarted = "/get-started"
|
||||
static dashboardHome = '/dashboard/home'
|
||||
static dashboardProfile = '/dashboard/profile'
|
||||
static dashboardVerification = '/dashboard/verification'
|
||||
static dashboardPayments = '/dashboard/payments'
|
||||
static dashboardLegals = '/dashboard/legals'
|
||||
}
|
||||
static homepage = "/";
|
||||
static loginpage = "/login";
|
||||
static personalBanking = "/personal-banking";
|
||||
static businessBanking = "/business-banking";
|
||||
static cooperateBanking = "/cooperate-banking";
|
||||
static letsGetStarted = "/lets-get-started";
|
||||
static getStarted = "/get-started";
|
||||
static dashboardHome = "/dashboard/home";
|
||||
static dashboardProfile = "/dashboard/profile";
|
||||
static dashboardVerification = "/dashboard/verification";
|
||||
static dashboardPayments = "/dashboard/payments";
|
||||
static dashboardLegals = "/dashboard/legals";
|
||||
static termsAndConditions = "/terms-and-conditions";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
userDetails: {},
|
||||
};
|
||||
|
||||
export const userSlice = createSlice({
|
||||
name: "userDetails",
|
||||
initialState,
|
||||
reducers: {
|
||||
updateUserDetails: (state, action) => {
|
||||
state.userDetails = { ...action.payload };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { updateUserDetails } = userSlice.actions;
|
||||
|
||||
export default userSlice.reducer;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
|
||||
import userDetailReducer from "./UserDetails";
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
userDetails: userDetailReducer,
|
||||
},
|
||||
});
|
||||
@@ -1,12 +1,21 @@
|
||||
import FBook from "../assets/icons/facebook.svg";
|
||||
import Twitter from "../assets/icons/twitter.svg";
|
||||
import Instagram from "../assets/icons/instagram.svg";
|
||||
import FBookWhite from "../assets/images/socials/facebook.svg";
|
||||
import LinkedInWhite from "../assets/images/socials/linkedin.svg";
|
||||
import XWhite from "../assets/images/socials/twitterx.svg";
|
||||
import WhatsappWhite from "../assets/images/socials/whatsapp.svg";
|
||||
import YoutubeWhite from "../assets/images/socials/youtube.svg";
|
||||
import InstagramWhite from "../assets/images/socials/instagram.svg";
|
||||
import { RouteHandler } from "../router/routes";
|
||||
|
||||
let process = import.meta.env;
|
||||
|
||||
export const top_header_data = [
|
||||
{ id: 1, name: "HOME" },
|
||||
{ id: 2, name: "PERSONAL" },
|
||||
{ id: 3, name: "BUSINESS" },
|
||||
{ id: 4, name: "CORPORATE" },
|
||||
{ id: 1, name: "HOME", href: RouteHandler.homepage },
|
||||
{ id: 2, name: "PERSONAL", href: RouteHandler.personalBanking },
|
||||
{ id: 3, name: "BUSINESS", href: RouteHandler.businessBanking },
|
||||
{ id: 4, name: "CORPORATE", href: RouteHandler.cooperateBanking },
|
||||
];
|
||||
|
||||
export const lowerMenuItems = [
|
||||
@@ -23,7 +32,7 @@ export const lowerMenuItems = [
|
||||
{
|
||||
id: 3,
|
||||
name: "CORPORATE BANKING",
|
||||
linkPath: "/corporate-banking",
|
||||
linkPath: "/cooperate-banking",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
@@ -42,8 +51,506 @@ export const lowerMenuItems = [
|
||||
},
|
||||
];
|
||||
|
||||
export const socialsIcons = [
|
||||
{ name: "facebook", image: FBook },
|
||||
{ name: "twitter", image: Twitter },
|
||||
{ name: "instagram", image: Instagram },
|
||||
export const _lowerMenuItems = [
|
||||
{
|
||||
name: "PERSONAL BANKING",
|
||||
linkPath: "/personal-banking",
|
||||
subItems: [
|
||||
{
|
||||
name: "CURRENT ACCOUNTS",
|
||||
linkPath: "/current-accounts",
|
||||
subItems: [
|
||||
{
|
||||
name: "CLASSIC CURRENT ACCOUNT",
|
||||
linkPath: "/personal-classic-current-account",
|
||||
},
|
||||
{
|
||||
name: "PREMIUM CURRENT ACCOUNT",
|
||||
linkPath: "/premium-current-account",
|
||||
},
|
||||
{
|
||||
name: "PERSONAL BUSINESS ACCOUNT",
|
||||
linkPath: "/personal-business-account",
|
||||
},
|
||||
{
|
||||
name: "DOMICILIARY CURRENT ACCOUNT",
|
||||
linkPath: "/domiciliary-current-account",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "SAVINGS ACCOUNTS",
|
||||
linkPath: "/savings-accounts",
|
||||
subItems: [
|
||||
{ name: "FCMB EASY ACCOUNT", linkPath: "/easy-account" },
|
||||
{ name: "KIDS (0-17 YRS)", linkPath: "/kids" },
|
||||
{ name: "FLEXX (18-30 YRS)", linkPath: "/flexx-account" },
|
||||
{
|
||||
name: "CLASSIC SAVINGS ACCOUNT",
|
||||
linkPath: "/classic-savings-account",
|
||||
},
|
||||
{
|
||||
name: "PREMIUM SAVINGS ACCOUNT",
|
||||
linkPath: "/fcmb-premium-savings-account",
|
||||
},
|
||||
{
|
||||
name: "FCMB SALARY SAVINGS ACCOUNT",
|
||||
linkPath: "/fcmb-salary-savings-account",
|
||||
},
|
||||
{
|
||||
name: "DOMICILIARY SAVINGS ACCOUNT",
|
||||
linkPath: "/domiciliary-savings-account",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "INVESTMENTS",
|
||||
linkPath: "/investment-accounts",
|
||||
subItems: [
|
||||
{ name: "FIXED DEPOSITS", linkPath: "/fixed-deposits" },
|
||||
{ name: "GRO (App)", linkPath: "/GRO" },
|
||||
{ name: "GRO (Web)", linkPath: "https://www.investwithgro.com/" },
|
||||
{
|
||||
name: "I-NEST SAVING",
|
||||
linkPath: "https://i-nest.fcmb.com/#/welcome",
|
||||
},
|
||||
{ name: "CALL DEPOSITS", linkPath: "/call-deposits" },
|
||||
{
|
||||
name: "EDUCATION INVESTMENT PLAN",
|
||||
linkPath: "/education-investment",
|
||||
},
|
||||
{
|
||||
name: "MUTUAL FUNDS",
|
||||
linkPath: "https://www.fcmbassetmanagement.com/mutual-funds/",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LOANS AND CREDIT CARDS",
|
||||
linkPath: "/loans-and-credit-cards",
|
||||
subItems: [
|
||||
{ name: "FASTCASH", linkPath: "/fastcash" },
|
||||
{ name: "SALARY PLUS LOAN", linkPath: "/salary-plus-loan" },
|
||||
{ name: "PREMIUM SALARY LOAN", linkPath: "/premium-salary-loan" },
|
||||
{ name: "AUTO LOAN", linkPath: "/auto-loan" },
|
||||
{ name: "AIRTIME LOAN", linkPath: "/airtime-loan" },
|
||||
{ name: "CREDIT CARDS", linkPath: "/credit-cards" },
|
||||
{
|
||||
name: "EASYLIFT LOAN",
|
||||
linkPath: "https://easyliftloanform.fcmb.com",
|
||||
},
|
||||
{ name: "MORTGAGE", linkPath: "http://mortgage.fcmb.com/" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "NON-RESIDENT NIGERIAN (NRN) BANKING",
|
||||
linkPath: "https://www.fcmb.com/non-resident-nigerian",
|
||||
},
|
||||
{
|
||||
name: "WAYS TO BANK",
|
||||
linkPath: "/ways-to-bank",
|
||||
subItems: [
|
||||
{ name: "FCMB MOBILE", linkPath: "/fcmb-mobile" },
|
||||
{
|
||||
name: "RETAIL INTERNET BANKING",
|
||||
linkPath: "https://ibank.fcmb.com/",
|
||||
},
|
||||
{ name: "USSD BANKING", linkPath: "/ussd" },
|
||||
{ name: "OUR BRANCH NETWORK", linkPath: "/branch-network" },
|
||||
{ name: "OUR ATM NETWORK", linkPath: "/atm-network" },
|
||||
{ name: "FLASHMECASH", linkPath: "/flashme-cash" },
|
||||
{ name: "OUR CARDS", linkPath: "/our-cards" },
|
||||
{ name: "FCMB ELECTRONIC CHANNELS", linkPath: "/e-channels" },
|
||||
{ name: "AGENT BANKING", linkPath: "/agent-banking" },
|
||||
{
|
||||
name: "FCMB SECURE COMMUNICATION",
|
||||
linkPath: "/secure-communication",
|
||||
},
|
||||
{ name: "TEMI", linkPath: "/temi" },
|
||||
],
|
||||
},
|
||||
{ name: "BANCASSURANCE", linkPath: "/bancassurance" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "BUSINESS BANKING",
|
||||
linkPath: "/business-banking",
|
||||
subItems: [
|
||||
{
|
||||
name: "PROPOSITIONS",
|
||||
linkPath: "",
|
||||
subItems: [
|
||||
{ name: "SHEVENTURES", linkPath: "/she-ventures" },
|
||||
{ name: "BUSINESS ZONE", linkPath: "https://businesszone.fcmb.com/" },
|
||||
{
|
||||
name: "FOOD BUSINESS SUPPORT",
|
||||
linkPath: "https://www.fcmb.com/food-business-support/",
|
||||
},
|
||||
{ name: "SCHOOL BUSINESS SUPPORT", linkPath: "/school-support" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "CURRENT ACCOUNTS",
|
||||
linkPath: "/business-current-accounts",
|
||||
subItems: [
|
||||
{
|
||||
name: "CORPORATE CURRENT ACCOUNT",
|
||||
linkPath: "/corporate-current-account",
|
||||
},
|
||||
{ name: "FCMB BUSINESS ACCOUNT", linkPath: "/fcmb-business-account" },
|
||||
{
|
||||
name: "DOMICILIARY CURRENT ACCOUNT",
|
||||
linkPath: "/business-domiciliary-current-account",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "SAVINGS ACCOUNTS",
|
||||
linkPath: "/node/178",
|
||||
subItems: [
|
||||
{
|
||||
name: "BUSINESS SAVINGS ACCOUNT",
|
||||
linkPath: "/business-savings-account",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LOANS",
|
||||
linkPath: "/business-loans",
|
||||
subItems: [
|
||||
{
|
||||
name: "SME DEVELOPMENT FINANCE FACILITY",
|
||||
linkPath: "/sme-development-finance-facility",
|
||||
},
|
||||
{
|
||||
name: "SME ASSET FINANCE FACILITY",
|
||||
linkPath: "/sme-asset-finance-facility",
|
||||
},
|
||||
{
|
||||
name: "SME WORKING CAPITAL FACILITY",
|
||||
linkPath: "/sme-working-capital-facility",
|
||||
},
|
||||
{ name: "QUICK LOAN", linkPath: "/quick-loan" },
|
||||
{
|
||||
name: "SME INVOICE DISCOUNTING FINANCE (IDF) FACILITY",
|
||||
linkPath: "/invoice-discounting-loan",
|
||||
},
|
||||
{
|
||||
name: "SME LOCAL PURCHASE ORDER (LPO) FINANCE FACILITY",
|
||||
linkPath: "/local-purchase-order-loan",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name: "BONDS & GUARANTEES", linkPath: "/bonds-and-guarantees" },
|
||||
{ name: "INTERVENTION FUNDS", linkPath: "/intervention-funds" },
|
||||
{ name: "TRADE SERVICE", linkPath: "/trade-service" },
|
||||
{
|
||||
name: "PAYMENT & COLLECTION",
|
||||
linkPath: "/payment-and-collection",
|
||||
subItems: [
|
||||
{ name: "COLLECTION SOLUTIONS", linkPath: "/collection-solutions" },
|
||||
{ name: "PAYMENT SOLUTIONS", linkPath: "/payment-solutions" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "WAYS TO BANK",
|
||||
linkPath: "/business-ways-to-bank",
|
||||
subItems: [
|
||||
{
|
||||
name: "BUSINESS INTERNET BANKING",
|
||||
linkPath: "https://ibank.fcmb.com/corporate/BbgLoginScreenUI.aspx",
|
||||
},
|
||||
{
|
||||
name: "CORPORATE INTERNET BANKING",
|
||||
linkPath: "https://www.fcmbonline.com/",
|
||||
},
|
||||
{ name: "OUR ATM NETWORK", linkPath: "/atm-network2" },
|
||||
{ name: "FCMB ONLINE", linkPath: "/fcmb-online-business" },
|
||||
{
|
||||
name: "FCMB ELECTRONIC CHANNELS",
|
||||
linkPath: "https://www.fcmb.com/e-channels",
|
||||
},
|
||||
{ name: "FCMB BUSINESS APP", linkPath: "/FCMB-business-app" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "CORPORATE BANKING",
|
||||
linkPath: "/cooperate-banking",
|
||||
subItems: [
|
||||
{
|
||||
name: "FOREIGN EXCHANGE SERVICES",
|
||||
linkPath: "/foreign-exchange-services",
|
||||
},
|
||||
{ name: "TRADE SERVICES", linkPath: "/node/166" },
|
||||
{ name: "CASH MANAGEMENT SOLUTIONS", linkPath: "/cash-management" },
|
||||
{ name: "CORPORATE FINANCE", linkPath: "/corporate-finance" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "GROUP & SUBSIDIARIES",
|
||||
linkPath: "",
|
||||
subItems: [
|
||||
{ name: "FCMB GROUP PLC", linkPath: "https://www.fcmbgroup.com/" },
|
||||
{
|
||||
name: "CSL STOCKBROKERS",
|
||||
linkPath: "https://www.cslstockbrokers.com/",
|
||||
},
|
||||
{
|
||||
name: "FCMB CAPITAL MARKETS",
|
||||
linkPath: "https://www.fcmbcapitalmarketsng.com/",
|
||||
},
|
||||
{
|
||||
name: "FCMB ASSET MANAGEMENT",
|
||||
linkPath: "https://www.fcmbassetmanagement.com/index/",
|
||||
},
|
||||
{
|
||||
name: "FCMB MICROFINANCE BANK",
|
||||
linkPath: "/fcmb-microfinance-initiative",
|
||||
},
|
||||
{ name: "FCMB UK", linkPath: "http://www.fcmbuk.com/" },
|
||||
{
|
||||
name: "FCMB PENSIONS LIMITED",
|
||||
linkPath: "https://www.fcmbpensions.com/",
|
||||
},
|
||||
{
|
||||
name: "CREDIT DIRECT LIMITED",
|
||||
linkPath: "https://www.creditdirect.ng",
|
||||
},
|
||||
{ name: "FCMB TRUSTEES", linkPath: "http://fcmbtrustees.com/" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ABOUT US",
|
||||
linkPath: "/about-us",
|
||||
subItems: [
|
||||
{
|
||||
name: "OUR VISION/MISSION/VALUES",
|
||||
linkPath: "/about-us/vision-mision-core-values",
|
||||
},
|
||||
{ name: "OUR HISTORY", linkPath: "/about-us/our-history" },
|
||||
{
|
||||
name: "INVESTOR RELATIONS",
|
||||
linkPath: "http://www.fcmbgroup.com/investor-relations",
|
||||
},
|
||||
{ name: "CSR", linkPath: "/corporate-social-responsibility/index.html" },
|
||||
{ name: "SUSTAINABILITY", linkPath: "/sustainability/index.html" },
|
||||
{ name: "OUR LEADERSHIP", linkPath: "/about-us/our-leadership" },
|
||||
{ name: "BOARD OF DIRECTORS", linkPath: "/about-us/board-of-directors" },
|
||||
{
|
||||
name: "MEDIA RELATIONS",
|
||||
linkPath: "/media-relations",
|
||||
subItems: [
|
||||
{ name: "PRESS RELEASES", linkPath: "/press-releases" },
|
||||
{ name: "MEDIA STATEMENTS", linkPath: "/press-statements" },
|
||||
],
|
||||
},
|
||||
{ name: "AWARDS AND RECOGNITION", linkPath: "/awards" },
|
||||
{
|
||||
name: "OUR POLICY",
|
||||
linkPath: "/our-policies",
|
||||
subItems: [
|
||||
{ name: "BUSINESS CONTINUITY", linkPath: "/business-continuity" },
|
||||
{
|
||||
name: "CORPORATE GOVERNANCE POLICY",
|
||||
linkPath: "/corporate-governance",
|
||||
},
|
||||
{ name: "PRIVACY POLICY", linkPath: "/privacy-policy" },
|
||||
{ name: "QUALITY POLICY", linkPath: "/quality-policy" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MY BANK AND I",
|
||||
linkPath: "",
|
||||
subItems: [
|
||||
{ name: "TELEPHONE SELF SERVICE", linkPath: "/telephone-self-service" },
|
||||
{
|
||||
name: "CURRENT CAMPAIGNS/PROMOS",
|
||||
linkPath: "/current-campaigns-promos",
|
||||
subItems: [
|
||||
{
|
||||
name: "BOOK YOUR FLIGHTS AND PAY IN INSTALMENTS WITH FCMB",
|
||||
linkPath: "/247travels",
|
||||
},
|
||||
{ name: "REFER AND WIN", linkPath: "/refer-and-win" },
|
||||
{ name: "CARD DISCOUNTS", linkPath: "/card-discounts" },
|
||||
{
|
||||
name: "FLEXX WRITING CHALLENGE",
|
||||
linkPath: "https://flexxzone.fcmb.com/writing-challenge/",
|
||||
},
|
||||
{
|
||||
name: "FLEXXPRENEUR",
|
||||
linkPath:
|
||||
"https://flexxzone.fcmb.com/2020/07/flexxpreneur-is-back-2/",
|
||||
},
|
||||
{
|
||||
name: "3-MONTH FREE BANKING",
|
||||
linkPath: "https://www.fcmb.com/campaign/smebanking",
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name: "CAREERS", linkPath: "/career" },
|
||||
{ name: "CUSTOMER FEEDBACK", linkPath: "/customer-feedback" },
|
||||
{ name: "CUSTOMER SERVICE", linkPath: "/customer-service" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const socialsIcons = [
|
||||
{ name: "facebook", image: FBook, link: process.VITE_FACEBOOK_URL },
|
||||
{ name: "twitter", image: Twitter, link: process.VITE_TWITTER_URL },
|
||||
{ name: "instagram", image: Instagram, link: process.VITE_INSTAGRAM_URL },
|
||||
];
|
||||
|
||||
export const footerItems = [
|
||||
{
|
||||
category: "PERSONAL BANKING",
|
||||
subItems: [
|
||||
{ text: "CURRENT ACCOUNTS", href: "/current-accounts" },
|
||||
{ text: "SAVINGS ACCOUNTS", href: "/savings-accounts" },
|
||||
{ text: "INVESTMENTS", href: "/investment-accounts" },
|
||||
{ text: "LOANS AND CREDIT CARDS", href: "/loans-and-credit-cards" },
|
||||
{
|
||||
text: "NON-RESIDENT NIGERIAN (NRN) BANKING",
|
||||
href: "https://www.fcmb.com/non-resident-nigerian",
|
||||
},
|
||||
{ text: "WAYS TO BANK", href: "/ways-to-bank" },
|
||||
{ text: "BANCASSURANCE", href: "/bancassurance" },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "BUSINESS BANKING",
|
||||
subItems: [
|
||||
{ text: "PROPOSITIONS", href: "" },
|
||||
{ text: "CURRENT ACCOUNTS", href: "/business-current-accounts" },
|
||||
{ text: "SAVINGS ACCOUNTS", href: "/node/178" },
|
||||
{ text: "LOANS", href: "/business-loans" },
|
||||
{ text: "BONDS & GUARANTEES", href: "/bonds-and-guarantees" },
|
||||
{ text: "INTERVENTION FUNDS", href: "/intervention-funds" },
|
||||
{ text: "TRADE SERVICE", href: "/trade-service" },
|
||||
{ text: "PAYMENT & COLLECTION", href: "/payment-and-collection" },
|
||||
{ text: "WAYS TO BANK", href: "/business-ways-to-bank" },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "COOPORATE BANKING",
|
||||
subItems: [
|
||||
{ text: "FOREIGN EXCHANGE SERVICES", href: "/foreign-exchange-services" },
|
||||
{ text: "TRADE SERVICES", href: "/node/166" },
|
||||
{ text: "CASH MANAGEMENT SOLUTIONS", href: "/cash-management" },
|
||||
{ text: "COOPORATE FINANCE", href: "/corporate-finance" },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "GROUP & SUBSIDIARIES",
|
||||
subItems: [
|
||||
{ text: "FCMB GROUP PLC", href: "https://www.fcmbgroup.com/" },
|
||||
{ text: "CSL STOCKBROKERS", href: "https://www.cslstockbrokers.com/" },
|
||||
{
|
||||
text: "FCMB CAPITAL MARKETS",
|
||||
href: "https://www.fcmbcapitalmarketsng.com/",
|
||||
},
|
||||
{
|
||||
text: "FCMB ASSET MANAGEMENT",
|
||||
href: "https://www.fcmbassetmanagement.com/index/",
|
||||
},
|
||||
{ text: "FCMB MICROFINANCE BANK", href: "/fcmb-microfinance-initiative" },
|
||||
{ text: "FCMB UK", href: "http://www.fcmbuk.com/" },
|
||||
{ text: "FCMB PENSIONS LIMITED", href: "https://www.fcmbpensions.com/" },
|
||||
{ text: "CREDIT DIRECT LIMITED", href: "https://www.creditdirect.ng" },
|
||||
{ text: "FCMB TRUSTEES", href: "http://fcmbtrustees.com/" },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "ABOUT US",
|
||||
subItems: [
|
||||
{
|
||||
text: "OUR VISION/MISSION/VALUES",
|
||||
href: "/about-us/vision-mision-core-values",
|
||||
},
|
||||
{ text: "OUR HISTORY", href: "/about-us/our-history" },
|
||||
{
|
||||
text: "INVESTOR RELATIONS",
|
||||
href: "http://www.fcmbgroup.com/investor-relations",
|
||||
},
|
||||
{ text: "CSR", href: "/corporate-social-responsibility/index.html" },
|
||||
{ text: "SUSTAINABILITY", href: "/sustainability/index.html" },
|
||||
{ text: "OUR LEADERSHIP", href: "/about-us/our-leadership" },
|
||||
{ text: "BOARD OF DIRECTORS", href: "/about-us/board-of-directors" },
|
||||
{ text: "MEDIA RELATIONS", href: "/media-relations" },
|
||||
{ text: "AWARDS AND RECOGNITION", href: "/awards" },
|
||||
{ text: "OUR POLICY", href: "/our-policies" },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "MY BANK AND I",
|
||||
subItems: [
|
||||
{ text: "TELEPHONE SELF SERVICE", href: "/telephone-self-service" },
|
||||
{ text: "CURRENT CAMPAIGNS/PROMOS", href: "/current-campaigns-promos" },
|
||||
{ text: "CAREERS", href: "/career" },
|
||||
{ text: "CUSTOMER FEEDBACK", href: "/customer-feedback" },
|
||||
{ text: "CUSTOMER SERVICE", href: "/customer-service" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const footerSocialLinks = [
|
||||
{
|
||||
href: "https://www.facebook.com/FcmbMyBank/",
|
||||
icon: FBookWhite,
|
||||
},
|
||||
{
|
||||
href: "https://twitter.com/myfcmb/",
|
||||
icon: XWhite,
|
||||
},
|
||||
{
|
||||
href: "https://www.linkedin.com/company/first-city-monument-bank-ltd/",
|
||||
icon: LinkedInWhite,
|
||||
},
|
||||
{
|
||||
href: "https://www.youtube.com/user/fcmbplc",
|
||||
icon: YoutubeWhite,
|
||||
},
|
||||
{
|
||||
href: "https://www.instagram.com/myfcmb/",
|
||||
icon: InstagramWhite,
|
||||
},
|
||||
{
|
||||
href: "https://api.whatsapp.com/send?phone=09099999814",
|
||||
icon: WhatsappWhite,
|
||||
},
|
||||
];
|
||||
|
||||
export const footerCustomerLinks = [
|
||||
{
|
||||
text: "PRIVACY POLICY",
|
||||
href: "https://www.fcmb.com/privacy-policy",
|
||||
},
|
||||
{
|
||||
text: "PRESS RELEASES",
|
||||
href: "/press-releases",
|
||||
},
|
||||
{
|
||||
text: "SHARE PRICE",
|
||||
href: "/",
|
||||
},
|
||||
{
|
||||
text: "WHISTLE BLOWER",
|
||||
href: "/fcmb-whistle-blower-form",
|
||||
},
|
||||
{
|
||||
text: "FRAUD PREVENTION",
|
||||
href: "/customer-service",
|
||||
},
|
||||
{
|
||||
text: "AML",
|
||||
href: "/customer-service",
|
||||
},
|
||||
{
|
||||
text: "CAREERS",
|
||||
href: "/career",
|
||||
},
|
||||
];
|
||||
|
||||