mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 09:31:20 -04:00
96 lines
2.5 KiB
JavaScript
96 lines
2.5 KiB
JavaScript
// Barcode Game State Hook
|
|
// Purpose: Subscribes only interested pages/components to barcode game state.
|
|
// Scope: Keeps scanner-game traffic out of the global session tree so unrelated
|
|
// UI pages do not receive or retain barcode game data.
|
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
import { useSocket } from '../context/SocketContext.jsx';
|
|
|
|
const EMPTY_BARCODE_GAME_STATE = {
|
|
activeGameId: null,
|
|
games: [],
|
|
activeGame: null,
|
|
counters: {
|
|
objects: [],
|
|
rovers: [],
|
|
codes: [],
|
|
},
|
|
recentEvents: [],
|
|
};
|
|
|
|
function normalizeState(payload = {}) {
|
|
return {
|
|
...EMPTY_BARCODE_GAME_STATE,
|
|
...(payload && typeof payload === 'object' ? payload : {}),
|
|
games: Array.isArray(payload?.games) ? payload.games : [],
|
|
counters: {
|
|
...EMPTY_BARCODE_GAME_STATE.counters,
|
|
...(payload?.counters && typeof payload.counters === 'object' ? payload.counters : {}),
|
|
},
|
|
recentEvents: Array.isArray(payload?.recentEvents) ? payload.recentEvents : [],
|
|
};
|
|
}
|
|
|
|
export default function useBarcodeGameState() {
|
|
const socket = useSocket();
|
|
const [state, setState] = useState(EMPTY_BARCODE_GAME_STATE);
|
|
|
|
useEffect(() => {
|
|
function handleState(payload = {}) {
|
|
setState(normalizeState(payload));
|
|
}
|
|
|
|
socket.emit('barcodeGame:subscribe', {}, (response = {}) => {
|
|
if (response.state) {
|
|
handleState(response.state);
|
|
}
|
|
});
|
|
socket.on('barcodeGame:state', handleState);
|
|
return () => {
|
|
socket.off('barcodeGame:state', handleState);
|
|
};
|
|
}, [socket]);
|
|
|
|
const voteForGame = useCallback(
|
|
(gameId) =>
|
|
new Promise((resolve, reject) => {
|
|
socket.emit('barcodeGame:vote', { gameId }, (response = {}) => {
|
|
if (response.error) {
|
|
reject(new Error(response.error));
|
|
return;
|
|
}
|
|
if (response.state) {
|
|
setState(normalizeState(response.state));
|
|
}
|
|
resolve(response);
|
|
});
|
|
}),
|
|
[socket],
|
|
);
|
|
|
|
const resetActiveGame = useCallback(
|
|
() =>
|
|
new Promise((resolve, reject) => {
|
|
socket.emit('barcodeGame:resetActive', {}, (response = {}) => {
|
|
if (response.error) {
|
|
reject(new Error(response.error));
|
|
return;
|
|
}
|
|
if (response.state) {
|
|
setState(normalizeState(response.state));
|
|
}
|
|
resolve(response);
|
|
});
|
|
}),
|
|
[socket],
|
|
);
|
|
|
|
return useMemo(
|
|
() => ({
|
|
state,
|
|
resetActiveGame,
|
|
voteForGame,
|
|
}),
|
|
[resetActiveGame, state, voteForGame],
|
|
);
|
|
}
|