Untitled

mail@pastecode.io avatar
unknown
javascript
2 months ago
22 kB
4
Indexable
Never
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> &nbsp;
            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>
    </>
  );
};
Leave a Comment