diff --git a/asc/package-lock.json b/asc/package-lock.json
index 582319d..0be8485 100644
--- a/asc/package-lock.json
+++ b/asc/package-lock.json
@@ -17,6 +17,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-router-dom": "^7.1.5",
"react-scripts": "^5.0.1",
"web-vitals": "^2.1.4"
}
@@ -4552,6 +4553,12 @@
"@types/node": "*"
}
},
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "license": "MIT"
+ },
"node_modules/@types/eslint": {
"version": "8.56.12",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz",
@@ -16101,6 +16108,55 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz",
+ "integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/cookie": "^0.6.0",
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0",
+ "turbo-stream": "2.4.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.5.tgz",
+ "integrity": "sha512-/4f9+up0Qv92D3bB8iN5P1s3oHAepSGa9h5k6tpTFlixTTskJZwKGhJ6vRJ277tLD1zuaZTt95hyGWV1Z37csQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.1.5"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/react-router/node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
@@ -17035,6 +17091,12 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -18432,6 +18494,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"license": "0BSD"
},
+ "node_modules/turbo-stream": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
+ "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
+ "license": "ISC"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/asc/package.json b/asc/package.json
index 986de28..7e0ac48 100644
--- a/asc/package.json
+++ b/asc/package.json
@@ -12,6 +12,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
+ "react-router-dom": "^7.1.5",
"react-scripts": "^5.0.1",
"web-vitals": "^2.1.4"
},
diff --git a/asc/src/App.js b/asc/src/App.js
index 04bf3da..498b2aa 100644
--- a/asc/src/App.js
+++ b/asc/src/App.js
@@ -1,10 +1,13 @@
// src/App.js
import React, { useState, useMemo, useEffect } from 'react';
-import { CssBaseline, Container, ThemeProvider, createTheme, IconButton } from '@mui/material';
-import { Brightness4, Brightness7 } from '@mui/icons-material';
+import { CssBaseline, Container, IconButton } from '@mui/material';
+import { ThemeProvider, createTheme } from '@mui/material/styles';
+import { BrowserRouter as Router, Route, Routes } 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() {
// Initialize theme from localStorage or default to 'light'
@@ -12,7 +15,7 @@ function App() {
try {
const savedMode = localStorage.getItem('themeMode');
return savedMode || 'light';
- } catch {
+ } catch (e) {
return 'light';
}
});
@@ -69,11 +72,15 @@ function App() {
>
{mode === 'dark' ? : }
- {!gameStarted ? (
- setGameStarted(true)} />
- ) : (
-
- )}
+
+
+ setGameStarted(true)} /> : }
+ />
+ } />
+
+
@@ -81,3 +88,4 @@ function App() {
}
export default App;
+
diff --git a/asc/src/components/GameSummary.js b/asc/src/components/GameSummary.js
new file mode 100644
index 0000000..c5ab3a4
--- /dev/null
+++ b/asc/src/components/GameSummary.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import { useScore } from '../context/ScoreContext';
+import { Button, Grid, Typography, Box } from '@mui/material';
+import { useNavigate } from 'react-router-dom';
+
+const GameSummary = () => {
+ const { state } = useScore();
+ const navigate = useNavigate();
+
+ const handleNewGame = () => {
+ navigate('/');
+ };
+
+ return (
+ <>
+ {/* Main Menu Button */}
+
+
+
+
+
+
+
+ Game Summary
+
+
+
+ {/* Total score */}
+
+
+ Total Score: {state.currentGame.totalScore}
+
+
+ Total Bullseyes: {state.currentGame.totalBullseyes}
+
+
+
+ {/* New game button */}
+
+
+
+
+ >
+ );
+};
+
+export default GameSummary;
+
diff --git a/asc/src/components/ScoreTracker.js b/asc/src/components/ScoreTracker.js
index b633f0e..bbe62f8 100644
--- a/asc/src/components/ScoreTracker.js
+++ b/asc/src/components/ScoreTracker.js
@@ -2,21 +2,43 @@
import React, { useState } from 'react';
import { useScore, ACTIONS } from '../context/ScoreContext';
import { Button, Grid, Typography, TextField, Box } from '@mui/material';
+import { useNavigate } from 'react-router-dom'; // <-- Add this import
const ScoreTracker = () => {
const { state, dispatch } = useScore();
- const [arrowScores, setArrowScores] = useState(['', '', '', '', '']);
+ const navigate = useNavigate(); // <-- Define the navigate hook
const gameType = state.currentGame.gameType;
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];
+ const updatedScores = [...arrowScores];
updatedScores[index] = value;
setArrowScores(updatedScores);
};
+ // Handle Add Round, Game Completion, etc.
+
+ const handleGameEnd = () => {
+ // Navigate to the summary page after the game ends
+ navigate('/summary');
+ };
+
+ // Rest of your component code (Rendering, Button handlers, etc.)
+};
+
+ // Handle adding a round
const handleAddRound = () => {
+ // Check if the max number of rounds is reached
+ if (state.currentGame.rounds.length >= maxRounds) {
+ navigate('/summary'); // Navigate to summary page when max rounds are reached
+ return;
+ }
+
+ // Validate Scores
const valid = arrowScores.slice(0, maxArrowsPerRound).every(score =>
(score >= 0 && score <= maxScore) || score.toUpperCase() === 'X'
);
@@ -25,17 +47,23 @@ const ScoreTracker = () => {
return;
}
- arrowScores.slice(0, maxArrowsPerRound).forEach((score) => {
+ // Add arrows to the current round
+ const roundArrows = arrowScores.slice(0, maxArrowsPerRound).map((score) => {
const arrowScore = score.toUpperCase() === 'X' ? maxScore : parseInt(score, 10);
- dispatch({
- type: ACTIONS.ADD_ARROW,
- payload: {
- roundIndex: state.currentGame.rounds.length,
- score: arrowScore,
- isBullseye: score.toUpperCase() === 'X',
- },
- });
+ return {
+ score: arrowScore,
+ isBullseye: score.toUpperCase() === 'X',
+ };
});
+
+ dispatch({
+ type: ACTIONS.ADD_ROUND,
+ payload: {
+ roundIndex: state.currentGame.rounds.length,
+ arrows: roundArrows,
+ },
+ });
+
setArrowScores(['', '', '', '', '']);
};
@@ -120,6 +148,13 @@ const ScoreTracker = () => {
>
X
+
+
@@ -150,19 +185,24 @@ const ScoreTracker = () => {
Bullseyes: {state.currentGame.totalBullseyes}
-
- {/* Round history */}
-
-
- {state.currentGame.rounds.map((round, roundIndex) => (
-
- Round {roundIndex + 1}: {round.arrows.join(', ')}
- (Total: {round.total}, Bullseyes: {round.bullseyes})
-
- ))}
-
-
-
+{/* Round history */}
+
+
+ {state.currentGame && state.currentGame.rounds && state.currentGame.rounds.length > 0 ? (
+ state.currentGame.rounds.map((round, roundIndex) => (
+
+ Round {roundIndex + 1}: {round.arrows ? round.arrows.join(', ') : 'No arrows'}
+ (Total: {round.total || 0}, Bullseyes: {round.bullseyes || 0})
+
+ ))
+ ) : (
+
+ No rounds played yet.
+
+ )}
+
+
+
);
};