Add delete functionality to multi-select

This commit is contained in:
Sam Becker 2024-07-21 00:16:22 -05:00
parent 6ccb1533d2
commit 50024bd115
4 changed files with 72 additions and 6 deletions

View File

@ -6,7 +6,6 @@ import SiteGrid from '@/components/SiteGrid';
import { useAppState } from '@/state/AppState';
import { clsx } from 'clsx/lite';
import { IoCloseSharp } from 'react-icons/io5';
import DeleteButton from './DeleteButton';
import { useState } from 'react';
import { Tags } from '@/tag';
import { usePathname } from 'next/navigation';
@ -14,6 +13,7 @@ import { PATH_GRID_INFERRED } from '@/site/paths';
import PhotoTagFieldset from './PhotoTagFieldset';
import { tagMultiplePhotosAction } from '@/photo/actions';
import { toastSuccess } from '@/toast';
import DeletePhotosButton from './DeletePhotosButton';
export default function AdminBatchEditPanelClient({
uniqueTags,
@ -96,7 +96,11 @@ export default function AdminBatchEditPanelClient({
>
Tag ...
</LoaderButton>
<DeleteButton disabled={isLoading} />
<DeletePhotosButton
photoIds={selectedPhotoIds}
disabled={isLoading}
onDelete={resetForm}
/>
</>}
<LoaderButton
icon={<IoCloseSharp size={20} className="translate-y-[-1.5px]" />}

View File

@ -0,0 +1,53 @@
'use client';
import LoaderButton from '@/components/primitives/LoaderButton';
import { photoQuantityText } from '@/photo';
import { deletePhotosAction } from '@/photo/actions';
import { toastSuccess, toastWarning } from '@/toast';
import { clsx } from 'clsx/lite';
import { ComponentProps, useState } from 'react';
import { BiTrash } from 'react-icons/bi';
export default function DeletePhotosButton({
photoIds = [],
onDelete,
className,
...rest
}: {
photoIds?: string[]
onDelete?: () => void
} & ComponentProps<typeof LoaderButton>) {
const [isLoading, setIsLoading] = useState(false);
const photosText = photoQuantityText(photoIds.length, false);
return (
<LoaderButton
{...rest}
title="Delete"
icon={<BiTrash size={16} />}
spinnerColor="text"
className={clsx(
'!text-red-500 dark:!text-red-600',
'active:!bg-red-100/50 active:dark:!bg-red-950/50',
'disabled:!bg-red-100/50 disabled:dark:!bg-red-950/50',
'!border-red-200 hover:!border-red-300',
'dark:!border-red-900/75 dark:hover:!border-red-900',
className,
)}
isLoading={isLoading}
// eslint-disable-next-line max-len
confirmText={`Are you sure you want to delete ${photosText}? This action cannot be undone.`}
onClick={() => {
setIsLoading(true);
deletePhotosAction(photoIds)
.then(() => {
toastSuccess(`${photosText} deleted`);
onDelete?.();
})
.catch(() => toastWarning(`Failed to delete ${photosText}`))
.finally(() => setIsLoading(false));
}}
/>
);
}

View File

@ -59,7 +59,7 @@ export default function LoaderButton(props: {
>
{(icon || isLoading) &&
<span className={clsx(
'min-w-[1.25rem] max-h-4 overflow-hidden',
'min-w-[1.25rem] max-h-5 overflow-hidden',
styleAs === 'button' ? 'translate-y-[-0.5px]' : 'translate-y-[0.5px]',
'inline-flex justify-center shrink-0',
)}>
@ -67,9 +67,7 @@ export default function LoaderButton(props: {
? <Spinner
size={14}
color={spinnerColor}
className={styleAs === 'button'
? 'translate-y-[2px]'
: 'translate-y-[0.5px]'}
className="translate-y-[0.5px]"
/>
: icon}
</span>}

View File

@ -236,6 +236,17 @@ export const toggleFavoritePhotoAction = async (
}
});
export const deletePhotosAction = async (photoIds: string[]) =>
runAuthenticatedAdminServerAction(async () => {
for (const photoId of photoIds) {
const photo = await getPhoto(photoId);
if (photo) {
await deletePhoto(photoId).then(() => deleteFile(photo.url));
}
}
revalidateAllKeysAndPaths();
});
export const deletePhotoAction = async (
photoId: string,
photoUrl: string,