From ebe123ed7edf24fbc7b8765ed709455a8513d6d5 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Sun, 19 Oct 2025 12:07:14 -0500 Subject: [PATCH] fix: replace native alerts with inline confirmations in ModerationPanel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed native browser confirm() dialogs and replaced with React state-based inline confirmations: - Removed confirm() from handleKick (kicks happen immediately) - Removed confirm() from handleTransferOwnership - Added confirmingTransferOwnership state variable - Added inline confirmation UI with Cancel/Confirm buttons - Follows pattern documented in UI_STYLE_GUIDE.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/web/.claude/settings.local.json | 3 +- .../src/components/nav/ModerationPanel.tsx | 201 +++++++++++++----- 2 files changed, 144 insertions(+), 60 deletions(-) diff --git a/apps/web/.claude/settings.local.json b/apps/web/.claude/settings.local.json index ab4cf5c0..cf94f119 100644 --- a/apps/web/.claude/settings.local.json +++ b/apps/web/.claude/settings.local.json @@ -101,7 +101,8 @@ "WebFetch(domain:abaci.one)", "Bash(do gh run list --limit 1 --workflow=\"Build and Deploy\" --json conclusion,status,databaseId --jq '.[0] | \"\"\\(.status) - \\(.conclusion // \"\"running\"\") - Run ID: \\(.databaseId)\"\"')", "Bash(node -e:*)", - "Bash(do gh run list --limit 1 --workflow=\"Build and Deploy\" --json conclusion,status,databaseId --jq '.[0] | \"\"\\(.status) - \\(.conclusion // \"\"running\"\") - Run \\(.databaseId)\"\"')" + "Bash(do gh run list --limit 1 --workflow=\"Build and Deploy\" --json conclusion,status,databaseId --jq '.[0] | \"\"\\(.status) - \\(.conclusion // \"\"running\"\") - Run \\(.databaseId)\"\"')", + "Bash(do ssh nas.home.network '/usr/local/bin/docker inspect soroban-abacus-flashcards --format=\"\"{{index .Config.Labels \\\"\"org.opencontainers.image.revision\\\"\"}}\"\"')" ], "deny": [], "ask": [] diff --git a/apps/web/src/components/nav/ModerationPanel.tsx b/apps/web/src/components/nav/ModerationPanel.tsx index 9ba26498..faf5bb42 100644 --- a/apps/web/src/components/nav/ModerationPanel.tsx +++ b/apps/web/src/components/nav/ModerationPanel.tsx @@ -114,6 +114,9 @@ export function ModerationPanel({ null ) + // Transfer ownership confirmation state + const [confirmingTransferOwnership, setConfirmingTransferOwnership] = useState(false) + // Auto-switch to Members tab when focusedUserId is provided useEffect(() => { if (isOpen && focusedUserId) { @@ -171,8 +174,6 @@ export function ModerationPanel({ }, [isOpen, roomId, members]) const handleKick = async (userId: string) => { - if (!confirm('Kick this player from the room?')) return - setActionLoading(`kick-${userId}`) try { const res = await fetch(`/api/arcade/rooms/${roomId}/kick`, { @@ -414,10 +415,9 @@ export function ModerationPanel({ const newOwner = members.find((m) => m.userId === selectedNewOwner) if (!newOwner) return - if (!confirm(`Transfer ownership to ${newOwner.displayName}? You will no longer be the host.`)) - return - + setConfirmingTransferOwnership(false) setActionLoading('transfer-ownership') + try { const res = await fetch(`/api/arcade/rooms/${roomId}/transfer-ownership`, { method: 'POST', @@ -436,6 +436,7 @@ export function ModerationPanel({ showError(err instanceof Error ? err.message : 'Failed to transfer ownership') } finally { setActionLoading(null) + setSelectedNewOwner('') // Reset selection } } @@ -1789,61 +1790,143 @@ export function ModerationPanel({ Transfer host privileges to another member. You will no longer be the host.

- + {!confirmingTransferOwnership ? ( + <> + - + + + ) : ( +
+
+ ⚠️ Confirm Transfer to{' '} + {members.find((m) => m.userId === selectedNewOwner)?.displayName}? +
+
+ You will no longer be the host and will lose moderation privileges. This + cannot be undone. +
+
+ + +
+
+ )}