Fix broken routing by unifying game state via Context API
This commit is contained in:
parent
6fc0820831
commit
82cae002f8
8 changed files with 53 additions and 20 deletions
|
|
@ -21,10 +21,13 @@ Mobile-first React web app for tracking Schaffhauser (Jass) card game rounds usi
|
|||
6. History Screen - Game storage and export functionality
|
||||
|
||||
### Development Commands
|
||||
- `npm run dev` - Start development server
|
||||
- `npm run build` - Build production version
|
||||
- `npm run preview` - Preview production build
|
||||
|
||||
### Development Server
|
||||
- A development server is always guaranteed to be running on localhost:5173
|
||||
- **Do not start the development server manually under any circumstances**
|
||||
|
||||
### Camera & Detection
|
||||
- Uses HTML5 Camera API with environment-facing camera preference
|
||||
- Card detection implemented with custom image processing techniques
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
"name": "tschausepp",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"dev": "vite --host 0.0.0.0",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tensorflow/tfjs": "^4.19.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"@tensorflow/tfjs": "^4.19.0"
|
||||
"react-router-dom": "^7.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.5",
|
||||
|
|
|
|||
12
src/App.jsx
12
src/App.jsx
|
|
@ -1,12 +1,20 @@
|
|||
import React from 'react';
|
||||
import { GameStateProvider, useGameStateContext } from './context/GameStateContext';
|
||||
import SetupScreen from './components/Setup/SetupScreen';
|
||||
import CameraScreen from './components/Camera/CameraScreen';
|
||||
import ResultsScreen from './components/Results/ResultsScreen';
|
||||
import HistoryScreen from './components/History/HistoryScreen';
|
||||
import useGameState from './hooks/useGameState';
|
||||
|
||||
const App = () => {
|
||||
const { gameState } = useGameState();
|
||||
return (
|
||||
<GameStateProvider>
|
||||
<AppContent />
|
||||
</GameStateProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const AppContent = () => {
|
||||
const { gameState } = useGameStateContext();
|
||||
|
||||
const renderScreen = () => {
|
||||
switch (gameState.currentScreen) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import React, { useRef, useEffect } from 'react';
|
||||
import { GameState } from '../../types';
|
||||
import useGameState from '../../hooks/useGameState';
|
||||
import { useGameStateContext } from '../../context/GameStateContext';
|
||||
import Detection from '../Detection/Detection';
|
||||
import Assignment from '../Assignment/Assignment';
|
||||
|
||||
const CameraScreen: React.FC = () => {
|
||||
const {
|
||||
gameState,
|
||||
setCurrentScreen,
|
||||
setCameraStream,
|
||||
scanTable,
|
||||
showResults
|
||||
} = useGameState();
|
||||
scanTable
|
||||
} = useGameStateContext();
|
||||
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
|
@ -99,7 +99,7 @@ const CameraScreen: React.FC = () => {
|
|||
<div className="screen camera-screen">
|
||||
<div className="camera-header">
|
||||
<h2>🎥 Round <span>{gameState.currentRound}</span></h2>
|
||||
<button onClick={() => window.location.hash = '#setup'} className="secondary">
|
||||
<button onClick={() => gameState.setCurrentScreen('setup')} className="secondary">
|
||||
End Round
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import { Game } from '../../types';
|
||||
import useGameState from '../../hooks/useGameState';
|
||||
import { useGameStateContext } from '../../context/GameStateContext';
|
||||
|
||||
const HistoryScreen: React.FC = () => {
|
||||
const { gameState, setCurrentScreen } = useGameState();
|
||||
const { gameState, setCurrentScreen } = useGameStateContext();
|
||||
|
||||
const renderHistory = () => {
|
||||
if (!gameState.gameHistory || gameState.gameHistory.length === 0) {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import React from 'react';
|
||||
import { GameState } from '../../types';
|
||||
import useGameState from '../../hooks/useGameState';
|
||||
import { useGameStateContext } from '../../context/GameStateContext';
|
||||
|
||||
const ResultsScreen: React.FC = () => {
|
||||
const {
|
||||
gameState,
|
||||
setCurrentScreen,
|
||||
saveGame
|
||||
} = useGameState();
|
||||
saveGame,
|
||||
setCurrentScreen
|
||||
} = useGameStateContext();
|
||||
|
||||
const calculateScores = () => {
|
||||
// Scoring logic based on card values
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Player, GameState } from '../../types';
|
||||
import useGameState from '../../hooks/useGameState';
|
||||
import { useGameStateContext } from '../../context/GameStateContext';
|
||||
|
||||
const SetupScreen: React.FC = () => {
|
||||
const {
|
||||
|
|
@ -9,7 +9,7 @@ const SetupScreen: React.FC = () => {
|
|||
updateCardValues,
|
||||
addPlayer,
|
||||
startNewGame
|
||||
} = useGameState();
|
||||
} = useGameStateContext();
|
||||
|
||||
const [newPlayerName, setNewPlayerName] = useState('');
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ const SetupScreen: React.FC = () => {
|
|||
<button onClick={startGame} disabled={gameState.players.length < 2}>
|
||||
Start Game
|
||||
</button>
|
||||
<button onClick={() => window.location.hash = '#history'} className="secondary">
|
||||
<button onClick={() => gameState.setCurrentScreen('history')} className="secondary">
|
||||
View History
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
21
src/context/GameStateContext.tsx
Normal file
21
src/context/GameStateContext.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import React, { createContext, useContext } from 'react';
|
||||
import useGameState from '../hooks/useGameState';
|
||||
|
||||
const GameStateContext = createContext<any>(null);
|
||||
|
||||
export const GameStateProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const value = useGameState();
|
||||
return (
|
||||
<GameStateContext.Provider value={value}>
|
||||
{children}
|
||||
</GameStateContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useGameStateContext = () => {
|
||||
const context = useContext(GameStateContext);
|
||||
if (!context) {
|
||||
throw new Error('useGameStateContext must be used within a GameStateProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue