Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c1af302aa | |||
| 945a5425f0 | |||
| 25545ad47e | |||
| 5efc935f05 | |||
| 69c43e1d88 | |||
| cb23cbd57c | |||
| 9c8e7dada4 | |||
| 22814f7e10 | |||
| bc9e26aad1 | |||
| 5cacd0f073 | |||
| 475e5c46a1 | |||
| 4af2f7ef10 | |||
| c60f49dc90 | |||
| 157151e6d1 | |||
| 2f7f482293 | |||
| ee86d40bcc | |||
| 409acd300d | |||
| fc7edec093 | |||
| 4637944fbd | |||
| cc44af7e55 | |||
| df5b4c89a4 | |||
| a37a5c24f5 | |||
| 890452af63 | |||
| 69b6850002 | |||
| dd8290af9a | |||
| 306ab06142 | |||
| 4d258a965b | |||
| f63171273e | |||
| b4bf96e841 | |||
| e20b7e32f1 | |||
| 6bd533c7ca | |||
| 408777353d | |||
| a2e039eab4 | |||
| 8d6cc5861e | |||
| 18967d720c | |||
| 044b2ef917 | |||
| 4f7fdfb2ba | |||
| ab389d6632 | |||
| 29538e3b6e | |||
| dd2df0d695 | |||
| a97db9a661 | |||
| 135cbce348 | |||
| 814bfe041a | |||
| d90d515f60 | |||
| e93a3dea68 | |||
| a50d5ec82d | |||
| 333ada0a1c | |||
| bb718953ad | |||
| a31b36686d | |||
| 00f4e1b565 | |||
| 6d302def04 | |||
| 82dd11a772 | |||
| 7e9c395f4a | |||
| 2cb5c471f6 | |||
| 4b008f6785 | |||
| f632099128 | |||
| 122eb31732 | |||
| 0207bf631a | |||
| f88b6df24c |
@@ -3,4 +3,15 @@ DIGIFI_PORT=5173
|
||||
# Social Links
|
||||
FACEBOOK_URL=https://www.facebook.com
|
||||
TWITTER_URL=https://twitter.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
|
||||
# ENQUIRIES CONTACTS
|
||||
VITE_CALL_ENDPOINT='09099000000'
|
||||
VITE_EMAIL_ENDPOINT='fcmbloan@support.com'
|
||||
|
||||
#BANK NAME
|
||||
VITE_BANK_NAME='First City Monument Bank'
|
||||
VITE_BANK_NAME_SHORT='FCMB'
|
||||
+8
-1
@@ -3,4 +3,11 @@ 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
|
||||
VITE_INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
|
||||
#BANK NAME
|
||||
VITE_BANK_NAME='First City Monument Bank'
|
||||
VITE_BANK_NAME_SHORT='FCMB'
|
||||
+8
-1
@@ -3,4 +3,11 @@ DIGIFI_PORT=5173
|
||||
# Social Links
|
||||
FACEBOOK_URL=https://www.facebook.com
|
||||
TWITTER_URL=https://twitter.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
|
||||
#BANK NAME
|
||||
VITE_BANK_NAME='First City Monument Bank'
|
||||
VITE_BANK_NAME_SHORT='FCMB'
|
||||
+5
-2
@@ -11,10 +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:
|
||||
|
||||
Generated
+100
@@ -9,10 +9,12 @@
|
||||
"version": "0.0.0",
|
||||
"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",
|
||||
@@ -1805,6 +1807,11 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.18",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz",
|
||||
@@ -1842,6 +1849,16 @@
|
||||
"postcss": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.8",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
|
||||
"integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-macros": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
|
||||
@@ -2030,6 +2047,17 @@
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
@@ -2124,6 +2152,14 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
@@ -2550,6 +2586,25 @@
|
||||
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
|
||||
@@ -2565,6 +2620,19 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/formik": {
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/formik/-/formik-2.4.5.tgz",
|
||||
@@ -3078,6 +3146,25 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||
@@ -3532,6 +3619,11 @@
|
||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
|
||||
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
@@ -3588,6 +3680,14 @@
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
|
||||
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz",
|
||||
"integrity": "sha512-zdbW5GstTzXaVKvGSyTaBalt7HSfuK5ovrzlpyiWHAFXndXTdd/1hdDHI4xBM1Mn7YriT6aqESucFl9kEXzrdw==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"axios": "^1.6.8",
|
||||
"clsx": "2.1.0",
|
||||
"formik": "2.4.5",
|
||||
"react": "^18.2.0",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
@@ -0,0 +1,17 @@
|
||||
type Props = {
|
||||
width?: string
|
||||
height?: string
|
||||
}
|
||||
|
||||
export default function CustomSpinner({width='w-6', height='h-6'}:Props) {
|
||||
|
||||
return (
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" className={`inline ${width} ${height} text-gray-200 animate-spin dark:text-gray-600 fill-blue-600`} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
||||
</svg>
|
||||
{/* <span className="sr-only">Loading...</span> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,73 +1,116 @@
|
||||
import { Button, InputCompOne, Stepper } from "..";
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
// import { RouteHandler } from "../../router/routes";
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:()=>any
|
||||
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) {
|
||||
|
||||
// let navigate = useNavigate();
|
||||
// const navigateToProfile = () => navigate(RouteHandler.dashboardProfile);
|
||||
//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>
|
||||
<div className="mt-[3.25rem] flex flex-col gap-9">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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]"
|
||||
placeholder="350,000"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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]"
|
||||
// selectValue=''
|
||||
selectOptions={duration}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</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 Option {
|
||||
value: string;
|
||||
label: string;
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
|
||||
const duration: Option[] = [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "6", label: "6 Months" },
|
||||
{ value: "12", label: "12 Months" },
|
||||
{ value: "18", label: "18 Months" },
|
||||
{ value: "24", label: "24 Months" },
|
||||
];
|
||||
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" },
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,12 +10,14 @@ interface DashboardHomeProps {}
|
||||
|
||||
const DashboardHome: FC<DashboardHomeProps> = () => {
|
||||
const [step, setStep] = React.useState(1);
|
||||
const [applicationDetails, setApplicationDetails] = React.useState({});
|
||||
|
||||
const handleNextStep = () => {
|
||||
const handleNextStep = (values:{}={}) => {
|
||||
if (step < 7) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
};
|
||||
setApplicationDetails((prev:{}) => ({...prev, ...values}))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
@@ -24,8 +26,9 @@ const DashboardHome: FC<DashboardHomeProps> = () => {
|
||||
{step === 3 && <DashboardHomeDetail handleNextStep={handleNextStep} />}
|
||||
{step === 4 && <DashboardHomeEmploymentInfo handleNextStep={handleNextStep} />}
|
||||
{step === 5 && <DashboardHomeRefereeInfo handleNextStep={handleNextStep} />}
|
||||
{step === 6 && <DashboardHomeAttestation handleNextStep={handleNextStep} />}
|
||||
{step === 6 && <DashboardHomeAttestation handleNextStep={handleNextStep} applicationDetails={applicationDetails} />}
|
||||
{step === 7 && <DashboardHomeIntro step={step} handleNextStep={handleNextStep} />}
|
||||
{/* <DashboardHomeAttestation handleNextStep={handleNextStep} applicationDetails={applicationDetails} /> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import React, { FC } from "react";
|
||||
import NairaBag from "../../assets/images/dashboard/naira-bag.png";
|
||||
import { Button } from "../";
|
||||
import React, { FC, useState, useEffect } from 'react';
|
||||
import NairaBag from '../../assets/images/dashboard/naira-bag.png';
|
||||
import {useNavigate} from 'react-router-dom'
|
||||
import { Button, Icons } from '../';
|
||||
import { useSelector } from 'react-redux';
|
||||
import PendingList from '../paginated-list/PendingList';
|
||||
import { PendingTableList } from '../../core/models';
|
||||
import { NewDateTimeFormatter } from '../../lib/NewDateTimeFormatter';
|
||||
import { getUserPendingLoanList } from '../../core/apiRequest';
|
||||
import {FormatAmount} from '../../lib/FormatAmount'
|
||||
import PendingLoanPopout from './PendingLoanPopout';
|
||||
import { RouteHandler } from '../../router/routes';
|
||||
|
||||
export interface DashBoardCardProps {
|
||||
title?: string;
|
||||
@@ -50,7 +59,7 @@ export const DashBoardCard: React.FC<DashBoardCardProps> = ({
|
||||
)}
|
||||
{desc && (
|
||||
<p className={`text-lg text-left ${descClass && descClass}`}>
|
||||
{desc}{" "}
|
||||
{desc}{' '}
|
||||
{descSpan && (
|
||||
<span className={`${descSpanClass && descSpanClass}`}>
|
||||
{descSpan}
|
||||
@@ -68,50 +77,155 @@ export const DashBoardCard: React.FC<DashBoardCardProps> = ({
|
||||
};
|
||||
|
||||
interface DashboardHomeIntroProps {
|
||||
handleNextStep: any;
|
||||
step?:number|string
|
||||
handleNextStep: (value: {}) => any;
|
||||
step?: number | string;
|
||||
}
|
||||
|
||||
const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step }) => {
|
||||
interface PopoutProps<T> {
|
||||
show?: boolean
|
||||
data?: T
|
||||
}
|
||||
|
||||
const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({
|
||||
handleNextStep,
|
||||
step,
|
||||
}) => {
|
||||
|
||||
const navigate = useNavigate()
|
||||
const { userDetails } = useSelector((state: any) => state?.userDetails); // CHECKS IF USER Details are avaliable
|
||||
|
||||
const [loanPopout, setLoanPopout] = useState<PopoutProps<PendingTableList>>({show:false, data:{}})
|
||||
const closePopout = () => {
|
||||
setLoanPopout({show:false, data:{}})
|
||||
}
|
||||
|
||||
const [userLoanList, setUserLoanList] = useState<{
|
||||
loading: boolean;
|
||||
data: PendingTableList;
|
||||
}>({ loading: true, data: [] });
|
||||
|
||||
useEffect(() => {
|
||||
let token = localStorage.getItem('token');
|
||||
let uid = localStorage.getItem('uid');
|
||||
if (!token || !uid) {
|
||||
return;
|
||||
}
|
||||
getUserPendingLoanList(uid)
|
||||
.then((res) => {
|
||||
if (!res || !res.data.loans) {
|
||||
setUserLoanList({ loading: false, data: [] });
|
||||
return;
|
||||
}
|
||||
setUserLoanList({ loading: false, data: res?.data?.loans });
|
||||
})
|
||||
.catch((err) => {
|
||||
setUserLoanList({ loading: false, data: [] });
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{step == 1 ?
|
||||
<>
|
||||
<h1 className="font-bold my-5 text-2xl">Hello, Olanrewaju</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, Olanrewaju</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>
|
||||
</>
|
||||
}
|
||||
<div className="w-full">
|
||||
{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>
|
||||
</>
|
||||
)}
|
||||
{userLoanList.loading ? null : (
|
||||
<div className="mt-5 w-full">
|
||||
<PendingList
|
||||
data={userLoanList.data}
|
||||
itemsPerPage={5}
|
||||
tableTitle="Current Applications"
|
||||
>
|
||||
{(data: any) => (
|
||||
<div className="w-full p-4 rounded-lg shadow-lg bg-white overflow-x-auto min-h-[250px] max-h-[450px]">
|
||||
<table className="text-[12px] sm:text-base w-full table-auto">
|
||||
<thead>
|
||||
<tr className="text-left border-b-2">
|
||||
<th className="px-1 py-4">Date</th>
|
||||
<th className="px-1 py-4 text-right">Amount</th>
|
||||
<th className="px-1 py-4 text-center min-w-[110px]">
|
||||
Payment Term
|
||||
</th>
|
||||
<th className="px-1 py-4 text-center">Status</th>
|
||||
<th className="px-1 py-4 text-right">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((item: any, index: any) => (
|
||||
<tr key={index || item} className="even:bg-slate-100">
|
||||
<td className="px-1 py-2">
|
||||
{NewDateTimeFormatter(item?.added)}
|
||||
</td>
|
||||
<td className="px-1 py-2 text-right">
|
||||
{FormatAmount(item?.loan_amount)}
|
||||
</td>
|
||||
<td className="px-1 py-2 text-center">
|
||||
{item?.payment_month}
|
||||
</td>
|
||||
<td className="px-1 py-2 text-center">
|
||||
<button
|
||||
className={`${!item?.status_text?.button && 'pointer-events-none border-0'} border p-2`}
|
||||
onClick={()=>setLoanPopout({show:true, data:item})}
|
||||
>
|
||||
{item?.status_text?.text || 'Pending'}
|
||||
</button>
|
||||
</td>
|
||||
<td className="flex justify-end px-1 py-2 text-right">
|
||||
<button className="flex flex-nowrap items-center px-2 py-1 border-2 border-black" onClick={()=>navigate(RouteHandler.dashboardPayments, {state:{application_uid: item?.application_uid}})}>
|
||||
View
|
||||
<Icons name="arrow-right" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</PendingList>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{loanPopout.show && <PendingLoanPopout data={loanPopout.data} action={closePopout} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
import React, {useState} from 'react'
|
||||
import ModalWrapper from '../modal/ModalWrapper'
|
||||
import { PendingTableList } from '../../core/models'
|
||||
import { NewDateTimeFormatter } from '../../lib/NewDateTimeFormatter'
|
||||
import { addCard } from '../../core/apiRequest'
|
||||
import CustomSpinner from '../CustomSpinner'
|
||||
|
||||
|
||||
interface Props<T> {
|
||||
action: ()=>void
|
||||
data?: T
|
||||
}
|
||||
|
||||
export default function PendingLoanPopout({data, action}:Props<PendingTableList>) {
|
||||
|
||||
const [addCardStatus, setAddCardStatus] = useState<{
|
||||
loading: boolean;
|
||||
status: boolean
|
||||
msg: string
|
||||
}>({ loading: false, status: false, msg: ''});
|
||||
|
||||
const handleAddCard = (appID:string) => {
|
||||
let reqData = {
|
||||
application_uid: appID
|
||||
|
||||
}
|
||||
setAddCardStatus({ loading: true, status: false, msg: ''})
|
||||
addCard(reqData).then(res => {
|
||||
if(res?.data?.call_return != '100'){
|
||||
setAddCardStatus({ loading: false, status: false, msg: 'failed to add card'})
|
||||
setTimeout(()=>{
|
||||
setAddCardStatus({ loading: false, status: false, msg: ''})
|
||||
},3000)
|
||||
}
|
||||
window.location.href = res?.data?.redirect_url
|
||||
setAddCardStatus({ loading: false, status: true, msg: 'card added'})
|
||||
action() // TO CLOSE MODAL
|
||||
}).catch(err => {
|
||||
setAddCardStatus({ loading: false, status: false, msg: 'failed to add card'})
|
||||
console.log('ERR', err)
|
||||
setTimeout(()=>{
|
||||
setAddCardStatus({ loading: false, status: false, msg: ''})
|
||||
},3000)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<ModalWrapper>
|
||||
<div className='modal-container'>
|
||||
<div className='modal-header'>
|
||||
<h1 className='modal-title'>Add Card</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="modal-close-btn"
|
||||
name='cancel'
|
||||
onClick={action}
|
||||
>
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
viewBox="0 0 36 36"
|
||||
fill="none"
|
||||
className="fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
|
||||
fill=""
|
||||
fillOpacity="0.6"
|
||||
/>
|
||||
<path
|
||||
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
|
||||
fill="#"
|
||||
fillOpacity="0.6"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className='modal-body'>
|
||||
<div className='w-full flex flex-col gap-2'>
|
||||
<div className='py-2 w-full flex gap-1'>
|
||||
<p className='font-semibold'>ID :</p>
|
||||
<p>{data?.application_uid}</p>
|
||||
</div>
|
||||
<div className='py-2 w-full flex gap-1'>
|
||||
<p className='font-semibold'>Loan Amount :</p>
|
||||
<p>{data?.loan_amount}</p>
|
||||
</div>
|
||||
<div className='py-2 w-full flex gap-1'>
|
||||
<p className='font-semibold'>Payment Month :</p>
|
||||
<p>{data?.payment_month}</p>
|
||||
</div>
|
||||
<div className='py-2 w-full flex gap-1'>
|
||||
<p className='font-semibold'>Added :</p>
|
||||
<p>{NewDateTimeFormatter(data?.added)}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button onClick={action} name='cancel' className='custom-btn text-red-500 border border-red-500 hover:text-red-700'>Cancel</button>
|
||||
{addCardStatus.loading ?
|
||||
<CustomSpinner width='w-6' height='h-6' />
|
||||
:
|
||||
<button onClick={()=>handleAddCard(data?.application_uid)} name='proceed' className={`custom-btn border border-sky-500 text-sky-500 hover:text-sky-700 ${addCardStatus.loading && 'opacity-20 pointer-events-none'}`}>Add Card</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
import {useState, useEffect} from 'react'
|
||||
import { Button, InputCompOne } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
import { getEmployer } from '../../../core/apiRequest';
|
||||
import CustomSpinner from '../../CustomSpinner';
|
||||
import { FormatAmount } from '../../../lib/FormatAmount';
|
||||
|
||||
type Props = {
|
||||
handleNextStep?:(value:{})=>any
|
||||
}
|
||||
|
||||
// type EmployerProps = {
|
||||
// loading?: boolean,
|
||||
// data?: Array<{[index:string]: string}> | {[index:string]: Array<{[index:string]: string}> }
|
||||
// }
|
||||
|
||||
const initialValues = {
|
||||
job_title: "",
|
||||
name: "",
|
||||
job_sector: "",
|
||||
industry: "",
|
||||
start_date: "",
|
||||
official_email:"",
|
||||
annual_salary: "",
|
||||
net_montlty: "",
|
||||
salary_date: "",
|
||||
employee_id: "",
|
||||
highest_eductaion: "",
|
||||
employer_uid: "",
|
||||
isChecked: true
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
isChecked: Yup.bool(), // use bool instead of boolean
|
||||
// .oneOf([true, false], "You must accept the terms and conditions"),
|
||||
job_title: Yup.string()
|
||||
.required("Required"),
|
||||
name: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
otherwise: () => Yup.string(),
|
||||
}),
|
||||
job_sector: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
}),
|
||||
industry: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
}),
|
||||
start_date: Yup.string()
|
||||
.required("Required"),
|
||||
official_email : Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
})
|
||||
.email("Invalid"),
|
||||
annual_salary: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
net_montlty: Yup.string()
|
||||
.required("Required")
|
||||
.test("no-e", "Invalid", (value:any) => {
|
||||
if (value && /^[0-9]*$/.test(value) == false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
salary_date: Yup.string()
|
||||
.required("Required"),
|
||||
employee_id: Yup.string()
|
||||
.required("Required"),
|
||||
highest_eductaion: Yup.string()
|
||||
.required("Required"),
|
||||
employer_uid: Yup.string().when('isChecked', {
|
||||
is: false,
|
||||
then: () => Yup.string().required('required'),
|
||||
}),
|
||||
});
|
||||
|
||||
export default function EmploymentDetail({handleNextStep}:Props) {
|
||||
|
||||
const [employerList, setEmployerList] = useState<any>({
|
||||
loading: true,
|
||||
data: {}
|
||||
})
|
||||
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
// if(values.employer_uid){
|
||||
// let employer_uid = values.employer_uid
|
||||
// delete values.employer_uid
|
||||
// handleNextStep({employer_uid, employment: values})
|
||||
// }else{
|
||||
// handleNextStep({employment: values})
|
||||
// }
|
||||
console.log('good')
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
getEmployer().then(res => {
|
||||
setEmployerList({loading:false, data:res?.data?.employer})
|
||||
// console.log('RES', res)
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
setEmployerList({loading:false, data:{}})
|
||||
})
|
||||
},[])
|
||||
|
||||
const formInitialValue = (employerList.loading || Object.keys(employerList?.data)?.length < 1) ? initialValues : {...initialValues, ...employerList?.data}
|
||||
|
||||
return (
|
||||
<>
|
||||
{employerList.loading ?
|
||||
<div className='flex flex-col justify-center items-center h-96'>
|
||||
<CustomSpinner width='w-8' height='h-8' />
|
||||
</div>
|
||||
:
|
||||
<div className="w-full">
|
||||
<Formik
|
||||
initialValues={formInitialValue}
|
||||
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 flex-col lg:flex-row items-start gap-[2rem]">
|
||||
<div className='w-full lg:max-w-[30rem] flex flex-col'>
|
||||
{/* <div className='w-full gap-[2rem]'>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="employer_uid"
|
||||
floatLabel="Employer Name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={{loading:employersList?.loading, data: employersList?.data?.records}}
|
||||
selectValue={props.values.employer_uid}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employer_uid && props.touched.employer_uid) ? props.errors.employer_uid : ''}
|
||||
disabled={props.values.isChecked}
|
||||
/>
|
||||
<div className='flex gap-4 items-start my-2'>
|
||||
<input
|
||||
type='checkbox'
|
||||
name="isChecked"
|
||||
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}
|
||||
checked={props.values.isChecked}
|
||||
/>
|
||||
<p className='text-[12px] text-justify'>Check here if employer is not on the list</p>
|
||||
</div>
|
||||
<div className={`hidden p-4 ${props.values.isChecked && 'hidden'}`}>
|
||||
Name: {'Name'}
|
||||
</div>
|
||||
</div> */}
|
||||
<div className={`w-full flex flex-col gap-[2rem] ${!props.values.isChecked && 'hidden'}`}>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="name"
|
||||
floatLabel="Employer name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
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 : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="official_email"
|
||||
floatLabel="Employers official email"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="example@gmail.com"
|
||||
value={props.values.official_email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.official_email && props.touched.official_email) ? props.errors.official_email : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="industry"
|
||||
floatLabel="Select your industry"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
disabled={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={props.values.industry}
|
||||
selectValue={props.values.industry}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.industry && props.touched.industry) ? props.errors.industry : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="job_sector"
|
||||
floatLabel="Job Sector"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
disabled={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={props.values.job_sector}
|
||||
selectValue={props.values.job_sector}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.job_sector && props.touched.job_sector) ? props.errors.job_sector : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-full lg:max-w-[30rem] flex flex-col gap-[2rem]'>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="job_title"
|
||||
floatLabel="Job Title"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
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="w-full"
|
||||
name="highest_eductaion"
|
||||
floatLabel="Highest level of education"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
disabled={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 : ''}
|
||||
/>
|
||||
<div className="w-full flex flex-col sm:flex-row items-center gap-4">
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="start_date"
|
||||
floatLabel="Date of resumption"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
inputType='text'
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="12/12/2015"
|
||||
value={props.values.start_date}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.start_date && props.touched.start_date) ? props.errors.start_date : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="salary_date"
|
||||
floatLabel="Salary payment date"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
inputType='text'
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="30th of every month"
|
||||
value={(props.values.salary_date)}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.salary_date && props.touched.salary_date) ? props.errors.salary_date : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full flex flex-col sm:flex-row items-center gap-4">
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="annual_salary"
|
||||
floatLabel="Annual Income"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="1,200,000"
|
||||
value={FormatAmount(props.values.annual_salary)}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.annual_salary && props.touched.annual_salary) ? props.errors.annual_salary : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="net_montlty"
|
||||
floatLabel="Net monthly salary"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="100,000"
|
||||
value={FormatAmount(props.values.net_montlty)}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.net_montlty && props.touched.net_montlty) ? props.errors.net_montlty : ''}
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="employee_id"
|
||||
floatLabel="Employee ID"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
disabled={true}
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="LS/001/005"
|
||||
value={props.values.employee_id}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employee_id && props.touched.employee_id) ? props.errors.employee_id : ''}
|
||||
/>
|
||||
<div className="hidden w-full">
|
||||
<Button
|
||||
className="my-4 btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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" },
|
||||
]
|
||||
}
|
||||
@@ -1,46 +1,146 @@
|
||||
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:()=>any
|
||||
handleNextStep:(value:{})=>any
|
||||
applicationDetails: {}
|
||||
}
|
||||
|
||||
export default function DashboardHomeAttestation({handleNextStep}:Props) {
|
||||
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_account: values?.account, disbursement: values}).then(res=>{
|
||||
console.log('APPLY FOR LOAN', res)
|
||||
handleNextStep({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>
|
||||
<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="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
<div className='max-w-[25.875rem] flex gap-4 items-start'>
|
||||
<input type='checkbox' className='w-4 h-4 p-2 accent-purple-600 text-purple-600 bg-gray-100 border-gray-300 rounded focus:ring-purple-500' />
|
||||
<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>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Apply"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</div>
|
||||
<p className='text-red-500 text-base'>NB: Must be your {import.meta.env.VITE_BANK_NAME_SHORT} 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 {import.meta.env.VITE_BANK_NAME_SHORT}
|
||||
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'}
|
||||
// }
|
||||
@@ -1,105 +1,182 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import { state } from '../../../utils/states';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:()=>any
|
||||
handleNextStep:(value:{})=>any
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
gender: "",
|
||||
address: "",
|
||||
marital_status: "",
|
||||
state: "",
|
||||
email:"",
|
||||
country:"NG"
|
||||
};
|
||||
|
||||
// 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>
|
||||
<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="applyIshInput"
|
||||
label="Select your gender"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
// selectValue=''
|
||||
selectOptions={gender}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
label="Marital status"
|
||||
labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
// selectValue=''
|
||||
selectOptions={maritalStatus}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
<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]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
// selectValue=''
|
||||
selectOptions={state}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
</div>
|
||||
<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"
|
||||
/>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</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 Option {
|
||||
value: string;
|
||||
label: string;
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
|
||||
const gender: Option[] = [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "male", label: "Male" },
|
||||
{ value: "female", label: "Female" },
|
||||
{ value: "others", label: "Prefer not to say" },
|
||||
];
|
||||
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: Option[] = [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "single", label: "Single" },
|
||||
{ value: "married", label: "Married" },
|
||||
{ value: "divorced", label: "Divorced" },
|
||||
];
|
||||
const maritalStatus: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "single", label: "Single" },
|
||||
{ value: "married", label: "Married" },
|
||||
{ value: "divorced", label: "Divorced" },
|
||||
]
|
||||
}
|
||||
|
||||
const state: Option[] = [
|
||||
{ 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" },
|
||||
]
|
||||
}
|
||||
@@ -1,162 +1,353 @@
|
||||
import {useState, useEffect} from 'react'
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
import { getEmployersList } from '../../../core/apiRequest';
|
||||
|
||||
type Props = {
|
||||
handleNextStep:()=>any
|
||||
handleNextStep:(value:{})=>any
|
||||
}
|
||||
|
||||
// type EmployerProps = {
|
||||
// loading?: boolean,
|
||||
// data?: Array<{[index:string]: string}> | {[index:string]: Array<{[index:string]: string}> }
|
||||
// }
|
||||
|
||||
const initialValues = {
|
||||
job_title: "",
|
||||
name: "",
|
||||
sector: "",
|
||||
industry: "",
|
||||
resumption_date: "",
|
||||
email:"",
|
||||
annual_income: "",
|
||||
monthly_salary: "",
|
||||
salary_payment_date: "",
|
||||
employment_id: "",
|
||||
highest_eductaion: "",
|
||||
employer_uid: "",
|
||||
isChecked: false
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
const validationSchema = Yup.object().shape({
|
||||
isChecked: Yup.bool(), // use bool instead of boolean
|
||||
// .oneOf([true, false], "You must accept the terms and conditions"),
|
||||
job_title: Yup.string()
|
||||
.required("Required"),
|
||||
name: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
otherwise: () => Yup.string(),
|
||||
}),
|
||||
sector: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
}),
|
||||
industry: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
}),
|
||||
resumption_date: Yup.string()
|
||||
.required("Required"),
|
||||
email: Yup.string().when('isChecked', {
|
||||
is: true,
|
||||
then: () => Yup.string().required('required'),
|
||||
})
|
||||
.email("Invalid"),
|
||||
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"),
|
||||
employer_uid: Yup.string().when('isChecked', {
|
||||
is: false,
|
||||
then: () => Yup.string().required('required'),
|
||||
}),
|
||||
});
|
||||
|
||||
export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
|
||||
|
||||
const [employersList, setEmployersList] = useState<any>({
|
||||
loading: true,
|
||||
data: []
|
||||
})
|
||||
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
// Remember to changed the checked value's name
|
||||
if(values.employer_uid){
|
||||
let employer_uid = values.employer_uid
|
||||
delete values.employer_uid
|
||||
handleNextStep({employer_uid, employment: values})
|
||||
}else{
|
||||
handleNextStep({employment: values})
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
getEmployersList().then(res => {
|
||||
setEmployersList({loading:false, data:res?.data})
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
setEmployersList({loading:false, data:[]})
|
||||
})
|
||||
},[])
|
||||
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full flex justify-center">
|
||||
<Stepper step={2} />
|
||||
</div>
|
||||
<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="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Job Sector"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
// selectValue=''
|
||||
selectOptions={jobSection}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Select your industry"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
// selectValue=''
|
||||
selectOptions={industry}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Date of resumption"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="12/12/2015"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Annual Income"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="1,200,000"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Net monthly salary"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="100,000"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Salary payment date"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="30th of every month"
|
||||
/>{" "}
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
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]"
|
||||
// selectValue=''
|
||||
selectOptions={qualification}
|
||||
// onChange={()=>{}}
|
||||
/>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</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 flex-col lg:flex-row items-start gap-[2rem]">
|
||||
<div className='w-full lg:max-w-[30rem] flex flex-col'>
|
||||
<div className='w-full gap-[2rem]'>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
name="employer_uid"
|
||||
floatLabel="Employer Name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={{loading:employersList?.loading, data: employersList?.data?.records}}
|
||||
selectValue={props.values.employer_uid}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employer_uid && props.touched.employer_uid) ? props.errors.employer_uid : ''}
|
||||
disabled={props.values.isChecked}
|
||||
/>
|
||||
<div className='flex gap-4 items-start my-2'>
|
||||
<input
|
||||
type='checkbox'
|
||||
name="isChecked"
|
||||
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}
|
||||
checked={props.values.isChecked}
|
||||
/>
|
||||
<p className='text-[12px] text-justify'>Check here if employer is not on the list</p>
|
||||
</div>
|
||||
<div className={`hidden p-4 ${props.values.isChecked && 'hidden'}`}>
|
||||
Name: {'Name'}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`w-full flex flex-col gap-[2rem] ${!props.values.isChecked && 'hidden'}`}>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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 : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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 : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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 : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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 : ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='w-full lg:max-w-[30rem] flex flex-col gap-[2rem]'>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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="w-full"
|
||||
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 : ''}
|
||||
/>
|
||||
<div className="w-full flex flex-col sm:flex-row items-center gap-4">
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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="w-full"
|
||||
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 : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full flex flex-col sm:flex-row items-center gap-4">
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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="w-full"
|
||||
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>
|
||||
<InputCompOne
|
||||
parentClass="w-full"
|
||||
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 className="w-full">
|
||||
<Button
|
||||
className="my-4 btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
interface Option {
|
||||
value: string;
|
||||
label: string;
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
|
||||
const jobSection: Option[] = [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "private (non academic)", label: "Private (non academic)" },
|
||||
];
|
||||
const jobSector: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "private (non academic)", label: "Private (non academic)" },
|
||||
]
|
||||
}
|
||||
|
||||
const industry: Option[] = [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "engineering", label: "Engineering" },
|
||||
];
|
||||
const industry: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "engineering", label: "Engineering" },
|
||||
]
|
||||
}
|
||||
|
||||
const qualification: Option[] = [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "b.sc + professional qualification", label: "B.Sc + Professional Qualification" },
|
||||
];
|
||||
const highestEductaion: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "b.sc + professional qualification", label: "B.Sc + Professional Qualification" },
|
||||
]
|
||||
}
|
||||
@@ -1,126 +1,244 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
type Props = {
|
||||
handleNextStep:()=>any
|
||||
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>
|
||||
<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="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Relationship"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Sister"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="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"
|
||||
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"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="BVN"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="2228457896"
|
||||
/>
|
||||
</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="applyIshInput"
|
||||
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"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="Relationship"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Sister"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="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"
|
||||
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"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="applyIshInput"
|
||||
floatLabel="BVN"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="2228457896"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
import {useEffect, useState} from 'react'
|
||||
import {useLocation, useNavigate} from 'react-router-dom'
|
||||
import { Button, InputCompOne } from "../../shared";
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
import { RouteHandler } from '../../../router/routes';
|
||||
import { getLoanDetail } from '../../../core/apiRequest';
|
||||
import CustomSpinner from '../../CustomSpinner';
|
||||
|
||||
|
||||
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 ReferenceDetails() {
|
||||
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const applicationUID = location?.state?.application_uid
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:{}) => {
|
||||
// handleNextStep(values)
|
||||
};
|
||||
|
||||
const [loanDetail, setLoanDetail] = useState<any>({
|
||||
loading: true,
|
||||
data: {}
|
||||
})
|
||||
|
||||
useEffect(()=>{
|
||||
if(!applicationUID){
|
||||
navigate(RouteHandler.dashboardHome)
|
||||
}
|
||||
getLoanDetail({application_uid:applicationUID}).then(res => {
|
||||
setLoanDetail({loading:false, data:res?.data?.loan})
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
setLoanDetail({loading:false, data:{}})
|
||||
})
|
||||
},[])
|
||||
|
||||
const formInitialValue = (loanDetail.loading || Object.keys(loanDetail?.data)?.length < 1) ? initialValues : loanDetail?.data
|
||||
return (
|
||||
<>
|
||||
{loanDetail.loading ?
|
||||
<div className='flex flex-col justify-center items-center h-96'>
|
||||
<CustomSpinner width='w-8' height='h-8' />
|
||||
</div>
|
||||
:
|
||||
<div className="w-full">
|
||||
<Formik
|
||||
initialValues={formInitialValue}
|
||||
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'>Loan Details</p>
|
||||
<div className='w-full flex flex-wrap items-center gap-4'>
|
||||
<InputCompOne
|
||||
parentClass="w-full sm:max-w-[10rem] flex flex-col gap-4"
|
||||
name="loan_amount"
|
||||
label="Amount"
|
||||
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="w-full sm:max-w-[10rem] flex flex-col gap-4"
|
||||
name="payment_month"
|
||||
label="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="w-full sm:max-w-[10rem] flex flex-col gap-4"
|
||||
name="sales_agent"
|
||||
label="agent ID"
|
||||
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 : ''}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
className="hidden 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" },
|
||||
]
|
||||
}
|
||||
@@ -17,7 +17,7 @@ const BottomFooterOne = () => {
|
||||
<CustomerLinks />
|
||||
</div>
|
||||
<p className="text-[.8125rem] text-[#333] leading-[1.42857]">
|
||||
© <span>{date}</span> First City Monument Bank (Licensed by the
|
||||
© <span>{date}</span> {import.meta.env.VITE_BANK_NAME} (Licensed by the
|
||||
Central Bank of Nigeria)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ export default function Footer() {
|
||||
<div className="w-full h-[5.4375rem] bg-[F7F7F7] flex items-center">
|
||||
<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
|
||||
{date} @ {import.meta.env.VITE_BANK_NAME} Limited
|
||||
</p>
|
||||
<div className="footer-social-icons flex justify-end items-center gap-2">
|
||||
{renderSocialLinks()}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import DebitAccount from "./DebitAccount";
|
||||
|
||||
|
||||
const ApplicantsAttestation: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -32,6 +32,7 @@ const BVN = ({handleNextStep}:Props) => {
|
||||
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log('values', values)
|
||||
handleNextStep()
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -70,7 +71,6 @@ const BVN = ({handleNextStep}:Props) => {
|
||||
<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"
|
||||
onClick={handleNextStep}
|
||||
>
|
||||
Enter
|
||||
</button>
|
||||
|
||||
@@ -1,61 +1,87 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import InputDetails from "./IntroDetails";
|
||||
import OTPSection from "./OtpSection";
|
||||
import SpouseDetails from "./SpouseDetails";
|
||||
import { Button } from "..";
|
||||
import React from "react";
|
||||
|
||||
// interface Option {
|
||||
// value: string;
|
||||
// label: string;
|
||||
// }
|
||||
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 {
|
||||
inputValues: {
|
||||
title: string;
|
||||
marital: string;
|
||||
agentId: string;
|
||||
bvn: string;
|
||||
firstName: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
surname: string;
|
||||
dob: string;
|
||||
secondName: string;
|
||||
spouseBVN: string;
|
||||
};
|
||||
setInputValues: React.Dispatch<React.SetStateAction<any>>;
|
||||
handleNextStep: any;
|
||||
}
|
||||
|
||||
const BasicInfo: React.FC<BasicInfoProps> = ({
|
||||
inputValues,
|
||||
setInputValues,
|
||||
handleNextStep,
|
||||
}) => {
|
||||
const [hideOTPComponent, setHideOTPComponent] = useState<boolean>(false);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
// const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleChange = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target as HTMLInputElement;
|
||||
setInputValues((prev: typeof inputValues) => ({ ...prev, [name]: value }));
|
||||
};
|
||||
// const handleInput = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
// const { name, value } = e.target as HTMLInputElement;
|
||||
|
||||
const handleInput = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target as HTMLInputElement;
|
||||
// if (name === "bvn") {
|
||||
// const isNumeric = /^[0-9]+$/.test(value);
|
||||
|
||||
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");
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
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 (
|
||||
@@ -64,38 +90,222 @@ const BasicInfo: React.FC<BasicInfoProps> = ({
|
||||
<h1 className="font-semibold text-[2.375rem] text-[#5C2684] my-[.5rem]">
|
||||
Let’s Get You Started
|
||||
</h1>
|
||||
<form>
|
||||
<InputDetails
|
||||
inputValues={inputValues}
|
||||
handleChange={handleChange}
|
||||
handleInput={handleInput}
|
||||
inputRef={inputRef}
|
||||
/>
|
||||
{!hideOTPComponent && (
|
||||
<>
|
||||
<OTPSection
|
||||
inputValues={inputValues}
|
||||
handleChange={handleChange}
|
||||
handleInput={handleInput}
|
||||
inputRef={inputRef}
|
||||
/>
|
||||
<SpouseDetails
|
||||
inputValues={inputValues}
|
||||
handleChange={handleChange}
|
||||
handleInput={handleInput}
|
||||
inputRef={inputRef}
|
||||
/>
|
||||
<Button
|
||||
className="mt-8 btn-R bg-[#5A2C82]"
|
||||
text="Enter"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</form>
|
||||
<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" },
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,8 +3,40 @@ 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">
|
||||
@@ -12,78 +44,101 @@ const DebitAccount: React.FC = () => {
|
||||
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]"
|
||||
/>
|
||||
<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="bankName"
|
||||
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]"
|
||||
/>
|
||||
<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="accountNumber"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[471px] w-full ml-5"
|
||||
label="Account Name"
|
||||
name="accountName"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
<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}
|
||||
defaultChecked
|
||||
// onChange={onChange}
|
||||
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>
|
||||
</div>
|
||||
<Button
|
||||
className="my-8 max-w-[33.875rem] btn-R bg-[#5A2C82] w-full h-11"
|
||||
text="Apply"
|
||||
type="button"
|
||||
onClick={()=>navigate(RouteHandler.letsGetStarted, {replace:true})}
|
||||
/>
|
||||
</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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
import React from "react";
|
||||
import { InputCompOne } from "..";
|
||||
|
||||
const EmploymentDetails: 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">
|
||||
EMPLOYMENT DETAILS
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[17.9375rem] w-full"
|
||||
label="Job Title"
|
||||
name="jobTitle"
|
||||
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]"
|
||||
/>
|
||||
<div className="flex items-center gap-[3.6875rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Employer’s Name"
|
||||
name="employerName"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Employer’s Official Email"
|
||||
name="employerOfficialEmail"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[9rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[17.9375rem] w-full"
|
||||
label="Resumption Date"
|
||||
name="resumptionDate"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[17.9375rem] w-full"
|
||||
label="Employee ID."
|
||||
name="employeeID"
|
||||
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] px-[.125rem] rounded-[.375rem]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[3.6875rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Salary ( Gross annual income )"
|
||||
name="salaryGross"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[23.1875rem] w-full"
|
||||
label="Salary ( Net monthly Income )"
|
||||
name="salaryNet"
|
||||
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]"
|
||||
/>
|
||||
</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
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] px-[.125rem] rounded-[.375rem]"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmploymentDetails;
|
||||
@@ -1,35 +1,9 @@
|
||||
import React 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 [step, setStep] = React.useState(1);
|
||||
|
||||
// const handleNextStep = () => {
|
||||
// if (step < 5) {
|
||||
// setStep(step + 1);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const handlePreviousStep: React.MouseEvent<HTMLButtonElement> = () => {
|
||||
// setStep(step - 1);
|
||||
// };
|
||||
|
||||
const [inputValues, setInputValues] = React.useState({
|
||||
title: "",
|
||||
marital: "",
|
||||
agentId: "",
|
||||
bvn: "",
|
||||
firstName: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
surname: "",
|
||||
dob: "",
|
||||
secondName: "",
|
||||
spouseBVN: "",
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="w-full flex items-center justify-center">
|
||||
@@ -38,8 +12,6 @@ const GetStarted = ({handleNextStep, step}:{handleNextStep:any, step:string|numb
|
||||
<main>
|
||||
{step === 2 && (
|
||||
<BasicInfo
|
||||
inputValues={inputValues}
|
||||
setInputValues={setInputValues}
|
||||
handleNextStep={handleNextStep}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
import React from "react";
|
||||
import InputCompOne from "../shared/InputCompOne";
|
||||
|
||||
interface Option {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface InputSectionProps {
|
||||
inputValues: {
|
||||
title: string;
|
||||
marital: string;
|
||||
agentId: string;
|
||||
bvn: string;
|
||||
};
|
||||
handleChange: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
handleInput: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
inputRef: React.RefObject<HTMLInputElement>;
|
||||
}
|
||||
|
||||
const InputSection: React.FC<InputSectionProps> = ({
|
||||
inputValues,
|
||||
handleChange,
|
||||
handleInput,
|
||||
inputRef,
|
||||
}) => {
|
||||
const basicInfoInputFields = [
|
||||
{
|
||||
label: "Title",
|
||||
name: "title",
|
||||
parentInputClass: "max-w-[224px] w-full",
|
||||
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,
|
||||
value: inputValues.title,
|
||||
},
|
||||
{
|
||||
label: "Marital Status",
|
||||
name: "marital",
|
||||
parentInputClass: "max-w-[224px] w-full",
|
||||
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,
|
||||
value: inputValues.marital,
|
||||
onInput: handleInput,
|
||||
},
|
||||
{
|
||||
label: "Direct Sales Agent ID",
|
||||
name: "agentId",
|
||||
parentInputClass: "max-w-[224px] w-full",
|
||||
labelClass:
|
||||
"font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#5C2684] mb-[2px]",
|
||||
select: true,
|
||||
selectClass: "w-full h-[36px] rounded-[6px]",
|
||||
selectOptions: [{ value: "", label: "Select" }],
|
||||
value: inputValues.agentId,
|
||||
onInput: handleInput,
|
||||
},
|
||||
{
|
||||
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] px-[2px] rounded-[6px]",
|
||||
value: inputValues.bvn,
|
||||
onInput: handleInput,
|
||||
maxLength: 10,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<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]">
|
||||
{basicInfoInputFields.map((field, index) => (
|
||||
<InputCompOne
|
||||
key={index}
|
||||
label={field.label}
|
||||
name={field.name}
|
||||
parentInputClass={field.parentInputClass}
|
||||
labelClass={field.labelClass}
|
||||
select={field.select}
|
||||
selectClass={field.selectClass}
|
||||
selectOptions={field.selectOptions}
|
||||
value={field.value}
|
||||
onChange={handleChange}
|
||||
onInput={field.onInput}
|
||||
placeholder={field.placeholder}
|
||||
labelSpan={field.labelSpan}
|
||||
labelSpanClass={field.labelSpanClass}
|
||||
input={field.input}
|
||||
inputClass={field.inputClass}
|
||||
maxLength={field.maxLength}
|
||||
ref={inputRef}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputSection;
|
||||
|
||||
const maritalStatusOptions: Option[] = [
|
||||
{ value: "", label: "Select" },
|
||||
{ value: "single", label: "Single" },
|
||||
{ value: "married", label: "Married" },
|
||||
{ value: "divorced", label: "Divorced" },
|
||||
{ value: "widowed", label: "Widowed" },
|
||||
];
|
||||
|
||||
const titleOptions: Option[] = [
|
||||
{ value: "", label: "Select" },
|
||||
{ value: "ms", label: "Ms" },
|
||||
{ value: "mr", label: "Mr" },
|
||||
{ value: "miss", label: "Miss" },
|
||||
{ value: "mrs", label: "Mrs" },
|
||||
];
|
||||
@@ -1,20 +1,56 @@
|
||||
import React from "react";
|
||||
import { Button, InputCompOne } from "..";
|
||||
|
||||
interface SliderProps {
|
||||
handleSliderChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
value: number;
|
||||
}
|
||||
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 [value, setValue] = React.useState(6);
|
||||
|
||||
const handleSliderChange = (e: any) => {
|
||||
setValue(e.target.value);
|
||||
// const handleSliderChange = (e: any) => {
|
||||
// setValue(e.target.value);
|
||||
// };
|
||||
|
||||
//FUNCTION TO HANDLE SUBMIT
|
||||
const handleSubmit = (values:any) => {
|
||||
console.log(values)
|
||||
handleNextStep()
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -35,95 +71,132 @@ const LoanAmountComp: React.FC<LoanAmountProps> = ({ handleNextStep }) => {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<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="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"
|
||||
/>
|
||||
<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"
|
||||
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"
|
||||
/>
|
||||
<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="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="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>
|
||||
|
||||
<Slider handleSliderChange={handleSliderChange} value={value} />
|
||||
<>
|
||||
<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="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</div>
|
||||
</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>
|
||||
);
|
||||
};
|
||||
// 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>
|
||||
// );
|
||||
// };
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
import React from "react";
|
||||
import InputCompOne from "../shared/InputCompOne";
|
||||
|
||||
interface OTPSectionProps {
|
||||
inputValues: {
|
||||
firstName: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
surname: string;
|
||||
dob: string;
|
||||
secondName: string;
|
||||
};
|
||||
handleChange: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
handleInput: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
inputRef: React.RefObject<HTMLInputElement>;
|
||||
}
|
||||
|
||||
const OTPSection: React.FC<OTPSectionProps> = ({
|
||||
inputValues,
|
||||
handleChange,
|
||||
handleInput,
|
||||
inputRef,
|
||||
}) => {
|
||||
return (
|
||||
<div className="mt-5">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="First Name"
|
||||
name="firstName"
|
||||
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={inputValues.firstName}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<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] px-[.125rem] rounded-[.375rem]"
|
||||
value={inputValues.phone}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<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] px-[.125rem] rounded-[.375rem]"
|
||||
value={inputValues.email}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
|
||||
<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] px-[.125rem] rounded-[.375rem] px-3"
|
||||
value={inputValues.surname}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<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
|
||||
inputClass="w-full h-[2.25rem] bg-[#EFEFEF] px-[.125rem] rounded-[.375rem] px-3"
|
||||
value={inputValues.dob}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem]"
|
||||
label="Second Name"
|
||||
name="secondName"
|
||||
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] px-3"
|
||||
value={inputValues.secondName}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OTPSection;
|
||||
@@ -1,126 +0,0 @@
|
||||
import React from "react";
|
||||
import { InputCompOne } from "..";
|
||||
|
||||
const ReferenceDetails: 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">
|
||||
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="referenceName"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Relationship with He/She"
|
||||
name="referenceRelationship"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[6.5625rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Phone Number"
|
||||
name="referencePhoneNumber"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Email Address"
|
||||
name="referenceEmail"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="BVN"
|
||||
name="ReferenceBvn"
|
||||
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]"
|
||||
/>
|
||||
</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="referenceName2"
|
||||
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] px-[.125rem] rounded-[.375rem]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Relationship with He/She"
|
||||
name="referenceRelationship2"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[6.5625rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Phone Number"
|
||||
name="referencePhoneNumber2"
|
||||
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]"
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="Email Address"
|
||||
name="referenceEmail2"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[20.3125rem] w-full"
|
||||
label="BVN"
|
||||
name="ReferenceBvn2"
|
||||
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]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReferenceDetails;
|
||||
@@ -1,49 +0,0 @@
|
||||
import React from "react";
|
||||
import { InputCompOne } from "..";
|
||||
|
||||
interface SpouseDetailsProps {
|
||||
inputValues: {
|
||||
spouseBVN: string;
|
||||
};
|
||||
handleChange: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
handleInput: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
inputRef: React.RefObject<HTMLInputElement>;
|
||||
}
|
||||
|
||||
const SpouseDetails: React.FC<SpouseDetailsProps> = ({
|
||||
inputValues,
|
||||
handleChange,
|
||||
handleInput,
|
||||
inputRef,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<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="spouseBVN"
|
||||
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] px-[.125rem] rounded-[.375rem]"
|
||||
value={inputValues.spouseBVN}
|
||||
onChange={handleChange}
|
||||
onInput={handleInput}
|
||||
ref={inputRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SpouseDetails;
|
||||
@@ -1,29 +1,400 @@
|
||||
import React from "react";
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
import EmploymentDetails from "./EmploymentDetails";
|
||||
import ReferenceDetails from "./ReferenceDetails";
|
||||
import { Button } from "..";
|
||||
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>
|
||||
<form action="" className="flex flex-col gap-6">
|
||||
<EmploymentDetails />
|
||||
<ReferenceDetails />
|
||||
<Button
|
||||
className="my-8 max-w-[20.3125rem] btn-R bg-[#5A2C82]"
|
||||
text="Continue"
|
||||
type="button"
|
||||
onClick={handleNextStep}
|
||||
/>
|
||||
</form>
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ const Header: React.FC<HiddenMenuItems> = ({
|
||||
<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">
|
||||
{[
|
||||
{ text: "Open An Account", href: RouteHandler.getStarted },
|
||||
{ text: "Open An Account", href: RouteHandler.letsGetStarted },
|
||||
{
|
||||
text: "Internet Banking",
|
||||
href: RouteHandler.businessBanking,
|
||||
|
||||
@@ -12,7 +12,7 @@ const EligiblityBox = () => {
|
||||
You must have a valid BVN
|
||||
</li>
|
||||
<li className="text-base leading-[1.5625rem]">
|
||||
Must have a salary or current bank account with FCMB
|
||||
Must have a salary or current bank account with {import.meta.env.VITE_BANK_NAME_SHORT}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FaCaretDown } from "react-icons/fa";
|
||||
import { FaCaretDown, FaCaretRight } from "react-icons/fa";
|
||||
|
||||
import dashIcon from "../../assets/images/dashboard/dashDefault.svg";
|
||||
type Props = {
|
||||
@@ -111,6 +111,8 @@ export default function Icons({ name, fillColor, className }: Props) {
|
||||
</svg>
|
||||
) :name == 'arrow-down'?
|
||||
<FaCaretDown className={`text-xl ${className && className}`} />
|
||||
:name == 'arrow-right'?
|
||||
<FaCaretRight className={`text-xl ${className && className}`} />
|
||||
:name == "dash-icon" ? (
|
||||
<img src={dashIcon} alt="dash-icon" />
|
||||
) : null}
|
||||
|
||||
@@ -1,32 +1,42 @@
|
||||
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 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"),
|
||||
.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()
|
||||
.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"),
|
||||
// .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;
|
||||
@@ -41,123 +51,208 @@ let initialValues = {
|
||||
otp: '',
|
||||
};
|
||||
|
||||
type ValidBVN = {
|
||||
verification_id: string;
|
||||
valid: undefined | boolean;
|
||||
};
|
||||
|
||||
const LetsGetStarted: React.FC = () => {
|
||||
const navigate = useNavigate()
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
// const [pinValues, setPinValues] = React.useState({
|
||||
// bvn: "",
|
||||
// otp: "",
|
||||
// });
|
||||
// const otpInputRef = React.useRef<HTMLInputElement>(null);
|
||||
|
||||
const [hideOTPComponent, setHideOTPComponent] = React.useState<boolean>(true);
|
||||
const firstInputRef = React.useRef<HTMLInputElement>(null);
|
||||
const secondInputRef = React.useRef<HTMLInputElement>(null);
|
||||
const [requestStatusBVN, setRequestStatusBVN] = React.useState<RequestStatus>(
|
||||
{ loading: false, status: undefined, message: '' }
|
||||
);
|
||||
|
||||
// const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// let { name, value } = e.target as HTMLInputElement;
|
||||
const [requestStatusOTP, setRequestStatusOTP] = React.useState<RequestStatus>(
|
||||
{ loading: false, status: undefined, message: '' }
|
||||
);
|
||||
|
||||
// setPinValues((prev) => ({ ...prev, [name]: value }));
|
||||
// };
|
||||
const [bvnIsValid, setBvnIsValid] = React.useState<ValidBVN>({
|
||||
verification_id: '',
|
||||
valid: undefined,
|
||||
});
|
||||
|
||||
const handleInput = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
let { name, value } = e.target as HTMLInputElement;
|
||||
|
||||
if (name === "bvn") {
|
||||
const regex = /^[0-9]+$/;
|
||||
|
||||
if (regex.test(value)) {
|
||||
if (value?.length == 11) {
|
||||
setHideOTPComponent(false);
|
||||
// secondInputRef.current?.focus();
|
||||
} else setHideOTPComponent(true);
|
||||
} else {
|
||||
console.log("object not found");
|
||||
}
|
||||
}
|
||||
// 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) => {
|
||||
console.log('values', values)
|
||||
navigate(RouteHandler.dashboardHome, {replace:true})
|
||||
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={handleSubmit}
|
||||
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] ">
|
||||
<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}
|
||||
onInput={handleInput}
|
||||
ref={firstInputRef}
|
||||
maxLength={11}
|
||||
error={(props.errors.bvn && props.touched.bvn) && props.errors.bvn}
|
||||
/>
|
||||
{!hideOTPComponent && (
|
||||
<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}
|
||||
onInput={handleInput}
|
||||
ref={secondInputRef}
|
||||
maxLength={11}
|
||||
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={!props.values.otp}
|
||||
>
|
||||
Enter
|
||||
</button>
|
||||
{(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
|
||||
}
|
||||
maxLength={11}
|
||||
/>
|
||||
<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
|
||||
}
|
||||
maxLength={5}
|
||||
/>
|
||||
)}
|
||||
<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>
|
||||
|
||||
{hideOTPComponent ? (
|
||||
<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
|
||||
className={`p-2 ${
|
||||
!requestStatusOTP.status
|
||||
? 'text-red-500'
|
||||
: 'text-emerald-500'
|
||||
}`}
|
||||
>
|
||||
{requestStatusOTP.message}
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-[#5C2684] mt-[1.5625rem] w-fit">
|
||||
***Did not receive OTP? Click to resend
|
||||
</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>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
export default function Payment() {
|
||||
return (
|
||||
<div>Payment Page</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ReactNode } from "react"
|
||||
|
||||
type Props = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export default function ModalWrapper({children}:Props) {
|
||||
return (
|
||||
<div className="z-50 fixed inset-0">
|
||||
<div className="bg-black/50 fixed inset-0"></div>
|
||||
<div className="relative h-full flex flex-col justify-center items-center">{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import { ReactNode, useEffect, useState } from "react";
|
||||
import { PendingTableList } from "../../core/models";
|
||||
|
||||
type PaginatedListProps = {
|
||||
data: PendingTableList,
|
||||
itemsPerPage?: number,
|
||||
filterItem?: string[],
|
||||
tableTitle?: string,
|
||||
titleClass?:string,
|
||||
children: (data:PendingTableList) => ReactNode;
|
||||
}
|
||||
|
||||
export default function PendingList({
|
||||
data,
|
||||
itemsPerPage = 5,
|
||||
filterItem,
|
||||
tableTitle,
|
||||
titleClass,
|
||||
children,
|
||||
}:PaginatedListProps) {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [filteredData, setFilteredData] = useState(data);
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const [newData, setNewData] = useState<any>([]);
|
||||
|
||||
const numberOfSelection = itemsPerPage;
|
||||
|
||||
const handlePrev = () => {
|
||||
if (currentPage != 0) {
|
||||
setCurrentPage((prev) => prev - numberOfSelection);
|
||||
}
|
||||
};
|
||||
const handleNext = () => {
|
||||
if (currentPage < data.length) {
|
||||
setCurrentPage((prev) => prev + numberOfSelection);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = ({ target: { value } }:{target: {value:string}}, name:string) => {
|
||||
setSearchTerm(value);
|
||||
let newFilteredData:any = data.filter((item:any) =>
|
||||
item[name].toLowerCase().startsWith(value.toLowerCase())
|
||||
);
|
||||
setFilteredData(newFilteredData);
|
||||
setCurrentPage(0);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setNewData(
|
||||
filteredData?.slice(currentPage, numberOfSelection + currentPage)
|
||||
);
|
||||
}, [currentPage, filteredData]);
|
||||
|
||||
useEffect(()=>{
|
||||
setCurrentPage(0)
|
||||
},[itemsPerPage])
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<h1 className={`text-2xl mb-5 font-semibold ${titleClass && titleClass}`}>{tableTitle}</h1>
|
||||
|
||||
{data.length > 0 && filterItem && (
|
||||
<div className="mb-10 flex justify-end items-center gap-2">
|
||||
{filterItem.map((item, index) => (
|
||||
<label
|
||||
key={index}
|
||||
className="flex flex-col sm:flex-row items-center gap-2 text-slate-600 dark:text-slate-100 transition-all duration-500"
|
||||
>
|
||||
Search by {item[0].toUpperCase() + item.slice(1)}
|
||||
<input
|
||||
name={item}
|
||||
type="text"
|
||||
className="py-1 px-2 text-sm min-w-[100px] text-black dark:text-white bg-white dark:bg-slate-800 rounded-full border-0 outline-none ring-1 ring-slate-300 dark:ring-white transition-all duration-500"
|
||||
value={searchTerm}
|
||||
onChange={(e) => {
|
||||
handleSearch(e, item);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{children(newData)}
|
||||
|
||||
{/* show prev and next button if data exist */}
|
||||
{(data.length > 0 && data.length > itemsPerPage) && (
|
||||
<div className="mt-5 md:mt-10 w-full flex gap-4 justify-center items-center">
|
||||
<button
|
||||
onClick={handlePrev}
|
||||
className={`w-6 h-6 md:w-12 md:h-12 text-sm md:text-lg rounded-full flex justify-center items-center transition-all duration-300 ${
|
||||
currentPage == 0
|
||||
? "text-slate-400 border-slate-400 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
|
||||
: "text-slate-600 border-slate-600 dark:text-white dark:border-white"
|
||||
}`}
|
||||
>
|
||||
<
|
||||
</button>
|
||||
|
||||
{data.length && data.map((item, index)=>{
|
||||
item = item
|
||||
if(index%itemsPerPage == 0 && index >= currentPage && index <= currentPage+itemsPerPage){
|
||||
return (
|
||||
<button
|
||||
key={index}
|
||||
onClick={handleNext}
|
||||
className={`w-6 h-6 md:w-12 md:h-12 text-sm md:text-lg rounded-full flex justify-center items-center border transition-all duration-300 ${
|
||||
currentPage != index
|
||||
? "text-slate-400 border-slate-400 dark:text-slate-400 dark:border-slate-400"
|
||||
: "text-slate-600 border-slate-600 dark:text-white dark:border-white pointer-events-none"
|
||||
}`}
|
||||
>
|
||||
{index/itemsPerPage +1}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
})}
|
||||
|
||||
<button
|
||||
onClick={handleNext}
|
||||
className={`w-6 h-6 md:w-12 md:h-12 text-sm md:text-lg rounded-full flex justify-center items-center transition-all duration-300 ${
|
||||
currentPage + numberOfSelection >= data.length
|
||||
? "text-slate-400 border-slate-400 dark:text-slate-400 dark:border-slate-400 pointer-events-none"
|
||||
: "text-slate-600 border-slate-600 dark:text-white dark:border-white"
|
||||
}`}
|
||||
>
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -8,16 +8,16 @@ export interface InputCompOneProps {
|
||||
labelSpanClass?: string;
|
||||
floatLabel?: string;
|
||||
placeholder?: string;
|
||||
value?: string;
|
||||
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onInput?: (e: React.FormEvent<HTMLInputElement>) => void;
|
||||
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?: { value: string; label: string }[];
|
||||
selectOptions?: {loading:boolean, data:{ [index: string]: string; }[]};
|
||||
inputType?: string;
|
||||
inputClass?: string;
|
||||
parentInputClass?: string;
|
||||
@@ -25,6 +25,7 @@ export interface InputCompOneProps {
|
||||
parentClass?: string;
|
||||
maxLength?: number;
|
||||
error?: string;
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
@@ -44,7 +45,7 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
selectValue,
|
||||
input = false,
|
||||
select = false,
|
||||
selectOptions = [],
|
||||
selectOptions = {loading:false, data:[]},
|
||||
inputType = "text",
|
||||
inputClass,
|
||||
parentInputClass,
|
||||
@@ -52,16 +53,17 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
parentClass,
|
||||
maxLength,
|
||||
error,
|
||||
disabled=false
|
||||
},
|
||||
forwardedRef
|
||||
) => {
|
||||
return (
|
||||
<div className={parentClass}>
|
||||
{label && (
|
||||
<label htmlFor={label ? label : floatLabel} className={labelClass}>
|
||||
<label htmlFor={label ? label : floatLabel} className={`flex gap-2 items-center flex-wrap ${labelClass}`}>
|
||||
{label}
|
||||
{labelSpan && <span className={labelSpanClass}>{labelSpan}</span>}
|
||||
{error && <span className='text-[10px] text-red-500'>{error}</span>}
|
||||
{error && label && <span className='text-[10px] text-red-500'>{error}</span>}
|
||||
</label>
|
||||
)}
|
||||
{input && (
|
||||
@@ -78,12 +80,16 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
className={`px-4 ${floatLabel && 'peer pt-4 placeholder:text-transparent'} ${inputClass}`}
|
||||
maxLength={maxLength}
|
||||
id={label ? label : floatLabel}
|
||||
disabled={disabled}
|
||||
/>
|
||||
{floatLabel &&
|
||||
<label
|
||||
htmlFor={label ? label : floatLabel}
|
||||
className={`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}</label>
|
||||
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>
|
||||
)}
|
||||
@@ -93,20 +99,46 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
name={name}
|
||||
id={label ? label : floatLabel}
|
||||
value={selectValue}
|
||||
className={`px-4 appearance-none ${floatLabel && 'peer pt-4'} ${selectClass}`}
|
||||
// onChange={onChange}
|
||||
className={`px-4 appearance-none ${floatLabel && 'peer pt-4'} ${selectClass} ${disabled && 'opacity-50'}`}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
>
|
||||
{selectOptions.map(({ value, label }) => (
|
||||
{typeof(selectOptions) == 'string' ?
|
||||
<option value={selectValue}>{selectValue}</option>
|
||||
:selectOptions.loading ?
|
||||
<option value=''>Loading...</option>
|
||||
: selectOptions.data.length && name == 'employer_uid' ?
|
||||
<>
|
||||
<option value=''>Please Select</option>
|
||||
{selectOptions.data.map(({ uid, name }) => (
|
||||
<option key={uid} value={uid}>
|
||||
{name}
|
||||
</option>
|
||||
))}
|
||||
</>
|
||||
: selectOptions.data.length && name != 'employer_uid' ?
|
||||
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={`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}</label>
|
||||
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'>
|
||||
|
||||
@@ -9,7 +9,7 @@ const Stepper: React.FC<StepperProps> = ({ step = 0 }) => {
|
||||
|
||||
return (
|
||||
<div className="flex justify-between items-center gap-5">
|
||||
{[...Array(6)].map((_, index) => (
|
||||
{[...Array(5)].map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`w-[1.875rem] border-[.1875rem] rounded-sm ${(step === index
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
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 = (uid:string) => {
|
||||
let reqData = {
|
||||
// customer_uid: localStorage.getItem('uid'),
|
||||
}
|
||||
return getAuxEnd(`/profile?uid=${uid}`, reqData)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET USER BY CUSTOMER UID
|
||||
export const getUserPendingLoanList = (uid:string) => {
|
||||
let reqData = {
|
||||
// customer_uid: localStorage.getItem('uid'),
|
||||
}
|
||||
return getAuxEnd(`/dash?uid=${uid}`, reqData)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET LIST OF EMPLOYERS
|
||||
export const getEmployersList = () => {
|
||||
let reqData = {
|
||||
// customer_uid: localStorage.getItem('uid'),
|
||||
}
|
||||
return getAuxEnd(`/employers`, reqData)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET USER EMPLOYER
|
||||
export const getEmployer = () => {
|
||||
let reqData = {
|
||||
uid: localStorage.getItem('uid'),
|
||||
}
|
||||
return getAuxEnd(`/dash/employer?uid=${reqData?.uid}`, null)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET LOAN DETAILS
|
||||
export const getLoanDetail = (postData:any) => {
|
||||
let reqData = {
|
||||
uid: localStorage.getItem('uid'),
|
||||
...postData
|
||||
}
|
||||
return getAuxEnd(`/loan/loandetail?uid=${reqData?.uid}&application_uid=${reqData?.application_uid}`, null)
|
||||
}
|
||||
|
||||
// FUNCTION TO ADD CARD
|
||||
export const addCard = (postData:any) => {
|
||||
let reqData = {
|
||||
uid: localStorage.getItem('uid'),
|
||||
...postData
|
||||
}
|
||||
return postAuxEnd('/addcard', 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,32 @@
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
export type PendingTableList = {
|
||||
status?: string | boolean
|
||||
application_uid?: string
|
||||
added?: string
|
||||
loan_amount?: string
|
||||
payment_month?: string
|
||||
status_text?: {
|
||||
text?: string
|
||||
button?: boolean
|
||||
advise?: string
|
||||
}
|
||||
}[];
|
||||
@@ -17,4 +17,33 @@ body {
|
||||
/* @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]
|
||||
}
|
||||
|
||||
.custom-btn{@apply min-w-[100px] transition-all duration-300 p-2 rounded-full}
|
||||
|
||||
|
||||
/* MODAL COMPONENT */
|
||||
.modal-container{
|
||||
animation-name: zoom;
|
||||
animation-duration: .2s;
|
||||
animation-timing-function: linear;
|
||||
@apply w-4/5 max-w-[600px] bg-white shadow-md rounded-2xl overflow-hidden
|
||||
}
|
||||
.modal-header {
|
||||
@apply w-full flex items-center justify-between p-5 py-8 border-b bg-sky-500
|
||||
}
|
||||
.modal-title {
|
||||
@apply text-2xl leading-8 font-bold text-white dark:text-white tracking-wide flex items-center
|
||||
}
|
||||
.modal-close-btn {
|
||||
@apply text-white dark:text-red-500
|
||||
}
|
||||
.modal-body {
|
||||
@apply w-full p-5 min-h-[150px] max-h-[500px] overflow-y-auto break-words flex flex-col justify-center items-center
|
||||
}
|
||||
.modal-footer {
|
||||
@apply w-full p-5 border-t flex justify-between items-center gap-4
|
||||
}
|
||||
/* MODAL COMPONENT */
|
||||
|
||||
|
||||
}
|
||||
@@ -1,32 +1,63 @@
|
||||
import { useState } from "react";
|
||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||
import Logo from "../../assets/icons/logo.svg";
|
||||
import { Icons } from "../../components";
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import Logo from '../../assets/icons/logo.svg';
|
||||
import { Icons } from '../../components';
|
||||
import { contactDetails } from '../../utils/data';
|
||||
|
||||
type Props = {
|
||||
asideDisplay?: () => void;
|
||||
logoutUser: () => void;
|
||||
};
|
||||
|
||||
export default function Aside({ asideDisplay }: Props) {
|
||||
export default function Aside({ asideDisplay, logoutUser }: Props) {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [openNestedLink, setOpenNestedLink] = useState<{ name: string | null }>(
|
||||
{ name: "" }
|
||||
{ name: '' }
|
||||
);
|
||||
|
||||
const handleOpenNestedLink = (e: any) => {
|
||||
if (!e || !e.target) {
|
||||
return setOpenNestedLink({ name: "" });
|
||||
return setOpenNestedLink({ name: '' });
|
||||
}
|
||||
if (openNestedLink.name && openNestedLink.name == e.target.name) {
|
||||
setOpenNestedLink({ name: "" });
|
||||
setOpenNestedLink({ name: '' });
|
||||
} else {
|
||||
setOpenNestedLink({ name: e.target.name });
|
||||
}
|
||||
};
|
||||
|
||||
// Track user activity
|
||||
useEffect(() => {
|
||||
let timeout: number;
|
||||
|
||||
const resetTimeout = () => {
|
||||
clearTimeout(timeout);
|
||||
timeout = window.setTimeout(() => {
|
||||
// Logout user after 7 minutes of inactivity
|
||||
logoutUser();
|
||||
}, 7 * 60 * 1000); // 7 minutes in milliseconds
|
||||
};
|
||||
|
||||
const handleUserActivity = () => {
|
||||
resetTimeout();
|
||||
};
|
||||
|
||||
// Attach event listeners to track user activity
|
||||
document.addEventListener('mousemove', handleUserActivity);
|
||||
document.addEventListener('keypress', handleUserActivity);
|
||||
|
||||
// Initialize timeout
|
||||
resetTimeout();
|
||||
|
||||
// Clear timeout and remove event listeners on component unmount
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
document.removeEventListener('mousemove', handleUserActivity);
|
||||
document.removeEventListener('keypress', handleUserActivity);
|
||||
};
|
||||
}, [logoutUser]);
|
||||
|
||||
return (
|
||||
<div className="py-5 px-10 flex flex-col h-full bg-inherit">
|
||||
<Link to="/">
|
||||
@@ -46,8 +77,8 @@ export default function Aside({ asideDisplay }: Props) {
|
||||
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]"
|
||||
? ' text-[#5C2684]'
|
||||
: ' text-[#585858]'
|
||||
}`}
|
||||
>
|
||||
{link.name}
|
||||
@@ -61,8 +92,8 @@ export default function Aside({ asideDisplay }: Props) {
|
||||
<div
|
||||
className={`transition-all duration-300 w-full z-1 ${
|
||||
openNestedLink.name == link.name
|
||||
? "relative top-0"
|
||||
: "absolute -top-[500px]"
|
||||
? 'relative top-0'
|
||||
: 'absolute -top-[500px]'
|
||||
}`}
|
||||
>
|
||||
{link.nestedLink.map((nextLink, index) => (
|
||||
@@ -71,17 +102,17 @@ export default function Aside({ asideDisplay }: Props) {
|
||||
asideDisplay && asideDisplay();
|
||||
}}
|
||||
key={index}
|
||||
to={nextLink.link ? nextLink.link : "#"}
|
||||
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]"
|
||||
? ' text-[#5C2684]'
|
||||
: 'text-[#585858]'
|
||||
}`}
|
||||
>
|
||||
<Icons
|
||||
name={nextLink.icon}
|
||||
fillColor={`${
|
||||
pathname == nextLink.link ? "#5C2684" : "#585858"
|
||||
pathname == nextLink.link ? '#5C2684' : '#585858'
|
||||
}`}
|
||||
/>
|
||||
{nextLink.name}
|
||||
@@ -97,14 +128,14 @@ export default function Aside({ asideDisplay }: Props) {
|
||||
asideDisplay && asideDisplay();
|
||||
}}
|
||||
key={index}
|
||||
to={link.link ? link.link : "#"}
|
||||
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]"
|
||||
pathname == link.link ? 'text-[#5C2684]' : 'text-[#585858]'
|
||||
}`}
|
||||
>
|
||||
<Icons
|
||||
name={link.icon}
|
||||
fillColor={`${pathname == link.link ? "#5C2684" : "#585858"}`}
|
||||
fillColor={`${pathname == link.link ? '#5C2684' : '#585858'}`}
|
||||
/>
|
||||
{link.name}
|
||||
</Link>
|
||||
@@ -115,24 +146,30 @@ export default function Aside({ asideDisplay }: Props) {
|
||||
<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={() => navigate("/login", { replace: true })}
|
||||
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]">
|
||||
{/* <p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Call: 09099000000
|
||||
</p>
|
||||
<p className="font-extrabold tracking-[3%] text-[#5A5A5A]">
|
||||
Email: fcmbloan@support.com
|
||||
</p>
|
||||
</p> */}
|
||||
{contactDetails.map(({ name, value }) => (
|
||||
<p
|
||||
key={name}
|
||||
className="font-extrabold tracking-[3%] text-[#5A5A5A]"
|
||||
>
|
||||
{name}: {value}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -150,29 +187,34 @@ type AsideLinksType = {
|
||||
}[];
|
||||
|
||||
const asideLinks: AsideLinksType = [
|
||||
{ name: "Dashboard", link: "/dashboard/home", icon: "dash-icon", nestedLink: [] },
|
||||
{
|
||||
name: "Your Profile",
|
||||
link: "/dashboard/profile",
|
||||
icon: "dash-icon",
|
||||
name: 'Dashboard',
|
||||
link: '/dashboard/home',
|
||||
icon: 'dash-icon',
|
||||
nestedLink: [],
|
||||
},
|
||||
{
|
||||
name: "Employment Details",
|
||||
link: "/dashboard/verification",
|
||||
icon: "dash-icon",
|
||||
name: 'Your Profile',
|
||||
link: '/dashboard/profile',
|
||||
icon: 'dash-icon',
|
||||
nestedLink: [],
|
||||
},
|
||||
{
|
||||
name: "Reference Details",
|
||||
link: "/dashboard/payments",
|
||||
icon: "dash-icon",
|
||||
name: 'Employment Details',
|
||||
link: '/dashboard/verification',
|
||||
icon: 'dash-icon',
|
||||
nestedLink: [],
|
||||
},
|
||||
{
|
||||
name: "Agreements",
|
||||
link: "/dashboard/legals",
|
||||
icon: "dash-icon",
|
||||
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:[
|
||||
|
||||
@@ -1,11 +1,61 @@
|
||||
|
||||
import {useState, useEffect} from 'react'
|
||||
import DashboardLayout from "./DashboardLayout";
|
||||
import { Outlet } from "react-router-dom";
|
||||
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')
|
||||
let uid = localStorage.getItem('uid')
|
||||
if(!token || !uid){
|
||||
navigate(RouteHandler.letsGetStarted, {replace:true})
|
||||
return
|
||||
}
|
||||
const getUser = () => { // FUNCTION TO GET USER BY ID
|
||||
// let data = {firstname:'firstname', lastname:'lastname', uid:'28273737646466464'}
|
||||
getUserByID(uid).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=>{
|
||||
navigate(RouteHandler.letsGetStarted, {replace:true})
|
||||
console.log('USER ERROR', err)
|
||||
})
|
||||
}
|
||||
if(!Object.keys(userDetails).length){
|
||||
getUser()
|
||||
}
|
||||
},[])
|
||||
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<Outlet />
|
||||
</DashboardLayout>
|
||||
<>
|
||||
{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>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
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);
|
||||
@@ -30,17 +34,22 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
// 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 />
|
||||
<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 asideDisplay={asideDisplay} />
|
||||
<Aside logoutUser={logoutUser} asideDisplay={asideDisplay} />
|
||||
</aside>
|
||||
<main className="dash-bg-image bg-[#F9F9F9] relative w-full overflow-y-auto overflow-x-hidden">
|
||||
|
||||
@@ -74,8 +83,8 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="flex p-5 relative">
|
||||
<div className="w-full p-5">{children}</div>
|
||||
<div className="flex p-2 md:p-5 relative">
|
||||
<div className="w-full p-2 md:p-5">{children}</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ interface GetStartedLayoutProps {
|
||||
const GetStartedLayout: React.FC<GetStartedLayoutProps> = ({ children }) => {
|
||||
return (
|
||||
<div className="containerMode mb-[5.4375rem]">
|
||||
<div className='sticky top-0 bg-white'>
|
||||
<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">
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// FUNCTION TO RETURN AMOUNT TO TWO DECIMAL PLACES
|
||||
export const FormatAmount = (
|
||||
amount = "00",
|
||||
) => {
|
||||
// Convert the number to a string
|
||||
let numStr = String(amount);
|
||||
|
||||
// Split the string into integer and decimal parts
|
||||
let parts = numStr.split(".");
|
||||
let integerPart = parts[0] || "";
|
||||
let decimalPart = parts[1] || "";
|
||||
|
||||
// Add thousands separators to the integer part
|
||||
let formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
|
||||
// Truncate or pad the decimal part to two decimal points
|
||||
let formattedDecimal = decimalPart.slice(0, 2).padEnd(2, "0");
|
||||
|
||||
// Combine the formatted integer and decimal parts
|
||||
let formattedNumber = '₦' + formattedInteger + '.' + formattedDecimal;
|
||||
|
||||
// return formattedNumber;
|
||||
return formattedNumber;
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
export function NewDateTimeFormatter(isoDateString:any, addHour = true) {
|
||||
const date = new Date(isoDateString);
|
||||
if (addHour) {
|
||||
date.setTime(date.getTime() + 1 * 60 * 60 * 1000);
|
||||
}
|
||||
const formattedDate = date.toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "numeric",
|
||||
day: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
// second: "2-digit",
|
||||
hour12: true,
|
||||
timeZone: "UTC",
|
||||
});
|
||||
return formattedDate;
|
||||
}
|
||||
+6
-1
@@ -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>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import ReferenceDetails from "../components/Dashboard/referenceDetails/ReferenceDetails";
|
||||
|
||||
export default function DashboardpaymentsPage() {
|
||||
return (
|
||||
<div>Dashboardpayments</div>
|
||||
<>
|
||||
<ReferenceDetails />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import EmploymentDetail from "../components/Dashboard/employmentDetails/EmploymentDetails";
|
||||
|
||||
export default function DashboardVerificationPage() {
|
||||
return (
|
||||
<div>DashboardVerification</div>
|
||||
<>
|
||||
<EmploymentDetail />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import React, {useEffect} from 'react'
|
||||
import {useLocation, useNavigate} from 'react-router-dom'
|
||||
import Payment from '../components/Payment/Payment'
|
||||
import { RouteHandler } from '../router/routes'
|
||||
|
||||
export default function PaymentPage() {
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
const queryParams = new URLSearchParams(location?.search);
|
||||
const trxRef = queryParams.get("trxref");
|
||||
const reference = queryParams.get("reference");
|
||||
console.log('LOC', trxRef, reference)
|
||||
|
||||
useEffect(()=>{
|
||||
if(!trxRef || !reference){
|
||||
navigate(RouteHandler.dashboardHome, {replace:true})
|
||||
}
|
||||
},[])
|
||||
return (
|
||||
<>
|
||||
<Payment />
|
||||
</>
|
||||
)
|
||||
}
|
||||
+3
-1
@@ -11,6 +11,7 @@ import PersonalBankingPage from "./PersonalBankingPage";
|
||||
import BusinessBankingPage from "./BusinessBankingPage";
|
||||
import CooperateBankingPage from "./CooperateBankingPage";
|
||||
import LetsGetStatedPage from "./LetsGetStatedPage";
|
||||
import PaymentPage from "./PaymentPage";
|
||||
|
||||
export {
|
||||
HomePage,
|
||||
@@ -25,5 +26,6 @@ export {
|
||||
PersonalBankingPage,
|
||||
BusinessBankingPage,
|
||||
CooperateBankingPage,
|
||||
LetsGetStatedPage
|
||||
LetsGetStatedPage,
|
||||
PaymentPage
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
CooperateBankingPage,
|
||||
PersonalBankingPage,
|
||||
LetsGetStatedPage,
|
||||
PaymentPage
|
||||
} from "../pages";
|
||||
import { DashboardAuth } from "../layouts";
|
||||
|
||||
@@ -66,6 +67,10 @@ const Routers = () => {
|
||||
path={RouteHandler.dashboardLegals}
|
||||
element={<DashboardLegalsPage />}
|
||||
/>
|
||||
<Route
|
||||
path={RouteHandler.paymentpage}
|
||||
element={<PaymentPage />}
|
||||
/>
|
||||
</Route>
|
||||
<Route path="*" element={<>Error Page</>} />
|
||||
</Routes>
|
||||
|
||||
@@ -12,4 +12,5 @@ export class RouteHandler {
|
||||
static dashboardPayments = "/dashboard/payments";
|
||||
static dashboardLegals = "/dashboard/legals";
|
||||
static termsAndConditions = "/terms-and-conditions";
|
||||
static paymentpage = "/payment";
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
+291
-286
@@ -1,556 +1,561 @@
|
||||
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";
|
||||
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", href: RouteHandler.homepage },
|
||||
{ id: 2, name: "PERSONAL", href: RouteHandler.personalBanking },
|
||||
{ id: 3, name: "BUSINESS", href: RouteHandler.businessBanking },
|
||||
{ id: 4, name: "CORPORATE", href: RouteHandler.cooperateBanking },
|
||||
{ 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 = [
|
||||
{
|
||||
id: 1,
|
||||
name: "PERSONAL BANKING",
|
||||
linkPath: "/personal-banking",
|
||||
name: 'PERSONAL BANKING',
|
||||
linkPath: '/personal-banking',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "BUSINESS BANKING",
|
||||
linkPath: "/business-banking",
|
||||
name: 'BUSINESS BANKING',
|
||||
linkPath: '/business-banking',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "CORPORATE BANKING",
|
||||
linkPath: "/cooperate-banking",
|
||||
name: 'CORPORATE BANKING',
|
||||
linkPath: '/cooperate-banking',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "GROUP & SUBSIDIARIES",
|
||||
linkPath: "",
|
||||
name: 'GROUP & SUBSIDIARIES',
|
||||
linkPath: '',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "ABOUT US",
|
||||
linkPath: "/about-us",
|
||||
name: 'ABOUT US',
|
||||
linkPath: '/about-us',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "MY BANK AND I",
|
||||
linkPath: "",
|
||||
name: 'MY BANK AND I',
|
||||
linkPath: '',
|
||||
},
|
||||
];
|
||||
|
||||
export const _lowerMenuItems = [
|
||||
{
|
||||
name: "PERSONAL BANKING",
|
||||
linkPath: "/personal-banking",
|
||||
name: 'PERSONAL BANKING',
|
||||
linkPath: '/personal-banking',
|
||||
subItems: [
|
||||
{
|
||||
name: "CURRENT ACCOUNTS",
|
||||
linkPath: "/current-accounts",
|
||||
name: 'CURRENT ACCOUNTS',
|
||||
linkPath: '/current-accounts',
|
||||
subItems: [
|
||||
{
|
||||
name: "CLASSIC CURRENT ACCOUNT",
|
||||
linkPath: "/personal-classic-current-account",
|
||||
name: 'CLASSIC CURRENT ACCOUNT',
|
||||
linkPath: '/personal-classic-current-account',
|
||||
},
|
||||
{
|
||||
name: "PREMIUM CURRENT ACCOUNT",
|
||||
linkPath: "/premium-current-account",
|
||||
name: 'PREMIUM CURRENT ACCOUNT',
|
||||
linkPath: '/premium-current-account',
|
||||
},
|
||||
{
|
||||
name: "PERSONAL BUSINESS ACCOUNT",
|
||||
linkPath: "/personal-business-account",
|
||||
name: 'PERSONAL BUSINESS ACCOUNT',
|
||||
linkPath: '/personal-business-account',
|
||||
},
|
||||
{
|
||||
name: "DOMICILIARY CURRENT ACCOUNT",
|
||||
linkPath: "/domiciliary-current-account",
|
||||
name: 'DOMICILIARY CURRENT ACCOUNT',
|
||||
linkPath: '/domiciliary-current-account',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "SAVINGS ACCOUNTS",
|
||||
linkPath: "/savings-accounts",
|
||||
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: `${import.meta.env.VITE_BANK_NAME_SHORT} 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: 'CLASSIC SAVINGS ACCOUNT',
|
||||
linkPath: '/classic-savings-account',
|
||||
},
|
||||
{
|
||||
name: "PREMIUM SAVINGS ACCOUNT",
|
||||
linkPath: "/fcmb-premium-savings-account",
|
||||
name: 'PREMIUM SAVINGS ACCOUNT',
|
||||
linkPath: '/fcmb-premium-savings-account',
|
||||
},
|
||||
{
|
||||
name: "FCMB SALARY SAVINGS ACCOUNT",
|
||||
linkPath: "/fcmb-salary-savings-account",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} SALARY SAVINGS ACCOUNT`,
|
||||
linkPath: '/fcmb-salary-savings-account',
|
||||
},
|
||||
{
|
||||
name: "DOMICILIARY SAVINGS ACCOUNT",
|
||||
linkPath: "/domiciliary-savings-account",
|
||||
name: 'DOMICILIARY SAVINGS ACCOUNT',
|
||||
linkPath: '/domiciliary-savings-account',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "INVESTMENTS",
|
||||
linkPath: "/investment-accounts",
|
||||
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: '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: 'I-NEST SAVING',
|
||||
linkPath: 'https://i-nest.fcmb.com/#/welcome',
|
||||
},
|
||||
{ name: "CALL DEPOSITS", linkPath: "/call-deposits" },
|
||||
{ name: 'CALL DEPOSITS', linkPath: '/call-deposits' },
|
||||
{
|
||||
name: "EDUCATION INVESTMENT PLAN",
|
||||
linkPath: "/education-investment",
|
||||
name: 'EDUCATION INVESTMENT PLAN',
|
||||
linkPath: '/education-investment',
|
||||
},
|
||||
{
|
||||
name: "MUTUAL FUNDS",
|
||||
linkPath: "https://www.fcmbassetmanagement.com/mutual-funds/",
|
||||
name: 'MUTUAL FUNDS',
|
||||
linkPath: 'https://www.fcmbassetmanagement.com/mutual-funds/',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LOANS AND CREDIT CARDS",
|
||||
linkPath: "/loans-and-credit-cards",
|
||||
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: '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: 'EASYLIFT LOAN',
|
||||
linkPath: 'https://easyliftloanform.fcmb.com',
|
||||
},
|
||||
{ name: "MORTGAGE", linkPath: "http://mortgage.fcmb.com/" },
|
||||
{ name: 'MORTGAGE', linkPath: 'http://mortgage.fcmb.com/' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "NON-RESIDENT NIGERIAN (NRN) BANKING",
|
||||
linkPath: "https://www.fcmb.com/non-resident-nigerian",
|
||||
name: 'NON-RESIDENT NIGERIAN (NRN) BANKING',
|
||||
linkPath: 'https://www.fcmb.com/non-resident-nigerian',
|
||||
},
|
||||
{
|
||||
name: "WAYS TO BANK",
|
||||
linkPath: "/ways-to-bank",
|
||||
name: 'WAYS TO BANK',
|
||||
linkPath: '/ways-to-bank',
|
||||
subItems: [
|
||||
{ name: "FCMB MOBILE", linkPath: "/fcmb-mobile" },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} MOBILE`, linkPath: '/fcmb-mobile' },
|
||||
{
|
||||
name: "RETAIL INTERNET BANKING",
|
||||
linkPath: "https://ibank.fcmb.com/",
|
||||
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: '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: `${import.meta.env.VITE_BANK_NAME_SHORT} ELECTRONIC CHANNELS`, linkPath: '/e-channels' },
|
||||
{ name: 'AGENT BANKING', linkPath: '/agent-banking' },
|
||||
{
|
||||
name: "FCMB SECURE COMMUNICATION",
|
||||
linkPath: "/secure-communication",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} SECURE COMMUNICATION`,
|
||||
linkPath: '/secure-communication',
|
||||
},
|
||||
{ name: "TEMI", linkPath: "/temi" },
|
||||
{ name: 'TEMI', linkPath: '/temi' },
|
||||
],
|
||||
},
|
||||
{ name: "BANCASSURANCE", linkPath: "/bancassurance" },
|
||||
{ name: 'BANCASSURANCE', linkPath: '/bancassurance' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "BUSINESS BANKING",
|
||||
linkPath: "/business-banking",
|
||||
name: 'BUSINESS BANKING',
|
||||
linkPath: '/business-banking',
|
||||
subItems: [
|
||||
{
|
||||
name: "PROPOSITIONS",
|
||||
linkPath: "",
|
||||
name: 'PROPOSITIONS',
|
||||
linkPath: '',
|
||||
subItems: [
|
||||
{ name: "SHEVENTURES", linkPath: "/she-ventures" },
|
||||
{ name: "BUSINESS ZONE", linkPath: "https://businesszone.fcmb.com/" },
|
||||
{ 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: 'FOOD BUSINESS SUPPORT',
|
||||
linkPath: 'https://www.fcmb.com/food-business-support/',
|
||||
},
|
||||
{ name: "SCHOOL BUSINESS SUPPORT", linkPath: "/school-support" },
|
||||
{ name: 'SCHOOL BUSINESS SUPPORT', linkPath: '/school-support' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "CURRENT ACCOUNTS",
|
||||
linkPath: "/business-current-accounts",
|
||||
name: 'CURRENT ACCOUNTS',
|
||||
linkPath: '/business-current-accounts',
|
||||
subItems: [
|
||||
{
|
||||
name: "CORPORATE CURRENT ACCOUNT",
|
||||
linkPath: "/corporate-current-account",
|
||||
name: 'CORPORATE CURRENT ACCOUNT',
|
||||
linkPath: '/corporate-current-account',
|
||||
},
|
||||
{ name: "FCMB BUSINESS ACCOUNT", linkPath: "/fcmb-business-account" },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} BUSINESS ACCOUNT`, linkPath: '/fcmb-business-account' },
|
||||
{
|
||||
name: "DOMICILIARY CURRENT ACCOUNT",
|
||||
linkPath: "/business-domiciliary-current-account",
|
||||
name: 'DOMICILIARY CURRENT ACCOUNT',
|
||||
linkPath: '/business-domiciliary-current-account',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "SAVINGS ACCOUNTS",
|
||||
linkPath: "/node/178",
|
||||
name: 'SAVINGS ACCOUNTS',
|
||||
linkPath: '/node/178',
|
||||
subItems: [
|
||||
{
|
||||
name: "BUSINESS SAVINGS ACCOUNT",
|
||||
linkPath: "/business-savings-account",
|
||||
name: 'BUSINESS SAVINGS ACCOUNT',
|
||||
linkPath: '/business-savings-account',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LOANS",
|
||||
linkPath: "/business-loans",
|
||||
name: 'LOANS',
|
||||
linkPath: '/business-loans',
|
||||
subItems: [
|
||||
{
|
||||
name: "SME DEVELOPMENT FINANCE FACILITY",
|
||||
linkPath: "/sme-development-finance-facility",
|
||||
name: 'SME DEVELOPMENT FINANCE FACILITY',
|
||||
linkPath: '/sme-development-finance-facility',
|
||||
},
|
||||
{
|
||||
name: "SME ASSET FINANCE FACILITY",
|
||||
linkPath: "/sme-asset-finance-facility",
|
||||
name: 'SME ASSET FINANCE FACILITY',
|
||||
linkPath: '/sme-asset-finance-facility',
|
||||
},
|
||||
{
|
||||
name: "SME WORKING CAPITAL FACILITY",
|
||||
linkPath: "/sme-working-capital-facility",
|
||||
name: 'SME WORKING CAPITAL FACILITY',
|
||||
linkPath: '/sme-working-capital-facility',
|
||||
},
|
||||
{ name: "QUICK LOAN", linkPath: "/quick-loan" },
|
||||
{ name: 'QUICK LOAN', linkPath: '/quick-loan' },
|
||||
{
|
||||
name: "SME INVOICE DISCOUNTING FINANCE (IDF) FACILITY",
|
||||
linkPath: "/invoice-discounting-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: '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: '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",
|
||||
name: 'PAYMENT & COLLECTION',
|
||||
linkPath: '/payment-and-collection',
|
||||
subItems: [
|
||||
{ name: "COLLECTION SOLUTIONS", linkPath: "/collection-solutions" },
|
||||
{ name: "PAYMENT SOLUTIONS", linkPath: "/payment-solutions" },
|
||||
{ name: 'COLLECTION SOLUTIONS', linkPath: '/collection-solutions' },
|
||||
{ name: 'PAYMENT SOLUTIONS', linkPath: '/payment-solutions' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "WAYS TO BANK",
|
||||
linkPath: "/business-ways-to-bank",
|
||||
name: 'WAYS TO BANK',
|
||||
linkPath: '/business-ways-to-bank',
|
||||
subItems: [
|
||||
{
|
||||
name: "BUSINESS INTERNET BANKING",
|
||||
linkPath: "https://ibank.fcmb.com/corporate/BbgLoginScreenUI.aspx",
|
||||
name: 'BUSINESS INTERNET BANKING',
|
||||
linkPath: 'https://ibank.fcmb.com/corporate/BbgLoginScreenUI.aspx',
|
||||
},
|
||||
{
|
||||
name: "CORPORATE INTERNET BANKING",
|
||||
linkPath: "https://www.fcmbonline.com/",
|
||||
name: 'CORPORATE INTERNET BANKING',
|
||||
linkPath: 'https://www.fcmbonline.com/',
|
||||
},
|
||||
{ name: "OUR ATM NETWORK", linkPath: "/atm-network2" },
|
||||
{ name: "FCMB ONLINE", linkPath: "/fcmb-online-business" },
|
||||
{ name: 'OUR ATM NETWORK', linkPath: '/atm-network2' },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} ONLINE`, linkPath: '/fcmb-online-business' },
|
||||
{
|
||||
name: "FCMB ELECTRONIC CHANNELS",
|
||||
linkPath: "https://www.fcmb.com/e-channels",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} ELECTRONIC CHANNELS`,
|
||||
linkPath: 'https://www.fcmb.com/e-channels',
|
||||
},
|
||||
{ name: "FCMB BUSINESS APP", linkPath: "/FCMB-business-app" },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} BUSINESS APP`, linkPath: '/FCMB-business-app' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "CORPORATE BANKING",
|
||||
linkPath: "/cooperate-banking",
|
||||
name: 'CORPORATE BANKING',
|
||||
linkPath: '/cooperate-banking',
|
||||
subItems: [
|
||||
{
|
||||
name: "FOREIGN EXCHANGE SERVICES",
|
||||
linkPath: "/foreign-exchange-services",
|
||||
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: 'TRADE SERVICES', linkPath: '/node/166' },
|
||||
{ name: 'CASH MANAGEMENT SOLUTIONS', linkPath: '/cash-management' },
|
||||
{ name: 'CORPORATE FINANCE', linkPath: '/corporate-finance' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "GROUP & SUBSIDIARIES",
|
||||
linkPath: "",
|
||||
name: 'GROUP & SUBSIDIARIES',
|
||||
linkPath: '',
|
||||
subItems: [
|
||||
{ name: "FCMB GROUP PLC", linkPath: "https://www.fcmbgroup.com/" },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} GROUP PLC`, linkPath: 'https://www.fcmbgroup.com/' },
|
||||
{
|
||||
name: "CSL STOCKBROKERS",
|
||||
linkPath: "https://www.cslstockbrokers.com/",
|
||||
name: 'CSL STOCKBROKERS',
|
||||
linkPath: 'https://www.cslstockbrokers.com/',
|
||||
},
|
||||
{
|
||||
name: "FCMB CAPITAL MARKETS",
|
||||
linkPath: "https://www.fcmbcapitalmarketsng.com/",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} CAPITAL MARKETS`,
|
||||
linkPath: 'https://www.fcmbcapitalmarketsng.com/',
|
||||
},
|
||||
{
|
||||
name: "FCMB ASSET MANAGEMENT",
|
||||
linkPath: "https://www.fcmbassetmanagement.com/index/",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} ASSET MANAGEMENT`,
|
||||
linkPath: 'https://www.fcmbassetmanagement.com/index/',
|
||||
},
|
||||
{
|
||||
name: "FCMB MICROFINANCE BANK",
|
||||
linkPath: "/fcmb-microfinance-initiative",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} MICROFINANCE BANK`,
|
||||
linkPath: '/fcmb-microfinance-initiative',
|
||||
},
|
||||
{ name: "FCMB UK", linkPath: "http://www.fcmbuk.com/" },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} UK`, linkPath: 'http://www.fcmbuk.com/' },
|
||||
{
|
||||
name: "FCMB PENSIONS LIMITED",
|
||||
linkPath: "https://www.fcmbpensions.com/",
|
||||
name: `${import.meta.env.VITE_BANK_NAME_SHORT} PENSIONS LIMITED`,
|
||||
linkPath: 'https://www.fcmbpensions.com/',
|
||||
},
|
||||
{
|
||||
name: "CREDIT DIRECT LIMITED",
|
||||
linkPath: "https://www.creditdirect.ng",
|
||||
name: 'CREDIT DIRECT LIMITED',
|
||||
linkPath: 'https://www.creditdirect.ng',
|
||||
},
|
||||
{ name: "FCMB TRUSTEES", linkPath: "http://fcmbtrustees.com/" },
|
||||
{ name: `${import.meta.env.VITE_BANK_NAME_SHORT} TRUSTEES`, linkPath: 'http://fcmbtrustees.com/' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ABOUT US",
|
||||
linkPath: "/about-us",
|
||||
name: 'ABOUT US',
|
||||
linkPath: '/about-us',
|
||||
subItems: [
|
||||
{
|
||||
name: "OUR VISION/MISSION/VALUES",
|
||||
linkPath: "/about-us/vision-mision-core-values",
|
||||
name: 'OUR VISION/MISSION/VALUES',
|
||||
linkPath: '/about-us/vision-mision-core-values',
|
||||
},
|
||||
{ name: "OUR HISTORY", linkPath: "/about-us/our-history" },
|
||||
{ name: 'OUR HISTORY', linkPath: '/about-us/our-history' },
|
||||
{
|
||||
name: "INVESTOR RELATIONS",
|
||||
linkPath: "http://www.fcmbgroup.com/investor-relations",
|
||||
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: '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",
|
||||
name: 'MEDIA RELATIONS',
|
||||
linkPath: '/media-relations',
|
||||
subItems: [
|
||||
{ name: "PRESS RELEASES", linkPath: "/press-releases" },
|
||||
{ name: "MEDIA STATEMENTS", linkPath: "/press-statements" },
|
||||
{ name: 'PRESS RELEASES', linkPath: '/press-releases' },
|
||||
{ name: 'MEDIA STATEMENTS', linkPath: '/press-statements' },
|
||||
],
|
||||
},
|
||||
{ name: "AWARDS AND RECOGNITION", linkPath: "/awards" },
|
||||
{ name: 'AWARDS AND RECOGNITION', linkPath: '/awards' },
|
||||
{
|
||||
name: "OUR POLICY",
|
||||
linkPath: "/our-policies",
|
||||
name: 'OUR POLICY',
|
||||
linkPath: '/our-policies',
|
||||
subItems: [
|
||||
{ name: "BUSINESS CONTINUITY", linkPath: "/business-continuity" },
|
||||
{ name: 'BUSINESS CONTINUITY', linkPath: '/business-continuity' },
|
||||
{
|
||||
name: "CORPORATE GOVERNANCE POLICY",
|
||||
linkPath: "/corporate-governance",
|
||||
name: 'CORPORATE GOVERNANCE POLICY',
|
||||
linkPath: '/corporate-governance',
|
||||
},
|
||||
{ name: "PRIVACY POLICY", linkPath: "/privacy-policy" },
|
||||
{ name: "QUALITY POLICY", linkPath: "/quality-policy" },
|
||||
{ name: 'PRIVACY POLICY', linkPath: '/privacy-policy' },
|
||||
{ name: 'QUALITY POLICY', linkPath: '/quality-policy' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MY BANK AND I",
|
||||
linkPath: "",
|
||||
name: 'MY BANK AND I',
|
||||
linkPath: '',
|
||||
subItems: [
|
||||
{ name: "TELEPHONE SELF SERVICE", linkPath: "/telephone-self-service" },
|
||||
{ name: 'TELEPHONE SELF SERVICE', linkPath: '/telephone-self-service' },
|
||||
{
|
||||
name: "CURRENT CAMPAIGNS/PROMOS",
|
||||
linkPath: "/current-campaigns-promos",
|
||||
name: 'CURRENT CAMPAIGNS/PROMOS',
|
||||
linkPath: '/current-campaigns-promos',
|
||||
subItems: [
|
||||
{
|
||||
name: "BOOK YOUR FLIGHTS AND PAY IN INSTALMENTS WITH FCMB",
|
||||
linkPath: "/247travels",
|
||||
name: `BOOK YOUR FLIGHTS AND PAY IN INSTALMENTS WITH ${import.meta.env.VITE_BANK_NAME_SHORT}`,
|
||||
linkPath: '/247travels',
|
||||
},
|
||||
{ name: "REFER AND WIN", linkPath: "/refer-and-win" },
|
||||
{ name: "CARD DISCOUNTS", linkPath: "/card-discounts" },
|
||||
{ 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: 'FLEXX WRITING CHALLENGE',
|
||||
linkPath: 'https://flexxzone.fcmb.com/writing-challenge/',
|
||||
},
|
||||
{
|
||||
name: "FLEXXPRENEUR",
|
||||
name: 'FLEXXPRENEUR',
|
||||
linkPath:
|
||||
"https://flexxzone.fcmb.com/2020/07/flexxpreneur-is-back-2/",
|
||||
'https://flexxzone.fcmb.com/2020/07/flexxpreneur-is-back-2/',
|
||||
},
|
||||
{
|
||||
name: "3-MONTH FREE BANKING",
|
||||
linkPath: "https://www.fcmb.com/campaign/smebanking",
|
||||
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" },
|
||||
{ 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 },
|
||||
{ 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",
|
||||
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: '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: '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" },
|
||||
{ text: 'WAYS TO BANK', href: '/ways-to-bank' },
|
||||
{ text: 'BANCASSURANCE', href: '/bancassurance' },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "BUSINESS BANKING",
|
||||
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" },
|
||||
{ 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",
|
||||
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" },
|
||||
{ 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",
|
||||
category: 'GROUP & SUBSIDIARIES',
|
||||
subItems: [
|
||||
{ text: "FCMB GROUP PLC", href: "https://www.fcmbgroup.com/" },
|
||||
{ text: "CSL STOCKBROKERS", href: "https://www.cslstockbrokers.com/" },
|
||||
{ text: `${import.meta.env.VITE_BANK_NAME_SHORT} 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: `${import.meta.env.VITE_BANK_NAME_SHORT} CAPITAL MARKETS`,
|
||||
href: 'https://www.fcmbcapitalmarketsng.com/',
|
||||
},
|
||||
{
|
||||
text: "FCMB ASSET MANAGEMENT",
|
||||
href: "https://www.fcmbassetmanagement.com/index/",
|
||||
text: `${import.meta.env.VITE_BANK_NAME_SHORT} 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/" },
|
||||
{ text: `${import.meta.env.VITE_BANK_NAME_SHORT} MICROFINANCE BANK`, href: '/fcmb-microfinance-initiative' },
|
||||
{ text: `${import.meta.env.VITE_BANK_NAME_SHORT} UK`, href: 'http://www.fcmbuk.com/' },
|
||||
{ text: `${import.meta.env.VITE_BANK_NAME_SHORT} PENSIONS LIMITED`, href: 'https://www.fcmbpensions.com/' },
|
||||
{ text: 'CREDIT DIRECT LIMITED', href: 'https://www.creditdirect.ng' },
|
||||
{ text: `${import.meta.env.VITE_BANK_NAME_SHORT} TRUSTEES`, href: 'http://fcmbtrustees.com/' },
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "ABOUT US",
|
||||
category: 'ABOUT US',
|
||||
subItems: [
|
||||
{
|
||||
text: "OUR VISION/MISSION/VALUES",
|
||||
href: "/about-us/vision-mision-core-values",
|
||||
text: 'OUR VISION/MISSION/VALUES',
|
||||
href: '/about-us/vision-mision-core-values',
|
||||
},
|
||||
{ text: "OUR HISTORY", href: "/about-us/our-history" },
|
||||
{ text: 'OUR HISTORY', href: '/about-us/our-history' },
|
||||
{
|
||||
text: "INVESTOR RELATIONS",
|
||||
href: "http://www.fcmbgroup.com/investor-relations",
|
||||
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" },
|
||||
{ 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",
|
||||
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" },
|
||||
{ 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/",
|
||||
href: 'https://www.facebook.com/FcmbMyBank/',
|
||||
icon: FBookWhite,
|
||||
},
|
||||
{
|
||||
href: "https://twitter.com/myfcmb/",
|
||||
href: 'https://twitter.com/myfcmb/',
|
||||
icon: XWhite,
|
||||
},
|
||||
{
|
||||
href: "https://www.linkedin.com/company/first-city-monument-bank-ltd/",
|
||||
href: 'https://www.linkedin.com/company/first-city-monument-bank-ltd/',
|
||||
icon: LinkedInWhite,
|
||||
},
|
||||
{
|
||||
href: "https://www.youtube.com/user/fcmbplc",
|
||||
href: 'https://www.youtube.com/user/fcmbplc',
|
||||
icon: YoutubeWhite,
|
||||
},
|
||||
{
|
||||
href: "https://www.instagram.com/myfcmb/",
|
||||
href: 'https://www.instagram.com/myfcmb/',
|
||||
icon: InstagramWhite,
|
||||
},
|
||||
{
|
||||
href: "https://api.whatsapp.com/send?phone=09099999814",
|
||||
href: 'https://api.whatsapp.com/send?phone=09099999814',
|
||||
icon: WhatsappWhite,
|
||||
},
|
||||
];
|
||||
|
||||
export const footerCustomerLinks = [
|
||||
{
|
||||
text: "PRIVACY POLICY",
|
||||
href: "https://www.fcmb.com/privacy-policy",
|
||||
text: 'PRIVACY POLICY',
|
||||
href: 'https://www.fcmb.com/privacy-policy',
|
||||
},
|
||||
{
|
||||
text: "PRESS RELEASES",
|
||||
href: "/press-releases",
|
||||
text: 'PRESS RELEASES',
|
||||
href: '/press-releases',
|
||||
},
|
||||
{
|
||||
text: "SHARE PRICE",
|
||||
href: "/",
|
||||
text: 'SHARE PRICE',
|
||||
href: '/',
|
||||
},
|
||||
{
|
||||
text: "WHISTLE BLOWER",
|
||||
href: "/fcmb-whistle-blower-form",
|
||||
text: 'WHISTLE BLOWER',
|
||||
href: '/fcmb-whistle-blower-form',
|
||||
},
|
||||
{
|
||||
text: "FRAUD PREVENTION",
|
||||
href: "/customer-service",
|
||||
text: 'FRAUD PREVENTION',
|
||||
href: '/customer-service',
|
||||
},
|
||||
{
|
||||
text: "AML",
|
||||
href: "/customer-service",
|
||||
text: 'AML',
|
||||
href: '/customer-service',
|
||||
},
|
||||
{
|
||||
text: "CAREERS",
|
||||
href: "/career",
|
||||
text: 'CAREERS',
|
||||
href: '/career',
|
||||
},
|
||||
];
|
||||
|
||||
export const contactDetails = [
|
||||
{ name: 'Call', value: import.meta.env.VITE_CALL_ENDPOINT },
|
||||
{ name: 'Email', value: import.meta.env.VITE_EMAIL_ENDPOINT },
|
||||
];
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
interface SelectOption {
|
||||
loading: boolean;
|
||||
data: {value: string;
|
||||
label: string}[]
|
||||
}
|
||||
|
||||
export const state: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{
|
||||
"value": "abia",
|
||||
"label": "Abia"
|
||||
},
|
||||
{
|
||||
"value": "adamawa",
|
||||
"label": "Adamawa"
|
||||
},
|
||||
{
|
||||
"value": "akwa ibom",
|
||||
"label": "Akwa Ibom"
|
||||
},
|
||||
{
|
||||
"value": "anambra",
|
||||
"label": "Anambra"
|
||||
},
|
||||
{
|
||||
"value": "bauchi",
|
||||
"label": "Bauchi"
|
||||
},
|
||||
{
|
||||
"value": "bayelsa",
|
||||
"label": "Bayelsa"
|
||||
},
|
||||
{
|
||||
"value": "benue",
|
||||
"label": "Benue"
|
||||
},
|
||||
{
|
||||
"value": "borno",
|
||||
"label": "Borno"
|
||||
},
|
||||
{
|
||||
"value": "cross river",
|
||||
"label": "Cross River"
|
||||
},
|
||||
{
|
||||
"value": "delta",
|
||||
"label": "Delta"
|
||||
},
|
||||
{
|
||||
"value": "ebonyi",
|
||||
"label": "Ebonyi"
|
||||
},
|
||||
{
|
||||
"value": "edo",
|
||||
"label": "Edo"
|
||||
},
|
||||
{
|
||||
"value": "ekiti",
|
||||
"label": "Ekiti"
|
||||
},
|
||||
{
|
||||
"value": "enugu",
|
||||
"label": "Enugu"
|
||||
},
|
||||
{
|
||||
"value": "fct - abuja",
|
||||
"label": "FCT - Abuja"
|
||||
},
|
||||
{
|
||||
"value": "gombe",
|
||||
"label": "Gombe"
|
||||
},
|
||||
{
|
||||
"value": "imo",
|
||||
"label": "Imo"
|
||||
},
|
||||
{
|
||||
"value": "jigawa",
|
||||
"label": "Jigawa"
|
||||
},
|
||||
{
|
||||
"value": "kaduna",
|
||||
"label": "Kaduna"
|
||||
},
|
||||
{
|
||||
"value": "kano",
|
||||
"label": "Kano"
|
||||
},
|
||||
{
|
||||
"value": "katsina",
|
||||
"label": "Katsina"
|
||||
},
|
||||
{
|
||||
"value": "kebbi",
|
||||
"label": "Kebbi"
|
||||
},
|
||||
{
|
||||
"value": "kogi",
|
||||
"label": "Kogi"
|
||||
},
|
||||
{
|
||||
"value": "kwara",
|
||||
"label": "Kwara"
|
||||
},
|
||||
{
|
||||
"value": "lagos",
|
||||
"label": "Lagos"
|
||||
},
|
||||
{
|
||||
"value": "nasarawa",
|
||||
"label": "Nasarawa"
|
||||
},
|
||||
{
|
||||
"value": "niger",
|
||||
"label": "Niger"
|
||||
},
|
||||
{
|
||||
"value": "ogun",
|
||||
"label": "Ogun"
|
||||
},
|
||||
{
|
||||
"value": "ondo",
|
||||
"label": "Ondo"
|
||||
},
|
||||
{
|
||||
"value": "osun",
|
||||
"label": "Osun"
|
||||
},
|
||||
{
|
||||
"value": "oyo",
|
||||
"label": "Oyo"
|
||||
},
|
||||
{
|
||||
"value": "plateau",
|
||||
"label": "Plateau"
|
||||
},
|
||||
{
|
||||
"value": "rivers",
|
||||
"label": "Rivers"
|
||||
},
|
||||
{
|
||||
"value": "sokoto",
|
||||
"label": "Sokoto"
|
||||
},
|
||||
{
|
||||
"value": "taraba",
|
||||
"label": "Taraba"
|
||||
},
|
||||
{
|
||||
"value": "yobe",
|
||||
"label": "Yobe"
|
||||
},
|
||||
{
|
||||
"value": "zamfara",
|
||||
"label": "Zamfara"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user