diff --git a/asc/src/App.js b/asc/src/App.js
index 7f60fac..7c65503 100644
--- a/asc/src/App.js
+++ b/asc/src/App.js
@@ -1,16 +1,14 @@
import React, { useState, useMemo, useEffect } from 'react';
import { CssBaseline, Container, IconButton } from '@mui/material';
-import { ThemeProvider, createTheme } from '@mui/material/styles'; // <-- Import createTheme
-import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
-import { ScoreProvider } from './context/ScoreContext'; // <-- Import ScoreProvider
-
-import MainMenu from './components/MainMenu';
+import { ThemeProvider, createTheme } from '@mui/material/styles';
+import { Brightness7, Brightness4 } from '@mui/icons-material';
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import { ScoreProvider } from './context/ScoreContext';
import GameSetup from './components/GameSetup';
import ScoreTracker from './components/ScoreTracker';
-import GameSummary from './components/GameSummary';
-import { Brightness7, Brightness4 } from '@mui/icons-material';
-function App() {
+const App = () => {
+ // Theme state
const [mode, setMode] = useState(() => {
try {
const savedMode = localStorage.getItem('themeMode');
@@ -42,36 +40,36 @@ function App() {
return (
-
-
-
+
+
- {mode === 'dark' ? : }
-
-
+ {/* Theme Toggle Button */}
+
+ {mode === 'dark' ? : }
+
+
+ {/* Routes for navigation */}
- } /> {/* MainMenu as the default page */}
- } />
- } />
- } />
+ } />
+ } />
-
-
+
+
);
-}
+};
export default App;
-
diff --git a/asc/src/AppRouter.js b/asc/src/AppRouter.js
index a0cd59a..f04075e 100644
--- a/asc/src/AppRouter.js
+++ b/asc/src/AppRouter.js
@@ -1,60 +1,75 @@
// File: src/AppRouter.js
-import React, { useState } from 'react';
-import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
+import React from 'react';
+import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
import { Container, IconButton } from '@mui/material';
import { Brightness7, Brightness4 } from '@mui/icons-material';
import GameSetup from './components/GameSetup';
import ScoreTracker from './components/ScoreTracker';
import GameSummary from './components/GameSummary';
import { useTheme } from './context/ThemeContext';
+import { useScore } from './context/ScoreContext';
+// The main router component
function AppRouter() {
const { mode, toggleTheme } = useTheme();
+ const { state } = useScore();
- const [gameStarted, setGameStarted] = useState(() => {
- try {
- const savedGame = localStorage.getItem('archeryScores');
- if (savedGame) {
- const parsedGame = JSON.parse(savedGame);
- return parsedGame.currentGame && parsedGame.currentGame.gameType !== null;
- }
- } catch {
- return false;
- }
- return false;
- });
+ // Check if a game is currently in progress
+ const isGameActive = () => {
+ return state.currentGame && state.currentGame.gameType !== null;
+ };
return (
-
-
+
- {mode === 'dark' ? : }
-
-
+
+ {mode === 'dark' ? : }
+
+
+ {/* Home route - redirects to score if a game is active */}
setGameStarted(true)} />
- :
+ isGameActive() ?
+ :
+
}
/>
- } />
+
+ {/* Explicit score tracker route */}
+ :
+
+ }
+ />
+
+ {/* Summary route */}
+ }
+ />
+
+ {/* Catch-all route for any invalid URLs */}
+ } />
-
-
+
+
);
}
diff --git a/asc/src/AppRouter.old b/asc/src/AppRouter.old
new file mode 100644
index 0000000..a0cd59a
--- /dev/null
+++ b/asc/src/AppRouter.old
@@ -0,0 +1,61 @@
+// File: src/AppRouter.js
+import React, { useState } from 'react';
+import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
+import { Container, IconButton } from '@mui/material';
+import { Brightness7, Brightness4 } from '@mui/icons-material';
+import GameSetup from './components/GameSetup';
+import ScoreTracker from './components/ScoreTracker';
+import GameSummary from './components/GameSummary';
+import { useTheme } from './context/ThemeContext';
+
+function AppRouter() {
+ const { mode, toggleTheme } = useTheme();
+
+ const [gameStarted, setGameStarted] = useState(() => {
+ try {
+ const savedGame = localStorage.getItem('archeryScores');
+ if (savedGame) {
+ const parsedGame = JSON.parse(savedGame);
+ return parsedGame.currentGame && parsedGame.currentGame.gameType !== null;
+ }
+ } catch {
+ return false;
+ }
+ return false;
+ });
+
+ return (
+
+
+ {mode === 'dark' ? : }
+
+
+
+ setGameStarted(true)} />
+ :
+ }
+ />
+ } />
+
+
+
+ );
+}
+
+export default AppRouter;
diff --git a/asc/src/ScoreContext.js b/asc/src/ScoreContext.js
new file mode 100644
index 0000000..2045e9f
--- /dev/null
+++ b/asc/src/ScoreContext.js
@@ -0,0 +1,118 @@
+// File: src/context/ScoreContext.js
+import React, { createContext, useContext, useReducer, useEffect } from 'react';
+
+// Action types
+export const ACTIONS = {
+ START_GAME: 'start_game',
+ END_GAME: 'end_game',
+ SAVE_GAME: 'save_game',
+ ADD_END: 'add_end', // Changed from UPDATE_SCORE to ADD_END to match ScoreTracker
+ // Add other actions as needed
+};
+
+// Initial state
+const initialState = {
+ currentGame: null,
+ gameHistory: [],
+ // Add other state properties as needed
+};
+
+// Get saved state from localStorage if available
+const getSavedState = () => {
+ try {
+ const savedState = localStorage.getItem('archeryScores');
+ if (savedState) {
+ return JSON.parse(savedState);
+ }
+ } catch (error) {
+ console.error('Error loading saved game state:', error);
+ }
+ return initialState;
+};
+
+// Reducer function
+const scoreReducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.START_GAME:
+ const newGame = {
+ gameType: action.payload.gameType,
+ isLeague: action.payload.isLeague,
+ targetFace: action.payload.targetFace,
+ dateStarted: new Date().toISOString(),
+ ends: [], // Changed from scores to ends to match ScoreTracker expectations
+ // Add other game properties as needed
+ };
+
+ return {
+ ...state,
+ currentGame: newGame,
+ };
+
+ case ACTIONS.END_GAME:
+ return {
+ ...state,
+ currentGame: null,
+ };
+
+ case ACTIONS.SAVE_GAME:
+ // Only save if there's a current game
+ if (!state.currentGame) return state;
+
+ const completedGame = {
+ ...state.currentGame,
+ dateCompleted: new Date().toISOString(),
+ };
+
+ return {
+ ...state,
+ gameHistory: [...state.gameHistory, completedGame],
+ };
+
+ case ACTIONS.ADD_END: // Changed from UPDATE_SCORE to ADD_END
+ // Handle adding a new end
+ if (!state.currentGame) return state;
+
+ return {
+ ...state,
+ currentGame: {
+ ...state.currentGame,
+ ends: [...(state.currentGame.ends || []), action.payload], // Updated to use ends instead of scores
+ }
+ };
+
+ default:
+ return state;
+ }
+};
+
+// Create context
+const ScoreContext = createContext();
+
+// Provider component
+export const ScoreProvider = ({ children }) => {
+ const [state, dispatch] = useReducer(scoreReducer, getSavedState());
+
+ // Save state to localStorage whenever it changes
+ useEffect(() => {
+ try {
+ localStorage.setItem('archeryScores', JSON.stringify(state));
+ } catch (error) {
+ console.error('Error saving game state:', error);
+ }
+ }, [state]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+// Custom hook for using the score context
+export const useScore = () => {
+ const context = useContext(ScoreContext);
+ if (context === undefined) {
+ throw new Error('useScore must be used within a ScoreProvider');
+ }
+ return context;
+};
diff --git a/asc/src/components/GameSetup.js b/asc/src/components/GameSetup.js
index 54cf74a..026d8f2 100644
--- a/asc/src/components/GameSetup.js
+++ b/asc/src/components/GameSetup.js
@@ -1,216 +1,215 @@
-import React, { useState } from 'react';
-import { useScore, ACTIONS } from '../context/ScoreContext';
-import { Button, Grid, Typography, TextField, Box } from '@mui/material';
+// File: src/components/GameSetup.js
+import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
+import {
+ Button,
+ Card,
+ CardContent,
+ CardHeader,
+ Grid,
+ Typography,
+ FormControl,
+ FormControlLabel,
+ FormLabel,
+ Radio,
+ RadioGroup,
+ Divider
+} from '@mui/material';
+import { useScore, ACTIONS } from '../context/ScoreContext';
-const ScoreTracker = () => {
- const { state, dispatch } = useScore();
+const GameSetup = () => {
+ const { dispatch } = useScore();
const navigate = useNavigate();
-
- const gameType = state.currentGame.gameType;
+ const [selectedGameType, setSelectedGameType] = useState('');
+ const [selectedTargetFace, setSelectedTargetFace] = useState('standard');
+ const [isLeague, setIsLeague] = useState(false);
- // Determine the number of arrows per round based on game type
- const maxArrowsPerRound = gameType === '450' ? 3 : 5;
- const maxScore = gameType === '450' ? 10 : 5;
- const maxRounds = gameType === '450' ? 16 : 12;
-
- const [arrowScores, setArrowScores] = useState(Array(maxArrowsPerRound).fill(''));
-
- const handleScoreChange = (index, value) => {
- const updatedScores = [...arrowScores];
- updatedScores[index] = value;
- setArrowScores(updatedScores);
+ // For debugging - will show in browser console
+ useEffect(() => {
+ console.log("GameSetup.js: League mode state:", isLeague);
+ }, [isLeague]);
+
+ const handleGameTypeSelect = (gameType) => {
+ console.log("GameSetup.js: Setting game type to:", gameType);
+ setSelectedGameType(gameType);
+ setSelectedTargetFace('standard'); // Reset to standard when game type changes
};
- const handleAddRound = () => {
- const valid = arrowScores.slice(0, maxArrowsPerRound).every(score =>
- (score >= 0 && score <= maxScore) || score.toUpperCase() === 'X'
- );
+ const handleGameModeChange = (event) => {
+ // Direct conversion to boolean using === comparison
+ const leagueMode = event.target.value === "league";
+ console.log("GameSetup.js: Setting isLeague to:", leagueMode);
+ setIsLeague(leagueMode);
+ };
+
+ const startGame = () => {
+ console.log("GameSetup.js: Start Game button clicked");
+ console.log("GameSetup.js: Current state:", {
+ selectedGameType,
+ isLeague,
+ selectedTargetFace
+ });
- if (!valid) {
- alert(`Please enter valid scores between 0-${maxScore} or X for bullseyes.`);
+ if (!selectedGameType) {
+ console.log("GameSetup.js: No game type selected, returning early");
return;
}
-
- const roundArrows = arrowScores.slice(0, maxArrowsPerRound).map((score) => {
- const arrowScore = score.toUpperCase() === 'X' ? maxScore : parseInt(score, 10);
- return {
- score: arrowScore,
- isBullseye: score.toUpperCase() === 'X',
- };
- });
-
- const roundTotal = roundArrows.reduce((sum, arrow) => sum + arrow.score, 0);
-
- dispatch({
- type: ACTIONS.ADD_ROUND,
- payload: {
- roundIndex: state.currentGame.rounds.length,
- arrows: roundArrows,
- total: roundTotal
- },
- });
-
- setArrowScores(Array(maxArrowsPerRound).fill(''));
-
- if (state.currentGame.rounds.length >= maxRounds - 1) {
- navigate('/summary');
+
+ try {
+ console.log("GameSetup.js: Dispatching START_GAME action");
+ dispatch({
+ type: ACTIONS.START_GAME,
+ payload: {
+ gameType: selectedGameType,
+ isLeague: isLeague,
+ targetFace: selectedTargetFace
+ }
+ });
+ console.log("GameSetup.js: Dispatch completed successfully");
+
+ // Use React Router navigation
+ navigate('/score');
+
+ } catch (error) {
+ console.error("GameSetup.js: Error in startGame function:", error);
}
};
- const handleMainMenu = () => {
- dispatch({ type: ACTIONS.RESET_GAME });
- navigate('/');
- };
+ // Determine if we should show target face options
+ const showTargetFaceOptions = selectedGameType !== '';
return (
-
- {/* Main Menu Button */}
-
-
-
+
+
+
+
+
+
+
+
+ Select your game type:
+
+
+
+
+
+
+
+
-
-
- {gameType} Round - Round {state.currentGame.rounds.length + 1}
-
-
+ {showTargetFaceOptions && (
+ <>
+
+
+
+ Game Settings:
+
+
+
+ {/* Game Mode Selection */}
+
+
+ Game Mode
+
+ }
+ label="Practice"
+ />
+ }
+ label="League"
+ />
+
+
+
+
+ {/* Target Face Selection */}
+
+
+ Target Face
+ setSelectedTargetFace(e.target.value)}
+ >
+ }
+ label="Standard"
+ />
+ {selectedGameType === '300' && (
+ }
+ label="5-Spot"
+ />
+ )}
+ {selectedGameType === '450' && (
+ }
+ label="3-Spot"
+ />
+ )}
+
+
+
- {/* Score input section */}
-
-
- {Array.from({ length: maxArrowsPerRound }).map((_, index) => (
- handleScoreChange(index, e.target.value)}
- placeholder="0"
- size="small"
- sx={{
- width: '60px',
- '& .MuiInputBase-input': {
- padding: '8px',
- textAlign: 'center'
- }
- }}
- inputProps={{
- maxLength: 1,
- style: { textAlign: 'center' }
- }}
- />
- ))}
-
-
-
- {/* Score buttons */}
-
-
- {Array.from({ length: maxScore + 1 }).map((_, i) => (
-
- ))}
-
-
-
-
- {/* Control buttons */}
-
-
-
-
-
-
-
- {/* Scores display */}
-
-
- Total Score: {state.currentGame.totalScore} |
- Bullseyes: {state.currentGame.totalBullseyes}
-
-
-
- {/* Round history */}
-
-
- {state.currentGame.rounds.length > 0 ? (
- state.currentGame.rounds.map((round, roundIndex) => (
-
- Round {roundIndex + 1}: {round.arrows.map(arrow => arrow.score).join(', ')}
- (Total: {round.total}, Bullseyes: {round.bullseyes})
-
- ))
- ) : (
-
- No rounds played yet.
-
- )}
-
+
+
+
+ >
+ )}
+
+
+
);
};
-export default ScoreTracker;
-
+export default GameSetup;
diff --git a/asc/src/components/GameSetup.old b/asc/src/components/GameSetup.old
new file mode 100644
index 0000000..8873b27
--- /dev/null
+++ b/asc/src/components/GameSetup.old
@@ -0,0 +1,219 @@
+// filename: GameSetup.js
+import React, { useState, useEffect } from 'react';
+import {
+ Button,
+ Card,
+ CardContent,
+ CardHeader,
+ Grid,
+ Typography,
+ FormControl,
+ FormControlLabel,
+ FormLabel,
+ Radio,
+ RadioGroup,
+ Divider
+} from '@mui/material';
+import { useScore, ACTIONS } from '../context/ScoreContext';
+
+
+
+
+const GameSetup = ({ onGameStart }) => {
+ const { dispatch } = useScore();
+ const [selectedGameType, setSelectedGameType] = useState('');
+ const [selectedTargetFace, setSelectedTargetFace] = useState('standard');
+ const [isLeague, setIsLeague] = useState(false);
+
+ // For debugging - will show in browser console
+ useEffect(() => {
+ console.log("GameSetup.js: League mode state:", isLeague);
+ }, [isLeague]);
+
+ const handleGameTypeSelect = (gameType) => {
+ console.log("GameSetup.js: Setting game type to:", gameType);
+ setSelectedGameType(gameType);
+ setSelectedTargetFace('standard'); // Reset to standard when game type changes
+ };
+
+ const handleGameModeChange = (event) => {
+ // Direct conversion to boolean using === comparison
+ const leagueMode = event.target.value === "league";
+ console.log("GameSetup.js: Setting isLeague to:", leagueMode);
+ setIsLeague(leagueMode);
+ };
+
+ const startGame = () => {
+ console.log("GameSetup.js: Start Game button clicked");
+ console.log("GameSetup.js: Current state:", {
+ selectedGameType,
+ isLeague,
+ selectedTargetFace
+ });
+
+ if (!selectedGameType) {
+ console.log("GameSetup.js: No game type selected, returning early");
+ return;
+ }
+
+ try {
+ console.log("GameSetup.js: Dispatching START_GAME action");
+ dispatch({
+ type: ACTIONS.START_GAME,
+ payload: {
+ gameType: selectedGameType,
+ isLeague: isLeague,
+ targetFace: selectedTargetFace
+ }
+ });
+ console.log("GameSetup.js: Dispatch completed successfully");
+
+ if (typeof onGameStart === 'function') {
+ console.log("GameSetup.js: Calling onGameStart function");
+ onGameStart();
+ } else {
+ console.log("GameSetup.js: onGameStart is not a function or is undefined:", onGameStart);
+ }
+ } catch (error) {
+ console.error("GameSetup.js: Error in startGame function:", error);
+ }
+ };
+
+ // Determine if we should show target face options
+ const showTargetFaceOptions = selectedGameType !== '';
+
+ return (
+
+
+
+
+
+
+
+
+ Select your game type:
+
+
+
+
+
+
+
+
+
+ {showTargetFaceOptions && (
+ <>
+
+
+
+ Game Settings:
+
+
+
+ {/* Game Mode Selection */}
+
+
+ Game Mode
+
+ }
+ label="Practice"
+ />
+ }
+ label="League"
+ />
+
+
+
+
+ {/* Target Face Selection */}
+
+
+ Target Face
+ setSelectedTargetFace(e.target.value)}
+ >
+ }
+ label="Standard"
+ />
+ {selectedGameType === '300' && (
+ }
+ label="5-Spot"
+ />
+ )}
+ {selectedGameType === '450' && (
+ }
+ label="3-Spot"
+ />
+ )}
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+ );
+};
+
+export default GameSetup;
diff --git a/asc/src/components/ScoreTracker.js b/asc/src/components/ScoreTracker.js
index 1be2b61..c153744 100644
--- a/asc/src/components/ScoreTracker.js
+++ b/asc/src/components/ScoreTracker.js
@@ -1,156 +1,319 @@
import React, { useState, useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
import {
Button,
Card,
CardContent,
CardHeader,
- FormControl,
- FormControlLabel,
- RadioGroup,
- Radio,
Grid,
Typography,
- Select,
- MenuItem
+ Box,
+ Paper,
+ IconButton,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Divider,
+ ButtonGroup
} from '@mui/material';
+import { Remove } from '@mui/icons-material';
import { useScore, ACTIONS } from '../context/ScoreContext';
-const GameSetup = ({ onGameStart }) => {
- const { dispatch } = useScore();
-
- const [selectedGameType, setSelectedGameType] = useState('');
- const [isLeague, setIsLeague] = useState(false); // This tracks if it's a league game
- const [selectedTargetFace, setSelectedTargetFace] = useState('single'); // Assuming single as default target face
-
- // Log isLeague to verify if it changes correctly
+const ScoreTracker = () => {
+ const { state, dispatch } = useScore();
+ const navigate = useNavigate();
+
+ // Local state for the current end
+ const [currentEnd, setCurrentEnd] = useState([]);
+
+ // Check if we have an active game, if not redirect to setup
useEffect(() => {
- console.log("Game mode isLeague:", isLeague); // Check this in the console
- }, [isLeague]);
-
- const handleGameModeChange = (event) => {
- const leagueMode = event.target.value === "league";
- setIsLeague(leagueMode); // Update isLeague based on user selection
+ if (!state.currentGame || !state.currentGame.gameType) {
+ navigate('/');
+ }
+ }, [state.currentGame, navigate]);
+
+ // Handle adding an arrow score
+ const handleAddArrow = (score) => {
+ // Add to current end
+ setCurrentEnd([...currentEnd, score]);
};
-
- const handleTargetFaceChange = (event) => {
- setSelectedTargetFace(event.target.value);
+
+ // Handle removing the last arrow
+ const handleRemoveArrow = () => {
+ if (currentEnd.length > 0) {
+ const newEnd = [...currentEnd];
+ newEnd.pop();
+ setCurrentEnd(newEnd);
+ }
};
-
- const startGame = () => {
- if (!selectedGameType) return;
-
- // Log the values to ensure they're correct
- console.log("Starting game with settings:", {
- gameType: selectedGameType,
- isLeague: isLeague,
- targetFace: selectedTargetFace
- });
-
+
+ // Calculate total for current end
+ const calculateEndTotal = (arrows) => {
+ return arrows.reduce((total, arrow) => {
+ if (arrow.toUpperCase() === 'X') {
+ return total + 10;
+ } else if (arrow.toUpperCase() === 'M') {
+ return total;
+ } else {
+ return total + parseInt(arrow);
+ }
+ }, 0);
+};
+
+ // Get button color based on score
+ const getButtonColor = (score) => {
+ switch(score) {
+ case 'X':
+ return { bgcolor: '#FF9800', color: 'white' }; // Orange
+ case '10':
+ return { bgcolor: '#9C27B0', color: 'white' }; // Purple
+ case '9':
+ case '8':
+ return { bgcolor: '#2196F3', color: 'white' }; // Blue
+ case '7':
+ case '6':
+ case '5':
+ case '4':
+ case '3':
+ case '2':
+ case '1':
+ return { bgcolor: '#4CAF50', color: 'white' }; // Green
+ case 'M':
+ return { bgcolor: '#9E9E9E', color: 'white' }; // Gray
+ default:
+ return { bgcolor: 'default' };
+ }
+ };
+
+ // Handle saving the current end
+ const handleSaveEnd = () => {
+ if (currentEnd.length > 0) {
+ // Create the end object
+ const endObject = {
+ arrows: [...currentEnd],
+ total: calculateEndTotal(currentEnd),
+ timestamp: new Date().toISOString()
+ };
+
+ // Dispatch to context
+ dispatch({
+ type: ACTIONS.ADD_END,
+ payload: endObject
+ });
+
+ // Clear current end
+ setCurrentEnd([]);
+ }
+ };
+
+ // Handle ending the game
+ const handleEndGame = () => {
+ // Save final scores to history first
dispatch({
- type: ACTIONS.START_GAME,
- payload: {
- gameType: selectedGameType,
- isLeague: isLeague, // Pass the league/practice mode correctly
- targetFace: selectedTargetFace
- }
+ type: ACTIONS.SAVE_GAME,
});
- onGameStart();
+
+ // Then end the current game
+ dispatch({
+ type: ACTIONS.END_GAME,
+ });
+
+ // Navigate to setup page
+ navigate('/');
};
+
+ // Early return if no game is active
+ if (!state.currentGame || !state.currentGame.gameType) {
+ return null; // Will be redirected by useEffect
+ }
+ // Get the number of arrows per end based on game type
+ const arrowsPerEnd = state.currentGame.gameType === '450' ? 6 : 5;
+
+ // Score button values
+ const scoreButtons = ['X', '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', 'M'];
+
return (
-
-
+
+
-
-
-
-
- Select your game type:
+
+ Target Face: {state.currentGame.targetFace || 'Standard'}
+
+
+ {/* Current game stats */}
+
+
+
+ Current Score: {state.currentGame.ends?.reduce((total, end) => total + end.total, 0) || 0}
-
-
-
-
-
-
-
-
- {/* Select League or Practice Mode */}
-
-
-
- Select game mode:
-
-
+ Ends Completed: {state.currentGame.ends?.length || 0}
+
+
+
+
+ {/* Score input section */}
+
+
+ Score Current End
+
+
+ {/* Score buttons */}
+
+
+ {scoreButtons.map((score) => {
+ const colorStyle = getButtonColor(score);
+ return (
+
+ );
+ })}
+
+
- }
- label="Practice"
- />
- }
- label="League"
- />
-
-
-
-
- {/* Target face selection */}
-
-
-
- Select target face:
-
-
+
+
+
+
+ {/* Current end display */}
+
+ {currentEnd.map((arrow, index) => {
+ let bgColor;
+ if (arrow.toUpperCase() === 'X') bgColor = '#FF9800'; // Orange
+ else if (arrow.toUpperCase() === '10') bgColor = '#9C27B0'; // Purple
+ else if (['9', '8'].includes(arrow)) bgColor = '#2196F3'; // Blue
+ else if (['7', '6', '5', '4', '3', '2', '1'].includes(arrow)) bgColor = '#4CAF50'; // Green
+ else if (arrow.toUpperCase() === 'M') bgColor = '#9E9E9E'; // Gray
+ else bgColor = 'default';
+
+ return (
+
+ {arrow.toUpperCase()}
+
+ );
+ })}
+ {Array(arrowsPerEnd - currentEnd.length).fill(0).map((_, index) => (
+
-
-
-
-
-
-
- {/* Start Game Button */}
-
-
-
+
+
+
+
+
+ {/* Previous ends display */}
+ {(state.currentGame.ends?.length > 0) && (
+
+
+ Previous Ends
+
+
+
+
+
+ End
+ Arrows
+ Total
+ Running Total
+
+
+
+ {state.currentGame.ends.map((end, endIndex) => {
+ const runningTotal = state.currentGame.ends
+ .slice(0, endIndex + 1)
+ .reduce((total, e) => total + e.total, 0);
+
+ return (
+
+ {endIndex + 1}
+
+ {end.arrows.join(', ')}
+
+ {end.total}
+ {runningTotal}
+
+ );
+ })}
+
+
+
+
+ )}
+
+
+ End Game
+
@@ -158,5 +321,4 @@ const GameSetup = ({ onGameStart }) => {
);
};
-export default GameSetup;
-
+export default ScoreTracker;