Untitled
unknown
javascript
2 years ago
22 kB
21
Indexable
import {
Box,
Button,
Card,
CardContent,
Divider,
Paper,
Stack,
Step,
StepLabel,
Stepper,
Typography,
} from '@mui/material';
// utils
import { enqueueSnackbar } from 'notistack';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useBoolean } from 'src/hooks/use-boolean';
import { getUserBank, getUserFinance } from 'src/redux/slices/user';
//
import { useLocales } from 'src/locales';
import { lang } from 'src/locales/multiLang';
// @component
import { Cancel, CheckCircle, HourglassEmpty } from '@mui/icons-material';
import {
Timeline,
TimelineConnector,
TimelineContent,
TimelineDot,
TimelineItem,
TimelineSeparator,
} from '@mui/lab';
import axios from 'axios';
import Iconify from 'src/components/iconify';
import LoadingSpinner from 'src/components/loading-screen/loading-spinner';
import axiosInstance, { API_ENDPOINTS } from 'src/utils/axios';
import { fWords } from 'src/utils/format-string';
import { fDateTime } from 'src/utils/format-time';
import useCBToken from 'src/utils/useCBToken';
import BusinessInformation from './finance-profile-request/BusinessInformation';
import UploadCNIC from './finance-profile-request/UploadCNIC';
import TrustBox from './trust-box';
import { CREDITBOOK_URL } from 'src/config-global';
export default function AdvanceKYC() {
//
const { t } = useLocales();
const creditBookToken = useCBToken();
const dispatch = useDispatch();
const {
auth: { userData, userAttachments },
user: { documents, userFinance },
} = useSelector((state) => state);
// get kyc
const [kycStatus, setKycStatus] = useState(fWords('not_applied'));
const [kycStatusesList, setKycStatusesList] = useState([]);
const handleRequestKYC = async () => {
loading.onTrue();
if (userFinance.lendingPartner === 'CreditBook') {
await handleCreditBookKYC();
} else {
loading.onFalse();
enqueueSnackbar('KYC Patner isnot assigned yet', { variant: 'error' });
}
};
// handle credit-book kyc
const handleCreditBookKYC = async () => {
await dispatch(getUserBank());
// ------------------
const tempData = [
{
resourceURL: `${userAttachments.url}${userAttachments.token}`,
name: 'tetsing',
},
];
// Define the data to be sent in the POST request
const partnerCnic = documents
.filter((doc) => doc.docType === 'Partner CNIC')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const partnershipDeed = documents
.filter((doc) => doc.docType === 'Partnership Deed')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const incorporationCertificate = documents
.filter((doc) => doc.docType === 'Incorporation Certificate')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const authorityLetter = documents
.filter((doc) => doc.docType === 'Authority Letter')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const directorsResolution = documents
.filter((doc) => doc.docType === "Director's Resolution")
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const memorandumArticlesAssociation = documents
.filter((doc) => doc.docType === 'Memorandum Articles Association')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const boardMemberCnic = documents
.filter((doc) => doc.docType === 'Board Member CNIC')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const pocCnic = documents
.filter((doc) => doc.docType === 'POC CNIC')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const beneficialOwnerCnic = documents
.filter((doc) => doc.docType === 'Beneficial Owner CNIC')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const cnicFront = documents
.filter((doc) => doc.docType === 'CNIC_FRONT')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const cnicBack = documents
.filter((doc) => doc.docType === 'CNIC_BACK')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const proprietorshipDeclaration = documents
.filter((doc) => doc.docType === 'Proprietorship Declaration')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const ntnCertificate = documents
.filter((doc) => doc.docType === 'ntn Certificate')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const bankStatement = documents
.filter((doc) => doc.docType === 'Bank Statement (6 Months)')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const pastPurchaseOrders = documents
.filter((doc) => doc.docType === 'Past Purchase Orders')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const pastInvoices = documents
.filter((doc) => doc.docType === 'Past Invoices')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const otherFiles = documents
.filter((doc) => doc.docType === 'Other Files')
.map((item) => ({
resourceURL: `${userAttachments.url}${item.path}${userAttachments.token}`,
name: item.title,
}));
const postData = {
partnerCnic: partnerCnic.length > 0 ? partnerCnic : tempData,
partnershipDeed: partnershipDeed.length > 0 ? partnershipDeed : tempData,
incorporationCertificate:
incorporationCertificate.length > 0 ? incorporationCertificate : tempData,
authorityLetter: authorityLetter.length > 0 ? authorityLetter : tempData,
directorsResolution: directorsResolution.length > 0 ? directorsResolution : tempData,
memorandumArticlesAssociation:
memorandumArticlesAssociation.length > 0 ? memorandumArticlesAssociation : tempData,
boardMemberCnic: boardMemberCnic.length > 0 ? boardMemberCnic : tempData,
pocCnic: pocCnic.length > 0 ? pocCnic : tempData,
beneficialOwnerCnic: beneficialOwnerCnic.length > 0 ? beneficialOwnerCnic : tempData,
cnicFront: cnicFront.length > 0 ? cnicFront : tempData,
cnicBack: cnicBack.length > 0 ? cnicBack : tempData,
proprietorshipDeclaration:
proprietorshipDeclaration.length > 0 ? proprietorshipDeclaration : tempData,
ntnCertificate: ntnCertificate.length > 0 ? ntnCertificate : tempData,
bankStatement: bankStatement.length > 0 ? bankStatement : tempData,
pastPurchaseOrders: pastPurchaseOrders.length > 0 ? pastPurchaseOrders : tempData,
pastInvoices: pastInvoices.length > 0 ? pastInvoices : tempData,
otherFiles: otherFiles.length > 0 ? otherFiles : tempData,
email: userData.email,
fullName: userData.name,
contactNumber: userData.mobileNumber,
businessName: userFinance.businessName,
// businessType: 'partnership',
businessType: userFinance.businessType.toLowerCase(),
businessAddress: userFinance.businessAddress,
ntn: userFinance.ntn,
};
let response = '';
try {
if (kycStatus.toLowerCase() === 'need more info') {
response = await axios.patch(
`${CREDITBOOK_URL}/api/v1/external-lending/sme/users`,
postData,
{
headers: {
accept: 'application/json',
Authorization: `Bearer ${creditBookToken}`,
'Content-Type': 'application/json',
},
}
);
} else {
response = await axios.post(
`${CREDITBOOK_URL}/api/v1/external-lending/sme/users`,
postData,
{
headers: {
accept: 'application/json',
Authorization: `Bearer ${creditBookToken}`,
'Content-Type': 'application/json',
},
}
);
}
// save all RAW responce on DB
await axiosInstance.post(`${API_ENDPOINTS.finance.add_LP_Raw_Responce}`, {
lendingPartner: 'CreditBook',
vendorId: userData.userId,
...response.data,
});
await axiosInstance.post(`${API_ENDPOINTS.finance.partner_webhook}`, {
lendingPartner: 'CreditBook',
email: userData.email,
event_data: {
status: 'pending',
reason: 'Update by User',
comment: '',
user_id: response?.data?.user?.id,
},
});
loading.onFalse();
setActiveStep(1);
debugger;
setKycStatus(fWords('pending'));
setKycStatusesList(response?.data?.kyb?.statuses);
enqueueSnackbar('Request submitted successfully!');
} catch (error) {
loading.onFalse();
enqueueSnackbar(error.response.data.message.toString(), { variant: 'error' });
}
};
const getKYCReport = async () => {
try {
const response = await axiosInstance.post(
`${API_ENDPOINTS.finance.get_kyc_logs}
`,
{
userId: userData.userId,
}
);
// console.log('🚀 ~ getKYCReport ~ response:', response);
// setKycStatus(userFinance?.advanceKyc[0]?.event_data?.status || 'Pending');
setKycStatus(fWords(userFinance?.advanceKyc[0]?.event_data?.status || 'not_applied'));
setKycStatusesList(response);
if (userFinance?.advanceKyc[0]?.event_data?.status) {
setActiveStep(1);
}
if (userFinance?.advanceKyc[0]?.event_data?.contract_url) {
setActiveStep(2);
}
if (userFinance.contractUrlSigned) {
setActiveStep(3);
}
} catch (error) {
console.log('🚀 ~ getKYCReport ~ error:', error);
}
// try {
// const response = await axios.get(
// `https://stage.creditbookapi.com/api/v1/external-lending/sme/users?email=${encodeURIComponent(
// userData.email
// )}`,
// {
// headers: {
// accept: 'application/json',
// Authorization: `Bearer ${creditBookToken}`,
// },
// }
// );
// setKycStatus(camelToSentenceCase(response?.data?.kyb?.status));
// setKycStatusesList(response?.data?.kyb?.statuses);
// if (response?.data?.kyb?.status) {
// setActiveStep(1);
// }
// } catch (error) {
// console.log('🚀 ~ getKYCReport ~ error:', error);
// }
};
// -----------------------------------------------
const getDetails = async () => {
loading.onTrue();
try {
await dispatch(getUserBank());
} catch (error) {
console.log('🚀 ~ getDetails ~ error:', error);
}
try {
await dispatch(getUserFinance(userData?.userId));
} catch (error) {
loading.onFalse();
}
loading.onFalse();
};
useEffect(() => {
getDetails();
}, []);
// ------------
useEffect(() => {
if (userFinance?.advanceKyc) {
getKYCReport();
}
}, [userFinance?.advanceKyc]);
//
const [activeStep, setActiveStep] = useState(0);
const completed = useBoolean();
const loading = useBoolean();
const submitting = useBoolean();
const [userInfo, setUserInfo] = useState({
cnicFrontImage: '',
cnicBackImage: '',
fullName: '',
fatherName: '',
DateOfBirth: '',
homeAddress: '',
cnicNumber: '',
frontRecognition: false,
backRecognition: false,
});
const steps = [
t(`${lang.financing}.review`),
kycStatus,
t(`${lang.financing}.econtrcat`),
t(`${lang.financing}.complete`),
];
// *
useEffect(() => {
if (userFinance?.applied || userFinance?.cnicFrontImage) {
completed.onTrue();
}
}, [userFinance?.applied]);
// action is passing to components
const action = <Box display="flex" justifyContent="flex-end" sx={{ p: 1.5 }}></Box>;
const buttonContent = () => {
if (
kycStatus.toLowerCase() === 'pending' ||
kycStatus.toLowerCase() === 'approved' ||
kycStatus.toLowerCase() === 'rejected'
) {
return <TimelineComponent statuses={kycStatusesList} />;
}
if (kycStatus.toLowerCase() === 'need more info') {
return (
<Button
color="primary"
variant="contained"
onClick={handleRequestKYC}
startIcon={<Iconify icon="formkit:submit" />}
>
Re-Submit Request
</Button>
);
}
return (
<Button
color="primary"
variant="contained"
onClick={handleRequestKYC}
startIcon={<Iconify icon="formkit:submit" />}
>
Submit Request
</Button>
);
};
function reviewInfo(step) {
switch (step) {
case 0:
return {
type: 'UploadCNIC',
component: (
<UploadCNIC
userInfo={userInfo}
userFinance={userFinance}
setUserInfo={setUserInfo}
completed={completed}
/>
),
};
case 1:
return {
type: 'BusinessInformation',
component: (
<BusinessInformation
action={action}
kycStatus={kycStatus}
completed={completed}
userFinance={userFinance}
submitting={submitting}
/>
),
};
case 2:
return {
type: 'request',
component: <Box sx={{ p: 4, textAlign: 'center' }}>{buttonContent()}</Box>,
};
default:
return {
type: 'Unknown',
component: 'Unknown step',
};
}
}
function signContract(step) {
switch (step) {
case 2:
return {
type: 'Signed',
component: (
<Card
sx={{
p: 4,
}}
>
<CardContent>
<Typography variant="h5" component="div">
Contract Information
</Typography>
<Typography
variant="body2"
color="text.secondary"
sx={{
mt: 4,
}}
>
URL: {userFinance?.advanceKyc[0]?.event_data?.contract_url}
</Typography>
<Button
sx={{
mt: 4,
}}
variant="contained"
color="primary"
href={userFinance?.advanceKyc[0]?.event_data?.contract_url}
onClick={async () => {
await axiosInstance.post(
`${API_ENDPOINTS.finance.signContract}
`,
{
_id: userData.userId,
}
);
}}
target="_blank"
>
Sign Contract
</Button>
</CardContent>
</Card>
),
};
case 3:
return {
type: 'request',
component: (
<Box sx={{ p: 4, textAlign: 'center' }}>
{Array.from({ length: 3 }).map((_, index) => (
<Paper
key={index}
elevation={3}
sx={{
p: 3,
my: 3,
minHeight: 120,
// bgcolor: (theme) => alpha(theme.palette.grey[500]),
}}
>
<Typography sx={{ my: 1 }}>{reviewInfo(index).component}</Typography>
</Paper>
))}
</Box>
),
};
default:
return {
type: 'Unknown',
component: 'Unknown step',
};
}
}
return (
<div>
{loading.value && <LoadingSpinner />}
<Stack sx={{ my: 2 }}>
<Stepper activeStep={activeStep} alternativeLabel>
{steps.map((label, index) => {
return (
<Step key={label}>
<StepLabel>{index === 0 ? 'Review Information' : label}</StepLabel>
</Step>
);
})}
</Stepper>
<Divider sx={{ my: 2 }} />
</Stack>
<Stack sx={{ my: 2 }}>
{kycStatus.toLowerCase() === 'need more info' && (
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
p: 2,
border: 1,
borderRadius: 1,
borderColor: 'grey.500',
textAlign: 'center',
fontSize: 14,
mb: 3,
}}
>
<span style={{ fontWeight: 'bolder' }}> Correction Required Remarks:</span>
Please Upload your Patner CNIC
</Box>
)}
{/* */}
<TrustBox />
</Stack>
<Stack sx={{ my: 2 }}>
{activeStep === steps.length ? (
<Paper
elevation={3}
sx={{
p: 3,
my: 3,
minHeight: 150,
// bgcolor: (theme) => alpha(theme.palette.grey[500], 0.12),
display: 'flex',
alignItems: 'center', // Vertical alignment
justifyContent: 'center', // Horizontal alignment
}}
>
<Typography sx={{ my: 1 }}>{t(`${lang.financing}.profileSubmitted`)}</Typography>
</Paper>
) : (
<>
{activeStep === 2
? signContract(activeStep).component
: Array.from({ length: 3 }).map((_, index) => (
<Paper
key={index}
elevation={3}
sx={{
p: 3,
my: 3,
minHeight: 120,
// bgcolor: (theme) => alpha(theme.palette.grey[500]),
}}
>
<Typography sx={{ my: 1 }}>{reviewInfo(index).component}</Typography>
</Paper>
))}
{/* <Box sx={{ display: 'flex' }}>
<Button
variant="outlined"
color="inherit"
disabled={activeStep === 0}
onClick={async () => {
setActiveStep((active) => active - 1);
}}
sx={{ mr: 1 }}
>
{t(`${lang.financing}.back`)}
</Button>
<Box sx={{ flexGrow: 1 }} />
</Box> */}
</>
)}
</Stack>
</div>
);
}
const TimelineComponent = ({ statuses }) => {
return (
<>
<Typography variant="h5" color="primary">
Request Tracking
</Typography>
<Timeline position="alternate">
{statuses
.toReversed()
.map((status, index) => (
<TimelineItem key={index}>
<TimelineSeparator>
<TimelineDot
color={
(status.status === 'approved' && 'success') ||
(status.status === 'pending' && 'warning') ||
(status.status === 'rejected' && 'error') ||
'info'
}
>
{(status.status === 'approved' && <CheckCircle />) ||
(status.status === 'pending' && <HourglassEmpty />) ||
(status.status === 'rejected' && <Cancel />) || <HourglassEmpty />}
</TimelineDot>
{index < statuses.length - 1 && <TimelineConnector />}
</TimelineSeparator>
<TimelineContent>
<Typography variant="h6" color="textPrimary">
{fWords(status?.status || 'pending')}
</Typography>
<Typography color="textSecondary">
{status?.Date ? fDateTime(status.Date) : fDateTime(status.timestamp)}
</Typography>
{/* <Typography color="textSecondary">{status.updated_by}</Typography> */}
{status?.requestBodyObj?.event_data?.reason && (
<Typography color="textSecondary">
Reason: {status?.requestBodyObj?.event_data?.reason || ''}
</Typography>
)}
</TimelineContent>
</TimelineItem>
))}
</Timeline>
</>
);
};
Editor is loading...
Leave a Comment