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