diff --git a/apps/web/src/components/PageWithNav.tsx b/apps/web/src/components/PageWithNav.tsx index 38f7a794..ca7a9a1f 100644 --- a/apps/web/src/components/PageWithNav.tsx +++ b/apps/web/src/components/PageWithNav.tsx @@ -3,7 +3,6 @@ import React from 'react' import { AppNavBar } from './AppNavBar' import { useGameMode } from '../contexts/GameModeContext' -import { useUserProfile } from '../contexts/UserProfileContext' import { GameContextNav } from './nav/GameContextNav' import { PlayerConfigDialog } from './nav/PlayerConfigDialog' @@ -15,10 +14,9 @@ interface PageWithNavProps { } export function PageWithNav({ navTitle, navEmoji, emphasizeGameContext = false, children }: PageWithNavProps) { - const { players, activePlayerCount, updatePlayer } = useGameMode() - const { profile } = useUserProfile() + const { players, activePlayers, setActive, activePlayerCount } = useGameMode() const [mounted, setMounted] = React.useState(false) - const [configurePlayerId, setConfigurePlayerId] = React.useState<1 | 2 | 3 | 4 | null>(null) + const [configurePlayerId, setConfigurePlayerId] = React.useState(null) // Delay mounting animation slightly for smooth transition React.useEffect(() => { @@ -26,57 +24,27 @@ export function PageWithNav({ navTitle, navEmoji, emphasizeGameContext = false, return () => clearTimeout(timer) }, []) - const handleRemovePlayer = (playerId: number) => { - updatePlayer(playerId, { isActive: false }) + const handleRemovePlayer = (playerId: string) => { + setActive(playerId, false) } - const handleAddPlayer = (playerId: number) => { - updatePlayer(playerId, { isActive: true }) + const handleAddPlayer = (playerId: string) => { + setActive(playerId, true) } - const handleConfigurePlayer = (playerId: number) => { - // Support configuring all players (1-4) - if (playerId >= 1 && playerId <= 4) { - setConfigurePlayerId(playerId as 1 | 2 | 3 | 4) - } + const handleConfigurePlayer = (playerId: string) => { + setConfigurePlayerId(playerId) } - // Transform players to use profile emojis and names for all players - const getPlayerEmoji = (playerId: number) => { - switch (playerId) { - case 1: return profile.player1Emoji - case 2: return profile.player2Emoji - case 3: return profile.player3Emoji - case 4: return profile.player4Emoji - default: return players.find(p => p.id === playerId)?.emoji || '😀' - } - } + // Get active and inactive players as arrays + const activePlayerList = Array.from(activePlayers) + .map(id => players.get(id)) + .filter(p => p !== undefined) + .map(p => ({ id: p.id, name: p.name, emoji: p.emoji })) - const getPlayerName = (playerId: number) => { - switch (playerId) { - case 1: return profile.player1Name - case 2: return profile.player2Name - case 3: return profile.player3Name - case 4: return profile.player4Name - default: return players.find(p => p.id === playerId)?.name || `Player ${playerId}` - } - } - - const activePlayers = players - .filter(p => p.isActive) - .map(player => ({ - ...player, - emoji: getPlayerEmoji(player.id), - name: getPlayerName(player.id) - })) - - const inactivePlayers = players - .filter(p => !p.isActive) - .map(player => ({ - ...player, - emoji: getPlayerEmoji(player.id), - name: getPlayerName(player.id) - })) + const inactivePlayerList = Array.from(players.values()) + .filter(p => !activePlayers.has(p.id)) + .map(p => ({ id: p.id, name: p.name, emoji: p.emoji })) // Compute game mode from active player count const gameMode = activePlayerCount === 0 ? 'none' : @@ -93,8 +61,8 @@ export function PageWithNav({ navTitle, navEmoji, emphasizeGameContext = false, navTitle={navTitle} navEmoji={navEmoji} gameMode={gameMode} - activePlayers={activePlayers} - inactivePlayers={inactivePlayers} + activePlayers={activePlayerList} + inactivePlayers={inactivePlayerList} shouldEmphasize={shouldEmphasize} showFullscreenSelection={showFullscreenSelection} onAddPlayer={handleAddPlayer} @@ -115,4 +83,4 @@ export function PageWithNav({ navTitle, navEmoji, emphasizeGameContext = false, )} ) -} \ No newline at end of file +} diff --git a/apps/web/src/components/nav/ActivePlayersList.tsx b/apps/web/src/components/nav/ActivePlayersList.tsx index c1d46991..d15d6526 100644 --- a/apps/web/src/components/nav/ActivePlayersList.tsx +++ b/apps/web/src/components/nav/ActivePlayersList.tsx @@ -1,7 +1,7 @@ import React from 'react' interface Player { - id: number + id: string name: string emoji: string } @@ -9,12 +9,12 @@ interface Player { interface ActivePlayersListProps { activePlayers: Player[] shouldEmphasize: boolean - onRemovePlayer: (playerId: number) => void - onConfigurePlayer: (playerId: number) => void + onRemovePlayer: (playerId: string) => void + onConfigurePlayer: (playerId: string) => void } export function ActivePlayersList({ activePlayers, shouldEmphasize, onRemovePlayer, onConfigurePlayer }: ActivePlayersListProps) { - const [hoveredPlayerId, setHoveredPlayerId] = React.useState(null) + const [hoveredPlayerId, setHoveredPlayerId] = React.useState(null) return ( <> diff --git a/apps/web/src/components/nav/AddPlayerButton.tsx b/apps/web/src/components/nav/AddPlayerButton.tsx index 6545ed0f..2700099a 100644 --- a/apps/web/src/components/nav/AddPlayerButton.tsx +++ b/apps/web/src/components/nav/AddPlayerButton.tsx @@ -1,7 +1,7 @@ import React from 'react' interface Player { - id: number + id: string name: string emoji: string } @@ -9,7 +9,7 @@ interface Player { interface AddPlayerButtonProps { inactivePlayers: Player[] shouldEmphasize: boolean - onAddPlayer: (playerId: number) => void + onAddPlayer: (playerId: string) => void } export function AddPlayerButton({ inactivePlayers, shouldEmphasize, onAddPlayer }: AddPlayerButtonProps) { @@ -30,7 +30,7 @@ export function AddPlayerButton({ inactivePlayers, shouldEmphasize, onAddPlayer } }, [showPopover]) - const handleAddPlayerClick = (playerId: number) => { + const handleAddPlayerClick = (playerId: string) => { onAddPlayer(playerId) setShowPopover(false) } diff --git a/apps/web/src/components/nav/FullscreenPlayerSelection.tsx b/apps/web/src/components/nav/FullscreenPlayerSelection.tsx index e28afade..e7b1db03 100644 --- a/apps/web/src/components/nav/FullscreenPlayerSelection.tsx +++ b/apps/web/src/components/nav/FullscreenPlayerSelection.tsx @@ -1,15 +1,15 @@ import React from 'react' interface Player { - id: number + id: string name: string emoji: string } interface FullscreenPlayerSelectionProps { inactivePlayers: Player[] - onSelectPlayer: (playerId: number) => void - onConfigurePlayer: (playerId: number) => void + onSelectPlayer: (playerId: string) => void + onConfigurePlayer: (playerId: string) => void isVisible: boolean } diff --git a/apps/web/src/components/nav/GameContextNav.tsx b/apps/web/src/components/nav/GameContextNav.tsx index 58698c88..21b95f13 100644 --- a/apps/web/src/components/nav/GameContextNav.tsx +++ b/apps/web/src/components/nav/GameContextNav.tsx @@ -7,7 +7,7 @@ import { FullscreenPlayerSelection } from './FullscreenPlayerSelection' type GameMode = 'none' | 'single' | 'battle' | 'tournament' interface Player { - id: number + id: string name: string emoji: string } @@ -20,9 +20,9 @@ interface GameContextNavProps { inactivePlayers: Player[] shouldEmphasize: boolean showFullscreenSelection: boolean - onAddPlayer: (playerId: number) => void - onRemovePlayer: (playerId: number) => void - onConfigurePlayer: (playerId: number) => void + onAddPlayer: (playerId: string) => void + onRemovePlayer: (playerId: string) => void + onConfigurePlayer: (playerId: string) => void } export function GameContextNav({ diff --git a/apps/web/src/components/nav/PlayerConfigDialog.tsx b/apps/web/src/components/nav/PlayerConfigDialog.tsx index c747dc27..fac6f600 100644 --- a/apps/web/src/components/nav/PlayerConfigDialog.tsx +++ b/apps/web/src/components/nav/PlayerConfigDialog.tsx @@ -1,54 +1,49 @@ import React, { useState } from 'react' -import { useUserProfile } from '../../contexts/UserProfileContext' +import { useGameMode } from '../../contexts/GameModeContext' import { EmojiPicker } from '../../app/games/matching/components/EmojiPicker' interface PlayerConfigDialogProps { - playerId: 1 | 2 | 3 | 4 + playerId: string onClose: () => void } export function PlayerConfigDialog({ playerId, onClose }: PlayerConfigDialogProps) { - const { profile, updatePlayerEmoji, updatePlayerName } = useUserProfile() + const { getPlayer, updatePlayer } = useGameMode() const [showEmojiPicker, setShowEmojiPicker] = useState(false) - const getCurrentName = () => { - switch (playerId) { - case 1: return profile.player1Name - case 2: return profile.player2Name - case 3: return profile.player3Name - case 4: return profile.player4Name - } + const player = getPlayer(playerId) + + if (!player) { + return null } - const getCurrentEmoji = () => { - switch (playerId) { - case 1: return profile.player1Emoji - case 2: return profile.player2Emoji - case 3: return profile.player3Emoji - case 4: return profile.player4Emoji - } - } - - const [tempName, setTempName] = useState(getCurrentName()) - const currentEmoji = getCurrentEmoji() + const [tempName, setTempName] = useState(player.name) const handleSave = () => { - updatePlayerName(playerId, tempName) + updatePlayer(playerId, { name: tempName }) onClose() } const handleEmojiSelect = (emoji: string) => { - updatePlayerEmoji(playerId, emoji) + updatePlayer(playerId, { emoji }) setShowEmojiPicker(false) } + // Get player number for UI theming (first 4 players get special colors) + const allPlayers = Array.from(useGameMode().players.values()).sort((a, b) => a.createdAt - b.createdAt) + const playerIndex = allPlayers.findIndex(p => p.id === playerId) + const displayNumber = playerIndex + 1 + + // Color based on player's actual color + const gradientColor = player.color + if (showEmojiPicker) { return ( setShowEmojiPicker(false)} - playerNumber={playerId} + playerNumber={displayNumber} /> ) } @@ -87,18 +82,12 @@ export function PlayerConfigDialog({ playerId, onClose }: PlayerConfigDialogProp

- Configure Player {playerId} + Configure Player