add confirm button for dangerous admin actions

This commit is contained in:
Brandon Egger 2023-09-05 20:27:33 -05:00
parent 8b42377453
commit f66c35a225
4 changed files with 88 additions and 11 deletions

View File

@ -1,4 +1,6 @@
import { ExclamationCircleIcon } from "@heroicons/react/24/solid";
import Link from "next/link";
import { useEffect, useState } from "react";
const AdminActionBody = ({
label,
@ -38,6 +40,53 @@ const AdminActionLink = ({
);
};
const AdminActionConfirmButton = ({
label,
onConfirm,
symbol,
type = "button",
}: {
label: string;
onConfirm?: () => void;
symbol: JSX.Element | undefined;
type?: HTMLButtonElement["type"];
}) => {
const [isConfirmView, setConfirmView] = useState(false);
useEffect(() => {
if (!isConfirmView) {
return;
}
setTimeout(() => {
if (isConfirmView) {
setConfirmView(false);
}
}, 5000);
}, [isConfirmView]);
if (isConfirmView) {
return (
<AdminActionButton
symbol={<ExclamationCircleIcon className="w-4 animate-ping" />}
label={`Confirm ${label}`}
onClick={onConfirm}
type={type}
/>
);
}
return (
<AdminActionButton
symbol={symbol}
label={label}
onClick={() => {
setConfirmView(true);
}}
/>
);
};
const AdminActionButton = ({
label,
onClick,
@ -65,4 +114,4 @@ const AdminActionButton = ({
);
};
export { AdminActionLink, AdminActionButton };
export { AdminActionLink, AdminActionButton, AdminActionConfirmButton };

View File

@ -1,6 +1,9 @@
import { XCircleIcon } from "@heroicons/react/20/solid";
import { AdminBarLayout } from "~/components/admin/ControlBar";
import { AdminActionButton, AdminActionLink } from "~/components/admin/common";
import {
AdminActionButton,
AdminActionConfirmButton,
} from "~/components/admin/common";
import Image from "next/image";
import {
ResourceForm,
@ -87,11 +90,15 @@ const EditResourcePage = () => {
onSubmit(formMethods.getValues());
}}
/>,
<AdminActionLink
<AdminActionConfirmButton
key="cancel"
symbol={<XCircleIcon className="w-4" />}
label="Cancel"
href={`/resources/${data.id}`}
onConfirm={() => {
router.push(`/resources/${data.id}`).catch((error) => {
console.error(error);
});
}}
/>,
]}
>

View File

@ -6,10 +6,14 @@ import { type AuditoryResource, type PlatformLink } from "@prisma/client";
import Image from "next/image";
import Link from "next/link";
import { AdminBarLayout } from "~/components/admin/ControlBar";
import { AdminActionLink } from "~/components/admin/common";
import {
AdminActionConfirmButton,
AdminActionLink,
} from "~/components/admin/common";
import { useRouter } from "next/router";
import { HeaderFooterLayout } from "~/layouts/HeaderFooterLayout";
import { QueryWaitWrapper } from "~/components/LoadingWrapper";
import { TrashIcon } from "@heroicons/react/24/outline";
export const PlatformLinkButton = ({
platformLink,
@ -122,13 +126,23 @@ const ResourceViewPage = () => {
return (
<HeaderFooterLayout>
<AdminBarLayout
actions={
actions={[
<AdminActionLink
key="edit"
symbol={<PencilSquareIcon className="w-4" />}
label="Edit Page"
href={`${router.asPath}/edit`}
/>
}
/>,
<AdminActionConfirmButton
key="delete"
label="Delete"
symbol={<TrashIcon className="w-4" />}
onConfirm={() => {
// todo
console.log("deleting");
}}
/>,
]}
>
<div className="mb-12">
<QueryWaitWrapper query={resourceQuery} Render={ConditionalView} />

View File

@ -7,7 +7,10 @@ import {
type UseFormReturn,
} from "react-hook-form";
import { AdminBarLayout } from "~/components/admin/ControlBar";
import { AdminActionButton, AdminActionLink } from "~/components/admin/common";
import {
AdminActionButton,
AdminActionConfirmButton,
} from "~/components/admin/common";
import {
type ResourceCreateInput,
ResourceForm,
@ -55,11 +58,15 @@ const EditResourcePage = () => {
.catch((error) => console.error(error));
}}
/>,
<AdminActionLink
<AdminActionConfirmButton
key="cancel"
symbol={<XCircleIcon className="w-4" />}
label="Cancel"
href={`/resources`}
onConfirm={() => {
router.push("/resources").catch((error) => {
console.error(error);
});
}}
/>,
]}
>