The pulse vote widget on /pulse and on /dispatches/[slug] now behaves the way the v5 spec asks: - Eyebrow shortens: 'This week's pulse' → 'This week's'. - Status line copy changes shape depending on whether the viewer has voted yet. Pre-vote: 'Vote to see how the council weighs in · Closes TUESDAY' — sets expectations that the percentages reveal after a vote. Post-vote: '2 of 7 voted · Closes TUESDAY · Click to change' — tells the viewer they can change their mind. - Each option now renders a right-aligned tabular-nums percentage badge, but only after the viewer has voted. Pre-vote there's no percentage on screen at all — voting is a commitment, not a peek. - Options stay clickable after voting (no `disabled`). Re-clicking a different option changes the vote. DB: new helper castOrChangeVote(pulseId, userId, optionIndex) does an UPSERT — INSERT on first vote, UPDATE option_index + voted_at on subsequent. Returns true if this was the brand-new vote, so the caller can write the 'voted' activity row exactly once and not double-count changes-of-mind in the feed. castVote(...) (INSERT OR IGNORE) stays in db.ts for callers that explicitly want first-vote-wins semantics. Status-class rename: .locked → .closed on both pulse-option and inline-poll-option. The class now reflects what it actually represents (the pulse is closed) rather than the false invariant 'the user has voted and can't change'. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| auth.ts | ||
| db.ts | ||
| format.ts | ||
| markdown.ts | ||
| notify.ts | ||
| routing.ts | ||