Initial ASC app
This commit is contained in:
110
asc/src/context/ScoreContext.js
Normal file
110
asc/src/context/ScoreContext.js
Normal file
@@ -0,0 +1,110 @@
|
||||
// src/context/ScoreContext.js
|
||||
import React, { createContext, useContext, useReducer, useEffect } from 'react';
|
||||
|
||||
// Define action types
|
||||
export const ACTIONS = {
|
||||
ADD_ARROW: 'ADD_ARROW',
|
||||
START_NEW_ROUND: 'START_NEW_ROUND',
|
||||
RESET_GAME: 'RESET_GAME',
|
||||
};
|
||||
|
||||
// Initial state structure
|
||||
const initialState = {
|
||||
currentGame: {
|
||||
gameType: null, // '450' or '300'
|
||||
rounds: [], // Array of rounds
|
||||
totalScore: 0,
|
||||
totalBullseyes: 0,
|
||||
dateStarted: null,
|
||||
},
|
||||
games: [], // Historical games
|
||||
};
|
||||
|
||||
// Reducer function
|
||||
const scoreReducer = (state, action) => {
|
||||
switch (action.type) {
|
||||
case ACTIONS.ADD_ARROW:
|
||||
const { roundIndex, score, isBullseye } = action.payload;
|
||||
const updatedRounds = [...state.currentGame.rounds];
|
||||
|
||||
// Update the specific round
|
||||
if (!updatedRounds[roundIndex]) {
|
||||
updatedRounds[roundIndex] = { arrows: [], total: 0, bullseyes: 0 };
|
||||
}
|
||||
|
||||
updatedRounds[roundIndex] = {
|
||||
...updatedRounds[roundIndex],
|
||||
arrows: [...updatedRounds[roundIndex].arrows, score],
|
||||
total: updatedRounds[roundIndex].total + score,
|
||||
bullseyes: updatedRounds[roundIndex].bullseyes + (isBullseye ? 1 : 0),
|
||||
};
|
||||
|
||||
// Calculate new totals
|
||||
const totalScore = updatedRounds.reduce((sum, round) => sum + round.total, 0);
|
||||
const totalBullseyes = updatedRounds.reduce((sum, round) => sum + round.bullseyes, 0);
|
||||
|
||||
return {
|
||||
...state,
|
||||
currentGame: {
|
||||
...state.currentGame,
|
||||
rounds: updatedRounds,
|
||||
totalScore,
|
||||
totalBullseyes,
|
||||
},
|
||||
};
|
||||
|
||||
case ACTIONS.START_NEW_ROUND:
|
||||
const { gameType } = action.payload;
|
||||
return {
|
||||
...state,
|
||||
currentGame: {
|
||||
gameType,
|
||||
rounds: [],
|
||||
totalScore: 0,
|
||||
totalBullseyes: 0,
|
||||
dateStarted: new Date().toISOString(),
|
||||
},
|
||||
};
|
||||
|
||||
case ACTIONS.RESET_GAME:
|
||||
return {
|
||||
...state,
|
||||
currentGame: initialState.currentGame,
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Create context
|
||||
const ScoreContext = createContext();
|
||||
|
||||
// Context provider component
|
||||
export const ScoreProvider = ({ children }) => {
|
||||
// Load state from localStorage on initial render
|
||||
const [state, dispatch] = useReducer(scoreReducer, initialState, () => {
|
||||
const localData = localStorage.getItem('archeryScores');
|
||||
return localData ? JSON.parse(localData) : initialState;
|
||||
});
|
||||
|
||||
// Save to localStorage whenever state changes
|
||||
useEffect(() => {
|
||||
localStorage.setItem('archeryScores', JSON.stringify(state));
|
||||
}, [state]);
|
||||
|
||||
return (
|
||||
<ScoreContext.Provider value={{ state, dispatch }}>
|
||||
{children}
|
||||
</ScoreContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Custom hook for using the score context
|
||||
export const useScore = () => {
|
||||
const context = useContext(ScoreContext);
|
||||
if (!context) {
|
||||
throw new Error('useScore must be used within a ScoreProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user