Compare commits

...

6 Commits

Author SHA1 Message Date
victorAnumudu 3998596fba validation bug fix 2024-04-16 20:56:34 +01:00
victorAnumudu 886fd64347 validated otp input to be numbers 2024-04-16 20:17:57 +01:00
tokslaw f95fd66c57 Merge branch 'layout-update' of DigiFi/digifi-www into master 2024-04-04 09:35:17 +00:00
tokslaw 98b5d4bc4f Merge branch 'Corporate' of DigiFi/digifi-www into master 2024-04-04 09:33:45 +00:00
victorAnumudu fd2b2245f5 updated layout style 2024-04-03 17:58:45 +01:00
victorAnumudu a7e97e1890 updated layout style 2024-04-03 17:55:55 +01:00
10 changed files with 242 additions and 130 deletions
+2 -2
View File
@@ -5,8 +5,8 @@ export default function Footer() {
const date = new Date().getFullYear(); const date = new Date().getFullYear();
return ( return (
<div className="w-full h-[5.4375rem] bg-[F7F7F7] flex items-center self-end"> <div className="w-full h-[5.4375rem] bg-[F7F7F7] flex items-center">
<div className="containerMode flex justify-between items-center flex-wrap gap-2"> <div className="containerMode flex justify-center md:justify-between items-center flex-wrap gap-2">
<p className="text-[.9375rem] tracking-[2%] font-semibold text-[#969696]"> <p className="text-[.9375rem] tracking-[2%] font-semibold text-[#969696]">
{date} @ First City Monument Bank Limited {date} @ First City Monument Bank Limited
</p> </p>
@@ -1,5 +1,4 @@
import React from "react"; import React from "react";
import CreditAccount from "./CreditAccount";
import DebitAccount from "./DebitAccount"; import DebitAccount from "./DebitAccount";
const ApplicantsAttestation: React.FC = () => { const ApplicantsAttestation: React.FC = () => {
@@ -21,7 +20,6 @@ const ApplicantsAttestation: React.FC = () => {
</p> </p>
</div> </div>
</div> </div>
<CreditAccount />
<DebitAccount /> <DebitAccount />
</> </>
); );
+1 -1
View File
@@ -32,7 +32,7 @@ const BasicInfo: React.FC<BasicInfoProps> = ({
setInputValues, setInputValues,
handleNextStep, handleNextStep,
}) => { }) => {
const [hideOTPComponent, setHideOTPComponent] = useState<boolean>(true); const [hideOTPComponent, setHideOTPComponent] = useState<boolean>(false);
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
const handleChange = (e: React.FormEvent<HTMLInputElement>) => { const handleChange = (e: React.FormEvent<HTMLInputElement>) => {
+62 -39
View File
@@ -1,67 +1,90 @@
import React from "react"; import React from "react";
import {useNavigate} from 'react-router-dom'
import { Button, InputCompOne } from ".."; import { Button, InputCompOne } from "..";
import { RouteHandler } from "../../router/routes";
const DebitAccount: React.FC = () => { const DebitAccount: React.FC = () => {
const navigate = useNavigate()
return ( return (
<div className="flex flex-col gap-9"> <>
<div className="w-full rounded py-3 bg-[#5C2684] px-5"> <div className="w-full rounded py-3 mb-9 bg-[#5C2684] px-5">
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit"> <p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
DEBIT ACCOUNT ( Your salary account for monthly repayment ) CREDIT ACCOUNT ( Your account to receive your loan )
</p> </p>
</div> </div>
<InputCompOne <InputCompOne
parentClass="max-w-[471px] w-full ml-5" parentClass="max-w-[29.4375rem] w-full my-5 ml-5"
label="Bank Name" label="Disbursement Account Number "
name="bankName" name="disbursementAccountNumber"
labelSpan="( Your FCMB Account )"
labelSpanClass="text-[12px] text-[#5C2684] ml-1"
parentInputClass="w-full" parentInputClass="w-full"
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]" labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
input input
inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]" inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]"
/> />
<div className="flex items-center gap-[59px]"> <div className="mt-9 flex flex-col gap-9">
<div className="w-full rounded py-3 bg-[#5C2684] px-5">
<p className="text-base text-[#FBB700] tracking-[3%] font-extrabold w-fit">
DEBIT ACCOUNT ( Your salary account for monthly repayment )
</p>
</div>
<InputCompOne <InputCompOne
parentClass="max-w-[471px] w-full ml-5" parentClass="max-w-[471px] w-full ml-5"
label="Account Number" label="Bank Name"
name="accountNumber" name="bankName"
parentInputClass="w-full" parentInputClass="w-full"
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]" labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
input input
inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]" inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]"
/> />
<InputCompOne
parentClass="max-w-[471px] w-full ml-5"
label="Account Name"
name="accountName"
parentInputClass="w-full"
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
input
inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]"
/>
</div>
<div className="max-w-[578px] flex items-center"> <div className="flex items-center gap-[59px]">
<input <InputCompOne
type="checkbox" parentClass="max-w-[471px] w-full ml-5"
// checked={true} label="Account Number"
defaultChecked name="accountNumber"
// onChange={onChange} parentInputClass="w-full"
className="form-checkbox h-[25px] w-[25px] rounded-sm text-[#5c2684] " labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
style={{ backgroundColor: "#5C2684" }} input
inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]"
/>
<InputCompOne
parentClass="max-w-[471px] w-full ml-5"
label="Account Name"
name="accountName"
parentInputClass="w-full"
labelClass="font-bold text-[18px] leading-[21.7808px] tracking-[2%] text-[#5C2684] mb-[2px]"
input
inputClass="w-full h-[36px] bg-[#EFEFEF] px-[2px] rounded-[6px]"
/>
</div>
<div className="max-w-[578px] flex items-center">
<input
type="checkbox"
// checked={true}
defaultChecked
// onChange={onChange}
className="form-checkbox h-[25px] w-[25px] rounded-sm text-[#5c2684] "
style={{ backgroundColor: "#5C2684" }}
/>
<label className="ml-2 text-gray-700">
I have read, understood and accept the{" "}
<span className="text-[#4545CB]">applicant's attestation</span> and
all the <span className="text-[#4545CB]">terms and conditions</span>{" "}
for FCMB premium salary loan.
</label>
</div>
<Button
className="my-8 max-w-[33.875rem] btn-R bg-[#5A2C82] w-full h-11"
text="Apply"
type="button"
onClick={()=>navigate(RouteHandler.dashboardHome, {replace:true})}
/> />
<label className="ml-2 text-gray-700">
I have read, understood and accept the{" "}
<span className="text-[#4545CB]">applicant's attestation</span> and
all the <span className="text-[#4545CB]">terms and conditions</span>{" "}
for FCMB premium salary loan.
</label>
</div> </div>
<Button </>
className="my-8 max-w-[33.875rem] btn-R bg-[#5A2C82] w-full h-11"
text="Apply"
type="button"
/>
</div>
); );
}; };
+127 -73
View File
@@ -1,21 +1,59 @@
import React from "react"; import React from "react";
import * as Yup from "yup";
import { Form, Formik } from "formik";
import { InputCompOne } from ".."; import { InputCompOne } from "..";
// To get the validation schema
const validationSchema = Yup.object().shape({
bvn: Yup.string()
.required("BVN is required")
.test("no-e", "Invalid number", (value:any) => {
if (value && /^[0-9]*$/.test(value) == false) {
return false;
}
return true;
})
.min(11, "must be 11 digits")
.max(11, "must be 11 digits"),
otp: Yup.string()
.required("OTP is required")
.test("no-e", "Invalid number", (value:any) => {
if (value && /^[0-9]*$/.test(value) == false) {
return false;
}
return true;
})
.min(5, "must be 5 digits")
.max(5, "must be 5 digits"),
// .test("no-e", "must be 11 characters", (value:any) => {
// if (value.length < 11) {
// return false;
// }
// return true;
// })
});
// initial values for formik
let initialValues = {
bvn: '',
otp: '',
};
const LetsGetStarted: React.FC = () => { const LetsGetStarted: React.FC = () => {
const [pinValues, setPinValues] = React.useState({ // const [pinValues, setPinValues] = React.useState({
bvn: "", // bvn: "",
otp: "", // otp: "",
}); // });
const [hideOTPComponent, setHideOTPComponent] = React.useState<boolean>(true); const [hideOTPComponent, setHideOTPComponent] = React.useState<boolean>(true);
const firstInputRef = React.useRef<HTMLInputElement>(null); const firstInputRef = React.useRef<HTMLInputElement>(null);
const secondInputRef = React.useRef<HTMLInputElement>(null); const secondInputRef = React.useRef<HTMLInputElement>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { // const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
let { name, value } = e.target as HTMLInputElement; // let { name, value } = e.target as HTMLInputElement;
setPinValues((prev) => ({ ...prev, [name]: value })); // setPinValues((prev) => ({ ...prev, [name]: value }));
}; // };
const handleInput = (e: React.FormEvent<HTMLInputElement>) => { const handleInput = (e: React.FormEvent<HTMLInputElement>) => {
let { name, value } = e.target as HTMLInputElement; let { name, value } = e.target as HTMLInputElement;
@@ -24,7 +62,7 @@ const LetsGetStarted: React.FC = () => {
const regex = /^[0-9]+$/; const regex = /^[0-9]+$/;
if (regex.test(value)) { if (regex.test(value)) {
if (value?.length == 10) { if (value?.length == 11) {
setHideOTPComponent(false); setHideOTPComponent(false);
// secondInputRef.current?.focus(); // secondInputRef.current?.focus();
} else setHideOTPComponent(true); } else setHideOTPComponent(true);
@@ -34,73 +72,89 @@ const LetsGetStarted: React.FC = () => {
} }
}; };
console.log(secondInputRef) const handleSubmit = (values:any) => {
console.log('values', values)
};
return ( return (
<div className="w-full"> <Formik
<div className="containerMode flex justify-between gap-1 xl:gap-8 flex-col"> initialValues={initialValues}
<div className="my-[4rem] flex items-center justify-center w-full"> validationSchema={validationSchema}
<h1 className="font-bold text-[2.375rem] text-[#5C2684] my-[.5rem] text-center"> onSubmit={handleSubmit}
Lets Get You Started >
</h1> {(props:any) => (
</div> <Form className="">
<form className="mx-auto flex flex-col gap-8 max-w-[31.625rem] "> <div className="w-full">
<InputCompOne <div className="containerMode flex justify-between gap-1 xl:gap-8 flex-col">
parentClass="flex flex-col gap-2" <div className="my-[4rem] flex items-center justify-center w-full">
label="Enter Your BVN " <h1 className="font-bold text-[2.375rem] text-[#5C2684] my-[.5rem] text-center">
name="bvn" Lets Get You Started
parentInputClass="w-full" </h1>
labelSpan="( To get your BVN, dial *565*0# )" </div>
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold" <div className="mx-auto flex flex-col gap-8 max-w-[31.625rem] ">
placeholder="Enter your BVN" <InputCompOne
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]" parentClass="flex flex-col gap-2"
input label="Enter Your BVN "
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4" name="bvn"
value={pinValues.bvn} parentInputClass="w-full"
onChange={handleChange} labelSpan="( To get your BVN, dial *565*0# )"
onInput={handleInput} labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
ref={firstInputRef} placeholder="Enter your BVN"
maxLength={10} labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
/> input
{!hideOTPComponent ? ( inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
<InputCompOne value={props.values.bvn}
parentClass="flex flex-col gap-2" onChange={props.handleChange}
label="Enter OTP " onInput={handleInput}
name="otp" ref={firstInputRef}
parentInputClass="w-full" maxLength={11}
labelSpan="( Please check your BVN phone number for verification pin )" error={(props.errors.bvn && props.touched.bvn) && props.errors.bvn}
labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold" />
placeholder="Enter your OTP" {!hideOTPComponent && (
labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]" <InputCompOne
input parentClass="flex flex-col gap-2"
inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4" label="Enter OTP "
value={pinValues.otp} name="otp"
onChange={handleChange} parentInputClass="w-full"
onInput={handleInput} labelSpan="( Please check your BVN phone number for verification pin )"
ref={secondInputRef} labelSpanClass="text-[13px] text-[#5a5a5a] font-semibold"
/> placeholder="Enter your OTP"
) : null} labelClass="font-bold text-[18px] leading-[21.78px] tracking-[2%] text-[#282828] mb-[2px] flex item-center gap-[4px]"
<button input
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" inputClass="w-full h-[3.625rem] rounded bg-[#EFEFEF] px-4"
disabled={!pinValues.otp} value={props.values.otp}
> onChange={props.handleChange}
Enter onInput={handleInput}
</button> ref={secondInputRef}
maxLength={11}
error={(props.errors.otp && props.touched.otp) && props.errors.otp}
/>
)}
<button
type='submit'
className="w-full h-[3.625rem] rounded bg-[#FBB700] rounded-2 px-4 text-[18px] text-[#282828] font-semibold disabled:text-[#282828] disabled:text-opacity-50"
disabled={!props.values.otp}
>
Enter
</button>
{hideOTPComponent ? ( {hideOTPComponent ? (
<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 and
secure. It is only important for us to verify your information and secure. It is only important for us to verify your information and
also give you access to your application profile/account. 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">
***Did not receive OTP? Click to resend ***Did not receive OTP? Click to resend
</p> </p>
)} )}
</form> </div>
</div> </div>
</div> </div>
</Form>
)}
</Formik>
); );
}; };
+3
View File
@@ -23,6 +23,7 @@ export interface InputCompOneProps {
parentSelectClass?: string; parentSelectClass?: string;
parentClass?: string; parentClass?: string;
maxLength?: number; maxLength?: number;
error?: string;
} }
const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>( const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
@@ -49,6 +50,7 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
parentSelectClass, parentSelectClass,
parentClass, parentClass,
maxLength, maxLength,
error,
}, },
forwardedRef forwardedRef
) => { ) => {
@@ -58,6 +60,7 @@ const InputCompOne = forwardRef<HTMLInputElement, InputCompOneProps>(
<label htmlFor="" className={labelClass}> <label htmlFor="" className={labelClass}>
{label} {label}
{labelSpan && <span className={labelSpanClass}>{labelSpan}</span>} {labelSpan && <span className={labelSpanClass}>{labelSpan}</span>}
{error && <span className='text-[10px] text-red-500'>{error}</span>}
</label> </label>
)} )}
{input && ( {input && (
+2 -1
View File
@@ -14,6 +14,7 @@ body {
@layer components { @layer components {
.containerMode { .containerMode {
@apply container mx-auto px-5 xxs:max-w-full sm:max-w-[98%] lg:max-w-[1100px]; /* @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]
} }
} }
@@ -43,6 +43,37 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
<Aside asideDisplay={asideDisplay} /> <Aside asideDisplay={asideDisplay} />
</aside> </aside>
<main className="dash-bg-image bg-[#F9F9F9] relative w-full overflow-y-auto overflow-x-hidden"> <main className="dash-bg-image bg-[#F9F9F9] relative w-full overflow-y-auto overflow-x-hidden">
<header className={`p-5 md:hidden sticky z-10 top-0 w-full bg-[#F9F9F9] border-b-2 border-[#E6E6E6]`}>
<div className='h-14 w-full flex justify-end items-center gap-5'>
{/* MENU HAND BURGER */}
{/* <div className='w-full'>Welcome Austin Catherine</div> */}
<div
className="relative md:hidden w-5 h-[20px] flex flex-col items-center justify-between"
onClick={asideDisplay}
>
<div
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
showAside ? "top-1/2 -translate-y-1/2 rotate-45" : "top-0"
}`}
></div>
<div
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-300 ${
showAside
? "top-1/2 -translate-y-1/2 rotate-[2000deg] opacity-0"
: "top-1/2 -translate-y-1/2"
}`}
></div>
<div
className={`absolute left-0 w-5 h-1 bg-black/80 dark:bg-white transition-all duration-500 ${
showAside
? "top-1/2 -translate-y-1/2 -rotate-45"
: "bottom-0"
}`}
></div>
</div>
</div>
</header>
<div className="flex p-5 relative"> <div className="flex p-5 relative">
<div className="w-full p-5">{children}</div> <div className="w-full p-5">{children}</div>
</div> </div>
+8 -6
View File
@@ -7,13 +7,15 @@ interface GetStartedLayoutProps {
const GetStartedLayout: React.FC<GetStartedLayoutProps> = ({ children }) => { const GetStartedLayout: React.FC<GetStartedLayoutProps> = ({ children }) => {
return ( return (
<div className="relative"> <div className="containerMode mb-[5.4375rem]">
<Header hideSidebar={true} hideMenu={true} /> <div className='sticky top-0 bg-white'>
<div className="flex flex-col min-h-[85vh] justify-between"> <Header hideSidebar={true} hideMenu={true} />
</div>
<div className="flex flex-col min-h-[70vh] justify-between">
{children} {children}
<div className="self-end w-full"> </div>
<Footer /> <div className="fixed bottom-0 left-0 bg-white w-full">
</div> <Footer />
</div> </div>
</div> </div>
); );
+6 -6
View File
@@ -1,23 +1,23 @@
import React from "react"; import React from "react";
import { Footer, LetsGetStartedNav } from "../components"; import { Footer, LetsGetStartedNav } from "../components";
import layoutImage from "../assets/images/test1-reverse.png"; // import layoutImage from "../assets/images/test1-reverse.png";
const LetsGetStartedLayout = ({ children }: { children: React.ReactNode }) => { const LetsGetStartedLayout = ({ children }: { children: React.ReactNode }) => {
return ( return (
<> <div className='containerMode mb-[5.4375rem]'>
<div className="grid md:grid-cols-2 h-[770px]"> <div className="w-full min-h-[90vh] grid lg:grid-cols-2">
<div className="w-full flex flex-col my-3"> <div className="w-full flex flex-col my-3">
<LetsGetStartedNav /> <LetsGetStartedNav />
{children} {children}
</div> </div>
<div className="w-full"> <div className="w-full h-96 lg:h-full bg-[url(../src/assets/images/test1-reverse.png)] bg-cover bg-no-repeat">
<img src={layoutImage} alt="" className="w-full h-full" /> {/* <img src={layoutImage} alt="" className="w-full h-full object-cover" /> */}
</div> </div>
</div> </div>
<div className="fixed bottom-0 left-0 bg-[#F7F7F7] w-full"> <div className="fixed bottom-0 left-0 bg-[#F7F7F7] w-full">
<Footer /> <Footer />
</div> </div>
</> </div>
); );
}; };