Improve upload delete UI feedback

This commit is contained in:
Sam Becker 2024-07-26 14:18:33 -05:00
parent e35489cba2
commit fd628ab409
6 changed files with 82 additions and 44 deletions

View File

@ -36,7 +36,7 @@ export default function AdminUploadsClient({
setIsAdding,
setUrlAddStatuses,
}} />}
<AdminUploadsTable {...{ isAdding, urlAddStatuses }} />
<AdminUploadsTable {...{ isAdding, urlAddStatuses, setUrlAddStatuses }} />
</div>
);
}

View File

@ -7,18 +7,18 @@ import { clsx } from 'clsx/lite';
import { FaRegCircleCheck } from 'react-icons/fa6';
import { pathForAdminUploadUrl } from '@/site/paths';
import AddButton from './AddButton';
import FormWithConfirm from '@/components/FormWithConfirm';
import { deleteBlobPhotoAction } from '@/photo/actions';
import DeleteFormButton from './DeleteFormButton';
import { UrlAddStatus } from './AdminUploadsClient';
import ResponsiveDate from '@/components/ResponsiveDate';
import DeleteBlobButton from './DeleteBlobButton';
export default function AdminUploadsTable({
isAdding,
urlAddStatuses,
setUrlAddStatuses,
}: {
isAdding?: boolean
urlAddStatuses: UrlAddStatus[]
setUrlAddStatuses?: (urlAddStatuses: UrlAddStatus[]) => void
}) {
const isComplete = urlAddStatuses.every(({ status }) => status === 'added');
@ -86,24 +86,13 @@ export default function AdminUploadsTable({
</>
: <>
<AddButton path={pathForAdminUploadUrl(url)} />
<FormWithConfirm
action={deleteBlobPhotoAction}
confirmText="Are you sure you want to delete this upload?"
>
<input
type="hidden"
name="redirectToPhotos"
value={urlAddStatuses.length < 2 ? 'true' : 'false'}
readOnly
/>
<input
type="hidden"
name="url"
value={url}
readOnly
/>
<DeleteFormButton />
</FormWithConfirm>
<DeleteBlobButton
url={url}
shouldRedirectToAdminPhotos={urlAddStatuses.length <= 1}
onDelete={() => setUrlAddStatuses?.(urlAddStatuses.filter(
({ url: urlToRemove }) => urlToRemove !== url,
))}
/>
</>}
</span>
</div>

View File

@ -0,0 +1,41 @@
'use client';
import { deleteUploadAction } from '@/photo/actions';
import DeleteButton from './DeleteButton';
import { useRouter } from 'next/navigation';
import { PATH_ADMIN_PHOTOS } from '@/site/paths';
import { useState } from 'react';
export default function DeleteUploadButton({
url,
shouldRedirectToAdminPhotos,
onDelete,
}: {
url: string
shouldRedirectToAdminPhotos?: boolean
onDelete?: () => void
}) {
const router = useRouter();
const [isDeleting, setIsDeleting] = useState(false);
return (
<DeleteButton
confirmText="Are you sure you want to delete this upload?"
onClick={() => {
setIsDeleting(true);
deleteUploadAction(url)
.then(() => {
onDelete?.();
if (shouldRedirectToAdminPhotos) {
router.push(PATH_ADMIN_PHOTOS);
} else {
setIsDeleting(false);
}
})
.catch(() => setIsDeleting(false));
}}
isLoading={isDeleting}
/>
);
}

View File

@ -0,0 +1,26 @@
import LoaderButton from '@/components/primitives/LoaderButton';
import { clsx } from 'clsx/lite';
import { ComponentProps } from 'react';
import { BiTrash } from 'react-icons/bi';
export default function DeleteButton({
className,
...rest
}: ComponentProps <typeof LoaderButton>) {
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,
)}
/>
);
}

View File

@ -5,15 +5,13 @@ import { photoQuantityText } from '@/photo';
import { deletePhotosAction } from '@/photo/actions';
import { useAppState } from '@/state/AppState';
import { toastSuccess, toastWarning } from '@/toast';
import { clsx } from 'clsx/lite';
import { ComponentProps, useState } from 'react';
import { BiTrash } from 'react-icons/bi';
import DeleteButton from './DeleteButton';
export default function DeletePhotosButton({
photoIds = [],
onDelete,
clearLocalState = true,
className,
onClick,
onFinish,
confirmText,
@ -34,19 +32,8 @@ export default function DeletePhotosButton({
const { invalidateSwr, registerAdminUpdate } = useAppState();
return (
<LoaderButton
<DeleteButton
{...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={confirmText ?? `Are you sure you want to delete ${photosText}? This action cannot be undone.`}

View File

@ -283,15 +283,10 @@ export const renamePhotoTagGloballyAction = async (formData: FormData) =>
}
});
export const deleteBlobPhotoAction = async (formData: FormData) =>
export const deleteUploadAction = async (url: string) =>
runAuthenticatedAdminServerAction(async () => {
await deleteFile(formData.get('url') as string);
await deleteFile(url);
revalidateAdminPaths();
if (formData.get('redirectToPhotos') === 'true') {
redirect(PATH_ADMIN_PHOTOS);
}
});
// Accessed from admin photo edit page