Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 'use client' import { useRouter } from 'next/navigation' import { useEffect, useRef } from 'react' import { PageWithNav } from '@/components/PageWithNav' import { css } from '../../../../styled-system/css' import { StandardGameLayout } from '@/components/StandardGameLayout' import { useFullscreen } from '@/contexts/FullscreenContext' import { useCardSorting } from '../Provider' import { SetupPhase } from './SetupPhase' import { PlayingPhaseDrag } from './PlayingPhaseDrag' import { ResultsPhase } from './ResultsPhase' export function GameComponent() { const router = useRouter() const { state, exitSession, startGame, goToSetup, isSpectating } = useCardSorting() const { setFullscreenElement } = useFullscreen() const gameRef = useRef<HTMLDivElement>(null) useEffect(() => { // Register fullscreen element if (gameRef.current) { setFullscreenElement(gameRef.current) } }, [setFullscreenElement]) return ( <PageWithNav navTitle="Card Sorting" navEmoji="🔢" emphasizePlayerSelection={state.gamePhase === 'setup'} onExitSession={() => { exitSession() router.push('/arcade') }} onSetup={ goToSetup ? () => { goToSetup() } : undefined } onNewGame={() => { startGame() }} > <StandardGameLayout> <div ref={gameRef} className={css({ flex: 1, display: 'flex', flexDirection: 'column', position: 'relative', overflow: 'hidden', // Remove all padding/margins for playing phase padding: state.gamePhase === 'playing' ? '0' : { base: '12px', sm: '16px', md: '20px' }, })} > {/* Spectator Mode Banner - only show in setup/results */} {isSpectating && state.gamePhase !== 'setup' && state.gamePhase !== 'playing' && ( <div className={css({ width: '100%', maxWidth: '1200px', background: 'linear-gradient(135deg, #fef3c7, #fde68a)', borderRadius: { base: '8px', md: '12px' }, padding: { base: '12px', md: '16px' }, marginBottom: { base: '12px', md: '16px' }, boxShadow: '0 4px 12px rgba(0,0,0,0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px', fontSize: { base: '14px', sm: '16px', md: '18px' }, fontWeight: 600, color: '#92400e', textAlign: 'center', alignSelf: 'center', })} > <span role="img" aria-label="watching"> 👀 </span> <span>Spectating {state.playerMetadata?.name || 'player'}'s game</span> </div> )} {/* For playing phase, render full viewport. For setup/results, use container */} {state.gamePhase === 'playing' ? ( <PlayingPhaseDrag /> ) : ( <main className={css({ width: '100%', maxWidth: '1200px', background: 'rgba(255,255,255,0.95)', borderRadius: { base: '12px', md: '20px' }, padding: { base: '12px', sm: '16px', md: '24px', lg: '32px' }, boxShadow: '0 10px 30px rgba(0,0,0,0.2)', flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', alignSelf: 'center', })} > {state.gamePhase === 'setup' && <SetupPhase />} {state.gamePhase === 'results' && <ResultsPhase />} </main> )} </div> </StandardGameLayout> </PageWithNav> ) } |