Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b203c59ff7 | |||
| fe2168ce53 | |||
| 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 | |||
| 29538e3b6e |
@@ -6,4 +6,12 @@ TWITTER_URL=https://twitter.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
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'
|
||||
+5
-1
@@ -6,4 +6,8 @@ VITE_TWITTER_URL=https://twitter.com
|
||||
VITE_INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
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
-1
@@ -6,4 +6,8 @@ TWITTER_URL=https://twitter.com
|
||||
INSTAGRAM_URL=https://www.instagram.com
|
||||
|
||||
# BACKEND END POINTS
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
|
||||
|
||||
#BANK NAME
|
||||
VITE_BANK_NAME='First City Monument Bank'
|
||||
VITE_BANK_NAME_SHORT='FCMB'
|
||||
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",
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -25,7 +25,6 @@ const validationSchema = Yup.object().shape({
|
||||
return true;
|
||||
}),
|
||||
sales_agent: Yup.string()
|
||||
.required("Required")
|
||||
});
|
||||
|
||||
export default function DashboardFormInit({handleNextStep}:Props) {
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import React, { FC } from "react";
|
||||
import NairaBag from "../../assets/images/dashboard/naira-bag.png";
|
||||
import { Button } from "../";
|
||||
import { useSelector } from "react-redux";
|
||||
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;
|
||||
@@ -51,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}
|
||||
@@ -69,51 +77,155 @@ export const DashBoardCard: React.FC<DashBoardCardProps> = ({
|
||||
};
|
||||
|
||||
interface DashboardHomeIntroProps {
|
||||
handleNextStep:(value:{})=>any
|
||||
step?:number|string
|
||||
handleNextStep: (value: {}) => any;
|
||||
step?: number | string;
|
||||
}
|
||||
|
||||
const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step }) => {
|
||||
const { userDetails } = useSelector((state:any) => state?.userDetails); // CHECKS IF USER Details are avaliable
|
||||
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, {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>
|
||||
</>
|
||||
}
|
||||
<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={props.values.highest_eductaion}
|
||||
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" },
|
||||
]
|
||||
}
|
||||
@@ -32,10 +32,9 @@ export default function DashboardHomeAttestation({handleNextStep, applicationDet
|
||||
//FUNCTION TO HANDLE LOAN APPLICATION
|
||||
const handleSubmit = (values:any) => {
|
||||
delete values.checked
|
||||
applyForLoan({...applicationDetails, disbursement: values}).then(res=>{
|
||||
applyForLoan({...applicationDetails,disbursement_account: values?.account, disbursement: values}).then(res=>{
|
||||
console.log('APPLY FOR LOAN', res)
|
||||
handleNextStep({disbursement: values})
|
||||
console.log('ApplicationDetails', {...applicationDetails, disbursement: values})
|
||||
}).catch(err=>{
|
||||
console.log(err)
|
||||
})
|
||||
@@ -53,7 +52,7 @@ export default function DashboardHomeAttestation({handleNextStep, applicationDet
|
||||
<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>
|
||||
<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}
|
||||
@@ -84,7 +83,7 @@ export default function DashboardHomeAttestation({handleNextStep, applicationDet
|
||||
className='w-4 h-4 p-2 accent-purple-600 text-purple-600 bg-gray-100 border-gray-300 rounded focus:ring-purple-500'
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
<p className='text-[12px] text-justify'>By pressing, you agree that you have read, understood and accept the <span className='text-blue-600'>applicatant's attestation</span> and <span className='text-blue-600'>terms and conditions</span> for FCMB
|
||||
<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>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Button, InputCompOne, Stepper } from '../../shared/index';
|
||||
|
||||
import { state } from '../../../utils/states';
|
||||
|
||||
import {Formik, Form} from 'formik'
|
||||
import * as Yup from "yup";
|
||||
|
||||
@@ -13,7 +15,7 @@ const initialValues = {
|
||||
marital_status: "",
|
||||
state: "",
|
||||
email:"",
|
||||
country:""
|
||||
country:"NG"
|
||||
};
|
||||
|
||||
// To get the validation schema
|
||||
@@ -171,16 +173,6 @@ const maritalStatus: SelectOption = {
|
||||
]
|
||||
}
|
||||
|
||||
const state: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
{ value: "", label: "Please Select" },
|
||||
{ value: "abia", label: "Abia" },
|
||||
{ value: "imo", label: "Imo" },
|
||||
{ value: "lagos", label: "Lagos" },
|
||||
]
|
||||
}
|
||||
|
||||
const country: SelectOption = {
|
||||
loading: false,
|
||||
data: [
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
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:(value:{})=>any
|
||||
}
|
||||
|
||||
// type EmployerProps = {
|
||||
// loading?: boolean,
|
||||
// data?: Array<{[index:string]: string}> | {[index:string]: Array<{[index:string]: string}> }
|
||||
// }
|
||||
|
||||
const initialValues = {
|
||||
job_title: "",
|
||||
name: "",
|
||||
@@ -18,24 +26,37 @@ const initialValues = {
|
||||
monthly_salary: "",
|
||||
salary_payment_date: "",
|
||||
employment_id: "",
|
||||
highest_eductaion: ""
|
||||
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()
|
||||
.required("Required"),
|
||||
sector: Yup.string()
|
||||
.required("Required"),
|
||||
industry: 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()
|
||||
.email("Invalid")
|
||||
.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) => {
|
||||
@@ -58,16 +79,41 @@ const validationSchema = Yup.object().shape({
|
||||
.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) => {
|
||||
handleNextStep({employment: values})
|
||||
// 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">
|
||||
@@ -83,155 +129,188 @@ export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
|
||||
<Form>
|
||||
<div className="mt-[3.25rem] flex flex-col gap-9">
|
||||
<p className='text-red-500 text-lg md:text-2xl'>Employment Informaton</p>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="job_title"
|
||||
floatLabel="Job Title"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Software Engineer"
|
||||
value={props.values.job_title}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.job_title && props.touched.job_title) ? props.errors.job_title : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="name"
|
||||
floatLabel="Employer name"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="Mr. Mark John"
|
||||
value={props.values.name}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.name && props.touched.name) ? props.errors.name : ''}
|
||||
/>
|
||||
<div 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 className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="sector"
|
||||
floatLabel="Job Sector"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={jobSector}
|
||||
selectValue={props.values.sector}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.sector && props.touched.sector) ? props.errors.sector : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="industry"
|
||||
floatLabel="Select your industry"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={industry}
|
||||
selectValue={props.values.industry}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.industry && props.touched.industry) ? props.errors.industry : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="resumption_date"
|
||||
floatLabel="Date of resumption"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="12/12/2015"
|
||||
value={props.values.resumption_date}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.resumption_date && props.touched.resumption_date) ? props.errors.resumption_date : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="email"
|
||||
floatLabel="Employers official email"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="example@gmail.com"
|
||||
value={props.values.email}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.email && props.touched.email) ? props.errors.email : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="annual_income"
|
||||
floatLabel="Annual Income"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="1,200,000"
|
||||
value={props.values.annual_income}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.annual_income && props.touched.annual_income) ? props.errors.annual_income : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="monthly_salary"
|
||||
floatLabel="Net monthly salary"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem] text-right"
|
||||
placeholder="100,000"
|
||||
value={props.values.monthly_salary}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.monthly_salary && props.touched.monthly_salary) ? props.errors.monthly_salary : ''}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-[4.125rem]">
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="salary_payment_date"
|
||||
floatLabel="Salary payment date"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputType='date'
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="30th of every month"
|
||||
value={props.values.salary_payment_date}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.salary_payment_date && props.touched.salary_payment_date) ? props.errors.salary_payment_date : ''}
|
||||
/>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="employment_id"
|
||||
floatLabel="Employee ID"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
placeholder="LS/001/005"
|
||||
value={props.values.employment_id}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.employment_id && props.touched.employment_id) ? props.errors.employment_id : ''}
|
||||
/>
|
||||
</div>
|
||||
<InputCompOne
|
||||
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
|
||||
name="highest_eductaion"
|
||||
floatLabel="Highest level of education"
|
||||
// labelClass="font-bold text-[1.125rem]"
|
||||
select={true}
|
||||
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
|
||||
selectOptions={highestEductaion}
|
||||
selectValue={props.values.highest_eductaion}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.highest_eductaion && props.touched.highest_eductaion) ? props.errors.highest_eductaion : ''}
|
||||
/>
|
||||
<Button
|
||||
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11"
|
||||
text="Next"
|
||||
type="submit"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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,42 +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 { useDispatch } from 'react-redux';
|
||||
import { updateUserDetails } from '../../store/UserDetails';
|
||||
|
||||
import { validateBVN, verifyOTP } from "../../core/apiRequest";
|
||||
import { RequestStatus } from "../../core/models";
|
||||
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()
|
||||
// .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"),
|
||||
// .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;
|
||||
@@ -52,151 +52,207 @@ let initialValues = {
|
||||
};
|
||||
|
||||
type ValidBVN = {
|
||||
verification_id:string
|
||||
valid: undefined | boolean
|
||||
}
|
||||
verification_id: string;
|
||||
valid: undefined | boolean;
|
||||
};
|
||||
|
||||
const LetsGetStarted: React.FC = () => {
|
||||
const dispatch = useDispatch()
|
||||
const navigate = useNavigate()
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
// const [pinValues, setPinValues] = React.useState({
|
||||
// bvn: "",
|
||||
// otp: "",
|
||||
// });
|
||||
// const otpInputRef = React.useRef<HTMLInputElement>(null);
|
||||
|
||||
const [requestStatusBVN, setRequestStatusBVN] = React.useState<RequestStatus>({loading:false, status:undefined, message:''});
|
||||
const [requestStatusBVN, setRequestStatusBVN] = React.useState<RequestStatus>(
|
||||
{ loading: false, status: undefined, message: '' }
|
||||
);
|
||||
|
||||
const [requestStatusOTP, setRequestStatusOTP] = React.useState<RequestStatus>({loading:false, status:undefined, message:''});
|
||||
const [requestStatusOTP, setRequestStatusOTP] = React.useState<RequestStatus>(
|
||||
{ loading: false, status: undefined, message: '' }
|
||||
);
|
||||
|
||||
const [bvnIsValid, setBvnIsValid] = React.useState<ValidBVN>({
|
||||
verification_id: '',
|
||||
valid: undefined
|
||||
valid: undefined,
|
||||
});
|
||||
|
||||
|
||||
// e: React.FormEvent<HTMLInputElement>
|
||||
// let { value } = e.target as HTMLInputElement;
|
||||
const bvnValidation = (values:any) => { // Function to Validate BVN
|
||||
let bvn = values.bvn
|
||||
setRequestStatusBVN({loading:true, status:false, message:''})
|
||||
validateBVN({bvn}).then(res => {
|
||||
if(!res || !res.data.call_return){
|
||||
setBvnIsValid({verification_id:'', valid: false})
|
||||
setRequestStatusBVN({loading:false, status:false, message:'unable to verify BVN'})
|
||||
return setTimeout(()=>{
|
||||
setRequestStatusBVN({loading:false, status:false, message:''})
|
||||
}, 4000)
|
||||
}
|
||||
setBvnIsValid({verification_id:res.data.verification_id, valid: true})
|
||||
setRequestStatusBVN({loading:false, status:true, message:'verified'})
|
||||
}).catch(err => {
|
||||
setBvnIsValid({verification_id:'', valid: false})
|
||||
console.log(err)
|
||||
})
|
||||
const bvnValidation = (values: any) => {
|
||||
// Function to Validate BVN
|
||||
let bvn = values.bvn;
|
||||
setRequestStatusBVN({ loading: true, status: false, message: '' });
|
||||
validateBVN({ bvn })
|
||||
.then((res) => {
|
||||
if (!res || !res.data.call_return) {
|
||||
setBvnIsValid({ verification_id: '', valid: false });
|
||||
setRequestStatusBVN({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: 'unable to verify BVN',
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestStatusBVN({ loading: false, status: false, message: '' });
|
||||
}, 4000);
|
||||
}
|
||||
setBvnIsValid({
|
||||
verification_id: res.data.verification_id,
|
||||
valid: true,
|
||||
});
|
||||
setRequestStatusBVN({
|
||||
loading: false,
|
||||
status: true,
|
||||
message: 'verified',
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
setBvnIsValid({ verification_id: '', valid: false });
|
||||
console.log(err);
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = (values:any) => { // Function to VERIFY OTP AND LOGIN USER
|
||||
setRequestStatusOTP({loading:true, status:false, message:''})
|
||||
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)
|
||||
})
|
||||
verifyOTP({ ...values, verification_id: bvnIsValid.verification_id })
|
||||
.then((res) => {
|
||||
if (!res || !res.data.call_return) {
|
||||
setRequestStatusOTP({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: 'wrong otp',
|
||||
});
|
||||
return setTimeout(() => {
|
||||
setRequestStatusOTP({ loading: false, status: false, message: '' });
|
||||
}, 4000);
|
||||
}
|
||||
// console.log(res.data)
|
||||
localStorage.setItem('token', res.data?.token);
|
||||
localStorage.setItem('uid', res?.data?.customer[0]?.uid);
|
||||
dispatch(updateUserDetails({ ...res?.data?.customer[0] }));
|
||||
navigate(RouteHandler.dashboardHome, { replace: true });
|
||||
})
|
||||
.catch((err) => {
|
||||
setRequestStatusOTP({
|
||||
loading: false,
|
||||
status: false,
|
||||
message: 'something went wrong, try again',
|
||||
});
|
||||
console.log(err);
|
||||
return setTimeout(() => {
|
||||
setRequestStatusOTP({ loading: false, status: false, message: '' });
|
||||
}, 4000);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={bvnIsValid.valid ? handleSubmit : bvnValidation}
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={bvnIsValid.valid ? handleSubmit : bvnValidation}
|
||||
>
|
||||
{(props:any) => (
|
||||
<Form className="">
|
||||
<div className="w-full">
|
||||
<div className="containerMode flex justify-between gap-1 xl:gap-8 flex-col">
|
||||
<div className="my-[4rem] flex items-center justify-center w-full">
|
||||
<h1 className="font-bold text-[2.375rem] text-[#5C2684] my-[.5rem] text-center">
|
||||
Let’s Get You Started
|
||||
</h1>
|
||||
</div>
|
||||
<div className="mx-auto flex flex-col gap-8 max-w-[31.625rem] ">
|
||||
<div className='w-full'>
|
||||
<InputCompOne
|
||||
parentClass="flex flex-col gap-2"
|
||||
label="Enter Your BVN "
|
||||
name="bvn"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( To get your BVN, dial *565*0# )"
|
||||
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
|
||||
placeholder="Enter your BVN"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
|
||||
value={props.values.bvn}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.bvn && props.touched.bvn) && props.errors.bvn}
|
||||
/>
|
||||
<p className={`p-2 ${!requestStatusBVN.status ? 'text-red-500' : 'text-emerald-500'}`}>{requestStatusBVN.loading ? 'verifying...' : requestStatusBVN.message}</p>
|
||||
{(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>
|
||||
{bvnIsValid.valid && (
|
||||
<InputCompOne
|
||||
parentClass="flex flex-col gap-2"
|
||||
label="Enter OTP "
|
||||
name="otp"
|
||||
parentInputClass="w-full"
|
||||
labelSpan="( Please check your BVN phone number for verification pin )"
|
||||
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
|
||||
placeholder="Enter your OTP"
|
||||
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
|
||||
input
|
||||
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
|
||||
value={props.values.otp}
|
||||
onChange={props.handleChange}
|
||||
error={(props.errors.otp && props.touched.otp) && props.errors.otp}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
type='submit'
|
||||
className="w-full h-[3.625rem] rounded bg-[#FBB700] rounded-2 px-4 text-[18px] text-[#282828] font-semibold disabled:text-[#282828] disabled:text-opacity-50"
|
||||
disabled={requestStatusBVN.loading || (!props.values.otp && bvnIsValid.valid)}
|
||||
>
|
||||
Enter
|
||||
</button>
|
||||
|
||||
<p className={`p-2 ${!requestStatusOTP.status ? 'text-red-500' : 'text-emerald-500'}`}>{requestStatusOTP.message}</p>
|
||||
<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>
|
||||
|
||||
{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
|
||||
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>
|
||||
);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export interface InputCompOneProps {
|
||||
selectValue?: string;
|
||||
input?: boolean;
|
||||
select?: boolean;
|
||||
selectOptions?: {loading:boolean, data:{ 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>(
|
||||
@@ -52,6 +53,7 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
parentClass,
|
||||
maxLength,
|
||||
error,
|
||||
disabled=false
|
||||
},
|
||||
forwardedRef
|
||||
) => {
|
||||
@@ -78,6 +80,7 @@ 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
|
||||
@@ -96,17 +99,29 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
|
||||
name={name}
|
||||
id={label ? label : floatLabel}
|
||||
value={selectValue}
|
||||
className={`px-4 appearance-none ${floatLabel && 'peer pt-4'} ${selectClass}`}
|
||||
className={`px-4 appearance-none ${floatLabel && 'peer pt-4'} ${selectClass} ${disabled && 'opacity-50'}`}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
>
|
||||
{selectOptions.loading ?
|
||||
<option value=''>Loading</option>
|
||||
: selectOptions.data.length ?
|
||||
selectOptions.data.map(({ value, label }) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
</option>
|
||||
))
|
||||
{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>
|
||||
}
|
||||
|
||||
+42
-1
@@ -26,11 +26,52 @@ export const applyForLoan = (postData:any) => {
|
||||
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)
|
||||
}
|
||||
@@ -10,8 +10,8 @@ export function postAuxEnd(uri: string, reqData: any): Promise<any> {
|
||||
// console.log('SAMPLE',innerReqData)
|
||||
// formData.append(reqData[value][innerValue], reqData[value][innerValue]);
|
||||
// }
|
||||
// formData.append(value, JSON.stringify(reqData[value]));
|
||||
formData.append(value, reqData[value]);
|
||||
formData.append(value, JSON.stringify(reqData[value]));
|
||||
// formData.append(value, reqData[value]);
|
||||
} else {
|
||||
formData.append(value, reqData[value]);
|
||||
}
|
||||
|
||||
+15
-1
@@ -15,4 +15,18 @@ export interface User {
|
||||
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,31 +1,63 @@
|
||||
import { useState } from "react";
|
||||
import { Link, useLocation } 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
|
||||
logoutUser: () => void;
|
||||
};
|
||||
|
||||
export default function Aside({ asideDisplay, logoutUser }: Props) {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
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="/">
|
||||
@@ -45,8 +77,8 @@ export default function Aside({ asideDisplay, logoutUser }: 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}
|
||||
@@ -60,8 +92,8 @@ export default function Aside({ asideDisplay, logoutUser }: 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) => (
|
||||
@@ -70,17 +102,17 @@ export default function Aside({ asideDisplay, logoutUser }: 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}
|
||||
@@ -96,14 +128,14 @@ export default function Aside({ asideDisplay, logoutUser }: 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>
|
||||
@@ -119,19 +151,25 @@ export default function Aside({ asideDisplay, logoutUser }: Props) {
|
||||
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>
|
||||
);
|
||||
@@ -149,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:[
|
||||
|
||||
@@ -83,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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
+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