feat: add Admin Control Panel, voting status check, and router security
Admin Control Panel: - Add full AdminControl.vue with 3 sections (Voting, Lottery, Global) - Add AdminLogin.vue with access code gate (20268888) - Add admin.ts store with state persistence - Add admin.types.ts with state machine types - Add router guards for /admin/director-console Voting System Fixes: - Add voting status check before accepting votes (VOTING_CLOSED error) - Fix client to display server error messages - Fix button disabled logic to prevent ambiguity in paused state - Auto-generate userId on connect to fix UNAUTHORIZED error Big Screen Enhancements: - Add LiveVotingView.vue with particle system - Add LotteryMachine.ts with 3-stage animation (Galaxy/Storm/Reveal) - Add useSocketClient.ts composable - Fix MainDisplay.vue SCSS syntax error - Add admin state sync listener in display store Server Updates: - Add admin.service.ts for state management - Add isVotingOpen() and getVotingStatus() methods - Add admin socket event handlers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref, computed, shallowRef } from 'vue';
|
||||
import { ref, computed, shallowRef, watch } from 'vue';
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
import type {
|
||||
ServerToClientEvents,
|
||||
@@ -7,6 +7,8 @@ import type {
|
||||
DrawStartPayload,
|
||||
DrawWinnerPayload,
|
||||
VoteUpdatePayload,
|
||||
AdminState,
|
||||
SystemPhase,
|
||||
} from '@gala/shared/types';
|
||||
import { SOCKET_EVENTS } from '@gala/shared/constants';
|
||||
|
||||
@@ -67,7 +69,7 @@ export const useDisplayStore = defineStore('display', () => {
|
||||
userId: 'screen_main',
|
||||
userName: 'Main Display',
|
||||
role: 'screen',
|
||||
}, () => {});
|
||||
}, () => { });
|
||||
});
|
||||
|
||||
socketInstance.on('disconnect', (reason) => {
|
||||
@@ -107,6 +109,28 @@ export const useDisplayStore = defineStore('display', () => {
|
||||
window.dispatchEvent(new CustomEvent('vote:updated', { detail: data }));
|
||||
});
|
||||
|
||||
// Admin state sync - listen for phase changes from director console
|
||||
socketInstance.on(SOCKET_EVENTS.ADMIN_STATE_SYNC as any, (state: AdminState) => {
|
||||
console.log('[Screen] Admin state sync received:', state.systemPhase);
|
||||
|
||||
// Map SystemPhase to display mode
|
||||
const phaseToMode: Record<SystemPhase, 'idle' | 'voting' | 'draw' | 'results'> = {
|
||||
'IDLE': 'idle',
|
||||
'VOTING': 'voting',
|
||||
'LOTTERY': 'draw',
|
||||
'RESULTS': 'results',
|
||||
};
|
||||
|
||||
const newMode = phaseToMode[state.systemPhase] || 'idle';
|
||||
if (currentMode.value !== newMode) {
|
||||
currentMode.value = newMode;
|
||||
// Emit custom event for App.vue to handle route navigation
|
||||
window.dispatchEvent(new CustomEvent('screen:mode_change', {
|
||||
detail: { mode: newMode, phase: state.systemPhase }
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
socket.value = socketInstance as GalaSocket;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user