redux document type arra updates

PHOTO EMBED

Thu Jul 20 2023 10:05:14 GMT+0000 (Coordinated Universal Time)

Saved by @JISSMONJOSE #react.js #css #javascript

yes it is working, our client needs further upadates here.

when user uploads all the required files and then moves to other component and return back to DocumentManager component. isRequired property is true in which userhas to upload the requried files again. 

i want to keep documentTypeArray in redux or any state management technique. so when user returns back it should be available. or you can try any other methods. 

ie once reuiqred docs are updated and when we move to documentmanager component, next step button should be disabled. 

below attaching code for your reference:

"""
function DocumentManager({
  handleNext, currentBtnStep, handleBack, willTypeID,
}: Props) {
  // const [documentTypeID, setDocumentTypeID] = useState<string>('');
  const [documentTypeArray, setDocumentTypeArray] = useState([]);
  const [documentTypeID, setDocumentTypeID] = useState();
  const [uniqueDocumentId, setUniqueDocumentId] = useState();
  const [witnessProfileGUID, setWitnessProfileGUID] = useState();
  const [willDocGuid, setWillDocGuid] = useState<string>('');
  // const bookedForProfileGUID = 'ba125f2d-8c78-41ce-b576-6aaef9b57c2a';
  const [uploadedFiles, setUploadedFiles] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const { state } = useLocation();
  const [showBookAppointnentModal, setShowBookAppointnentModal] = useState(false);

  const [documentIsRequired, setDocumentIsRequired] = useState<boolean>(false);

  // check document is required or not and
  useEffect(() => {
    const isRequiredDocumentsExist = documentTypeArray.some((d) => d.isRequired);
    setDocumentIsRequired(isRequiredDocumentsExist);
  }, [documentTypeArray]);

  // profile guid
  const { isSpouseSelected, spouseGuid, profileGuid } = useSelector(willPersonalInformationSelector);

  const dispatch = useDispatch();

  const handleOpenModal = () => {
    setShowModal(true);
  };
  const handleCloseModal = () => {
    setShowModal(false);
  };

  const handleBookAppointmentModalOpen = () => {
    setShowBookAppointnentModal(true);
  };

  const handleBookAppointmentModalClose = () => {
    setShowBookAppointnentModal(false);
  };

  const handleBookAppointmentModalContinue = () => {
    setShowBookAppointnentModal(false);
    // handleNext(currentBtnStep, 'upload');
  };

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await trackPromise(api.getAppointmentDetail(profileGuid));
        console.log('fetch AppointmentDetail Result', response?.data?.Output);
        // log the timeSlotID
        console.log('timeSlotID:', response?.data?.Output?.timeSlotID);
        if (response?.data?.Output?.timeSlotID === 0) {
          console.log('No appointment details found! Opening modal');
          handleBookAppointmentModalOpen();
        } else {
          const appointmentDetails = response.data.Output;
          console.log('Appointment details:', appointmentDetails);
        }
      } catch (error) {
        console.error('Error fetching appointment detail:', error);
      }
    };
    fetchData();
  }, []);

  // API results from Redux
  const {
    bookedforprofileguid,
    docType,
    documentTypeList,
    documentsList,
    docTypeID,
    isDocumentsChanged,
  } = useSelector(willDocumentUploadSelector);
  const { mirrorWillCheck } = useSelector(willsValidatorSelector);
  // custom hook for document list
  const uploadedDocumentsList = useDocumentsList(documentsList);

  /**
   * Retrieves the list of document types and sets it to the document type array.
   *
   * @return {void} No return value.
   */
  const getDocumentTypeList = () => {
    const documentTypes: any = [];
    documentTypeList.forEach((d: DocumentTypeList) => {
      documentTypes.push({
        documentTypeID: d.docTypeID,
        documentTypeName: d.fileName,
        witnessProfileGUID: d.witnessProfileGUID,
        isRequired: d.isRequired,
      });
    });
    setDocumentTypeArray(documentTypes);
  };

  // API calls inside useEffects -------
  useEffect(() => {
    // dispatch<any>(fetchDocumentTypeList(bookedForProfileGUID));
    dispatch<any>(fetchDocumentTypeList(isSpouseSelected ? spouseGuid : profileGuid));
  }, [dispatch, isSpouseSelected]);

  useEffect(() => {
    // Dispatch the fetchDocumentsList action when documentTypeID changes
    dispatch<any>(fetchDocumentsList(isSpouseSelected ? spouseGuid : profileGuid, documentTypeID, witnessProfileGUID));
  }, [uniqueDocumentId, documentTypeID, isDocumentsChanged, isSpouseSelected]);

  // Result transformation for UI
  useEffect(() => {
    getDocumentTypeList();
  }, [documentTypeList]);

  const { handleSubmit } = useForm();
  /**
   * Sets the active element to the given element string.
   *
   * @param {string} element - The string representing the active element to set.
   */
  const handleElementClick = (docTypeId: any, witnessProfileGUID: any) => {
    const uniqueDocumentId: any = `${docTypeId}-${witnessProfileGUID}`;
    setUniqueDocumentId(uniqueDocumentId);
    setDocumentTypeID(docTypeId);
    setWitnessProfileGUID(witnessProfileGUID);
  };
  /**
   * Returns the background color style object for a given element.
   *
   * @param {string} element - The element to get background style for.
   * @return {Object} The background color style object for the given element.
   */
  const getBackgroundStyle = (element: any) => ({
    backgroundColor: uniqueDocumentId === element ? '#023979' : '#F4F4F4',
  });

  /**
   * Returns an object representing the style to be applied to the title element.
   *
   * @param {string} element - The element to apply the style to.
   * @return {Object} An object containing the color property to be applied to the title element.
   */
  const getTitleStyle = (element: any) => ({
    color: uniqueDocumentId === element ? '#FFFFFF' : '#1B202D',
  });

  const getFileUploadIcon = (element: any) => (uniqueDocumentId === element ? FileUploadIcon : FileUploadIconDark);

  const getTickMarkicon = (element: any) => (uniqueDocumentId === element ? TickMarkIconGreen : TickMarkIconGrey);

  /**
   * Handles click event on "Add File" button.
   *
   * @param {any} e - The event object.
   * @return {void} Nothing is returned by this function.
   */

  const handleAddFileClick = (e: any) => {
    e.preventDefault();
    if (e.target !== e.currentTarget) {
      return;
    }
    document.getElementById('file-upload-input')?.click();
  };

  /**
   * Handles the file input change event.
   *
   * @param {any} e - the event object
   * @return {void}
   */
  const handleFileInputChange = (e: any) => {
    const newFiles = Array.from(e.target.files);
    checkFileValidity(newFiles);
  };

  /**
   * Updates the document type array by setting the 'isRequired' property to false for the document type
   * with the specified 'documentTypeID'. Returns the updated document type array.
   *
   * @param {any} documentTypeID - The ID of the document type to update
   * @return {void}
   */
  const updateDocumentTypeArray = (documentTypeID: any): void => {
    const updatedDocumentTypeArray = documentTypeArray.map((doc) => (doc.documentTypeID === documentTypeID ? { ...doc, isRequired: false } : doc));
    setDocumentTypeArray(updatedDocumentTypeArray);
  };

  /**
   * Handles the file drop event by checking the validity of the accepted files.
   *
   * @param {any} acceptedFiles - the files that have been accepted for upload
   */
  const handleFileDrop = (acceptedFiles: any) => {
    checkFileValidity(acceptedFiles);
  };

  /**
   * Prevents the click event from propagating and executing other click events.
   *
   * @param {any} e - the click event to be stopped from propagating
   */
  const handleRowItemClick = (e: any) => {
    e.stopPropagation();
  };

  /**
   * Filters files by their extension and size, and adds the valid files to the uploadedFiles state.
   *
   * @param {Array} files - The array of files to be checked.
   * @return {void} Returns nothing.
   */

  // Check the validity of uploaded files
  const checkFileValidity = async (files: any[]) => {
    const validExtensions = ['.pdf', '.jpeg', '.jpg', '.bmp', '.doc', '.docx'];
    const maxFileSize = 20 * 1024 * 1024;

    // Filter valid files based on extension and file size
    const validFiles = files.filter((file: { name: string; size: number; }) => {
      // Check if the file extension is valid
      const isValidExtension = validExtensions.some((ext) => file.name.toLowerCase().endsWith(ext));
      // Check if the file size is within the allowed limit
      const isWithinMaxSize = file.size <= maxFileSize;
      return isValidExtension && isWithinMaxSize;
    });

    // Filter invalid files
    const invalidFiles = files.filter(
      (file: any) => !validFiles.includes(file),
    );
    if (invalidFiles.length > 0) {
      // Display an alert message for invalid files
      const invalidFileNames = invalidFiles
        .map((file: { name: any; }) => file.name)
        .join(', ');
      alert(
        `Invalid files: ${invalidFileNames}. Please use A4-size PDF, JPEG, BMP, DOC, or DOCX files that are within 20MB.`,
      );
    } else {
      // Add valid files to the uploaded files list
      const updatedUploadedFiles = [...uploadedFiles, ...validFiles];
      setUploadedFiles(updatedUploadedFiles);

      // Update the document type array with the document type ID.
      updateDocumentTypeArray(documentTypeID);

      const formData = new FormData();
      for (let i = 0; i < validFiles.length; i++) {
        const file = validFiles[i];
        formData.append('FileDoc', file, file.name);
      }

      dispatch<any>(
        saveDocument(
          isSpouseSelected ? spouseGuid : profileGuid,
          documentTypeID,
          witnessProfileGUID,
          formData,
        ),
      );
    }
  };

  /**
   * Removes a file from the system.
   *
   * @param {string} willDocGuid - the unique identifier of the file to be removed
   * @return {any} the result of the delete operation
   */
  const removeFile = (willDocGuid: string) => {
    setWillDocGuid(willDocGuid);
    handleOpenModal();
  };

  const deleteFile = () => {
    console.log(`Delete the doc with GUID: ${willDocGuid}`);
    dispatch<any>(deleteDocument(willDocGuid));
    // log the result of the delete operation
    console.log('File removed successfully!');
    setShowModal(false);
  };

  const handleUploadDocument = (data: any) => {
    console.log(data);
    // handle document upload
    handleNext(currentBtnStep, 'upload');
  };

  const {
    getRootProps, // Props for the file drop zone element
    getInputProps, // Props for the file input element
  } = useDropzone({
    onDrop: handleFileDrop, // Callback function for handling dropped or selected files
  });

  return (
    <main>
      <section>
        {mirrorWillCheck && <MirrorWillSwitcher />}
        <header className="header mt-4">Upload Documents</header>
        <p className="description">
          Upload the documents in PDF or JPEG format. Click on Next Step to save
          the files once all the documents have been uploaded
        </p>
      </section>
      <div className="row document-upload-container">
        <div className="col-lg-6 content-wrapper">
          {documentTypeArray?.map((type) => (
            <div
              className={`top${
                uniqueDocumentId === `${type?.documentTypeID}-${type?.witnessProfileGUID}` ? ' active' : ''
              }`}
              style={getBackgroundStyle(`${type?.documentTypeID}-${type?.witnessProfileGUID}`)}
              onClick={() => handleElementClick(type?.documentTypeID, type?.witnessProfileGUID)}
            >
              <div className="left-container">
                <div className="file-upload-icon">
                  <img
                    src={getFileUploadIcon(`${type?.documentTypeID}-${type?.witnessProfileGUID}`)}
                    alt="File Uploader Icon"
                  />
                </div>
                <div
                  className="document-title"
                  style={getTitleStyle(`${type?.documentTypeID}-${type?.witnessProfileGUID}`)}
                >
                  {type.documentTypeName}
                </div>
              </div>
              <div className="tick-icon">
                <img
                  src={getTickMarkicon(`${type?.documentTypeID}-${type?.witnessProfileGUID}`)}
                  alt="Tick Mark"
                />
              </div>
            </div>
          ))}
        </div>

        <div
          className="col-lg-6 row-item"
          {...getRootProps()}
          onClick={handleRowItemClick}
        >
          <div className="file-upload-arrow">
            <img src={FileArrowIcon} alt="File Upload Arrow Icon" />
          </div>
          <div className="file-upload-text">
            Drag and drop document here to upload
          </div>
          <div className="file-attach-instructions">
            Please attach the file(s) below (use the Add button). We recommend
            using A4-size PDF, BMP, PNG, DOC, DOCX, JPG and JPEG files. File
            size cannot be more than 20 megabytes (MB). Your files will be
            uploaded when you submit your form.
          </div>
          <div className="file-add-button">
            <button className="add-file-btn" onClick={handleAddFileClick}>
              Add File
            </button>
            <input
              type="file"
              id="file-upload-input"
              name="file-upload-input"
              accept=".pdf, .bmp, .png, .doc, .docx, .jpg, .jpeg"
              multiple
              onChange={handleFileInputChange}
              style={{ display: 'none' }}
              {...getInputProps()}
            />
          </div>
          {uploadedDocumentsList.length > 0
            && uploadedDocumentsList.map((file: any, index) => (
              <div className="file-list-item" key={index}>
                <div className="file-info">
                  <div className="file-icon">
                    <img src={FileListIcon} alt="File List Icon" />
                  </div>
                  <div className="file-name">{file.fileName}</div>
                </div>
                <div className="close-icon" onClick={() => removeFile(file.willDocGuid)}>
                  <span className="close-icon-text">Remove</span>
                </div>
              </div>
            ))}
        </div>
      </div>
      {/* log documentIsRequired on template */}
      {/* {documentIsRequired && <div>Document is required</div>} */}
      <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
        <button
          type="button"
          className="next-btn"
          onClick={() => handleNext(state === 'Guardianship Will' ? 6 : currentBtnStep, 'upload')}
          disabled={documentIsRequired}
        >
          Next Step
        </button>
      </Box>
      <span className="next-btn-text mt-4">
        *Before clicking next, please make sure the details provided here are
        correct.
      </span>
      <DeleteConfirmationModal
        show={showModal}
        handleClose={handleCloseModal}
        handleContinue={deleteFile}
        type="Document"
      />
      {
          (willTypeID === 1 || willTypeID === 2) && (
            <DocumentManagerModal
              showBookAppointnentModal={showBookAppointnentModal}
              handleBookAppointmentModalClose={handleBookAppointmentModalClose}
              handleBookAppointmentModalContinue={handleBookAppointmentModalContinue}
              handleNext={handleNext}
              currentBtnStep={currentBtnStep}
              handleBack={handleBack}
            />
          )
        }

    </main>
  );
}

"""
content_copyCOPY