diff --git a/src/admin/AdminPhotoMenuClient.tsx b/src/admin/AdminPhotoMenuClient.tsx index 4ebdbc5e..5bc80ff5 100644 --- a/src/admin/AdminPhotoMenuClient.tsx +++ b/src/admin/AdminPhotoMenuClient.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ComponentProps } from 'react'; +import { ComponentProps, useMemo } from 'react'; import { pathForAdminPhotoEdit, pathForPhoto } from '@/site/paths'; import { deletePhotoAction, toggleFavoritePhotoAction } from '@/photo/actions'; import { FaRegEdit, FaRegStar, FaStar } from 'react-icons/fa'; @@ -8,17 +8,19 @@ import { Photo, deleteConfirmationTextForPhoto } from '@/photo'; import { isPathFavs, isPhotoFav } from '@/tag'; import { usePathname } from 'next/navigation'; import { BiTrash } from 'react-icons/bi'; -import MoreMenu from '@/components/more/MoreMenu'; +import MoreMenu, { MoreMenuItem } from '@/components/more/MoreMenu'; import { useAppState } from '@/state/AppState'; import { RevalidatePhoto } from '@/photo/InfinitePhotoScroll'; export default function AdminPhotoMenuClient({ photo, revalidatePhoto, + includeFavorite = true, ...props }: Omit, 'items'> & { photo: Photo revalidatePhoto?: RevalidatePhoto + includeFavorite?: boolean }) { const { isUserSignedIn, registerAdminUpdate } = useAppState(); @@ -27,49 +29,64 @@ export default function AdminPhotoMenuClient({ const shouldRedirectFav = isPathFavs(path) && isFav; const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path; + const items = useMemo(() => { + const items: MoreMenuItem[] = [{ + label: 'Edit', + icon: , + href: pathForAdminPhotoEdit(photo.id), + }]; + if (includeFavorite) { + items.push({ + label: isFav ? 'Unfavorite' : 'Favorite', + icon: isFav + ? + : , + action: () => toggleFavoritePhotoAction( + photo.id, + shouldRedirectFav, + ).then(() => revalidatePhoto?.(photo.id)), + }); + } + items.push({ + label: 'Delete', + icon: , + action: () => { + if (confirm(deleteConfirmationTextForPhoto(photo))) { + return deletePhotoAction( + photo.id, + photo.url, + shouldRedirectDelete, + ).then(() => { + revalidatePhoto?.(photo.id, true); + registerAdminUpdate?.(); + }); + } + }, + }); + return items; + }, [ + photo, + includeFavorite, + isFav, + shouldRedirectFav, + revalidatePhoto, + shouldRedirectDelete, + registerAdminUpdate, + ]); + return ( isUserSignedIn ? , - href: pathForAdminPhotoEdit(photo.id), - }, { - label: isFav ? 'Unfavorite' : 'Favorite', - icon: isFav - ? - : , - action: () => toggleFavoritePhotoAction( - photo.id, - shouldRedirectFav, - ).then(() => revalidatePhoto?.(photo.id)), - }, { - label: 'Delete', - icon: , - action: () => { - if (confirm(deleteConfirmationTextForPhoto(photo))) { - return deletePhotoAction( - photo.id, - photo.url, - shouldRedirectDelete, - ).then(() => { - revalidatePhoto?.(photo.id, true); - registerAdminUpdate?.(); - }); - } - }, - }, - ], + items, ...props, }}/> : null diff --git a/src/app/tag/hidden/[photoId]/page.tsx b/src/app/tag/hidden/[photoId]/page.tsx index a68bf348..52853db3 100644 --- a/src/app/tag/hidden/[photoId]/page.tsx +++ b/src/app/tag/hidden/[photoId]/page.tsx @@ -71,6 +71,7 @@ export default async function PhotoTagHiddenPage({ dateRange, tag: TAG_HIDDEN, shouldShare: false, + includeFavoriteInAdminMenu: false, }} /> ); } diff --git a/src/components/more/MoreMenu.tsx b/src/components/more/MoreMenu.tsx index 51625b4b..fc1b5d84 100644 --- a/src/components/more/MoreMenu.tsx +++ b/src/components/more/MoreMenu.tsx @@ -4,17 +4,19 @@ import { clsx } from 'clsx/lite'; import { FiMoreHorizontal } from 'react-icons/fi'; import MoreMenuItem from './MoreMenuItem'; +export interface MoreMenuItem { + label: ReactNode + icon?: ReactNode + href?: string + action?: () => Promise | void +} + export default function MoreMenu({ items, className, buttonClassName, }: { - items: { - label: ReactNode - icon?: ReactNode - href?: string - action?: () => Promise | void - }[] + items: MoreMenuItem[] className?: string buttonClassName?: string }){ diff --git a/src/photo/PhotoDetailPage.tsx b/src/photo/PhotoDetailPage.tsx index 38ec6027..ed70dec8 100644 --- a/src/photo/PhotoDetailPage.tsx +++ b/src/photo/PhotoDetailPage.tsx @@ -26,6 +26,7 @@ export default function PhotoDetailPage({ count, dateRange, shouldShare, + includeFavoriteInAdminMenu, }: { photo: Photo photos: Photo[] @@ -38,6 +39,7 @@ export default function PhotoDetailPage({ count?: number dateRange?: PhotoDateRange shouldShare?: boolean + includeFavoriteInAdminMenu?: boolean }) { return (
@@ -117,6 +119,7 @@ export default function PhotoDetailPage({ shouldShareCamera={camera !== undefined} shouldShareSimulation={simulation !== undefined} shouldScrollOnShare={false} + includeFavoriteInAdminMenu={includeFavoriteInAdminMenu} />, ]} /> diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index 5937acd0..1d599484 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -47,6 +47,7 @@ export default function PhotoLarge({ shouldShareSimulation, shouldShareFocalLength, shouldScrollOnShare, + includeFavoriteInAdminMenu, onVisible, }: { photo: Photo @@ -63,6 +64,7 @@ export default function PhotoLarge({ shouldShareSimulation?: boolean shouldShareFocalLength?: boolean shouldScrollOnShare?: boolean + includeFavoriteInAdminMenu?: boolean onVisible?: () => void }) { const ref = useRef(null); @@ -130,6 +132,7 @@ export default function PhotoLarge({