fix(ui): replace browser confirm dialogs with ConfirmModal component (#1060)

Replace 10 instances of native browser confirm() dialogs with the
existing ConfirmModal component for consistent UX across the dashboard.

Changes:
- Add ConfirmModal to 5 files (combos, endpoints, proxy pools, providers, connections)
- Maintain same confirmation flow with improved styling
- Use 'danger' variant for destructive actions
- Preserve all existing functionality

Affected areas:
- Combo deletion (combos page)
- API key deletion/pausing (EndpointPageClient)
- Proxy pool management (single/bulk delete, disable dead proxies)
- Provider operations (disable all models, delete connection, delete compatible node)
- Connection management (ConnectionsCard)

All changes manually tested and verified.
This commit is contained in:
Zanuar Tri Romadon authored and GitHub committed 2026-05-13 15:32:17 +07:00
1 parent 5cab23d92e
commit 3c2503c4b4
5 files changed
+225 -114

No files matched your search

@@ -2,7 +2,7 @@
import { useState, useEffect, useRef, useCallback } from "react";
import PropTypes from "prop-types";
import { Card, Button, Input, Modal, CardSkeleton, Toggle } from "@/shared/components";
import { Card, Button, Input, Modal, CardSkeleton, Toggle, ConfirmModal } from "@/shared/components";
import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard";
const TUNNEL_BENEFITS = [
@@ -44,6 +44,7 @@ export default function APIPageClient({ machineId }) {
const [showAddModal, setShowAddModal] = useState(false);
const [newKeyName, setNewKeyName] = useState("");
const [createdKey, setCreatedKey] = useState(null);
const [confirmState, setConfirmState] = useState(null);
const [requireApiKey, setRequireApiKey] = useState(false);
const [requireLogin, setRequireLogin] = useState(true);
@@ -660,22 +661,26 @@ export default function APIPageClient({ machineId }) {
};
const handleDeleteKey = async (id) => {
if (!confirm("Delete this API key?")) return;
try {
const res = await fetch(`/api/keys/${id}`, { method: "DELETE" });
if (res.ok) {
setKeys(keys.filter((k) => k.id !== id));
// Clean up visibility state
setVisibleKeys(prev => {
const next = new Set(prev);
next.delete(id);
return next;
});
setConfirmState({
title: "Delete API Key",
message: "Delete this API key?",
onConfirm: async () => {
setConfirmState(null);
try {
const res = await fetch(`/api/keys/${id}`, { method: "DELETE" });
if (res.ok) {
setKeys(keys.filter((k) => k.id !== id));
setVisibleKeys(prev => {
const next = new Set(prev);
next.delete(id);
return next;
});
}
} catch (error) {
console.log("Error deleting key:", error);
}
}
} catch (error) {
console.log("Error deleting key:", error);
}
});
};
const handleToggleKey = async (id, isActive) => {
@@ -1108,9 +1113,14 @@ export default function APIPageClient({ machineId }) {
checked={key.isActive ?? true}
onChange={(checked) => {
if (key.isActive && !checked) {
if (confirm(`Pause API key "${key.name}"?\n\nThis key will stop working immediately but can be resumed later.`)) {
handleToggleKey(key.id, checked);
}
setConfirmState({
title: "Pause API Key",
message: `Pause API key "${key.name}"?\n\nThis key will stop working immediately but can be resumed later.`,
onConfirm: async () => {
setConfirmState(null);
handleToggleKey(key.id, checked);
}
});
} else {
handleToggleKey(key.id, checked);
}
@@ -1344,6 +1354,16 @@ export default function APIPageClient({ machineId }) {
</div>
</div>
</Modal>
{/* Confirm Modal */}
<ConfirmModal
isOpen={!!confirmState}
onClose={() => setConfirmState(null)}
onConfirm={confirmState?.onConfirm}
title={confirmState?.title || "Confirm"}
message={confirmState?.message}
variant="danger"
/>
</div>
);
}