@@ -31,6 +31,7 @@ export const CreateMatchModal: React.FC<CreateMatchModalProps> = ({
3131 const [ isRated , setIsRated ] = useState < boolean > ( true )
3232 const [ aiType , setAiType ] = useState < 'greedy' | 'random' | 'gnubg_easy' | 'gnubg_medium' | 'gnubg_hard' | 'gnubg_expert' > ( 'greedy' )
3333 const [ isCreating , setIsCreating ] = useState ( false )
34+ const [ error , setError ] = useState < string | null > ( null )
3435 const isAuthenticated = authService . isAuthenticated ( )
3536
3637 // Reset to default when modal opens
@@ -40,6 +41,7 @@ export const CreateMatchModal: React.FC<CreateMatchModalProps> = ({
4041 setTargetScore ( 1 )
4142 setIsRated ( true )
4243 setAiType ( 'greedy' )
44+ setError ( null )
4345 }
4446 } , [ isOpen , defaultOpponentType ] )
4547
@@ -52,6 +54,7 @@ export const CreateMatchModal: React.FC<CreateMatchModalProps> = ({
5254
5355 const handleCreate = async ( ) => {
5456 setIsCreating ( true )
57+ setError ( null )
5558 try {
5659 // Determine if game can be rated
5760 const canBeRated = isAuthenticated && opponentType !== 'AI'
@@ -71,16 +74,17 @@ export const CreateMatchModal: React.FC<CreateMatchModalProps> = ({
7174 await hub ?. createMatch ( config )
7275 console . log ( '[CreateMatchModal] CreateMatch completed' )
7376 onClose ( )
74- } catch ( error ) {
75- console . error ( '[CreateMatchModal] Failed to create match:' , error )
77+ } catch ( err ) {
78+ console . error ( '[CreateMatchModal] Failed to create match:' , err )
79+ setError ( 'Failed to create game. Please try again.' )
7680 } finally {
7781 setIsCreating ( false )
7882 }
7983 }
8084
8185 return (
8286 < Dialog open = { isOpen } onOpenChange = { onClose } >
83- < DialogContent >
87+ < DialogContent className = "sm:max-w-md" >
8488 < DialogHeader >
8589 < DialogTitle >
8690 { opponentType === 'AI' ? 'Play vs Computer' : 'Play Online' }
@@ -125,83 +129,68 @@ export const CreateMatchModal: React.FC<CreateMatchModalProps> = ({
125129 { /* AI Type - Only show for AI opponents */ }
126130 { opponentType === 'AI' && (
127131 < div className = "space-y-3" >
128- < Label > AI Difficulty</ Label >
132+ < Label > Difficulty</ Label >
129133 < RadioGroup value = { aiType } onValueChange = { ( value ) => setAiType ( value as 'greedy' | 'random' | 'gnubg_easy' | 'gnubg_medium' | 'gnubg_hard' | 'gnubg_expert' ) } >
130- < div className = "flex items-center space-x-2" >
131- < RadioGroupItem value = "greedy" id = "ai-greedy" />
132- < Label htmlFor = "ai-greedy" className = "font-normal cursor-pointer" >
133- < div className = "flex flex-col" >
134- < span > Greedy Bot</ span >
135- < span className = "text-sm text-muted-foreground" > Strategic play: prioritizes hitting and bearing off</ span >
136- </ div >
137- </ Label >
138- </ div >
139134 < div className = "flex items-center space-x-2" >
140135 < RadioGroupItem value = "random" id = "ai-random" />
141136 < Label htmlFor = "ai-random" className = "font-normal cursor-pointer" >
142- < div className = "flex flex-col" >
143- < span > Random Bot</ span >
144- < span className = "text-sm text-muted-foreground" > Makes random valid moves - good for practice</ span >
145- </ div >
137+ Beginner < span className = "text-muted-foreground" > - random moves</ span >
146138 </ Label >
147139 </ div >
148- < div className = "border-t pt-3 mt-2" >
149- < span className = "text-sm font-medium text-muted-foreground" > GNU Backgammon (Neural Network AI)</ span >
140+ < div className = "flex items-center space-x-2" >
141+ < RadioGroupItem value = "greedy" id = "ai-greedy" />
142+ < Label htmlFor = "ai-greedy" className = "font-normal cursor-pointer" >
143+ Easy < span className = "text-muted-foreground" > - basic strategy</ span >
144+ </ Label >
150145 </ div >
151146 < div className = "flex items-center space-x-2" >
152147 < RadioGroupItem value = "gnubg_easy" id = "ai-gnubg-easy" />
153148 < Label htmlFor = "ai-gnubg-easy" className = "font-normal cursor-pointer" >
154- < div className = "flex flex-col" >
155- < span > Easy (GNUBG)</ span >
156- < span className = "text-sm text-muted-foreground" > 0-ply analysis (~1200 ELO) - instant moves, makes mistakes</ span >
157- </ div >
149+ Intermediate < span className = "text-muted-foreground" > - ~1200 ELO</ span >
158150 </ Label >
159151 </ div >
160152 < div className = "flex items-center space-x-2" >
161153 < RadioGroupItem value = "gnubg_medium" id = "ai-gnubg-medium" />
162154 < Label htmlFor = "ai-gnubg-medium" className = "font-normal cursor-pointer" >
163- < div className = "flex flex-col" >
164- < span > Medium (GNUBG)</ span >
165- < span className = "text-sm text-muted-foreground" > 1-ply analysis (~1600 ELO) - fast, decent play</ span >
166- </ div >
155+ Advanced < span className = "text-muted-foreground" > - ~1600 ELO</ span >
167156 </ Label >
168157 </ div >
169158 < div className = "flex items-center space-x-2" >
170159 < RadioGroupItem value = "gnubg_hard" id = "ai-gnubg-hard" />
171160 < Label htmlFor = "ai-gnubg-hard" className = "font-normal cursor-pointer" >
172- < div className = "flex flex-col" >
173- < span > Hard (GNUBG) (Recommended)</ span >
174- < span className = "text-sm text-muted-foreground" > 2-ply analysis (~1900 ELO) - strong play</ span >
175- </ div >
161+ Hard < span className = "text-muted-foreground" > - ~1900 ELO</ span >
176162 </ Label >
177163 </ div >
178164 < div className = "flex items-center space-x-2" >
179165 < RadioGroupItem value = "gnubg_expert" id = "ai-gnubg-expert" />
180166 < Label htmlFor = "ai-gnubg-expert" className = "font-normal cursor-pointer" >
181- < div className = "flex flex-col" >
182- < span > Expert (GNUBG)</ span >
183- < span className = "text-sm text-muted-foreground" > 3-ply analysis (~2100 ELO) - world-class play, slower</ span >
184- </ div >
167+ Expert < span className = "text-muted-foreground" > - ~2100 ELO</ span >
185168 </ Label >
186169 </ div >
187170 </ RadioGroup >
188171 </ div >
189172 ) }
190173
191174 { /* Time Control - Always ChicagoPoint */ }
192- < div className = "p-3 bg-blue-50 border border-blue-200 rounded-md" >
175+ < div className = "p-3 bg-muted border rounded-md" >
193176 < div className = "space-y-1" >
194- < p className = "text-sm font-medium text-blue-900 " > Time Control: Chicago Point</ p >
195- < p className = "text-sm text-blue-800 " >
177+ < p className = "text-sm font-medium" > Time Control: Chicago Point</ p >
178+ < p className = "text-sm text-muted-foreground " >
196179 12-second delay + { 2 * targetScore } -minute reserve time
197180 </ p >
198- < p className = "text-xs text-blue-700 " >
181+ < p className = "text-xs text-muted-foreground " >
199182 Reserve time adjusts as match progresses: 2min per point remaining
200183 </ p >
201184 </ div >
202185 </ div >
203186
204187 { /* Rated/Unrated - Only show for authenticated users playing online */ }
188+ { error && (
189+ < div className = "text-sm text-red-500 bg-red-50 p-3 rounded-md" >
190+ { error }
191+ </ div >
192+ ) }
193+
205194 { isAuthenticated && opponentType !== 'AI' && (
206195 < div className = "flex items-center justify-between" >
207196 < div className = "space-y-0.5" >
0 commit comments