@@ -82,6 +82,16 @@ export const PlaySetupModal: React.FC<Props> = (props: Props) => {
82
82
const [ timeControl , setTimeControl ] = useState < TimeControl > (
83
83
props . timeControl || TimeControlOptions [ 0 ] ,
84
84
)
85
+ const [ timeMinutes , setTimeMinutes ] = useState < number > ( ( ) => {
86
+ const initial = props . timeControl || TimeControlOptions [ 0 ]
87
+ if ( initial === 'unlimited' ) return 0
88
+ return parseInt ( initial . split ( '+' ) [ 0 ] )
89
+ } )
90
+ const [ incrementSeconds , setIncrementSeconds ] = useState < number > ( ( ) => {
91
+ const initial = props . timeControl || TimeControlOptions [ 0 ]
92
+ if ( initial === 'unlimited' ) return 0
93
+ return parseInt ( initial . split ( '+' ) [ 1 ] )
94
+ } )
85
95
const [ isBrain , setIsBrain ] = useState < boolean > ( props . isBrain || false )
86
96
const [ sampleMoves , setSampleMoves ] = useState < boolean > (
87
97
props . sampleMoves || true ,
@@ -102,6 +112,38 @@ export const PlaySetupModal: React.FC<Props> = (props: Props) => {
102
112
103
113
const [ openMoreOptions , setMoreOptionsOpen ] = useState < boolean > ( true )
104
114
115
+ const handlePresetSelect = useCallback ( ( preset : TimeControl ) => {
116
+ setTimeControl ( preset )
117
+ if ( preset === 'unlimited' ) {
118
+ setTimeMinutes ( 0 )
119
+ setIncrementSeconds ( 0 )
120
+ } else {
121
+ const [ minutes , increment ] = preset . split ( '+' ) . map ( Number )
122
+ setTimeMinutes ( minutes )
123
+ setIncrementSeconds ( increment )
124
+ }
125
+ } , [ ] )
126
+
127
+ const handleSliderChange = useCallback (
128
+ ( newTimeMinutes : number , newIncrementSeconds : number ) => {
129
+ setTimeMinutes ( newTimeMinutes )
130
+ setIncrementSeconds ( newIncrementSeconds )
131
+
132
+ if ( newTimeMinutes === 0 && newIncrementSeconds === 0 ) {
133
+ setTimeControl ( 'unlimited' )
134
+ } else {
135
+ const newTimeControl =
136
+ `${ newTimeMinutes } +${ newIncrementSeconds } ` as TimeControl
137
+ if ( TimeControlOptions . includes ( newTimeControl ) ) {
138
+ setTimeControl ( newTimeControl )
139
+ } else {
140
+ setTimeControl ( newTimeControl )
141
+ }
142
+ }
143
+ } ,
144
+ [ ] ,
145
+ )
146
+
105
147
const start = useCallback (
106
148
( color : Color | undefined ) => {
107
149
const player = color ?? [ 'white' , 'black' ] [ Math . floor ( Math . random ( ) * 2 ) ]
@@ -248,19 +290,82 @@ export const PlaySetupModal: React.FC<Props> = (props: Props) => {
248
290
</ div >
249
291
250
292
< div >
251
- < label
252
- htmlFor = "time-control-select"
253
- className = "mb-1 block text-sm font-medium text-primary"
254
- >
255
- Time control:
256
- </ label >
257
- < div id = "time-control-select" >
258
- < OptionSelect
259
- options = { TimeControlOptions }
260
- labels = { TimeControlOptionNames }
261
- selected = { timeControl }
262
- onChange = { setTimeControl }
263
- />
293
+ < div className = "mb-3 flex items-center justify-between" >
294
+ < span className = "text-sm font-medium text-primary" >
295
+ Time Control:
296
+ </ span >
297
+ < div className = "flex gap-1" >
298
+ { TimeControlOptions . map ( ( option , index ) => (
299
+ < button
300
+ key = { option }
301
+ onClick = { ( ) => handlePresetSelect ( option ) }
302
+ className = { `rounded px-2 py-1 text-xs font-medium transition-colors ${
303
+ timeControl === option
304
+ ? 'bg-human-4 text-white'
305
+ : 'bg-background-2 text-secondary hover:bg-background-3 hover:text-primary'
306
+ } `}
307
+ >
308
+ { TimeControlOptionNames [ index ] }
309
+ </ button >
310
+ ) ) }
311
+ </ div >
312
+ </ div >
313
+
314
+ < div className = "space-y-3" >
315
+ < div >
316
+ < div className = "mb-2 flex items-center justify-between" >
317
+ < label
318
+ htmlFor = "time-minutes-slider"
319
+ className = "text-xs font-medium text-primary"
320
+ >
321
+ Time (minutes)
322
+ </ label >
323
+ < span className = "text-xs text-secondary" >
324
+ { timeMinutes }
325
+ </ span >
326
+ </ div >
327
+ < input
328
+ id = "time-minutes-slider"
329
+ type = "range"
330
+ min = "0"
331
+ max = "60"
332
+ step = "1"
333
+ value = { timeMinutes }
334
+ onChange = { ( e ) =>
335
+ handleSliderChange (
336
+ Number ( e . target . value ) ,
337
+ incrementSeconds ,
338
+ )
339
+ }
340
+ className = "h-2 w-full cursor-pointer appearance-none rounded-lg bg-background-2 [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:cursor-pointer [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:bg-human-4 [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-human-4"
341
+ />
342
+ </ div >
343
+
344
+ < div >
345
+ < div className = "mb-2 flex items-center justify-between" >
346
+ < label
347
+ htmlFor = "increment-seconds-slider"
348
+ className = "text-xs font-medium text-primary"
349
+ >
350
+ Increment (seconds)
351
+ </ label >
352
+ < span className = "text-xs text-secondary" >
353
+ { incrementSeconds }
354
+ </ span >
355
+ </ div >
356
+ < input
357
+ id = "increment-seconds-slider"
358
+ type = "range"
359
+ min = "0"
360
+ max = "30"
361
+ step = "1"
362
+ value = { incrementSeconds }
363
+ onChange = { ( e ) =>
364
+ handleSliderChange ( timeMinutes , Number ( e . target . value ) )
365
+ }
366
+ className = "h-2 w-full cursor-pointer appearance-none rounded-lg bg-background-2 [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:cursor-pointer [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:bg-human-4 [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-human-4"
367
+ />
368
+ </ div >
264
369
</ div >
265
370
</ div >
266
371
0 commit comments