Round system redesign: criteria voting, audience voting, pipeline view, and admin UX improvements
- Schema: Extend LiveVotingSession with votingMode, criteriaJson, audience fields; add AudienceVoter model; make LiveVote.userId nullable for audience voters - Backend: Criteria-based voting with weighted scores, audience registration/voting with token-based dedup, configurable jury/audience weight in results - Jury UI: Criteria scoring with per-criterion sliders alongside simple 1-10 mode - Public audience voting page at /vote/[sessionId] with mobile-first design - Admin live voting: Tabbed layout (Session/Config/Results), criteria config, audience settings, weight-adjustable results with tie detection - Round type settings: Visual card selector replacing dropdown, feature tags - Round detail page: Live event status section, type-specific stats and actions - Round pipeline view: Horizontal visualization with bottleneck detection, List/Pipeline toggle on rounds page - SSE: Separate jury/audience vote events, audience vote tracking - Field visibility: Hide irrelevant fields per round type in create/edit forms Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,13 @@ export interface VoteUpdate {
|
||||
timestamp: string
|
||||
}
|
||||
|
||||
export interface AudienceVoteUpdate {
|
||||
projectId: string
|
||||
audienceVotes: number
|
||||
audienceAverage: number | null
|
||||
timestamp: string
|
||||
}
|
||||
|
||||
export interface SessionStatusUpdate {
|
||||
status: string
|
||||
timestamp: string
|
||||
@@ -23,6 +30,7 @@ export interface ProjectChangeUpdate {
|
||||
|
||||
interface SSECallbacks {
|
||||
onVoteUpdate?: (data: VoteUpdate) => void
|
||||
onAudienceVote?: (data: AudienceVoteUpdate) => void
|
||||
onSessionStatus?: (data: SessionStatusUpdate) => void
|
||||
onProjectChange?: (data: ProjectChangeUpdate) => void
|
||||
onConnected?: () => void
|
||||
@@ -65,6 +73,15 @@ export function useLiveVotingSSE(
|
||||
}
|
||||
})
|
||||
|
||||
es.addEventListener('audience_vote', (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data) as AudienceVoteUpdate
|
||||
callbacksRef.current.onAudienceVote?.(data)
|
||||
} catch {
|
||||
// Ignore parse errors
|
||||
}
|
||||
})
|
||||
|
||||
es.addEventListener('session_status', (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data) as SessionStatusUpdate
|
||||
|
||||
Reference in New Issue
Block a user