2
2
/* eslint-disable jsx-a11y/alt-text */
3
3
import { PieceSymbol } from 'chess.ts'
4
4
5
- import { Color } from 'src/types'
5
+ import { BaseGame , Color } from 'src/types'
6
6
7
7
const pieceTypes : PieceSymbol [ ] = [ 'k' , 'q' , 'r' , 'b' , 'n' , 'p' ]
8
8
@@ -22,6 +22,7 @@ const pieceColorMap: { [key: string]: string } = {
22
22
}
23
23
24
24
interface Props {
25
+ game : BaseGame
25
26
isBrain : boolean
26
27
color : Color
27
28
movablePieceTypes : PieceSymbol [ ]
@@ -37,6 +38,7 @@ interface Props {
37
38
}
38
39
39
40
export const HandBrainPlayControls : React . FC < Props > = ( {
41
+ game,
40
42
playerActive,
41
43
gameOver,
42
44
isBrain,
@@ -61,118 +63,175 @@ export const HandBrainPlayControls: React.FC<Props> = ({
61
63
: 'Waiting for opponent'
62
64
63
65
return (
64
- < div >
65
- < div
66
- id = "play-controls"
67
- className = "flex flex-col items-center justify-center p-6"
68
- >
66
+ < div className = "flex h-full w-full flex-col border-white/40 bg-background-1" >
67
+ < div id = "play-controls" className = "flex h-full flex-col" >
69
68
{ gameOver ? (
70
- < >
69
+ < div className = "flex flex-col gap-2 p-4" >
70
+ { game . id ? (
71
+ < button
72
+ onClick = { ( ) => {
73
+ window . open (
74
+ `/analysis/${ game . id } /${ isBrain ? 'brain' : 'hand' } ` ,
75
+ '_blank' ,
76
+ )
77
+ } }
78
+ className = "flex items-center justify-center rounded border border-engine-2/20 bg-engine-3/5 px-4 py-2 text-sm font-semibold text-engine-1 transition-colors duration-200 hover:border-engine-2/50 hover:bg-engine-3/10"
79
+ >
80
+ ANALYZE GAME
81
+ </ button >
82
+ ) : null }
71
83
{ playAgain ? (
72
84
< button
73
85
onClick = { playAgain }
74
- className = "flex w-full justify-center rounded bg-human-3 py-2 text-primary transition duration-200 hover:bg-human-4 "
86
+ className = "flex w-full items-center justify-center rounded border border-human-2/20 bg-human-3/5 px-4 py-2 text-sm font-semibold tracking-wider text-human-1 transition-colors duration-200 hover:border-human-2/50 hover: bg-human-3/10 "
75
87
>
76
- Play again
88
+ PLAY AGAIN
77
89
</ button >
78
90
) : null }
79
- </ >
91
+ </ div >
80
92
) : (
81
- < div className = "flex w-full flex-col items-center justify-center gap-4" >
82
- < div className = "flex flex-col items-center justify-center" >
83
- < p className = "font-bold" > { status } </ p >
84
- < h2 className = "text-base" >
85
- { isBrain ? 'You are the brain' : 'You are the hand' }
86
- </ h2 >
87
- </ div >
88
- { isBrain ? (
89
- < div className = "flex w-full flex-wrap items-start justify-center gap-2" >
90
- { pieceTypes . map ( ( p ) => (
91
- < button
92
- key = { p }
93
- onClick = { ( ) => selectPiece ( p ) }
94
- disabled = {
95
- movablePieceTypes . indexOf ( p ) == - 1 ||
96
- ! playerActive ||
97
- ! ! selectedPiece
98
- }
99
- className = "flex h-16 w-16 items-center justify-center rounded border border-primary/10 bg-[#f0d9b5] disabled:bg-background-1"
100
- >
101
- < img
102
- src = { `/assets/pieces/${ pieceColorMap [ color [ 0 ] + p ] } .svg` }
103
- />
104
- </ button >
105
- ) ) }
106
- </ div >
107
- ) : (
108
- < div className = "h-30 w-30 flex items-center justify-center" >
109
- { selectedPiece ? (
110
- < img
111
- src = { `/assets/pieces/${ pieceColorMap [ color [ 0 ] + selectedPiece ] } .svg` }
112
- className = "h-20 w-20 rounded bg-[#f0d9b5] bg-contain"
113
- />
114
- ) : null }
93
+ < >
94
+ { /* Status Section */ }
95
+ < div className = "border-b border-white/10 bg-background-1 p-3" >
96
+ < div className = "space-y-1 text-center" >
97
+ < p
98
+ className = { `text-sm font-semibold uppercase tracking-wider ${
99
+ playerActive ? 'text-human-1' : 'text-secondary'
100
+ } `}
101
+ >
102
+ { status }
103
+ </ p >
104
+ < p className = "text-xs font-medium text-secondary/70" >
105
+ { isBrain ? 'You are the brain' : 'You are the hand' }
106
+ </ p >
115
107
</ div >
116
- ) }
108
+ </ div >
117
109
118
- { /* Maia timing toggle */ }
110
+ { /* Piece Selection or Display */ }
111
+ < div className = "border-b border-white/5 bg-human-3/5 p-4" >
112
+ { isBrain ? (
113
+ < div className = "flex flex-col gap-3" >
114
+ < p className = "text-center text-xs font-semibold uppercase tracking-wide text-human-2" >
115
+ SELECT PIECE
116
+ </ p >
117
+ < div className = "mx-auto grid max-w-48 grid-cols-3 gap-2" >
118
+ { pieceTypes . map ( ( p ) => (
119
+ < button
120
+ key = { p }
121
+ onClick = { ( ) => selectPiece ( p ) }
122
+ disabled = {
123
+ movablePieceTypes . indexOf ( p ) == - 1 ||
124
+ ! playerActive ||
125
+ ! ! selectedPiece
126
+ }
127
+ className = { `flex h-12 w-12 items-center justify-center border transition-colors duration-200 ${
128
+ movablePieceTypes . indexOf ( p ) !== - 1 &&
129
+ playerActive &&
130
+ ! selectedPiece
131
+ ? 'border-white/20 bg-[#f0d9b5] hover:border-white/30 hover:bg-[#e6d0a6]'
132
+ : 'cursor-not-allowed border-white/5 bg-background-2 opacity-50'
133
+ } `}
134
+ >
135
+ < img
136
+ src = { `/assets/pieces/${ pieceColorMap [ color [ 0 ] + p ] } .svg` }
137
+ className = "h-6 w-6"
138
+ alt = { pieceColorMap [ color [ 0 ] + p ] }
139
+ />
140
+ </ button >
141
+ ) ) }
142
+ </ div >
143
+ </ div >
144
+ ) : (
145
+ < div className = "flex flex-col items-center gap-3" >
146
+ < p className = "text-center text-xs font-semibold uppercase tracking-wide text-human-2" >
147
+ SELECTED PIECE
148
+ </ p >
149
+ < div className = "flex h-16 w-16 items-center justify-center" >
150
+ { selectedPiece ? (
151
+ < div className = "border border-white/20 bg-[#f0d9b5] p-2" >
152
+ < img
153
+ src = { `/assets/pieces/${ pieceColorMap [ color [ 0 ] + selectedPiece ] } .svg` }
154
+ className = "h-12 w-12"
155
+ alt = { pieceColorMap [ color [ 0 ] + selectedPiece ] }
156
+ />
157
+ </ div >
158
+ ) : (
159
+ < div className = "flex h-12 w-12 items-center justify-center border border-dashed border-white/20 bg-background-2" >
160
+ < span className = "text-xs text-secondary/50" > ...</ span >
161
+ </ div >
162
+ ) }
163
+ </ div >
164
+ </ div >
165
+ ) }
166
+ </ div >
167
+
168
+ { /* Maia Timing Toggle */ }
119
169
{ simulateMaiaTime !== undefined && setSimulateMaiaTime && (
120
- < div className = "w-full" >
121
- < div className = "mb-2 text-center text-xs font-medium text-primary/70" >
122
- Maia thinking time
170
+ < div className = "border-b border-white/5 bg-human-3/5 p-3" >
171
+ < div className = "flex flex-col gap-2" >
172
+ < p className = "text-center text-xs font-semibold tracking-wider text-human-2" >
173
+ MAIA THINKING TIME
174
+ </ p >
175
+ < div className = "flex overflow-hidden border border-white/10 bg-background-1" >
176
+ < button
177
+ className = { `flex-1 px-3 py-1.5 text-xs font-medium transition-colors duration-200 ${
178
+ ! simulateMaiaTime
179
+ ? 'bg-human-3 text-white'
180
+ : 'text-primary hover:bg-background-2'
181
+ } `}
182
+ onClick = { ( ) => setSimulateMaiaTime ( false ) }
183
+ >
184
+ Instant
185
+ </ button >
186
+ < button
187
+ className = { `flex-1 px-3 py-1.5 text-xs font-medium transition-colors duration-200 ${
188
+ simulateMaiaTime
189
+ ? 'bg-human-3 text-white'
190
+ : 'text-primary hover:bg-background-2'
191
+ } `}
192
+ onClick = { ( ) => setSimulateMaiaTime ( true ) }
193
+ >
194
+ Human-like
195
+ </ button >
196
+ </ div >
123
197
</ div >
124
- < div className = "flex w-full overflow-hidden rounded border border-primary/10" >
198
+ </ div >
199
+ ) }
200
+
201
+ { /* Action Buttons */ }
202
+ < div className = "flex-1 p-3" >
203
+ < div className = "flex flex-col gap-2" >
204
+ { offerDraw && (
125
205
< button
126
- className = { `flex-1 px-3 py-1 text-xs font-medium transition-all duration-200 ${
127
- ! simulateMaiaTime
128
- ? 'bg-human-3 text-white'
129
- : 'bg-background-1 text-primary hover:bg-background-2'
206
+ onClick = { offerDraw }
207
+ disabled = { ! playerActive }
208
+ className = { `w-full border px-4 py-2 text-sm font-semibold transition-colors duration-200 ${
209
+ playerActive
210
+ ? 'border-white/10 bg-engine-3/5 text-engine-1 hover:border-white/20 hover:bg-engine-3/10'
211
+ : 'cursor-not-allowed border-white/5 bg-background-2 text-secondary/40'
130
212
} `}
131
- onClick = { ( ) => setSimulateMaiaTime ( false ) }
132
213
>
133
- Instant
214
+ OFFER DRAW
134
215
</ button >
216
+ ) }
217
+
218
+ { /* Resign Button - Smaller and Less Prominent */ }
219
+ < div className = "flex justify-center" >
135
220
< button
136
- className = { `flex-1 px-3 py-1 text-xs font-medium transition-all duration-200 ${
137
- simulateMaiaTime
138
- ? 'bg-human-3 text-white'
139
- : 'bg-background-1 text-primary hover:bg-background-2'
221
+ onClick = { resign }
222
+ disabled = { ! resign || ! playerActive }
223
+ className = { `rounded px-3 py-1 text-xs font-medium transition-colors duration-200 ${
224
+ resign && playerActive
225
+ ? 'text-red-400/80 hover:bg-red-500/5 hover:text-red-300'
226
+ : 'cursor-not-allowed text-secondary/30'
140
227
} `}
141
- onClick = { ( ) => setSimulateMaiaTime ( true ) }
142
228
>
143
- Human-like
229
+ Resign
144
230
</ button >
145
231
</ div >
146
232
</ div >
147
- ) }
148
-
149
- { offerDraw ? (
150
- < button
151
- onClick = { offerDraw }
152
- disabled = { ! playerActive }
153
- className = { `flex w-full justify-center rounded px-4 py-2 text-primary transition duration-200 ${
154
- playerActive
155
- ? 'bg-engine-3 hover:bg-engine-4'
156
- : 'cursor-not-allowed bg-background-2 text-primary/50'
157
- } `}
158
- >
159
- < p className = "font-medium uppercase tracking-wide" >
160
- Offer draw
161
- </ p >
162
- </ button >
163
- ) : null }
164
- < button
165
- onClick = { resign }
166
- disabled = { ! resign || ! playerActive }
167
- className = { `flex w-full justify-center rounded px-4 py-1.5 text-primary transition duration-200 ${
168
- resign && playerActive
169
- ? 'bg-human-3 hover:bg-human-4'
170
- : 'cursor-not-allowed bg-background-2 text-primary/50'
171
- } `}
172
- >
173
- < p className = "text-sm font-medium" > Resign</ p >
174
- </ button >
175
- </ div >
233
+ </ div >
234
+ </ >
176
235
) }
177
236
</ div >
178
237
</ div >
0 commit comments