Skip to content

feat(voting): add quick vote to synergy detail modal (#212)#262

Open
Doberjohn wants to merge 12 commits intomasterfrom
feature/212-quick-vote
Open

feat(voting): add quick vote to synergy detail modal (#212)#262
Doberjohn wants to merge 12 commits intomasterfrom
feature/212-quick-vote

Conversation

@Doberjohn
Copy link
Copy Markdown
Owner

Summary

  • Add three-button quick vote (lower / about right / higher) to the synergy detail modal
  • Show animated distribution bar with community results after voting
  • localStorage deduplication prevents re-voting on the same pair
  • Supabase pair_scores view extended with accuracy distribution columns
  • State machine hook (useQuickVote) manages full vote lifecycle: hidden → ready → submitting → result → error
  • Rate-limit detection with auto-recovery after 30s

New Components

  • DistributionBar — three-segment animated percentage bar with rounding correction
  • QuickVoteControl — vote UI rendering 5 states with accessibility (aria-pressed, role="alert")
  • useQuickVote — state machine hook with double-submit guard, optimistic UI, useEffect cancellation

Security

  • Migration preserves security_invoker = true on pair_scores view (RLS enforced)
  • localStorage operations wrapped in try-catch (SecurityError, QuotaExceeded)
  • useRef guard prevents concurrent double-submission

Test plan

  • 195 engine tests passing
  • 579 web unit tests passing (11 new: 7 supabase, 2 hook, 2 component)
  • 74 E2E tests passing (chromium)
  • Lint clean (0 errors)
  • Supabase integration tests passing (8/8)
  • Storybook stories for both new components

Closes #212

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

Doberjohn and others added 10 commits April 6, 2026 20:52
Brainstormed and documented UI/UX design for synergy modal quick vote
feature including state machine, distribution bar, mobile layout,
animation specs, and Supabase migration plan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6-task TDD plan: Supabase migration, distribution query,
DistributionBar component, useQuickVote hook, QuickVoteControl
component, modal integration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…#212)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix silent localStorage error handling (getStoredVote/storeVote)
- Add try-catch to vote callback and .catch() to useEffect
- Fix fontSize to use template literal px strings (project convention)
- Fix aria-pressed to use undefined instead of false for idle state
- Export Accuracy type, use in QuickVoteControlProps
- Add error logging in generic error branch
- Add 5 missing tests: retry from error, reversed card order lookup,
  rate-limited buttons disabled, result with null distribution,
  rounding correction sum-to-100

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical: add security_invoker to migration, optimistic userChoice,
useEffect cancellation guard. Important: double-submit useRef guard,
DistributionBar two-phase animation, loading indicator for null
distribution, getAccuracyDistribution test coverage. Suggestions:
safe removeItem, Record<Accuracy>, rename error→submission_failed,
consolidate Accuracy type, rate-limit auto-recovery.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
inkweave Ready Ready Preview, 💬 1 unresolved
✅ 2 resolved
Apr 7, 2026 11:38am

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

size-limit report 📦

Path Size
Total JS bundle 224.87 KB (+1.51% 🔺)
Card data JSON 249.3 KB (0%)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

⚡ Lighthouse Results

URL TBT LCP CLS FCP SI
/ 🟢 41ms 🔴 4689ms 🟢 0.003 🔴 2517ms 🟢 2517ms
/browse 🟢 59ms 🔴 4395ms 🟢 0.008 🔴 2673ms 🟢 2673ms
/card/957 🟢 15ms 🔴 4070ms 🟢 0.001 🔴 2746ms 🟢 2746ms
/card/957/synergies 🟢 18ms 🔴 4390ms 🟢 0.001 🔴 2658ms 🟢 2658ms
/playstyles 🟢 41ms 🔴 4909ms 🟢 0.001 🔴 2583ms 🟢 2583ms
/playstyles/lore-denial 🟢 10ms 🔴 4543ms 🟢 0.001 🔴 2679ms 🟢 2679ms
Threshold 🚫 500ms ⚠️ 3000ms 🚫 0.1 ⚠️ 2200ms ⚠️ 4000ms

Median of 3 runs. 🟢 ≤75% of limit · 🟠 within limit · 🔴 over limit · 🚫 merge-blocking · ⚠️ warning

The shared/hooks mock only provided useTransitionPresence, leaving
useResponsive and useScrollLock undefined. On Linux CI (identical
path resolution), QuickVoteControl's useResponsive import hits the
same mock and crashes. On Windows, different path canonicalization
meant the mock didn't intercept the child component's import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mock paths in __tests__/ must account for being one directory deeper
than the component. Add missing shared/components stubs (RenderProfiler,
CardLightbox, StrengthBadge). On Windows, wrong paths silently fell
through to real modules; on Linux CI, Vitest correctly resolves and
intercepts them, requiring complete mock factories.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Synergy Modal Quick Vote

1 participant