Răsfoiți Sursa

optimize PageBulkExportSelectModal

Yuki Takei 6 luni în urmă
părinte
comite
8338490e86

+ 80 - 56
apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx

@@ -1,7 +1,7 @@
 import { format } from 'date-fns/format';
 import { useAtomValue } from 'jotai';
 import { useTranslation } from 'next-i18next';
-import { type JSX, useState } from 'react';
+import { type JSX, useCallback, useMemo, useState } from 'react';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { toastError, toastSuccess } from '~/client/util/toastr';
@@ -13,9 +13,8 @@ import {
   usePageBulkExportSelectModalStatus,
 } from '../states/modal';
 
-const PageBulkExportSelectModal = (): JSX.Element => {
+const PageBulkExportSelectModalSubstance = (): JSX.Element => {
   const { t } = useTranslation();
-  const status = usePageBulkExportSelectModalStatus();
   const { close } = usePageBulkExportSelectModalActions();
   const currentPagePath = useCurrentPagePath();
   const isPdfBulkExportEnabled = useAtomValue(isPdfBulkExportEnabledAtom);
@@ -28,7 +27,7 @@ const PageBulkExportSelectModal = (): JSX.Element => {
     { createdAt: string } | undefined
   >(undefined);
 
-  const startBulkExport = async (format: PageBulkExportFormat) => {
+  const startBulkExport = useCallback(async (format: PageBulkExportFormat) => {
     try {
       setFormatMemoForRestart(format);
       await apiv3Post('/page-bulk-export', { path: currentPagePath, format });
@@ -43,9 +42,9 @@ const PageBulkExportSelectModal = (): JSX.Element => {
       }
     }
     close();
-  };
+  }, [close, currentPagePath, t]);
 
-  const restartBulkExport = async () => {
+  const restartBulkExport = useCallback(async () => {
     if (formatMemoForRestart != null) {
       try {
         await apiv3Post('/page-bulk-export', {
@@ -54,60 +53,74 @@ const PageBulkExportSelectModal = (): JSX.Element => {
           restartJob: true,
         });
         toastSuccess(t('page_export.bulk_export_started'));
-      } catch (e) {
+      } catch {
         toastError(t('page_export.failed_to_export'));
       }
       setIsRestartModalOpened(false);
     }
-  };
+  }, [currentPagePath, formatMemoForRestart, t]);
+
+  const handleCloseRestartModal = useCallback(() => {
+    setIsRestartModalOpened(false);
+  }, []);
+
+  // Memoize format display text to prevent recalculation
+  const formatDisplayText = useMemo(() => {
+    if (!formatMemoForRestart) return '';
+    return formatMemoForRestart === PageBulkExportFormat.md
+      ? t('page_export.markdown')
+      : 'PDF';
+  }, [formatMemoForRestart, t]);
+
+  // Memoize formatted date to prevent recalculation
+  const formattedCreatedAt = useMemo(() => {
+    if (!duplicateJobInfo?.createdAt) return '';
+    return format(new Date(duplicateJobInfo.createdAt), 'MM/dd HH:mm');
+  }, [duplicateJobInfo?.createdAt]);
 
   return (
     <>
-      {status != null && (
-        <Modal isOpen={status.isOpened} toggle={close} size="lg">
-          <ModalHeader tag="h4" toggle={close}>
-            {t('page_export.bulk_export')}
-          </ModalHeader>
-          <ModalBody>
-            <p className="card custom-card bg-warning-subtle pt-3 px-3">
-              {t('page_export.bulk_export_download_explanation')}
-              <span className="mt-3">
-                <span className="material-symbols-outlined me-1">warning</span>
-                {t('Warning')}
-              </span>
-              <ul className="mt-2">
-                <li>{t('page_export.bulk_export_exec_time_warning')}</li>
-                <li>{t('page_export.large_bulk_export_warning')}</li>
-              </ul>
-            </p>
-            {t('page_export.choose_export_format')}:
-            <div className="d-flex justify-content-center mt-3">
-              <button
-                className="btn btn-primary"
-                type="button"
-                onClick={() => startBulkExport(PageBulkExportFormat.md)}
-              >
-                {t('page_export.markdown')}
-              </button>
-              {isPdfBulkExportEnabled && (
-                <button
-                  className="btn btn-primary ms-2"
-                  type="button"
-                  onClick={() => startBulkExport(PageBulkExportFormat.pdf)}
-                >
-                  PDF
-                </button>
-              )}
-            </div>
-          </ModalBody>
-        </Modal>
-      )}
+      <ModalHeader tag="h4" toggle={close}>
+        {t('page_export.bulk_export')}
+      </ModalHeader>
+      <ModalBody>
+        <p className="card custom-card bg-warning-subtle pt-3 px-3">
+          {t('page_export.bulk_export_download_explanation')}
+          <span className="mt-3">
+            <span className="material-symbols-outlined me-1">warning</span>
+            {t('Warning')}
+          </span>
+          <ul className="mt-2">
+            <li>{t('page_export.bulk_export_exec_time_warning')}</li>
+            <li>{t('page_export.large_bulk_export_warning')}</li>
+          </ul>
+        </p>
+        {t('page_export.choose_export_format')}:
+        <div className="d-flex justify-content-center mt-3">
+          <button
+            className="btn btn-primary"
+            type="button"
+            onClick={() => startBulkExport(PageBulkExportFormat.md)}
+          >
+            {t('page_export.markdown')}
+          </button>
+          {isPdfBulkExportEnabled && (
+            <button
+              className="btn btn-primary ms-2"
+              type="button"
+              onClick={() => startBulkExport(PageBulkExportFormat.pdf)}
+            >
+              PDF
+            </button>
+          )}
+        </div>
+      </ModalBody>
 
       <Modal
         isOpen={isRestartModalOpened}
-        toggle={() => setIsRestartModalOpened(false)}
+        toggle={handleCloseRestartModal}
       >
-        <ModalHeader tag="h4" toggle={() => setIsRestartModalOpened(false)}>
+        <ModalHeader tag="h4" toggle={handleCloseRestartModal}>
           {t('page_export.export_in_progress')}
         </ModalHeader>
         <ModalBody>
@@ -120,15 +133,11 @@ const PageBulkExportSelectModal = (): JSX.Element => {
               <ul>
                 {formatMemoForRestart && (
                   <li>
-                    {t('page_export.format')}:{' '}
-                    {formatMemoForRestart === PageBulkExportFormat.md
-                      ? t('page_export.markdown')
-                      : 'PDF'}
+                    {t('page_export.format')}: {formatDisplayText}
                   </li>
                 )}
                 <li>
-                  {t('page_export.started_on')}:{' '}
-                  {format(new Date(duplicateJobInfo.createdAt), 'MM/dd HH:mm')}
+                  {t('page_export.started_on')}: {formattedCreatedAt}
                 </li>
               </ul>
             </div>
@@ -137,7 +146,7 @@ const PageBulkExportSelectModal = (): JSX.Element => {
             <button
               className="btn btn-primary"
               type="button"
-              onClick={() => restartBulkExport()}
+              onClick={restartBulkExport}
             >
               {t('page_export.restart')}
             </button>
@@ -148,4 +157,19 @@ const PageBulkExportSelectModal = (): JSX.Element => {
   );
 };
 
+const PageBulkExportSelectModal = (): JSX.Element => {
+  const status = usePageBulkExportSelectModalStatus();
+
+  // Early return for performance optimization
+  if (!status?.isOpened) {
+    return <></>;
+  }
+
+  return (
+    <Modal isOpen={status.isOpened} size="lg">
+      <PageBulkExportSelectModalSubstance />
+    </Modal>
+  );
+};
+
 export default PageBulkExportSelectModal;