feat: add confirm modal

This commit is contained in:
kawamataryo 2024-11-24 20:04:59 +09:00
parent 1640928837
commit 242be1e9be
3 changed files with 148 additions and 5 deletions

View File

@ -0,0 +1,39 @@
import type { Meta, StoryObj } from "@storybook/react";
import useConfirm, { ConfirmationDialog } from "./ConfirmDialog";
const meta = {
title: "Components/ConfirmDialog",
component: ConfirmationDialog,
} satisfies Meta<typeof ConfirmationDialog>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
message: "Are you sure you want to proceed?",
open: false,
handleConfirm: () => {},
handleCancel: () => {},
},
render: (args) => {
const { ConfirmationDialog, confirm } = useConfirm({
message: args.message,
});
const handleClick = async () => {
const result = await confirm();
alert(`Confirmed: ${result}`);
};
return (
<div>
<button type="button" onClick={handleClick} className="btn btn-primary">
Open Confirm Dialog
</button>
<ConfirmationDialog />
</div>
);
},
};

View File

@ -0,0 +1,97 @@
import { useState } from "react";
export const ConfirmationDialog = ({
title,
message,
open,
handleConfirm,
handleCancel,
cancelText = "Cancel",
okText = "OK",
}: {
title?: string;
message: string;
open: boolean;
cancelText?: string;
okText?: string;
handleConfirm: () => void;
handleCancel: () => void;
}) => (
<dialog id="my_modal_1" className="modal" open={open}>
<div className="modal-box">
{title && <h3 className="font-bold text-xl mb-2">{title}</h3>}
<p className="text-sm">{message}</p>
<div className="modal-action">
<form method="dialog">
<div className="flex gap-2">
<button
className="btn btn-neutral btn-sm min-w-24"
type="button"
onClick={handleCancel}
>
{cancelText}
</button>
<button
className="btn btn-primary btn-sm min-w-24"
type="button"
onClick={handleConfirm}
>
{okText}
</button>
</div>
</form>
</div>
</div>
</dialog>
);
const useConfirm = ({
title = "Confirm",
message = "Are you sure you want to proceed?",
cancelText = "Cancel",
okText = "OK",
}: {
title?: string;
message?: string;
cancelText?: string;
okText?: string;
}) => {
const [promise, setPromise] = useState(null);
const confirm = () => {
return new Promise((resolve, reject) => {
setPromise({ resolve });
});
};
const handleClose = () => {
setPromise(null);
};
const handleConfirm = () => {
promise?.resolve(true);
handleClose();
};
const handleCancel = () => {
promise?.resolve(false);
handleClose();
};
return {
ConfirmationDialog: () => (
<ConfirmationDialog
title={title}
message={message}
open={promise !== null}
handleConfirm={handleConfirm}
handleCancel={handleCancel}
cancelText={cancelText}
okText={okText}
/>
),
confirm,
};
};
export default useConfirm;

View File

@ -1,6 +1,7 @@
import UserCard from "~lib/components/UserCard"; import UserCard from "~lib/components/UserCard";
import { useBskyUserManager } from "~lib/hooks/useBskyUserManager"; import { useBskyUserManager } from "~lib/hooks/useBskyUserManager";
import "./style.css"; import "./style.css";
import useConfirm from "~lib/components/ConfirmDialog";
import Sidebar from "~lib/components/Sidebar"; import Sidebar from "~lib/components/Sidebar";
const Option = () => { const Option = () => {
@ -15,17 +16,22 @@ const Option = () => {
matchTypeStats, matchTypeStats,
} = useBskyUserManager(); } = useBskyUserManager();
const handleActionAll = async () => { const { confirm, ConfirmationDialog } = useConfirm({
if ( title: "Proceed with Execution?",
!window.confirm( message:
"User detection is not perfect and may include false positives. Do you still want to proceed?", "User detection is not perfect and may include false positives. Do you still want to proceed?",
) cancelText: "Cancel",
) { okText: "OK",
});
const handleActionAll = async () => {
if (!(await confirm())) {
return; return;
} }
await actionAll(); await actionAll();
}; };
return ( return (
<> <>
<div className="flex h-screen"> <div className="flex h-screen">
@ -55,6 +61,7 @@ const Option = () => {
</div> </div>
</div> </div>
</div> </div>
<ConfirmationDialog />
</div> </div>
</> </>
); );