From 13295bd24d04400655f5f2c0402a09705062d711 Mon Sep 17 00:00:00 2001 From: heimoshuiyu Date: Wed, 28 May 2025 09:57:46 +0800 Subject: [PATCH] Refactor: Replace window.confirm with custom dialog component --- src/components/ListAPI.tsx | 89 ++++++++++++++--------- src/components/editMessage.tsx | 32 ++++---- src/components/ui/confirmation-dialog.tsx | 48 ++++++++++++ 3 files changed, 123 insertions(+), 46 deletions(-) create mode 100644 src/components/ui/confirmation-dialog.tsx diff --git a/src/components/ListAPI.tsx b/src/components/ListAPI.tsx index 656b38a..ecbc990 100644 --- a/src/components/ListAPI.tsx +++ b/src/components/ListAPI.tsx @@ -46,6 +46,7 @@ import { Input } from "./ui/input"; import { SetAPIsTemplate } from "./setAPIsTemplate"; import { isVailedJSON } from "@/utils/isVailedJSON"; import { toast } from 'sonner'; +import { ConfirmationDialog } from "./ui/confirmation-dialog"; interface APITemplateDropdownProps { label: string; @@ -151,6 +152,8 @@ function APIsDropdownList({ const { toast } = useToast(); const [open, setOpen] = React.useState(false); const [editingTemplate, setEditingTemplate] = useState(null); + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); + const [templateToDelete, setTemplateToDelete] = useState(null); let API = templateAPIs; let setAPI = setTemplateAPIs; @@ -186,8 +189,13 @@ function APIsDropdownList({ }; const handleDelete = (template: TemplateAPI) => { - if (window.confirm(`Are you sure you want to delete "${template.name}"?`)) { - const newAPI = API.filter(t => t.name !== template.name); + setTemplateToDelete(template); + setDeleteDialogOpen(true); + }; + + const confirmDelete = () => { + if (templateToDelete) { + const newAPI = API.filter(t => t.name !== templateToDelete.name); setAPI(newAPI); toast({ title: "Success", @@ -271,6 +279,16 @@ function APIsDropdownList({ onClose={() => setEditingTemplate(null)} /> )} + { + setDeleteDialogOpen(false); + setTemplateToDelete(null); + }} + onConfirm={confirmDelete} + title="Delete Template" + description={`Are you sure you want to delete "${templateToDelete?.name}"?`} + /> ); } @@ -460,6 +478,8 @@ function ChatTemplateDropdownList() { const [open, setOpen] = React.useState(false); const [editingTemplate, setEditingTemplate] = useState(null); const { toast } = useToast(); + const [confirmDialogOpen, setConfirmDialogOpen] = useState(false); + const [templateToApply, setTemplateToApply] = useState(null); const handleEdit = (template: TemplateChatStore) => { setEditingTemplate(template); @@ -479,16 +499,32 @@ function ChatTemplateDropdownList() { }; const handleDelete = (template: TemplateChatStore) => { - if (window.confirm(`Are you sure you want to delete "${template.name}"?`)) { - const newTemplates = templates.filter(t => t.name !== template.name); - setTemplates(newTemplates); - toast({ - title: "Success", - description: "Template deleted successfully", - }); + setTemplateToApply(template); + setConfirmDialogOpen(true); + }; + + const handleTemplateSelect = (template: TemplateChatStore) => { + if (chatStore.history.length > 0 || chatStore.systemMessageContent) { + setTemplateToApply(template); + setConfirmDialogOpen(true); + } else { + applyTemplate(template); } }; + const applyTemplate = (template: TemplateChatStore) => { + setChatStore({ + ...newChatStore({ + ...chatStore, + ...{ + use_this_history: template.history ?? chatStore.history, + }, + ...template, + }), + }); + setOpen(false); + }; + return (

@@ -512,30 +548,7 @@ function ChatTemplateDropdownList() { { - if ( - chatStore.history.length > 0 || - chatStore.systemMessageContent - ) { - const confirm = window.confirm( - "This will replace the current chat history. Are you sure? " - ); - if (!confirm) { - setOpen(false); - return; - } - } - setChatStore({ - ...newChatStore({ - ...chatStore, - ...{ - use_this_history: t.history ?? chatStore.history, - }, - ...t, - }), - }); - setOpen(false); - }} + onSelect={() => handleTemplateSelect(t)} >

{t.name} @@ -576,6 +589,16 @@ function ChatTemplateDropdownList() { onClose={() => setEditingTemplate(null)} /> )} + { + setConfirmDialogOpen(false); + setTemplateToApply(null); + }} + onConfirm={() => templateToApply && applyTemplate(templateToApply)} + title="Replace Chat History" + description="This will replace the current chat history. Are you sure?" + />
); } diff --git a/src/components/editMessage.tsx b/src/components/editMessage.tsx index 9562898..000ca81 100644 --- a/src/components/editMessage.tsx +++ b/src/components/editMessage.tsx @@ -14,6 +14,7 @@ import { } from "@/components/ui/dialog"; import { Button } from "./ui/button"; import { AppChatStoreContext, AppContext } from "../pages/App"; +import { ConfirmationDialog } from "./ui/confirmation-dialog"; interface EditMessageProps { chat: ChatStoreMessage; @@ -22,9 +23,19 @@ interface EditMessageProps { } export function EditMessage(props: EditMessageProps) { const { chatStore, setChatStore } = useContext(AppChatStoreContext); + const [showConfirmDialog, setShowConfirmDialog] = useState(false); const { showEdit, setShowEdit, chat } = props; + const handleSwitchMessageType = () => { + if (typeof chat.content === "string") { + chat.content = []; + } else { + chat.content = ""; + } + setChatStore({ ...chatStore }); + }; + return ( {/* @@ -46,19 +57,7 @@ export function EditMessage(props: EditMessageProps) { + setShowConfirmDialog(false)} + onConfirm={handleSwitchMessageType} + title="Switch Message Type" + description="Change message type will clear the content, are you sure?" + /> ); } diff --git a/src/components/ui/confirmation-dialog.tsx b/src/components/ui/confirmation-dialog.tsx new file mode 100644 index 0000000..4ea7383 --- /dev/null +++ b/src/components/ui/confirmation-dialog.tsx @@ -0,0 +1,48 @@ +import React from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, + DialogDescription, +} from "./dialog"; +import { Button } from "./button"; + +interface ConfirmationDialogProps { + isOpen: boolean; + onClose: () => void; + onConfirm: () => void; + title: string; + description: string; +} + +export function ConfirmationDialog({ + isOpen, + onClose, + onConfirm, + title, + description +}: ConfirmationDialogProps) { + return ( + + + + {title} + {description} + + + + + + + + ); +} \ No newline at end of file