Advertisement
bruno83

stari kod za DocumentForm 79-17

Nov 13th, 2024
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. old DocumentForm.jsx:
  2.  
  3. import { DeleteOutlined, ExclamationCircleOutlined, CommentOutlined } from '@ant-design/icons';
  4. import { App, Button, Checkbox, Collapse, Divider, Form, Input, Modal, Timeline, Tree } from 'antd';
  5. import Title from 'antd/es/typography/Title';
  6. import { isEmpty, isEqual, some } from 'lodash';
  7. import React, { useEffect, useMemo, useState } from 'react';
  8. import { useTranslation } from 'react-i18next';
  9. import ReactQuill from 'react-quill-new';
  10. import { useDispatch } from 'react-redux';
  11. import { useNavigate } from 'react-router-dom';
  12. import { useFileDrawer } from '../../context/FileDrawerContext';
  13. import { getDocumentTypes } from '../../store/group/groupActions';
  14. import { parseQuillText } from '../../utils';
  15. import { decodeDetails } from '../../utils/pdfUtils';
  16. import withLoadStatus from '../common/withLoadStatus';
  17.  
  18. const modules = {
  19.   clipboard: {
  20.     matchVisual: false,
  21.   },
  22.   toolbar: {
  23.     container: [
  24.       ['bold', 'italic', 'underline', 'strike'], // Bold, Italic, Underline, Strikethrough
  25.       [{ header: [1, 2, 3, 4, 5, 6, false] }], // Heading sizes
  26.       [{ align: [] }], // Alignment
  27.       [{ list: 'ordered' }, { list: 'bullet' }], // Ordered & unordered lists
  28.       [{ indent: '-1' }, { indent: '+1' }], // Indent & Outdent
  29.       ['clean'], // Clear formatting
  30.     ],
  31.   },
  32. };
  33.  
  34. const normalizeValue = (value) => {
  35.   return value === '<p><br></p>' ? '' : value;
  36. };
  37.  
  38. const DocumentForm = ({
  39.   startLoading,
  40.   stopLoading,
  41.   isLoading,
  42.   parentId,
  43.   contextId,
  44.   contextNotes,
  45.   getContextNotes,
  46.   document,
  47.   isEditing,
  48.   updateAction,
  49.   createAction,
  50.   hasChanges,
  51.   setHasChanges,
  52.   fetchDocuments,
  53. }) => {
  54.   const { t } = useTranslation();
  55.   const { modal } = App.useApp();
  56.  
  57.   const [selectedDocument, setSelectedDocument] = useState(document || { noteRefs: [] });
  58.   const [selectedNotes, setSelectedNotes] = useState([]);
  59.   const [selectedFiles, setSelectedFiles] = useState({});
  60.   const dispatch = useDispatch();
  61.   const navigate = useNavigate();
  62.   const [form] = Form.useForm();
  63.  
  64.   const [initialFieldValues, setInitialFieldValues] = useState(null);
  65.   const [importedNotes, setImportedNotes] = useState([]);
  66.   const [header, setHeader] = useState(selectedDocument?.header || '');
  67.   const [footer, setFooter] = useState(selectedDocument?.footer || '');
  68.   const { openDrawer } = useFileDrawer();
  69.  
  70.   const handleFormChange = () => {
  71.     if (initialFieldValues) {
  72.       const currentFieldValues = form.getFieldsValue();
  73.  
  74.       // Normalize values for header and footer
  75.       const normalizedCurrentValues = {
  76.         ...currentFieldValues,
  77.         header: normalizeValue(currentFieldValues.header),
  78.         footer: normalizeValue(currentFieldValues.footer),
  79.       };
  80.  
  81.       const normalizedInitialValues = {
  82.         ...initialFieldValues,
  83.         header: normalizeValue(initialFieldValues.header),
  84.         footer: normalizeValue(initialFieldValues.footer),
  85.       };
  86.  
  87.       const hasDifferences = some(
  88.         normalizedCurrentValues,
  89.         (value, key) => value !== normalizedInitialValues[key],
  90.       );
  91.  
  92.       setHasChanges(hasDifferences);
  93.     }
  94.   };
  95.  
  96.   useEffect(() => {
  97.     const hasDifferences = !isEqual(selectedDocument.noteRefs, document?.noteRefs || []);
  98.  
  99.     setHasChanges(hasDifferences);
  100.   }, [selectedDocument.noteRefs, document?.noteRefs]);
  101.  
  102.   const handleCancel = () => {
  103.     form.resetFields();
  104.     setHasChanges(false);
  105.  
  106.     if (isEditing) {
  107.       if (document.noteRefs && document.details) {
  108.         const decodedDetails = decodeDetails(document.details);
  109.         const noteRefsMap = new Map(document.noteRefs.map((note) => [note.id, note]));
  110.  
  111.         const detailedNotes = decodedDetails.map(({ id, note, files, note_activities }) => {
  112.           const noteRef = noteRefsMap.get(id) || {};
  113.  
  114.           return {
  115.             ...noteRef,
  116.             id,
  117.             note: note || '',
  118.             files: files || [],
  119.             subject: noteRef.subject || '',
  120.             note_activities: note_activities || [],
  121.           };
  122.         });
  123.  
  124.         setImportedNotes(detailedNotes);
  125.       }
  126.     } else {
  127.       setImportedNotes([]);
  128.     }
  129.   };
  130.  
  131.   useEffect(() => {
  132.     const headerKeys = document?.noteRefs?.map((ref) => `header-${ref.id}`) || [];
  133.  
  134.     const headerValues = headerKeys.reduce((acc, key) => {
  135.       const headerId = key.split('header-')[1];
  136.       const matchingNoteRef = document.noteRefs.find((ref) => ref.id === headerId);
  137.       const noteValue = matchingNoteRef?.note || form.getFieldValue(key) || '';
  138.       acc[key] = noteValue;
  139.  
  140.       return acc;
  141.     }, {});
  142.  
  143.     form.setFieldsValue({
  144.       name: document?.name || form.getFieldValue('name') || '',
  145.       header: document?.header || form.getFieldValue('header') || '',
  146.       footer: document?.footer || form.getFieldValue('footer') || '',
  147.       ...headerValues,
  148.     });
  149.  
  150.     setInitialFieldValues({
  151.       name: document?.name || form.getFieldValue('name') || '',
  152.       header: document?.header || form.getFieldValue('header') || '',
  153.       footer: document?.footer || form.getFieldValue('footer') || '',
  154.       ...headerValues,
  155.     });
  156.   }, [form, document?.name, document?.footer, document?.header, document?.noteRefs]);
  157.  
  158.   useEffect(() => {
  159.     if (selectedDocument.noteRefs && selectedDocument.details) {
  160.       const decodedDetails = decodeDetails(selectedDocument.details);
  161.       const noteRefsMap = new Map(selectedDocument.noteRefs.map((note) => [note.id, note]));
  162.  
  163.       const detailedNotes = decodedDetails.map(({ id, note, files, note_activities }) => {
  164.         const noteRef = noteRefsMap.get(id) || {};
  165.  
  166.         return {
  167.           ...noteRef,
  168.           id,
  169.           note: note || '',
  170.           files: files || [],
  171.           subject: noteRef.subject || '',
  172.           note_activities: note_activities || [],
  173.         };
  174.       });
  175.  
  176.       setImportedNotes(detailedNotes);
  177.     }
  178.   }, [selectedDocument]);
  179.  
  180.   const handleQuillChange = (key, content) => {
  181.     if (key === 'header') {
  182.       setHeader(content);
  183.     } else if (key === 'footer') {
  184.       setFooter(content);
  185.     } else {
  186.       // Update the notes state for specific note ID
  187.       setImportedNotes((prevNotes) =>
  188.         prevNotes.map((note) => (note.id === key ? { ...note, note: content } : note)),
  189.       );
  190.     }
  191.   };
  192.  
  193.   const [isModalOpen, setIsModalOpen] = useState(false);
  194.  
  195.   const showModal = async () => {
  196.     await dispatch(getContextNotes(parentId));
  197.     setIsModalOpen(true);
  198.   };
  199.  
  200.   const handleOk = () => {
  201.     // Create an array to hold the note references with selected files
  202.     const newNoteRefs = contextNotes
  203.       .filter((note) => selectedNotes.includes(note.id)) // Filter notes based on selected notes
  204.       .map((note) => ({
  205.         ...note, // Spread the whole note object
  206.         files: note.files.filter((file) => selectedFiles[note.id]?.includes(file.id)), // Filter files based on selected file IDs
  207.       }));
  208.  
  209.     const existingNotes = decodeDetails(selectedDocument.details) || [];
  210.  
  211.     // Combine existing notes with new notes, ensuring uniqueness based on id
  212.     const combinedNotes = [
  213.       ...existingNotes,
  214.       ...newNoteRefs.map((note) => ({
  215.         id: note.id,
  216.         note: note.note,
  217.         files: note.files,
  218.         note_activities: note.note_activities,
  219.       })),
  220.     ];
  221.  
  222.     // Create the new details string from the combined notes
  223.     const updatedDetails = !isEmpty(combinedNotes)
  224.       ? `<ul>${combinedNotes
  225.           .map(
  226.             (note) =>
  227.               `<li data-note-id="${note.id}" data-note-text="${note.note}">${note.note}
  228.               ${
  229.                 !isEmpty(note.files) &&
  230.                 `<ul>${note.files
  231.                   .map((file) => {
  232.                     return `<li data-file-name="${file.name}" data-file-description="${
  233.                      file.description || ''
  234.                    }" data-file-url="${file.url}" data-file-mime_type="${file.mime_type}">${
  235.                       file.name
  236.                     }</li>`;
  237.                   })
  238.                   .join('')}</ul>`
  239.               }
  240.               ${
  241.                 !isEmpty(note.note_activities) &&
  242.                 `<ul>${note.note_activities
  243.                   .map((activity) => {
  244.                     return `<li data-comment-id="${activity.id}" data-comment-subject="${activity.subject}" data-comment-created_by="${activity.created_by}" data-comment-completed_at="${activity.completed_at}">${activity.comment}</li>`;
  245.                   })
  246.                   .join('')}</ul>`
  247.               }
  248.           </li>`,
  249.           )
  250.           .join('')}</ul>`
  251.       : '';
  252.  
  253.     // Set the selectedDocument with the noteRefs
  254.     setSelectedDocument((prevDocument) => ({
  255.       ...prevDocument,
  256.       noteRefs: [...(prevDocument.noteRefs || []), ...newNoteRefs],
  257.       details: updatedDetails,
  258.     }));
  259.  
  260.     setIsModalOpen(false);
  261.     setSelectedNotes([]);
  262.     setSelectedFiles({});
  263.   };
  264.  
  265.   const handleModalCancel = () => {
  266.     setIsModalOpen(false);
  267.     setSelectedNotes([]);
  268.     setSelectedFiles({});
  269.   };
  270.  
  271.   const handleNoteCheckboxChange = (noteId) => {
  272.     const isNoteSelected = selectedNotes.includes(noteId);
  273.     const updatedSelectedNotes = isNoteSelected
  274.       ? selectedNotes.filter((id) => id !== noteId) // Uncheck if already selected
  275.       : [...selectedNotes, noteId]; // Check if not selected
  276.  
  277.     // Update the selected files based on note selection
  278.     const updatedSelectedFiles = { ...selectedFiles };
  279.  
  280.     if (isNoteSelected) {
  281.       // If note is being unchecked, remove all files
  282.       delete updatedSelectedFiles[noteId];
  283.     } else {
  284.       // If note is being checked, select all files
  285.       const filesToSelect = contextNotes
  286.         .find((note) => note.id === noteId)
  287.         ?.files.map((file) => file.id); // Use file.id
  288.       if (filesToSelect) {
  289.         updatedSelectedFiles[noteId] = filesToSelect; // Add all file IDs
  290.       }
  291.     }
  292.  
  293.     // Update selected files to ensure files are selected based on their notes
  294.     selectedNotes.forEach((selectedNoteId) => {
  295.       // Initialize array if it doesn't exist
  296.       if (!updatedSelectedFiles[selectedNoteId]) {
  297.         updatedSelectedFiles[selectedNoteId] = [];
  298.       }
  299.     });
  300.  
  301.     setSelectedNotes(updatedSelectedNotes);
  302.     setSelectedFiles(updatedSelectedFiles);
  303.   };
  304.  
  305.   const handleFileCheckboxChange = (noteId, fileId) => {
  306.     // Change fileName to fileId
  307.     const updatedSelectedFiles = {
  308.       ...selectedFiles,
  309.       [noteId]: selectedFiles[noteId]
  310.         ? selectedFiles[noteId].includes(fileId) // Change to fileId
  311.           ? selectedFiles[noteId].filter((id) => id !== fileId) // Change to fileId
  312.           : [...(selectedFiles[noteId] || []), fileId] // Change to fileId
  313.         : [fileId], // Change to fileId
  314.     };
  315.  
  316.     // Update the selected notes if files are being checked and the note is not already selected
  317.     const updatedSelectedNotes = Object.keys(updatedSelectedFiles).reduce((acc, id) => {
  318.       if (updatedSelectedFiles[id].length > 0 && !acc.includes(id)) {
  319.         acc.push(id); // Add noteId if at least one file is selected
  320.       }
  321.       return acc;
  322.     }, selectedNotes);
  323.  
  324.     setSelectedFiles(updatedSelectedFiles);
  325.     setSelectedNotes(updatedSelectedNotes);
  326.   };
  327.  
  328.   const items = contextNotes.map((note) => {
  329.     const totalFiles = note.files.length;
  330.     const selectedFileCount = selectedFiles[note.id]?.length || 0;
  331.  
  332.     // Determine if the note checkbox should be indeterminate
  333.     const isIntermediate = selectedFileCount > 0 && selectedFileCount < totalFiles;
  334.  
  335.     return {
  336.       key: note.id,
  337.       label: (
  338.         <div style={{ display: 'flex', alignItems: 'center' }}>
  339.           <Checkbox
  340.             checked={selectedNotes.includes(note.id)}
  341.             indeterminate={isIntermediate} // Set indeterminate based on file selection state
  342.             onChange={() => handleNoteCheckboxChange(note.id)}
  343.             onClick={(e) => e.stopPropagation()}
  344.           />
  345.           <Title level={4} style={{ margin: '0 0 0 8px' }}>
  346.             {note.subject}
  347.           </Title>
  348.         </div>
  349.       ),
  350.       children: (
  351.         <div style={{ paddingLeft: '20px' }}>
  352.           <p>{parseQuillText(note.note)}</p>
  353.           <div>
  354.             {note.files.map((file) => (
  355.               <Checkbox
  356.                 key={file.id}
  357.                 checked={selectedFiles[note.id]?.includes(file.id)}
  358.                 onChange={() => handleFileCheckboxChange(note.id, file.id)}
  359.               >
  360.                 {file.name}
  361.               </Checkbox>
  362.             ))}
  363.           </div>
  364.         </div>
  365.       ),
  366.     };
  367.   });
  368.  
  369.   const treeData = useMemo(() => {
  370.     // Ensure selectedDocument is not null or undefined before accessing noteRefs
  371.     if (!selectedDocument || !selectedDocument.noteRefs) return [];
  372.  
  373.     // Map through all noteRefs and create a unique tree structure for each note's files
  374.     return selectedDocument.noteRefs.map((note) => ({
  375.       noteId: note.id,
  376.       files: note.files.map((file) => ({
  377.         title: file.name,
  378.         key: file.id,
  379.         ...file,
  380.       })),
  381.     }));
  382.   }, [selectedDocument]);
  383.  
  384.   const handleFileClick = (fileId, noteId) => {
  385.     if (Array.isArray(fileId) && fileId.length === 1) {
  386.       const fileToDownload = selectedDocument.noteRefs
  387.         .flatMap((note) => note.files)
  388.         .find((file) => file.id === fileId[0]);
  389.  
  390.       if (fileToDownload) {
  391.         openDrawer({
  392.           file: { ...fileToDownload },
  393.           parentId: noteId,
  394.         });
  395.       }
  396.     }
  397.   };
  398.  
  399.   const handleSubmit = async (values) => {
  400.     startLoading();
  401.     const response = await dispatch(getDocumentTypes()).unwrap();
  402.  
  403.     const details = !isEmpty(importedNotes)
  404.       ? `<ul>${importedNotes
  405.           .map(
  406.             (note) => `<li data-note-id="${note.id}" data-note-text="${note.note}">${note.note}
  407.           ${
  408.             !isEmpty(note.files) &&
  409.             `<ul>${note.files
  410.               .map((file) => {
  411.                 return `<li data-file-name="${file.name}" data-file-description="${
  412.                  file.description || ''
  413.                }" data-file-url="${file.url}" data-file-mime_type="${file.mime_type}">${
  414.                   file.name
  415.                 }</li>`;
  416.               })
  417.               .join('')}</ul>`
  418.           }
  419.           ${
  420.             !isEmpty(note.note_activities) &&
  421.             `<ul>${note.note_activities
  422.               .map(
  423.                 (activity) =>
  424.                   `<li data-comment-id="${activity.id}" data-comment-subject="${activity.subject}" data-comment-created_by="${activity.created_by}" data-comment-completed_at="${activity.completed_at}">${activity.comment}</li>`,
  425.               )
  426.               .join('')}</ul>`
  427.           }
  428.         </li>`,
  429.           )
  430.           .join('')}</ul>`
  431.       : '';
  432.  
  433.     const updatedNoteRefs = importedNotes.map((note) => ({
  434.       ...note,
  435.       note: note.note || '',
  436.     }));
  437.  
  438.     const { name } = values;
  439.  
  440.     const document = {
  441.       name,
  442.       header,
  443.       footer,
  444.       details,
  445.       type: response,
  446.       noteRefs: updatedNoteRefs,
  447.       link: 'link',
  448.       version: selectedDocument.version || 1,
  449.     };
  450.  
  451.     if (isEditing) {
  452.       await dispatch(
  453.         updateAction({
  454.           parentId,
  455.           contextId,
  456.           document,
  457.           successMessage: t('notifications.company.notes.update'),
  458.         }),
  459.       ).unwrap();
  460.     } else {
  461.       await dispatch(
  462.         createAction({
  463.           contextId,
  464.           document,
  465.           successMessage: t('notifications.company.notes.create'),
  466.         }),
  467.       ).unwrap();
  468.     }
  469.  
  470.     await dispatch(fetchDocuments(contextId)).unwrap();
  471.     stopLoading();
  472.     setHasChanges(false);
  473.     if (!isEditing) navigate(-1);
  474.   };
  475.  
  476.   const showCommentDeleteConfirm = (noteId) => {
  477.     modal.confirm({
  478.       title: t('document.form.deleteModalTitle'),
  479.       icon: <ExclamationCircleOutlined />,
  480.       content: t('document.form.deleteModalContent'),
  481.       okText: t('button.delete'),
  482.       okType: 'danger',
  483.       cancelText: t('button.cancel'),
  484.       onOk() {
  485.         handleDeleteNoteComment(noteId);
  486.       },
  487.     });
  488.   };
  489.  
  490.   const handleDeleteNoteComment = (noteId) => {
  491.     const existingNotes = decodeDetails(selectedDocument.details) || [];
  492.  
  493.     const updatedNoteRefs = selectedDocument.noteRefs.map((note) => {
  494.       if (note.id === noteId) {
  495.         return {
  496.           ...note,
  497.           note_activities: [],
  498.         };
  499.       }
  500.       return note;
  501.     });
  502.  
  503.     const updatedExistingNotes = existingNotes.map((note) => {
  504.       if (note.id === noteId) {
  505.         return {
  506.           ...note,
  507.           note_activities: [],
  508.         };
  509.       }
  510.       return note;
  511.     });
  512.  
  513.     const updatedDetails = `<ul>${updatedExistingNotes
  514.       .map(
  515.         (note) => `<li data-note-id="${note.id}" data-note-text="${note.note}">${note.note}
  516.         ${
  517.           !isEmpty(note.files) &&
  518.           `<ul>${note.files
  519.             .map((file) => {
  520.               return `<li data-file-name="${file.name}" data-file-description="${
  521.                file.description || ''
  522.              }" data-file-url="${file.url}" data-file-mime_type="${file.mime_type}">${
  523.                 file.name
  524.               }</li>`;
  525.             })
  526.             .join('')}</ul>`
  527.         }
  528.         ${
  529.           !isEmpty(note.note_activities) &&
  530.           `<ul>${note.note_activities
  531.             .map((activity) => {
  532.               return `<li data-comment-id="${activity.id}" data-comment-subject="${activity.subject}" data-comment-created_by="${activity.created_by}" data-comment-completed_at="${activity.completed_at}">${activity.comment}</li>`;
  533.             })
  534.             .join('')}</ul>`
  535.         }
  536.       </li>`,
  537.       )
  538.       .join('')}</ul>`;
  539.  
  540.     setSelectedDocument({
  541.       ...selectedDocument,
  542.       noteRefs: updatedNoteRefs,
  543.       details: updatedDetails,
  544.     });
  545.   };
  546.  
  547.   const showDeleteConfirm = (noteId) => {
  548.     modal.confirm({
  549.       title: t('document.form.deleteModalTitle'),
  550.       icon: <ExclamationCircleOutlined />,
  551.       content: t('document.form.deleteModalContent'),
  552.       okText: t('button.delete'),
  553.       okType: 'danger',
  554.       cancelText: t('button.cancel'),
  555.       onOk() {
  556.         handleDeleteNote(noteId);
  557.       },
  558.     });
  559.   };
  560.  
  561.   const handleDeleteNote = (noteId) => {
  562.     const existingNotes = decodeDetails(selectedDocument.details) || [];
  563.  
  564.     const updatedNoteRefs = selectedDocument.noteRefs.filter((note) => note.id !== noteId);
  565.  
  566.     const updatedExistingNotes = existingNotes.filter((note) => note.id !== noteId);
  567.  
  568.     const updatedDetails = `<ul>${updatedExistingNotes
  569.       .map(
  570.         (note) => `<li data-note-id="${note.id}" data-note-text="${note.note}">${note.note}
  571.         ${
  572.           !isEmpty(note.files) &&
  573.           `<ul>${note.files
  574.             .map((file) => {
  575.               return `<li data-file-name="${file.name}" data-file-description="${
  576.                file.description || ''
  577.              }" data-file-url="${file.url}" data-file-mime_type="${file.mime_type}">${
  578.                 file.name
  579.               }</li>`;
  580.             })
  581.             .join('')}</ul>`
  582.         }
  583.         ${
  584.           !isEmpty(note.note_activities) &&
  585.           `<ul>${note.note_activities
  586.             .map((activity) => {
  587.               return `<li data-comment-id="${activity.id}" data-comment-subject="${activity.subject}" data-comment-created_by="${activity.created_by}" data-comment-completed_at="${activity.completed_at}">${activity.comment}</li>`;
  588.             })
  589.             .join('')}</ul>`
  590.         }
  591.       </li>`,
  592.       )
  593.       .join('')}</ul>`;
  594.  
  595.     setSelectedDocument({
  596.       ...selectedDocument,
  597.       noteRefs: updatedNoteRefs,
  598.       details: updatedDetails,
  599.     });
  600.   };
  601.  
  602.   const formatedActivities = (note) => {
  603.     return note.note_activities
  604.       ?.slice()
  605.       .sort((a, b) => new Date(b.completed_at) - new Date(a.completed_at))
  606.       .map((activity) => ({
  607.         dot: <CommentOutlined />,
  608.         children: (
  609.           <div>
  610.             <div>{activity.comment}</div>
  611.             <div className='mt-3 text-xs'>
  612.               {new Date(activity.completed_at).toLocaleString()} - {activity.created_by}
  613.             </div>
  614.           </div>
  615.         ),
  616.       }));
  617.   };
  618.  
  619.   return (
  620.     <Form
  621.       name='document'
  622.       form={form}
  623.       labelCol={{
  624.         xs: { span: 24 },
  625.         md: { span: 6 },
  626.       }}
  627.       wrapperCol={{
  628.         xs: { span: 24 },
  629.         md: { span: 18 },
  630.       }}
  631.       labelAlign='left'
  632.       layout='horizontal'
  633.       initialValues={{
  634.         remember: true,
  635.       }}
  636.       onValuesChange={handleFormChange}
  637.       onFinish={handleSubmit}
  638.       autoComplete='on'
  639.       className='max-w-[60rem]'
  640.     >
  641.       <Modal
  642.         title={t('document.form.modalTitle')}
  643.         open={isModalOpen}
  644.         onOk={handleOk}
  645.         okText='Import'
  646.         onCancel={handleModalCancel}
  647.       >
  648.         <Collapse items={items} expandIconPosition='end' />
  649.       </Modal>
  650.  
  651.       <Title level={2}>{t('document.form.headerInfo')}</Title>
  652.       <Form.Item
  653.         label={t('document.form.documentInputLabel')}
  654.         tooltip={t('document.form.documentInputTooltip')}
  655.         name='name'
  656.         className='custom-form-item'
  657.         validateTrigger='onBlur'
  658.         initialValue={document?.name || ''}
  659.         rules={[
  660.           {
  661.             required: true,
  662.             message: 'Please input the document name!',
  663.           },
  664.         ]}
  665.       >
  666.         <Input />
  667.       </Form.Item>
  668.       <Form.Item
  669.         label={t('document.form.headerInputLabel')}
  670.         tooltip={t('document.form.headerInputTooltip')}
  671.         name='header'
  672.         className='custom-form-item'
  673.         validateTrigger='onBlur'
  674.         initialValue={document?.header || ''}
  675.       >
  676.         <ReactQuill
  677.           theme='snow'
  678.           placeholder={'Your header text goes here...'}
  679.           value={header}
  680.           onChange={(content) => handleQuillChange('header', content)}
  681.           modules={modules}
  682.         />
  683.       </Form.Item>
  684.       <Divider />
  685.  
  686.       <div className='flex justify-between'>
  687.         <Title level={2} className='inline-block w-full'>
  688.           {t('document.form.details')}
  689.         </Title>
  690.         <div className='my-6 flex w-full justify-end'>
  691.           <Button type='primary' onClick={showModal}>
  692.             {t('button.importNotes')}
  693.           </Button>
  694.         </div>
  695.       </div>
  696.  
  697.       {importedNotes?.map((note, index) => {
  698.         // Find the corresponding tree data for the current note
  699.         const currentTreeData = treeData.find((data) => data.noteId === note.id)?.files || [];
  700.  
  701.         return (
  702.           <div key={note.id}>
  703.             {index !== 0 && <Divider />}
  704.             <div className='mb-2 flex items-center justify-end'>
  705.               <Button
  706.                 type='text'
  707.                 danger
  708.                 onClick={() => showDeleteConfirm(note.id)}
  709.                 icon={<DeleteOutlined />}
  710.               >
  711.                 {t('button.delete')}
  712.               </Button>
  713.             </div>
  714.  
  715.             <Form.Item
  716.               label={note.subject} // Access subject directly from importedNotes
  717.               tooltip={t('document.form.headerInputTooltip')}
  718.               name={`header-${note.id}`}
  719.               className='custom-form-item'
  720.               validateTrigger='onBlur'
  721.               initialValue={note.note || ''}
  722.             >
  723.               <ReactQuill
  724.                 theme='snow'
  725.                 placeholder='Your text goes here...'
  726.                 value={note.note || ''}
  727.                 onChange={(content) => handleQuillChange(note.id, content)}
  728.                 modules={modules}
  729.               />
  730.             </Form.Item>
  731.  
  732.             {!isEmpty(currentTreeData) && (
  733.               <Form.Item label={t('document.form.attachedFilesInputLabel')} key={note.id}>
  734.                 <Tree
  735.                   className='-ml-6'
  736.                   treeData={currentTreeData}
  737.                   height={300}
  738.                   onSelect={(fileId) => handleFileClick(fileId, note.id)}
  739.                 />
  740.               </Form.Item>
  741.             )}
  742.  
  743.             {!isEmpty(formatedActivities(note)) && (
  744.               <>
  745.                 <div className='mb-2 flex items-center justify-end'>
  746.                   <Button
  747.                     type='text'
  748.                     danger
  749.                     onClick={() => showCommentDeleteConfirm(note.id)}
  750.                     icon={<DeleteOutlined />}
  751.                   >
  752.                     {t('button.delete')}
  753.                   </Button>
  754.                 </div>
  755.                 <Form.Item label='Comments' key={note.id}>
  756.                   <Timeline
  757.                     className='max-h-[15rem] overflow-y-auto px-5 pt-1'
  758.                     items={formatedActivities(note)}
  759.                   />
  760.                 </Form.Item>
  761.               </>
  762.             )}
  763.           </div>
  764.         );
  765.       })}
  766.       <Divider />
  767.  
  768.       <Title level={2}>{t('document.form.footerInfo')}</Title>
  769.       <Form.Item
  770.         label={t('document.form.footerInputLabel')}
  771.         tooltip={t('document.form.footerInputTooltip')}
  772.         name='footer'
  773.         className='custom-form-item'
  774.         validateTrigger='onBlur'
  775.         initialValue={document?.footer || ''}
  776.       >
  777.         <ReactQuill
  778.           theme='snow'
  779.           placeholder='Your footer text goes here...'
  780.           value={footer}
  781.           onChange={(content) => handleQuillChange('footer', content)}
  782.           modules={modules}
  783.         />
  784.       </Form.Item>
  785.  
  786.       <Form.Item
  787.         wrapperCol={{
  788.           xs: { offset: 0, span: 24 },
  789.           md: { offset: 6, span: 18 },
  790.         }}
  791.       >
  792.         <Button
  793.           type='primary'
  794.           htmlType='submit'
  795.           className='w-full md:w-auto'
  796.           loading={isLoading}
  797.           disabled={!hasChanges}
  798.         >
  799.           {isEditing ? t('button.update') : t('button.create')}
  800.         </Button>
  801.         <Button htmlType='button' className='mt-2 w-full md:ml-3 md:w-auto' onClick={handleCancel}>
  802.           {t('button.cancel')}
  803.         </Button>
  804.       </Form.Item>
  805.     </Form>
  806.   );
  807. };
  808.  
  809. export default withLoadStatus(DocumentForm);
  810.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement