Compare commits

...

14 Commits

14 changed files with 678 additions and 459 deletions
+4
View File
@@ -11,3 +11,7 @@ VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1'
# ENQUIRIES CONTACTS # ENQUIRIES CONTACTS
VITE_CALL_ENDPOINT='09099000000' VITE_CALL_ENDPOINT='09099000000'
VITE_EMAIL_ENDPOINT='fcmbloan@support.com' VITE_EMAIL_ENDPOINT='fcmbloan@support.com'
#BANK NAME
VITE_BANK_NAME='First City Monument Bank'
VITE_BANK_NAME_SHORT='FCMB'
+4
View File
@@ -7,3 +7,7 @@ VITE_INSTAGRAM_URL=https://www.instagram.com
# BACKEND END POINTS # 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'
+4
View File
@@ -7,3 +7,7 @@ INSTAGRAM_URL=https://www.instagram.com
# BACKEND END POINTS # 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'
+72 -52
View File
@@ -1,11 +1,11 @@
import React, { FC, useState, useEffect } from "react"; import React, { FC, useState, useEffect } from 'react';
import NairaBag from "../../assets/images/dashboard/naira-bag.png"; import NairaBag from '../../assets/images/dashboard/naira-bag.png';
import { Button, Icons } from "../"; import { Button, Icons } from '../';
import { useSelector } from "react-redux"; import { useSelector } from 'react-redux';
import PendingList from "../paginated-list/PendingList"; import PendingList from '../paginated-list/PendingList';
import { PendingTableList } from "../../core/models"; import { PendingTableList } from '../../core/models';
import { NewDateTimeFormatter } from "../../lib/NewDateTimeFormatter"; import { NewDateTimeFormatter } from '../../lib/NewDateTimeFormatter';
import { getUserPendingLoanList } from "../../core/apiRequest"; import { getUserPendingLoanList } from '../../core/apiRequest';
export interface DashBoardCardProps { export interface DashBoardCardProps {
title?: string; title?: string;
@@ -55,7 +55,7 @@ export const DashBoardCard: React.FC<DashBoardCardProps> = ({
)} )}
{desc && ( {desc && (
<p className={`text-lg text-left ${descClass && descClass}`}> <p className={`text-lg text-left ${descClass && descClass}`}>
{desc}{" "} {desc}{' '}
{descSpan && ( {descSpan && (
<span className={`${descSpanClass && descSpanClass}`}> <span className={`${descSpanClass && descSpanClass}`}>
{descSpan} {descSpan}
@@ -73,40 +73,50 @@ export const DashBoardCard: React.FC<DashBoardCardProps> = ({
}; };
interface DashboardHomeIntroProps { interface DashboardHomeIntroProps {
handleNextStep:(value:{})=>any handleNextStep: (value: {}) => any;
step?:number|string step?: number | string;
} }
const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step }) => { const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({
handleNextStep,
step,
}) => {
const { userDetails } = useSelector((state: any) => state?.userDetails); // CHECKS IF USER Details are avaliable const { userDetails } = useSelector((state: any) => state?.userDetails); // CHECKS IF USER Details are avaliable
const [userLoanList, setUserLoanList] = useState<{loading:boolean, data:PendingTableList}>({loading: true, data:[]}) const [userLoanList, setUserLoanList] = useState<{
loading: boolean;
data: PendingTableList;
}>({ loading: true, data: [] });
useEffect(() => { useEffect(() => {
let token = localStorage.getItem('token') let token = localStorage.getItem('token');
let uid = localStorage.getItem('uid') let uid = localStorage.getItem('uid');
if (!token || !uid) { if (!token || !uid) {
return return;
} }
getUserPendingLoanList(uid).then(res => { getUserPendingLoanList(uid)
console.log('RES', res) .then((res) => {
console.log('RES', userLoanList) console.log('RES', res);
console.log('RES', userLoanList);
if (!res || !res.data.loans) { if (!res || !res.data.loans) {
setUserLoanList({loading:false, data:[]}) setUserLoanList({ loading: false, data: [] });
return return;
} }
setUserLoanList({loading:false, data:res?.data?.loans}) setUserLoanList({ loading: false, data: res?.data?.loans });
}).catch(err => {
console.log(err)
setUserLoanList({loading:false, data:[]})
}) })
},[]) .catch((err) => {
console.log(err);
setUserLoanList({ loading: false, data: [] });
});
}, []);
return ( return (
<div className='w-full'> <div className="w-full">
{step == 1 ? {step == 1 ? (
<> <>
<h1 className="font-bold my-5 text-2xl">Hello, {userDetails.firstname}</h1> <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 "> <div className="group w-full lg:w-[27.8125rem] h-[12.75rem] mt-7 ">
<DashBoardCard <DashBoardCard
cardClass="bg-[#5C2684] relative" cardClass="bg-[#5C2684] relative"
@@ -122,9 +132,11 @@ const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step
/> />
</div> </div>
</> </>
: ) : (
<> <>
<h1 className="font-bold my-5 text-2xl">Welcome Back, {userDetails.firstname}</h1> <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 "> <div className="group w-full lg:w-[27.8125rem] h-[12.75rem] mt-7 ">
<DashBoardCard <DashBoardCard
cardClass="bg-[#5C2684] relative" cardClass="bg-[#5C2684] relative"
@@ -140,39 +152,47 @@ const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step
/> />
</div> </div>
</> </>
} )}
{userLoanList.loading ? {userLoanList.loading ? null : (
null <div className="mt-5 w-full">
:
<div className='mt-5 w-full'>
<PendingList <PendingList
data={userLoanList.data} data={userLoanList.data}
itemsPerPage={5} itemsPerPage={5}
tableTitle='Current Applications' tableTitle="Current Applications"
> >
{(data: any) => ( {(data: any) => (
<div className="w-full p-4 rounded-lg shadow-lg bg-white overflow-x-auto min-h-[250px] max-h-[450px]"> <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"> <table className="text-[12px] sm:text-base w-full table-auto">
<thead> <thead>
<tr className='text-left border-b-2'> <tr className="text-left border-b-2">
<th className='px-1 py-4'>Date</th> <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-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 min-w-[110px]">
<th className='px-1 py-4 text-center'>Status</th> Payment Term
<th className='px-1 py-4'>Action</th> </th>
<th className="px-1 py-4 text-center">Status</th>
<th className="px-1 py-4 text-right">Action</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{data.map((item: any, index: any) => ( {data.map((item: any, index: any) => (
<tr key={index || item} className='even:bg-slate-100'> <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">
<td className='px-1 py-2 text-right'>{item?.loan_amount}</td> {NewDateTimeFormatter(item?.added)}
<td className='px-1 py-2 text-center'>{item?.payment_month}</td> </td>
<td className='px-1 py-2 text-center'>{item?.status}</td> <td className="px-1 py-2 text-right">
<td className='px-1 py-2'> {item?.loan_amount}
<button className='px-2 py-1 border-2 border-black flex gap-2 items-center'> </td>
<td className="px-1 py-2 text-center">
{item?.payment_month}
</td>
<td className="px-1 py-2 text-center">
{item?.status}
</td>
<td className="px-1 py-2 text-right">
<button className="px-2 py-1 border-2 border-black">
View View
<Icons name='arrow-right' /> <Icons name="arrow-right" />
</button> </button>
</td> </td>
</tr> </tr>
@@ -183,7 +203,7 @@ const DashboardHomeIntro: FC<DashboardHomeIntroProps> = ({ handleNextStep, step
)} )}
</PendingList> </PendingList>
</div> </div>
} )}
</div> </div>
); );
}; };
@@ -53,7 +53,7 @@ export default function DashboardHomeAttestation({handleNextStep, applicationDet
<Stepper step={4} /> <Stepper step={4} />
</div> </div>
<p className='my-10 text-red-500 text-lg md:text-2xl'>Applicant's Attestation and Debit Instruction</p> <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 <Formik
initialValues={initialValues} initialValues={initialValues}
validationSchema={validationSchema} validationSchema={validationSchema}
@@ -84,7 +84,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' 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} 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 premium salary loan. You also give us permission to collect financial information and run credit checks on the account provided through our partners
</p> </p>
</div> </div>
@@ -1,12 +1,20 @@
import {useState, useEffect} from 'react'
import { Button, InputCompOne, Stepper } from '../../shared/index'; import { Button, InputCompOne, Stepper } from '../../shared/index';
import {Formik, Form} from 'formik' import {Formik, Form} from 'formik'
import * as Yup from "yup"; import * as Yup from "yup";
import { getEmployersList } from '../../../core/apiRequest';
type Props = { type Props = {
handleNextStep:(value:{})=>any handleNextStep:(value:{})=>any
} }
// type EmployerProps = {
// loading?: boolean,
// data?: Array<{[index:string]: string}> | {[index:string]: Array<{[index:string]: string}> }
// }
const initialValues = { const initialValues = {
job_title: "", job_title: "",
name: "", name: "",
@@ -18,24 +26,37 @@ const initialValues = {
monthly_salary: "", monthly_salary: "",
salary_payment_date: "", salary_payment_date: "",
employment_id: "", employment_id: "",
highest_eductaion: "" highest_eductaion: "",
employer_uid: "",
isChecked: false
}; };
// To get the validation schema // To get the validation schema
const validationSchema = Yup.object().shape({ 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() job_title: Yup.string()
.required("Required"), .required("Required"),
name: Yup.string() name: Yup.string().when('isChecked', {
.required("Required"), is: true,
sector: Yup.string() then: () => Yup.string().required('required'),
.required("Required"), otherwise: () => Yup.string(),
industry: Yup.string() }),
.required("Required"), 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() resumption_date: Yup.string()
.required("Required"), .required("Required"),
email: Yup.string() email: Yup.string().when('isChecked', {
.email("Invalid") is: true,
.required("Required"), then: () => Yup.string().required('required'),
})
.email("Invalid"),
annual_income: Yup.string() annual_income: Yup.string()
.required("Required") .required("Required")
.test("no-e", "Invalid", (value:any) => { .test("no-e", "Invalid", (value:any) => {
@@ -58,16 +79,41 @@ const validationSchema = Yup.object().shape({
.required("Required"), .required("Required"),
highest_eductaion: Yup.string() highest_eductaion: Yup.string()
.required("Required"), .required("Required"),
employer_uid: Yup.string().when('isChecked', {
is: false,
then: () => Yup.string().required('required'),
}),
}); });
export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) { export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
const [employersList, setEmployersList] = useState<any>({
loading: true,
data: []
})
//FUNCTION TO HANDLE SUBMIT //FUNCTION TO HANDLE SUBMIT
const handleSubmit = (values:any) => { const handleSubmit = (values:any) => {
// Remember to changed the checked value's name
if(values.employer_uid){
let employer_uid = values.employer_uid
delete values.employer_uid
handleNextStep({employer_uid, employment: values})
}else{
handleNextStep({employment: values}) handleNextStep({employment: values})
}
}; };
useEffect(()=>{
getEmployersList().then(res => {
setEmployersList({loading:false, data:res?.data})
}).catch(err => {
console.log(err)
setEmployersList({loading:false, data:[]})
})
},[])
return ( return (
<div className="w-full"> <div className="w-full">
@@ -83,9 +129,91 @@ export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
<Form> <Form>
<div className="mt-[3.25rem] flex flex-col gap-9"> <div className="mt-[3.25rem] flex flex-col gap-9">
<p className='text-red-500 text-lg md:text-2xl'>Employment Informaton</p> <p className='text-red-500 text-lg md:text-2xl'>Employment Informaton</p>
<div className="flex items-center gap-[4.125rem]"> <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 <InputCompOne
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4" 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" name="job_title"
floatLabel="Job Title" floatLabel="Job Title"
// labelClass="font-bold text-[1.125rem]" // labelClass="font-bold text-[1.125rem]"
@@ -97,47 +225,20 @@ export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
error={(props.errors.job_title && props.touched.job_title) ? props.errors.job_title : ''} error={(props.errors.job_title && props.touched.job_title) ? props.errors.job_title : ''}
/> />
<InputCompOne <InputCompOne
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4" parentClass="w-full"
name="name" name="highest_eductaion"
floatLabel="Employer name" floatLabel="Highest level of education"
// labelClass="font-bold text-[1.125rem]"
input
inputClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
placeholder="Mr. Mark John"
value={props.values.name}
onChange={props.handleChange}
error={(props.errors.name && props.touched.name) ? props.errors.name : ''}
/>
</div>
<div className="flex items-center gap-[4.125rem]">
<InputCompOne
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4"
name="sector"
floatLabel="Job Sector"
// labelClass="font-bold text-[1.125rem]" // labelClass="font-bold text-[1.125rem]"
select={true} select={true}
selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]" selectClass="w-full h-[3.625rem] bg-[#EFEFEF] px-4 rounded-[.375rem]"
selectOptions={jobSector} selectOptions={highestEductaion}
selectValue={props.values.sector} selectValue={props.values.highest_eductaion}
onChange={props.handleChange} onChange={props.handleChange}
error={(props.errors.sector && props.touched.sector) ? props.errors.sector : ''} 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 <InputCompOne
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4" 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 : ''}
/>
</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" name="resumption_date"
floatLabel="Date of resumption" floatLabel="Date of resumption"
// labelClass="font-bold text-[1.125rem]" // labelClass="font-bold text-[1.125rem]"
@@ -150,47 +251,7 @@ export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
error={(props.errors.resumption_date && props.touched.resumption_date) ? props.errors.resumption_date : ''} error={(props.errors.resumption_date && props.touched.resumption_date) ? props.errors.resumption_date : ''}
/> />
<InputCompOne <InputCompOne
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4" 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 : ''}
/>
</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" name="salary_payment_date"
floatLabel="Salary payment date" floatLabel="Salary payment date"
// labelClass="font-bold text-[1.125rem]" // labelClass="font-bold text-[1.125rem]"
@@ -202,8 +263,35 @@ export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
onChange={props.handleChange} onChange={props.handleChange}
error={(props.errors.salary_payment_date && props.touched.salary_payment_date) ? props.errors.salary_payment_date : ''} 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 <InputCompOne
parentClass="max-w-[25.875rem] w-full flex flex-col gap-4" 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" name="employment_id"
floatLabel="Employee ID" floatLabel="Employee ID"
// labelClass="font-bold text-[1.125rem]" // labelClass="font-bold text-[1.125rem]"
@@ -214,25 +302,16 @@ export default function DashboardHomeEmploymentInfo({handleNextStep}:Props) {
onChange={props.handleChange} onChange={props.handleChange}
error={(props.errors.employment_id && props.touched.employment_id) ? props.errors.employment_id : ''} error={(props.errors.employment_id && props.touched.employment_id) ? props.errors.employment_id : ''}
/> />
</div> <div className="w-full">
<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 <Button
className="my-8 max-w-[25.875rem] btn-Y text-black w-full h-11" className="my-4 btn-Y text-black w-full h-11"
text="Next" text="Next"
type="submit" type="submit"
/> />
</div> </div>
</div>
</div>
</div>
</Form> </Form>
)} )}
</Formik> </Formik>
+1 -1
View File
@@ -17,7 +17,7 @@ const BottomFooterOne = () => {
<CustomerLinks /> <CustomerLinks />
</div> </div>
<p className="text-[.8125rem] text-[#333] leading-[1.42857]"> <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) Central Bank of Nigeria)
</p> </p>
</div> </div>
+1 -1
View File
@@ -8,7 +8,7 @@ export default function Footer() {
<div className="w-full h-[5.4375rem] bg-[F7F7F7] flex items-center"> <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"> <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]"> <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> </p>
<div className="footer-social-icons flex justify-end items-center gap-2"> <div className="footer-social-icons flex justify-end items-center gap-2">
{renderSocialLinks()} {renderSocialLinks()}
@@ -12,7 +12,7 @@ const EligiblityBox = () => {
You must have a valid BVN You must have a valid BVN
</li> </li>
<li className="text-base leading-[1.5625rem]"> <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> </li>
</ul> </ul>
</div> </div>
+120 -64
View File
@@ -1,42 +1,42 @@
import React from "react"; import React from 'react';
import * as Yup from "yup"; import * as Yup from 'yup';
import { Form, Formik } from "formik"; import { Form, Formik } from 'formik';
import { InputCompOne } from ".."; import { InputCompOne } from '..';
import {useNavigate} from 'react-router-dom' import { useNavigate } from 'react-router-dom';
import { RouteHandler } from "../../router/routes"; import { RouteHandler } from '../../router/routes';
import { useDispatch } from "react-redux"; import { useDispatch } from 'react-redux';
import { updateUserDetails } from "../../store/UserDetails"; import { updateUserDetails } from '../../store/UserDetails';
import { validateBVN, verifyOTP } from "../../core/apiRequest"; import { validateBVN, verifyOTP } from '../../core/apiRequest';
import { RequestStatus } from "../../core/models"; import { RequestStatus } from '../../core/models';
// To get the validation schema // To get the validation schema
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
bvn: Yup.string() bvn: Yup.string()
.required("BVN is required") .required('BVN is required')
.test("no-e", "Invalid number", (value:any) => { .test('no-e', 'Invalid number', (value: any) => {
if (value && /^[0-9]*$/.test(value) == false) { if (value && /^[0-9]*$/.test(value) == false) {
return false; return false;
} }
return true; return true;
}) })
.min(11, "must be 11 digits") .min(11, 'must be 11 digits')
.max(11, "must be 11 digits"), .max(11, 'must be 11 digits'),
otp: Yup.string() otp: Yup.string()
// .when('require_otp', { // .when('require_otp', {
// is: true, // is: true,
// then: Yup.string().required("OTP is required") // then: Yup.string().required("OTP is required")
// }) // })
// .required("OTP is required") // .required("OTP is required")
.test("no-e", "Invalid number", (value:any) => { .test('no-e', 'Invalid number', (value: any) => {
if (value && /^[0-9]*$/.test(value) == false) { if (value && /^[0-9]*$/.test(value) == false) {
return false; return false;
} }
return true; return true;
}) })
.min(5, "must be 5 digits") .min(5, 'must be 5 digits')
.max(5, "must be 5 digits"), .max(5, 'must be 5 digits'),
// .test("no-e", "must be 11 characters", (value:any) => { // .test("no-e", "must be 11 characters", (value:any) => {
// if (value.length < 11) { // if (value.length < 11) {
// return false; // return false;
@@ -52,72 +52,100 @@ let initialValues = {
}; };
type ValidBVN = { type ValidBVN = {
verification_id:string verification_id: string;
valid: undefined | boolean valid: undefined | boolean;
} };
const LetsGetStarted: React.FC = () => { const LetsGetStarted: React.FC = () => {
const dispatch = useDispatch() const dispatch = useDispatch();
const navigate = useNavigate() const navigate = useNavigate();
// const [pinValues, setPinValues] = React.useState({ // const [pinValues, setPinValues] = React.useState({
// bvn: "", // bvn: "",
// otp: "", // otp: "",
// }); // });
// const otpInputRef = React.useRef<HTMLInputElement>(null); // 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>({ const [bvnIsValid, setBvnIsValid] = React.useState<ValidBVN>({
verification_id: '', verification_id: '',
valid: undefined valid: undefined,
}); });
// e: React.FormEvent<HTMLInputElement> // e: React.FormEvent<HTMLInputElement>
// let { value } = e.target as HTMLInputElement; // let { value } = e.target as HTMLInputElement;
const bvnValidation = (values:any) => { // Function to Validate BVN const bvnValidation = (values: any) => {
let bvn = values.bvn // Function to Validate BVN
setRequestStatusBVN({loading:true, status:false, message:''}) let bvn = values.bvn;
validateBVN({bvn}).then(res => { setRequestStatusBVN({ loading: true, status: false, message: '' });
validateBVN({ bvn })
.then((res) => {
if (!res || !res.data.call_return) { if (!res || !res.data.call_return) {
setBvnIsValid({verification_id:'', valid: false}) setBvnIsValid({ verification_id: '', valid: false });
setRequestStatusBVN({loading:false, status:false, message:'unable to verify BVN'}) setRequestStatusBVN({
loading: false,
status: false,
message: 'unable to verify BVN',
});
return setTimeout(() => { return setTimeout(() => {
setRequestStatusBVN({loading:false, status:false, message:''}) setRequestStatusBVN({ loading: false, status: false, message: '' });
}, 4000) }, 4000);
} }
setBvnIsValid({verification_id:res.data.verification_id, valid: true}) setBvnIsValid({
setRequestStatusBVN({loading:false, status:true, message:'verified'}) verification_id: res.data.verification_id,
}).catch(err => { valid: true,
setBvnIsValid({verification_id:'', valid: false}) });
console.log(err) 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 const handleSubmit = (values: any) => {
setRequestStatusOTP({loading:true, status:false, message:''}) // Function to VERIFY OTP AND LOGIN USER
setRequestStatusOTP({ loading: true, status: false, message: '' });
// console.log('values', values) // console.log('values', values)
verifyOTP({...values, verification_id:bvnIsValid.verification_id}).then(res=>{ verifyOTP({ ...values, verification_id: bvnIsValid.verification_id })
.then((res) => {
if (!res || !res.data.call_return) { if (!res || !res.data.call_return) {
setRequestStatusOTP({loading:false, status:false, message:'wrong otp'}) setRequestStatusOTP({
loading: false,
status: false,
message: 'wrong otp',
});
return setTimeout(() => { return setTimeout(() => {
setRequestStatusOTP({loading:false, status:false, message:''}) setRequestStatusOTP({ loading: false, status: false, message: '' });
},4000) }, 4000);
} }
// console.log(res.data) // console.log(res.data)
localStorage.setItem('token', res.data?.token) localStorage.setItem('token', res.data?.token);
localStorage.setItem('uid', res?.data?.customer[0]?.uid) localStorage.setItem('uid', res?.data?.customer[0]?.uid);
dispatch(updateUserDetails({ ...res?.data?.customer[0] })); dispatch(updateUserDetails({ ...res?.data?.customer[0] }));
navigate(RouteHandler.dashboardHome, {replace:true}) 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)
}) })
.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 ( return (
@@ -136,7 +164,7 @@ const LetsGetStarted: React.FC = () => {
</h1> </h1>
</div> </div>
<div className="mx-auto flex flex-col gap-8 max-w-[31.625rem] "> <div className="mx-auto flex flex-col gap-8 max-w-[31.625rem] ">
<div className='w-full'> <div className="w-full">
<InputCompOne <InputCompOne
parentClass="flex flex-col gap-2" parentClass="flex flex-col gap-2"
label="Enter Your BVN " label="Enter Your BVN "
@@ -150,9 +178,22 @@ const LetsGetStarted: React.FC = () => {
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4" inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
value={props.values.bvn} value={props.values.bvn}
onChange={props.handleChange} onChange={props.handleChange}
error={(props.errors.bvn && props.touched.bvn) && props.errors.bvn} 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> <p
className={`p-2 ${
!requestStatusBVN.status
? 'text-red-500'
: 'text-emerald-500'
}`}
>
{requestStatusBVN.loading
? 'verifying...'
: requestStatusBVN.message}
</p>
</div> </div>
{bvnIsValid.valid && ( {bvnIsValid.valid && (
<InputCompOne <InputCompOne
@@ -168,24 +209,39 @@ const LetsGetStarted: React.FC = () => {
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4" inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
value={props.values.otp} value={props.values.otp}
onChange={props.handleChange} onChange={props.handleChange}
error={(props.errors.otp && props.touched.otp) && props.errors.otp} error={
props.errors.otp && props.touched.otp && props.errors.otp
}
maxLength={5}
/> />
)} )}
<button <button
type='submit' 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" 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)} disabled={
requestStatusBVN.loading ||
(!props.values.otp && bvnIsValid.valid)
}
> >
Enter Enter
</button> </button>
<p className={`p-2 ${!requestStatusOTP.status ? 'text-red-500' : 'text-emerald-500'}`}>{requestStatusOTP.message}</p> <p
className={`p-2 ${
!requestStatusOTP.status
? 'text-red-500'
: 'text-emerald-500'
}`}
>
{requestStatusOTP.message}
</p>
{bvnIsValid.valid || bvnIsValid.valid == undefined ? ( {bvnIsValid.valid || bvnIsValid.valid == undefined ? (
<p className="text-[#5C2684] mt-[1.5625rem] w-fit"> <p className="text-[#5C2684] mt-[1.5625rem] w-fit">
***Every personal information attached to your BVN is safe and ***Every personal information attached to your BVN is safe
secure. It is only important for us to verify your information and and secure. It is only important for us to verify your
also give you access to your application profile/account. information and also give you access to your application
profile/account.
</p> </p>
) : ( ) : (
<p className="text-[#5C2684] mt-[1.5625rem] w-fit"> <p className="text-[#5C2684] mt-[1.5625rem] w-fit">
+17 -4
View File
@@ -17,7 +17,7 @@ export interface InputCompOneProps {
selectValue?: string; selectValue?: string;
input?: boolean; input?: boolean;
select?: boolean; select?: boolean;
selectOptions?: {loading:boolean, data:{ value: string; label: string }[]}; selectOptions?: {loading:boolean, data:{ [index: string]: string; }[]};
inputType?: string; inputType?: string;
inputClass?: string; inputClass?: string;
parentInputClass?: string; parentInputClass?: string;
@@ -25,6 +25,7 @@ export interface InputCompOneProps {
parentClass?: string; parentClass?: string;
maxLength?: number; maxLength?: number;
error?: string; error?: string;
disabled?: boolean
} }
const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>( const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
@@ -52,6 +53,7 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
parentClass, parentClass,
maxLength, maxLength,
error, error,
disabled=false
}, },
forwardedRef forwardedRef
) => { ) => {
@@ -78,6 +80,7 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
className={`px-4 ${floatLabel && 'peer pt-4 placeholder:text-transparent'} ${inputClass}`} className={`px-4 ${floatLabel && 'peer pt-4 placeholder:text-transparent'} ${inputClass}`}
maxLength={maxLength} maxLength={maxLength}
id={label ? label : floatLabel} id={label ? label : floatLabel}
disabled={disabled}
/> />
{floatLabel && {floatLabel &&
<label <label
@@ -96,12 +99,22 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
name={name} name={name}
id={label ? label : floatLabel} id={label ? label : floatLabel}
value={selectValue} 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} onChange={onChange}
disabled={disabled}
> >
{selectOptions.loading ? {selectOptions.loading ?
<option value=''>Loading</option> <option value=''>Loading...</option>
: selectOptions.data.length ? : 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 }) => ( selectOptions.data.map(({ value, label }) => (
<option key={value} value={value}> <option key={value} value={value}>
{label} {label}
+8
View File
@@ -41,3 +41,11 @@ export const getUserPendingLoanList = (uid:string) => {
} }
return getAuxEnd(`/dash?uid=${uid}`, reqData) 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)
}
+32 -1
View File
@@ -1,4 +1,4 @@
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation } from 'react-router-dom';
import Logo from '../../assets/icons/logo.svg'; import Logo from '../../assets/icons/logo.svg';
import { Icons } from '../../components'; import { Icons } from '../../components';
@@ -27,6 +27,37 @@ export default function Aside({ asideDisplay, logoutUser }: Props) {
} }
}; };
// 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 ( return (
<div className="py-5 px-10 flex flex-col h-full bg-inherit"> <div className="py-5 px-10 flex flex-col h-full bg-inherit">
<Link to="/"> <Link to="/">
+24 -24
View File
@@ -82,7 +82,7 @@ export const _lowerMenuItems = [
name: 'SAVINGS ACCOUNTS', name: 'SAVINGS ACCOUNTS',
linkPath: '/savings-accounts', linkPath: '/savings-accounts',
subItems: [ subItems: [
{ name: 'FCMB EASY ACCOUNT', linkPath: '/easy-account' }, { name: `${import.meta.env.VITE_BANK_NAME_SHORT} EASY ACCOUNT`, linkPath: '/easy-account' },
{ name: 'KIDS (0-17 YRS)', linkPath: '/kids' }, { name: 'KIDS (0-17 YRS)', linkPath: '/kids' },
{ name: 'FLEXX (18-30 YRS)', linkPath: '/flexx-account' }, { name: 'FLEXX (18-30 YRS)', linkPath: '/flexx-account' },
{ {
@@ -94,7 +94,7 @@ export const _lowerMenuItems = [
linkPath: '/fcmb-premium-savings-account', linkPath: '/fcmb-premium-savings-account',
}, },
{ {
name: 'FCMB SALARY SAVINGS ACCOUNT', name: `${import.meta.env.VITE_BANK_NAME_SHORT} SALARY SAVINGS ACCOUNT`,
linkPath: '/fcmb-salary-savings-account', linkPath: '/fcmb-salary-savings-account',
}, },
{ {
@@ -150,7 +150,7 @@ export const _lowerMenuItems = [
name: 'WAYS TO BANK', name: 'WAYS TO BANK',
linkPath: '/ways-to-bank', linkPath: '/ways-to-bank',
subItems: [ subItems: [
{ name: 'FCMB MOBILE', linkPath: '/fcmb-mobile' }, { name: `${import.meta.env.VITE_BANK_NAME_SHORT} MOBILE`, linkPath: '/fcmb-mobile' },
{ {
name: 'RETAIL INTERNET BANKING', name: 'RETAIL INTERNET BANKING',
linkPath: 'https://ibank.fcmb.com/', linkPath: 'https://ibank.fcmb.com/',
@@ -160,10 +160,10 @@ export const _lowerMenuItems = [
{ name: 'OUR ATM NETWORK', linkPath: '/atm-network' }, { name: 'OUR ATM NETWORK', linkPath: '/atm-network' },
{ name: 'FLASHMECASH', linkPath: '/flashme-cash' }, { name: 'FLASHMECASH', linkPath: '/flashme-cash' },
{ name: 'OUR CARDS', linkPath: '/our-cards' }, { name: 'OUR CARDS', linkPath: '/our-cards' },
{ name: 'FCMB ELECTRONIC CHANNELS', linkPath: '/e-channels' }, { name: `${import.meta.env.VITE_BANK_NAME_SHORT} ELECTRONIC CHANNELS`, linkPath: '/e-channels' },
{ name: 'AGENT BANKING', linkPath: '/agent-banking' }, { name: 'AGENT BANKING', linkPath: '/agent-banking' },
{ {
name: 'FCMB SECURE COMMUNICATION', name: `${import.meta.env.VITE_BANK_NAME_SHORT} SECURE COMMUNICATION`,
linkPath: '/secure-communication', linkPath: '/secure-communication',
}, },
{ name: 'TEMI', linkPath: '/temi' }, { name: 'TEMI', linkPath: '/temi' },
@@ -197,7 +197,7 @@ export const _lowerMenuItems = [
name: 'CORPORATE CURRENT ACCOUNT', name: 'CORPORATE CURRENT ACCOUNT',
linkPath: '/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', name: 'DOMICILIARY CURRENT ACCOUNT',
linkPath: '/business-domiciliary-current-account', linkPath: '/business-domiciliary-current-account',
@@ -265,12 +265,12 @@ export const _lowerMenuItems = [
linkPath: 'https://www.fcmbonline.com/', linkPath: 'https://www.fcmbonline.com/',
}, },
{ name: 'OUR ATM NETWORK', linkPath: '/atm-network2' }, { name: 'OUR ATM NETWORK', linkPath: '/atm-network2' },
{ name: 'FCMB ONLINE', linkPath: '/fcmb-online-business' }, { name: `${import.meta.env.VITE_BANK_NAME_SHORT} ONLINE`, linkPath: '/fcmb-online-business' },
{ {
name: 'FCMB ELECTRONIC CHANNELS', name: `${import.meta.env.VITE_BANK_NAME_SHORT} ELECTRONIC CHANNELS`,
linkPath: 'https://www.fcmb.com/e-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' },
], ],
}, },
], ],
@@ -292,33 +292,33 @@ export const _lowerMenuItems = [
name: 'GROUP & SUBSIDIARIES', name: 'GROUP & SUBSIDIARIES',
linkPath: '', linkPath: '',
subItems: [ 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', name: 'CSL STOCKBROKERS',
linkPath: 'https://www.cslstockbrokers.com/', linkPath: 'https://www.cslstockbrokers.com/',
}, },
{ {
name: 'FCMB CAPITAL MARKETS', name: `${import.meta.env.VITE_BANK_NAME_SHORT} CAPITAL MARKETS`,
linkPath: 'https://www.fcmbcapitalmarketsng.com/', linkPath: 'https://www.fcmbcapitalmarketsng.com/',
}, },
{ {
name: 'FCMB ASSET MANAGEMENT', name: `${import.meta.env.VITE_BANK_NAME_SHORT} ASSET MANAGEMENT`,
linkPath: 'https://www.fcmbassetmanagement.com/index/', linkPath: 'https://www.fcmbassetmanagement.com/index/',
}, },
{ {
name: 'FCMB MICROFINANCE BANK', name: `${import.meta.env.VITE_BANK_NAME_SHORT} MICROFINANCE BANK`,
linkPath: '/fcmb-microfinance-initiative', 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', name: `${import.meta.env.VITE_BANK_NAME_SHORT} PENSIONS LIMITED`,
linkPath: 'https://www.fcmbpensions.com/', linkPath: 'https://www.fcmbpensions.com/',
}, },
{ {
name: 'CREDIT DIRECT LIMITED', name: 'CREDIT DIRECT LIMITED',
linkPath: 'https://www.creditdirect.ng', 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/' },
], ],
}, },
{ {
@@ -372,7 +372,7 @@ export const _lowerMenuItems = [
linkPath: '/current-campaigns-promos', linkPath: '/current-campaigns-promos',
subItems: [ subItems: [
{ {
name: 'BOOK YOUR FLIGHTS AND PAY IN INSTALMENTS WITH FCMB', name: `BOOK YOUR FLIGHTS AND PAY IN INSTALMENTS WITH ${import.meta.env.VITE_BANK_NAME_SHORT}`,
linkPath: '/247travels', linkPath: '/247travels',
}, },
{ name: 'REFER AND WIN', linkPath: '/refer-and-win' }, { name: 'REFER AND WIN', linkPath: '/refer-and-win' },
@@ -447,21 +447,21 @@ export const footerItems = [
{ {
category: 'GROUP & SUBSIDIARIES', category: 'GROUP & SUBSIDIARIES',
subItems: [ subItems: [
{ text: 'FCMB GROUP PLC', href: 'https://www.fcmbgroup.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: 'CSL STOCKBROKERS', href: 'https://www.cslstockbrokers.com/' },
{ {
text: 'FCMB CAPITAL MARKETS', text: `${import.meta.env.VITE_BANK_NAME_SHORT} CAPITAL MARKETS`,
href: 'https://www.fcmbcapitalmarketsng.com/', href: 'https://www.fcmbcapitalmarketsng.com/',
}, },
{ {
text: 'FCMB ASSET MANAGEMENT', text: `${import.meta.env.VITE_BANK_NAME_SHORT} ASSET MANAGEMENT`,
href: 'https://www.fcmbassetmanagement.com/index/', href: 'https://www.fcmbassetmanagement.com/index/',
}, },
{ text: 'FCMB MICROFINANCE BANK', href: '/fcmb-microfinance-initiative' }, { text: `${import.meta.env.VITE_BANK_NAME_SHORT} MICROFINANCE BANK`, href: '/fcmb-microfinance-initiative' },
{ text: 'FCMB UK', href: 'http://www.fcmbuk.com/' }, { text: `${import.meta.env.VITE_BANK_NAME_SHORT} UK`, href: 'http://www.fcmbuk.com/' },
{ text: 'FCMB PENSIONS LIMITED', href: 'https://www.fcmbpensions.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: 'CREDIT DIRECT LIMITED', href: 'https://www.creditdirect.ng' },
{ text: 'FCMB TRUSTEES', href: 'http://fcmbtrustees.com/' }, { text: `${import.meta.env.VITE_BANK_NAME_SHORT} TRUSTEES`, href: 'http://fcmbtrustees.com/' },
], ],
}, },
{ {