86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
import { create } from 'zustand'
|
|
import type { MilitarySituation } from '@/data/mockData'
|
|
import { INITIAL_MOCK_DATA } from '@/data/mockData'
|
|
import { fetchSituation } from '@/api/situation'
|
|
import { connectSituationWebSocket } from '@/api/websocket'
|
|
import { useStatsStore } from './statsStore'
|
|
|
|
interface SituationState {
|
|
situation: MilitarySituation
|
|
isConnected: boolean
|
|
lastError: string | null
|
|
isLoading: boolean
|
|
setSituation: (situation: MilitarySituation) => void
|
|
fetchAndSetSituation: () => Promise<void>
|
|
setConnected: (connected: boolean) => void
|
|
setLastError: (error: string | null) => void
|
|
}
|
|
|
|
export const useSituationStore = create<SituationState>((set) => ({
|
|
situation: INITIAL_MOCK_DATA,
|
|
isConnected: false,
|
|
lastError: null,
|
|
isLoading: false,
|
|
|
|
setSituation: (situation) => set({ situation }),
|
|
|
|
fetchAndSetSituation: async () => {
|
|
set({ isLoading: true, lastError: null })
|
|
try {
|
|
const situation = await fetchSituation()
|
|
set({ situation })
|
|
} catch (err) {
|
|
set({
|
|
lastError: err instanceof Error ? err.message : 'Failed to fetch situation',
|
|
})
|
|
} finally {
|
|
set({ isLoading: false })
|
|
}
|
|
},
|
|
|
|
setConnected: (isConnected) => set({ isConnected }),
|
|
|
|
setLastError: (lastError) => set({ lastError }),
|
|
}))
|
|
|
|
export function fetchAndSetSituation(): Promise<void> {
|
|
return useSituationStore.getState().fetchAndSetSituation()
|
|
}
|
|
|
|
let disconnectWs: (() => void) | null = null
|
|
let pollInterval: ReturnType<typeof setInterval> | null = null
|
|
|
|
const POLL_INTERVAL_MS = 3000
|
|
|
|
function pollSituation() {
|
|
fetchSituation()
|
|
.then((situation) => useSituationStore.getState().setSituation(situation))
|
|
.catch(() => {})
|
|
}
|
|
|
|
export function startSituationWebSocket(): () => void {
|
|
useSituationStore.getState().setLastError(null)
|
|
|
|
disconnectWs = connectSituationWebSocket((payload) => {
|
|
const { situation, stats } = payload as { situation?: MilitarySituation; stats?: { viewers?: number; cumulative?: number; feedbackCount?: number; shareCount?: number } }
|
|
useSituationStore.getState().setConnected(true)
|
|
if (situation) useSituationStore.getState().setSituation(situation)
|
|
if (stats) useStatsStore.getState().setStats(stats)
|
|
})
|
|
|
|
pollSituation()
|
|
pollInterval = setInterval(pollSituation, POLL_INTERVAL_MS)
|
|
|
|
return stopSituationWebSocket
|
|
}
|
|
|
|
export function stopSituationWebSocket(): void {
|
|
disconnectWs?.()
|
|
disconnectWs = null
|
|
if (pollInterval) {
|
|
clearInterval(pollInterval)
|
|
pollInterval = null
|
|
}
|
|
useSituationStore.getState().setConnected(false)
|
|
}
|