From bc1a730be22463d85d6894845a21dfbdb10ca556 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 21 Jul 2024 11:59:46 -0500 Subject: [PATCH] Add batch favorites --- src/admin/AdminBatchEditPanelClient.tsx | 40 ++++++++++++++++++------- src/admin/DeletePhotosButton.tsx | 2 +- src/photo/index.ts | 18 +++++++---- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/admin/AdminBatchEditPanelClient.tsx b/src/admin/AdminBatchEditPanelClient.tsx index f3c82509..7195aac6 100644 --- a/src/admin/AdminBatchEditPanelClient.tsx +++ b/src/admin/AdminBatchEditPanelClient.tsx @@ -7,7 +7,7 @@ import { useAppState } from '@/state/AppState'; import { clsx } from 'clsx/lite'; import { IoCloseSharp } from 'react-icons/io5'; import { useState } from 'react'; -import { Tags } from '@/tag'; +import { TAG_FAVS, Tags } from '@/tag'; import { usePathname } from 'next/navigation'; import { PATH_GRID_INFERRED } from '@/site/paths'; import PhotoTagFieldset from './PhotoTagFieldset'; @@ -15,6 +15,7 @@ import { tagMultiplePhotosAction } from '@/photo/actions'; import { toastSuccess } from '@/toast'; import DeletePhotosButton from './DeletePhotosButton'; import { photoQuantityText } from '@/photo'; +import { FaArrowDown, FaRegStar } from 'react-icons/fa6'; export default function AdminBatchEditPanelClient({ uniqueTags, @@ -41,11 +42,15 @@ export default function AdminBatchEditPanelClient({ setTagErrorMessage(''); }; - const photosText = photoQuantityText(selectedPhotoIds?.length ?? 0, false); + const photosText = photoQuantityText( + selectedPhotoIds?.length ?? 0, + false, + false, + ); - const renderPhotoText = () => selectedPhotoIds?.length === 0 - ? 'Select photos below' - : `${photosText} selected`; + const renderPhotoCTA = () => selectedPhotoIds?.length === 0 + ? <> Select photos below + : <>{photosText} selected; const renderActions = () => isInTagMode ? <> @@ -70,9 +75,7 @@ export default function AdminBatchEditPanelClient({ selectedPhotoIds ?? [], ) .then(() => { - toastSuccess( - `Tags applied to ${photosText}` - ); + toastSuccess(`${photosText} tagged`); resetForm(); }) .finally(() => setIsPerformingSelectEdit?.(false)); @@ -98,6 +101,23 @@ export default function AdminBatchEditPanelClient({ onDelete={resetForm} onFinish={() => setIsPerformingSelectEdit?.(false)} /> + } + disabled={isPerformingSelectEdit} + confirmText={`Are you sure you want to favorite ${photosText}?`} + onClick={() => { + setIsPerformingSelectEdit?.(true); + tagMultiplePhotosAction( + TAG_FAVS, + selectedPhotoIds ?? [], + ) + .then(() => { + toastSuccess(`${photosText} favorited`); + resetForm(); + }) + .finally(() => setIsPerformingSelectEdit?.(false)); + }} + /> setTags('')} disabled={isPerformingSelectEdit} @@ -145,8 +165,8 @@ export default function AdminBatchEditPanelClient({ openOnLoad hideLabel /> - :
- {renderPhotoText()} + :
+ {renderPhotoCTA()}
} {tagErrorMessage && diff --git a/src/admin/DeletePhotosButton.tsx b/src/admin/DeletePhotosButton.tsx index 68492f4a..b71f89e7 100644 --- a/src/admin/DeletePhotosButton.tsx +++ b/src/admin/DeletePhotosButton.tsx @@ -29,7 +29,7 @@ export default function DeletePhotosButton({ } & ComponentProps) { const [isLoading, setIsLoading] = useState(false); - const photosText = photoQuantityText(photoIds.length, false); + const photosText = photoQuantityText(photoIds.length, false, false); const { invalidateSwr, registerAdminUpdate } = useAppState(); diff --git a/src/photo/index.ts b/src/photo/index.ts index 2d861363..646bd13e 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -194,13 +194,19 @@ export const titleForPhoto = (photo: Photo) => export const altTextForPhoto = (photo: Photo) => photo.semanticDescription || titleForPhoto(photo); -export const photoLabelForCount = (count: number) => - count === 1 ? 'Photo' : 'Photos'; +export const photoLabelForCount = (count: number, capitalize = true) => + capitalize + ? count === 1 ? 'Photo' : 'Photos' + : count === 1 ? 'photo' : 'photos'; -export const photoQuantityText = (count: number, includeParentheses = true) => +export const photoQuantityText = ( + count: number, + includeParentheses = true, + capitalize?: boolean, +) => includeParentheses - ? `(${count} ${photoLabelForCount(count)})` - : `${count} ${photoLabelForCount(count)}`; + ? `(${count} ${photoLabelForCount(count, capitalize)})` + : `${count} ${photoLabelForCount(count, capitalize)}`; export const deleteConfirmationTextForPhoto = (photo: Photo) => `Are you sure you want to delete "${titleForPhoto(photo)}?"`; @@ -219,7 +225,7 @@ export const descriptionForPhotoSet = ( : [ explicitCount ?? photos.length, descriptor, - photoLabelForCount(explicitCount ?? photos.length), + photoLabelForCount(explicitCount ?? photos.length, false), ].join(' '); const sortPhotosByDate = (