kurita-0: client/src/KuritaState.ts
import clone from 'lodash/clone'
import {createContext, useCallback, useEffect, useReducer} from 'react'
import KuritaClient, {ServerEvent, ServerBracketState} from './KuritaClient'
type KuritaState = {
bracket?: ServerBracketState,
}
type KuritaAction = (
{
type: 'receive-event',
payload: ServerEvent,
} | {
type: 'send-vote',
payload: string,
}
)
const initialState: KuritaState = {
bracket: undefined,
}
function reducer(state: KuritaState, action: KuritaAction): KuritaState {
switch (action.type) {
case 'receive-event':
switch (action.payload.event) {
case 'start':
return {
...state,
bracket: action.payload.bracket,
}
case 'score':
const newState = clone(state)
if (newState.bracket) {
newState.bracket.current.game = action.payload.scores
}
return newState
}
case 'send-vote':
const newState = clone(state)
const votedCompetitor = newState.bracket.current.game.find(
({competitor}) => competitor === action.payload
)
votedCompetitor.score++
return newState
default:
return state
}
}
export function useKurita(client: KuritaClient): [KuritaState, (action: KuritaAction) => void] {
const [state, dispatch] = useReducer(reducer, initialState)
const fullDispatch = useCallback(
(action: KuritaAction) => {
if (action.type === 'send-vote') {
client.send({
event: 'vote',
for: action.payload,
})
}
dispatch(action)
},
[client],
)
useEffect(() => {
const unsubscribe = client.subscribe(event => {
dispatch({type: 'receive-event', payload: event})
})
return unsubscribe
}, [client])
return [state, fullDispatch]
}