refactor(matching): integrate game type into nav, remove redundant header

Removed redundant in-game header and integrated all game info into the nav bar:

**Changes:**
- MemoryPairsGame now sets navTitle/navEmoji based on gameType:
  - Complement Pairs (🤝) for complement-pairs mode
  - Abacus Match (🧮) for abacus-numeral mode
- Removed redundant game header from GamePhase that showed:
  - Game type emoji and name (now in nav)
  - Player count "⚔️ 3Ps" (visible via player avatars in nav)
  - New Game button (already in nav dropdown menu)
- Cleaned up unused imports and variables

**Result:**
- No duplicate information displayed
- Cleaner game interface with more space for gameplay
- All game/room info consolidated in the persistent nav bar

Applied to both /games/matching and /arcade/matching versions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-10-11 10:57:37 -05:00
parent c13da68a98
commit 389df29dc3
4 changed files with 16 additions and 168 deletions

View File

@@ -1,26 +1,11 @@
'use client'
import { css } from '../../../../../styled-system/css'
import { useGameMode } from '../../../../contexts/GameModeContext'
import { pluralizeWord } from '../../../../utils/pluralization'
import { useMemoryPairs } from '../context/MemoryPairsContext'
import { MemoryGrid } from './MemoryGrid'
export function GamePhase() {
const { state, resetGame: _resetGame, activePlayers } = useMemoryPairs()
const { players: playerMap, activePlayers: activePlayerIds } = useGameMode()
// Convert Map to array and create mapping from numeric index to player
const _playersArray = Array.from(playerMap.values())
const activePlayersArray = Array.from(activePlayerIds)
.map((id) => playerMap.get(id))
.filter((p): p is NonNullable<typeof p> => p !== undefined)
// Map player ID (UUID string) to actual player data using array index
const currentPlayerIndex = activePlayers.indexOf(state.currentPlayer)
const _currentPlayerData =
currentPlayerIndex >= 0 ? activePlayersArray[currentPlayerIndex] : undefined
const _activePlayerData = activePlayersArray
const { state } = useMemoryPairs()
return (
<div
@@ -32,51 +17,7 @@ export function GamePhase() {
flexDirection: 'column',
})}
>
{/* Minimal Game Header */}
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: { base: '8px 12px', sm: '10px 16px', md: '12px 20px' },
background:
'linear-gradient(135deg, rgba(102, 126, 234, 0.08), rgba(118, 75, 162, 0.08))',
borderRadius: '12px',
marginBottom: { base: '12px', sm: '16px', md: '20px' },
border: '1px solid rgba(102, 126, 234, 0.15)',
flexShrink: 0,
})}
>
{/* Game Mode Indicator - Compact */}
<div
className={css({
display: 'flex',
alignItems: 'center',
gap: '8px',
fontSize: { base: '14px', sm: '15px' },
fontWeight: 'bold',
color: 'gray.600',
})}
>
<span className={css({ fontSize: { base: '16px', sm: '18px' } })}>
{state.gameType === 'abacus-numeral' ? '🧮' : '🤝'}
</span>
<span className={css({ display: { base: 'none', sm: 'inline' } })}>
{state.gameType === 'abacus-numeral' ? 'Abacus Match' : 'Complement Pairs'}
</span>
{state.gameMode === 'multiplayer' && (
<>
<span className={css({ color: 'gray.400' })}></span>
<span>
{activePlayers.length}
{pluralizeWord(activePlayers.length, 'P')}
</span>
</>
)}
</div>
</div>
{/* Player Status Bar - Removed, now using nav avatars as turn indicator */}
{/* Game header removed - game type and player info now shown in nav bar */}
{/* Memory Grid - The main game area */}
<div

View File

@@ -25,10 +25,14 @@ export function MemoryPairsGame() {
}
}, [setFullscreenElement])
// Determine nav title and emoji based on game type
const navTitle = state.gameType === 'abacus-numeral' ? 'Abacus Match' : 'Complement Pairs'
const navEmoji = state.gameType === 'abacus-numeral' ? '🧮' : '🤝'
return (
<PageWithNav
navTitle="Memory Pairs"
navEmoji="🧩"
navTitle={navTitle}
navEmoji={navEmoji}
emphasizeGameContext={state.gamePhase === 'setup'}
canModifyPlayers={canModifyPlayers}
onExitSession={() => {

View File

@@ -1,26 +1,11 @@
'use client'
import { css } from '../../../../../styled-system/css'
import { useGameMode } from '../../../../contexts/GameModeContext'
import { pluralizeWord } from '../../../../utils/pluralization'
import { useMemoryPairs } from '../context/MemoryPairsContext'
import { MemoryGrid } from './MemoryGrid'
export function GamePhase() {
const { state, resetGame, activePlayers } = useMemoryPairs()
const { players: playerMap, activePlayers: activePlayerIds } = useGameMode()
// Convert Map to array and create mapping from numeric index to player
const _playersArray = Array.from(playerMap.values())
const activePlayersArray = Array.from(activePlayerIds)
.map((id) => playerMap.get(id))
.filter((p): p is NonNullable<typeof p> => p !== undefined)
// Map player ID (UUID string) to actual player data using array index
const currentPlayerIndex = activePlayers.indexOf(state.currentPlayer)
const _currentPlayerData =
currentPlayerIndex >= 0 ? activePlayersArray[currentPlayerIndex] : undefined
const _activePlayerData = activePlayersArray
const { state } = useMemoryPairs()
return (
<div
@@ -32,93 +17,7 @@ export function GamePhase() {
flexDirection: 'column',
})}
>
{/* Minimal Game Header */}
<div
className={css({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: { base: '8px 12px', sm: '10px 16px', md: '12px 20px' },
background:
'linear-gradient(135deg, rgba(102, 126, 234, 0.08), rgba(118, 75, 162, 0.08))',
borderRadius: '12px',
marginBottom: { base: '12px', sm: '16px', md: '20px' },
border: '1px solid rgba(102, 126, 234, 0.15)',
flexShrink: 0,
})}
>
{/* Game Mode Indicator - Compact */}
<div
className={css({
display: 'flex',
alignItems: 'center',
gap: '8px',
fontSize: { base: '14px', sm: '15px' },
fontWeight: 'bold',
color: 'gray.600',
})}
>
<span className={css({ fontSize: { base: '16px', sm: '18px' } })}>
{state.gameType === 'abacus-numeral' ? '🧮' : '🤝'}
</span>
<span className={css({ display: { base: 'none', sm: 'inline' } })}>
{state.gameType === 'abacus-numeral' ? 'Abacus Match' : 'Complement Pairs'}
</span>
{state.gameMode === 'multiplayer' && (
<>
<span className={css({ color: 'gray.400' })}></span>
<span>
{activePlayers.length}
{pluralizeWord(activePlayers.length, 'P')}
</span>
</>
)}
</div>
{/* Game Controls */}
<div
className={css({
display: 'flex',
alignItems: 'center',
gap: '12px',
})}
>
{/* New Game Button */}
<button
className={css({
background: 'linear-gradient(135deg, #ffeaa7, #fab1a0)',
color: '#2d3436',
border: 'none',
borderRadius: '10px',
padding: { base: '8px 12px', sm: '10px 16px' },
fontSize: { base: '13px', sm: '14px' },
fontWeight: 'bold',
cursor: 'pointer',
transition: 'all 0.2s ease',
boxShadow: '0 2px 6px rgba(255, 234, 167, 0.3)',
_hover: {
transform: 'translateY(-1px)',
boxShadow: '0 3px 8px rgba(255, 234, 167, 0.5)',
background: 'linear-gradient(135deg, #fdcb6e, #e17055)',
},
})}
onClick={resetGame}
>
<div
className={css({
display: 'flex',
alignItems: 'center',
gap: '6px',
})}
>
<span>🔄</span>
<span>New Game</span>
</div>
</button>
</div>
</div>
{/* Player Status Bar - Removed, now using nav avatars as turn indicator */}
{/* Game header removed - game type and player info now shown in nav bar */}
{/* Memory Grid - The main game area */}
<div

View File

@@ -23,10 +23,14 @@ export function MemoryPairsGame() {
}
}, [setFullscreenElement])
// Determine nav title and emoji based on game type
const navTitle = state.gameType === 'abacus-numeral' ? 'Abacus Match' : 'Complement Pairs'
const navEmoji = state.gameType === 'abacus-numeral' ? '🧮' : '🤝'
return (
<PageWithNav
navTitle="Memory Pairs"
navEmoji="🧩"
navTitle={navTitle}
navEmoji={navEmoji}
emphasizeGameContext={state.gamePhase === 'setup'}
currentPlayerId={state.currentPlayer}
playerScores={state.scores}