1+ import React , { createContext , useContext , useMemo , useReducer } from 'react' ;
2+ import type { fullPlayerDataType } from 'types/displayDataTypes' ;
3+
4+ export type LoadStatus = 'idle' | 'loading' | 'ready' | 'error' ;
5+
6+ interface AppState {
7+ status : LoadStatus ;
8+ loadedAt ?: number ;
9+ saveSignature ?: string ;
10+ players : fullPlayerDataType [ ] ;
11+ error ?: string ;
12+ }
13+
14+ const initialState : AppState = {
15+ status : 'idle' ,
16+ players : [ ] ,
17+ } ;
18+
19+ type AppAction =
20+ | { type : 'loadSaveRequested' ; payload ?: { fileName ?: string } }
21+ | { type : 'loadSaveSucceeded' ; payload : { saveSignature : string ; players : fullPlayerDataType [ ] } }
22+ | { type : 'loadSaveFailed' ; payload : { error : string | undefined } }
23+ | { type : 'clearSave' } ;
24+
25+ function appReducer ( state : AppState , action : AppAction ) : AppState {
26+ switch ( action . type ) {
27+ case 'loadSaveRequested' :
28+ return { ...state , status : 'loading' } ;
29+ case 'loadSaveSucceeded' :
30+ return {
31+ status : 'ready' ,
32+ loadedAt : Date . now ( ) ,
33+ saveSignature : action . payload . saveSignature ,
34+ players : action . payload . players ,
35+ } ;
36+ case 'loadSaveFailed' :
37+ return { ...state , status : 'error' , error : action . payload . error ?? undefined } ;
38+ case 'clearSave' :
39+ return { ...initialState } ;
40+ default :
41+ return state ;
42+ }
43+ }
44+
45+ const AppContext = createContext < { state : AppState ; dispatch : React . Dispatch < AppAction > } | undefined > ( undefined ) ;
46+
47+ export const AppProvider : React . FC < React . PropsWithChildren > = ( { children } ) => {
48+ const [ state , dispatch ] = useReducer ( appReducer , initialState ) ;
49+ const value = useMemo ( ( ) => ( { state, dispatch } ) , [ state ] ) ;
50+ return < AppContext . Provider value = { value } > { children } </ AppContext . Provider > ;
51+ } ;
52+
53+ export const useAppStore = ( ) => {
54+ const ctx = useContext ( AppContext ) ;
55+ if ( ! ctx ) throw new Error ( 'useAppStore must be used within AppProvider' ) ;
56+ return ctx ;
57+ } ;
58+
59+ export const useAppSelector = < T , > ( select : ( s : AppState ) => T ) : T => {
60+ const { state } = useAppStore ( ) ;
61+ return select ( state ) ;
62+ } ;
63+
64+ // Example selectors
65+ export const usePlayers = ( ) => useAppSelector ( s => s . players ) ;
66+ export const useLoadStatus = ( ) => useAppSelector ( s => s . status ) ;
67+ export const usePlayerByName = ( name : string ) => useAppSelector ( s => s . players . find ( p => p . playerName === name ) ) ;
0 commit comments