diff --git a/apps/web/src/components/nav/CreateRoomModal.tsx b/apps/web/src/components/nav/CreateRoomModal.tsx index efde7405..42b2b4a6 100644 --- a/apps/web/src/components/nav/CreateRoomModal.tsx +++ b/apps/web/src/components/nav/CreateRoomModal.tsx @@ -1,6 +1,9 @@ import { useState } from 'react' +import * as Select from '@radix-ui/react-select' +import { animated } from '@react-spring/web' import { Modal } from '@/components/common/Modal' import { useCreateRoom } from '@/hooks/useRoomData' +import { getAvailableGames } from '@/lib/arcade/game-registry' export interface CreateRoomModalProps { /** @@ -24,10 +27,9 @@ export interface CreateRoomModalProps { */ export function CreateRoomModal({ isOpen, onClose, onSuccess }: CreateRoomModalProps) { const { mutateAsync: createRoom, isPending } = useCreateRoom() + const availableGames = getAvailableGames() const [error, setError] = useState('') - const [gameName, setGameName] = useState<'matching' | 'memory-quiz' | 'complement-race'>( - 'matching' - ) + const [gameName, setGameName] = useState('__choose_later__') // Special value = user will choose later const [accessMode, setAccessMode] = useState< 'open' | 'password' | 'approval-only' | 'restricted' >('open') @@ -35,7 +37,7 @@ export function CreateRoomModal({ isOpen, onClose, onSuccess }: CreateRoomModalP const handleClose = () => { setError('') - setGameName('matching') + setGameName('__choose_later__') setAccessMode('open') setPassword('') onClose() @@ -59,9 +61,13 @@ export function CreateRoomModal({ isOpen, onClose, onSuccess }: CreateRoomModalP try { // Create the room (creator is auto-added as first member) + // If no game selected (choose later), use first available game as default + const selectedGame = + gameName === '__choose_later__' ? availableGames[0]?.manifest.name || 'matching' : gameName + await createRoom({ name, - gameName, + gameName: selectedGame, creatorName: 'Player', gameConfig: { difficulty: 6 }, accessMode, @@ -153,77 +159,308 @@ export function CreateRoomModal({ isOpen, onClose, onSuccess }: CreateRoomModalP -
- {[ - { value: 'matching' as const, emoji: '🃏', label: 'Memory', desc: 'Matching' }, - { value: 'memory-quiz' as const, emoji: '🧠', label: 'Memory', desc: 'Quiz' }, - { - value: 'complement-race' as const, - emoji: '⚡', - label: 'Complement', - desc: 'Race', - }, - ].map((game) => ( - - ))} -
+ + { + e.currentTarget.style.opacity = '0.7' + }} + onMouseLeave={(e) => { + e.currentTarget.style.opacity = '1' + }} + > + ▲ + + + + { + if (gameName !== '__choose_later__') { + e.currentTarget.style.background = 'rgba(255, 255, 255, 0.08)' + } + }} + onMouseLeave={(e) => { + if (gameName !== '__choose_later__') { + e.currentTarget.style.background = 'transparent' + } + }} + > + +
+ +
+
Choose later
+
+ Pick on the game selection page +
+
+
+
+
+ +
+ + {availableGames.map((game) => { + const gameId = game.manifest.name + // Map game gradients to colors + const gradientColors: Record = { + pink: 'rgba(236, 72, 153, 0.2)', + purple: 'rgba(168, 85, 247, 0.2)', + blue: 'rgba(59, 130, 246, 0.2)', + green: 'rgba(34, 197, 94, 0.2)', + orange: 'rgba(249, 115, 22, 0.2)', + red: 'rgba(239, 68, 68, 0.2)', + } + const bgColor = + gradientColors[game.manifest.gradient || 'blue'] || gradientColors.blue + + return ( + { + if (gameName !== gameId) { + e.currentTarget.style.background = 'rgba(255, 255, 255, 0.05)' + } + }} + onMouseLeave={(e) => { + if (gameName !== gameId) { + e.currentTarget.style.background = 'transparent' + } + }} + > + +
+ {game.manifest.icon} +
+
+ {game.manifest.displayName} +
+
+ {game.manifest.description} +
+
+ + {game.manifest.maxPlayers === 1 + ? '👤 Solo' + : `👥 ${game.manifest.maxPlayers}p`} + + + {game.manifest.difficulty} + +
+
+
+
+
+ ) + })} + + + { + e.currentTarget.style.opacity = '0.7' + }} + onMouseLeave={(e) => { + e.currentTarget.style.opacity = '1' + }} + > + ▼ + + + + +
{/* Access Mode Selection */}