From a5e3969d0af10ef5430fded9a4cb69c79c69137c Mon Sep 17 00:00:00 2001 From: Tim McCarthy Date: Fri, 4 Sep 2026 19:35:49 -0700 Subject: [PATCH] Let players dismiss completed duel feedback --- TODO.md | 2 +- frontend/src/components/ScenePhase.svelte | 25 ++++++++++++++++--- .../components/scene/ChallengePanel.svelte | 11 +++++--- frontend/src/lib/changelog.js | 3 ++- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index be606e9..4c86d41 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,7 @@ ## Features - [x] Add an online indicator that displays if a player is connected -- [x] PvP challenges should linger in the UI after completion so that players can see the result +- [x] PvP challenges should linger in the UI after completion so that players can see the result, then dismiss it for themselves - [x] Add hat/gun icons next to player names on the player list to indicate if they're the captain and/or have a gat - [x] Replace red/green borders of successful/failed cards with checks and crosses in the upper corner of the card. - [ ] Add a note taking area to store game state between sessions diff --git a/frontend/src/components/ScenePhase.svelte b/frontend/src/components/ScenePhase.svelte index be06a64..157f9f1 100644 --- a/frontend/src/components/ScenePhase.svelte +++ b/frontend/src/components/ScenePhase.svelte @@ -11,12 +11,31 @@ // The inline Event Log can be toggled from a fixed corner button to declutter. let logOpen = true; + let dismissedDuelIds = []; + $: dismissalKey = `dismissed-duels:${state.game.id}:${state.player.id}:${state.game.current_scene_number}`; + $: dismissedDuelIds = loadDismissals(dismissalKey); + + function loadDismissals(key) { + try { + const ids = JSON.parse(localStorage.getItem(key) || '[]'); + return Array.isArray(ids) ? ids : []; + } catch { return []; } + } + + function dismissDuel(id) { + dismissedDuelIds = [...dismissedDuelIds, id]; + try { localStorage.setItem(dismissalKey, JSON.stringify(dismissedDuelIds)); } catch { /* Still dismiss when storage is unavailable. */ } + } + + $: completedDuels = (state.challenges || []).filter(c => + c.challenge_type === 'pvp' && ['succeeded', 'failed'].includes(c.status) && !dismissedDuelIds.includes(c.id) + ); $: hand = state.player.hand_cards ? JSON.parse(state.player.hand_cards) : []; $: playerTechs = { J: state.player.tech_jack, Q: state.player.tech_queen, K: state.player.tech_king }; $: isDeep = state.player.role === 'deep'; $: openChallenges = (state.challenges || []).filter(c => c.status === 'open'); - // Keep duel results visible to the whole table for the rest of the scene. - $: showChallengeArea = isDeep || openChallenges.length > 0 || (state.challenges || []).some(c => c.challenge_type === 'pvp' && ['succeeded', 'failed'].includes(c.status)); + // Keep results visible until this player dismisses them. + $: showChallengeArea = isDeep || openChallenges.length > 0 || completedDuels.length > 0;
@@ -50,7 +69,7 @@ {#if showChallengeArea}
- + dismissDuel(event.detail)} />
{/if} diff --git a/frontend/src/components/scene/ChallengePanel.svelte b/frontend/src/components/scene/ChallengePanel.svelte index 0f733c3..2629a7f 100644 --- a/frontend/src/components/scene/ChallengePanel.svelte +++ b/frontend/src/components/scene/ChallengePanel.svelte @@ -1,10 +1,13 @@