From aa4308421234e1b2e1394c58c2e429cbd04676eb Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 3 May 2025 11:28:16 -0500 Subject: [PATCH] Memoize admin menus --- src/admin/AdminAppMenu.tsx | 264 ++++++++++++++++++----------------- src/admin/AdminPhotoMenu.tsx | 74 +++++----- 2 files changed, 180 insertions(+), 158 deletions(-) diff --git a/src/admin/AdminAppMenu.tsx b/src/admin/AdminAppMenu.tsx index e66a0dfe..4cd251eb 100644 --- a/src/admin/AdminAppMenu.tsx +++ b/src/admin/AdminAppMenu.tsx @@ -16,7 +16,7 @@ import { IoArrowDown, IoArrowUp, IoCloseSharp } from 'react-icons/io5'; import { clsx } from 'clsx/lite'; import AdminAppInfoIcon from './AdminAppInfoIcon'; import { signOutAction } from '@/auth/actions'; -import { ComponentProps } from 'react'; +import { ComponentProps, useMemo } from 'react'; import useIsKeyBeingPressed from '@/utility/useIsKeyBeingPressed'; import IconPhoto from '@/components/icons/IconPhoto'; import IconUpload from '@/components/icons/IconUpload'; @@ -63,133 +63,149 @@ export default function AdminAppMenu({ const showAppInsightsLink = photosCountTotal > 0 && !isAltPressed; - const sectionUpload: ComponentProps[] = []; - const sectionMain: ComponentProps[] = []; - const sectionSignOut: ComponentProps[] = []; - - sectionUpload.push({ - label: 'Upload Photos', - icon: , - annotation: isLoadingAdminData && - , - action: startUpload, - }); - - if (uploadsCount) { - sectionMain.push({ - label: 'Uploads', - annotation: `${uploadsCount}`, - icon: , - href: PATH_ADMIN_UPLOADS, - }); - } - if (photosCountNeedSync) { - sectionMain.push({ - label: 'Updates', - annotation: <> - - {photosCountNeedSync} - - - , - icon: , - href: PATH_ADMIN_PHOTOS_UPDATES, - }); - } - if (photosCountTotal) { - sectionMain.push({ - label: 'Manage Photos', - ...photosCountTotal && { - annotation: `${photosCountTotal}`, - }, - icon: [] = + useMemo(() => ([{ + label: 'Upload Photos', + icon: , - href: PATH_ADMIN_PHOTOS, - }); - } - if (tagsCount) { - sectionMain.push({ - label: 'Manage Tags', - annotation: `${tagsCount}`, - icon: , - href: PATH_ADMIN_TAGS, - }); - } - if (recipesCount) { - sectionMain.push({ - label: 'Manage Recipes', - annotation: `${recipesCount}`, - icon: , - href: PATH_ADMIN_RECIPES, - }); - } - if (photosCountTotal) { - sectionMain.push({ - label: isSelecting - ? 'Exit Batch Edit' - : 'Batch Edit ...', - icon: isSelecting - ? - : , + action: startUpload, + }]), [isLoadingAdminData, startUpload]); + + const sectionMain: ComponentProps[] = useMemo(() => { + const items: ComponentProps[] = []; + + if (uploadsCount) { + items.push({ + label: 'Uploads', + annotation: `${uploadsCount}`, + icon: , - href: PATH_GRID_INFERRED, - action: () => { - if (isSelecting) { - setSelectedPhotoIds?.(undefined); - } else { - setSelectedPhotoIds?.([]); - } - if (document.activeElement instanceof HTMLElement) { - document.activeElement.blur(); - } - }, - shouldPreventDefault: false, + href: PATH_ADMIN_UPLOADS, + }); + } + if (photosCountNeedSync) { + items.push({ + label: 'Updates', + annotation: <> + + {photosCountNeedSync} + + + , + icon: , + href: PATH_ADMIN_PHOTOS_UPDATES, + }); + } + if (photosCountTotal) { + items.push({ + label: 'Manage Photos', + ...photosCountTotal && { + annotation: `${photosCountTotal}`, + }, + icon: , + href: PATH_ADMIN_PHOTOS, + }); + } + if (tagsCount) { + items.push({ + label: 'Manage Tags', + annotation: `${tagsCount}`, + icon: , + href: PATH_ADMIN_TAGS, + }); + } + if (recipesCount) { + items.push({ + label: 'Manage Recipes', + annotation: `${recipesCount}`, + icon: , + href: PATH_ADMIN_RECIPES, + }); + } + if (photosCountTotal) { + items.push({ + label: isSelecting + ? 'Exit Batch Edit' + : 'Batch Edit ...', + icon: isSelecting + ? + : , + href: PATH_GRID_INFERRED, + action: () => { + if (isSelecting) { + setSelectedPhotoIds?.(undefined); + } else { + setSelectedPhotoIds?.([]); + } + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } + }, + shouldPreventDefault: false, + }); + } + items.push({ + label: showAppInsightsLink + ? 'App Insights' + : 'App Configuration', + icon: , + href: showAppInsightsLink + ? PATH_ADMIN_INSIGHTS + : PATH_ADMIN_CONFIGURATION, }); - } - sectionMain.push({ - label: showAppInsightsLink - ? 'App Insights' - : 'App Configuration', - icon: , - href: showAppInsightsLink - ? PATH_ADMIN_INSIGHTS - : PATH_ADMIN_CONFIGURATION, - }); + return items; + }, [ + isSelecting, + photosCountNeedSync, + photosCountTotal, + recipesCount, + setSelectedPhotoIds, + showAppInsightsLink, + tagsCount, + uploadsCount, + ]); - sectionSignOut.push({ - label: 'Sign Out', - icon: , - action: () => signOutAction().then(clearAuthStateAndRedirectIfNecessary), - }); + const sectionSignOut: ComponentProps[] = + useMemo(() => ([{ + label: 'Sign Out', + icon: , + action: () => signOutAction().then(clearAuthStateAndRedirectIfNecessary), + }]), [clearAuthStateAndRedirectIfNecessary]); + + const sections = useMemo(() => + [sectionUpload, sectionMain, sectionSignOut] + , [sectionUpload, sectionMain, sectionSignOut]); return ( *>*]:translate-y-[6px]', !animateMenuClose && '[&>*>*]:duration-300', )} - sections={[ - sectionUpload, - sectionMain, - sectionSignOut, - ]} + sections={sections} ariaLabel="Admin Menu" /> ); diff --git a/src/admin/AdminPhotoMenu.tsx b/src/admin/AdminPhotoMenu.tsx index eae233e2..64fefc73 100644 --- a/src/admin/AdminPhotoMenu.tsx +++ b/src/admin/AdminPhotoMenu.tsx @@ -46,8 +46,8 @@ export default function AdminPhotoMenu({ const shouldRedirectFav = isPathFavs(path) && isFav; const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path; - const sections = useMemo(() => { - const sectionMain: ComponentProps[] = [{ + const sectionMain = useMemo(() => { + const items: ComponentProps[] = [{ label: 'Edit', icon: Sync @@ -103,32 +103,8 @@ export default function AdminPhotoMenu({ .then(() => revalidatePhoto?.(photo.id)), ...showKeyCommands && { keyCommand: KEY_COMMANDS.sync }, }); - const sectionDelete: ComponentProps[] = [{ - label: 'Delete', - icon: , - className: 'text-error *:hover:text-error', - color: 'red', - action: () => { - if (confirm(deleteConfirmationTextForPhoto(photo))) { - return deletePhotoAction( - photo.id, - photo.url, - shouldRedirectDelete, - ).then(() => { - revalidatePhoto?.(photo.id, true); - registerAdminUpdate?.(); - }); - } - }, - ...showKeyCommands && { - keyCommandModifier: KEY_COMMANDS.delete[0], - keyCommand: KEY_COMMANDS.delete[1], - }, - }]; - return [sectionMain, sectionDelete]; + + return items; }, [ photo, showKeyCommands, @@ -136,15 +112,49 @@ export default function AdminPhotoMenu({ isFav, shouldRedirectFav, revalidatePhoto, + ]); + + const sectionDelete: ComponentProps[] = useMemo(() => [{ + label: 'Delete', + icon: , + className: 'text-error *:hover:text-error', + color: 'red', + action: () => { + if (confirm(deleteConfirmationTextForPhoto(photo))) { + return deletePhotoAction( + photo.id, + photo.url, + shouldRedirectDelete, + ).then(() => { + revalidatePhoto?.(photo.id, true); + registerAdminUpdate?.(); + }); + } + }, + ...showKeyCommands && { + keyCommandModifier: KEY_COMMANDS.delete[0], + keyCommand: KEY_COMMANDS.delete[1], + }, + }], [ + photo, + showKeyCommands, + revalidatePhoto, shouldRedirectDelete, registerAdminUpdate, ]); + const sections = useMemo(() => + [sectionMain, sectionDelete] + , [sectionMain, sectionDelete]); + return ( isUserSignedIn ? : null );