@@ -23,23 +23,32 @@ function TournamentBracketPage() {
2323
2424 const [ competitors , setCompetitors ] = useState ( [ ] ) ;
2525 const [ newCompetitor , setNewCompetitor ] = useState ( '' ) ;
26+ const [ newCompetitorCharLimitError , setNewCompetitorCharLimitError ] = useState ( false ) ;
2627 const [ editingIndex , setEditingIndex ] = useState ( null ) ;
2728 const [ editingText , setEditingText ] = useState ( '' ) ;
2829 const [ nameError , setNameError ] = useState ( '' ) ;
2930 const newCompetitorInputRef = useRef ( null ) ;
3031
3132 const addCompetitor = ( ) => {
3233 const trimmedCompetitor = newCompetitor . trim ( ) ;
33- if ( trimmedCompetitor && competitors . length < 64 ) {
34+ if ( trimmedCompetitor ) {
35+ if ( trimmedCompetitor . length > 5 ) {
36+ addToast ( { title : 'Error' , message : 'Competitor name cannot exceed 5 characters.' , duration : 3000 } ) ;
37+ return ;
38+ }
3439 if ( competitors . includes ( trimmedCompetitor ) ) {
3540 setNameError ( 'Competitor names must be unique.' ) ;
3641 addToast ( { title : 'Error' , message : 'Competitor names must be unique.' , duration : 3000 } ) ;
3742 return ;
3843 }
39- setCompetitors ( [ ...competitors , trimmedCompetitor ] ) ;
40- setNewCompetitor ( '' ) ;
41- setNameError ( '' ) ;
42- newCompetitorInputRef . current . focus ( ) ;
44+ if ( competitors . length < 64 ) {
45+ setCompetitors ( [ ...competitors , trimmedCompetitor ] ) ;
46+ setNewCompetitor ( '' ) ;
47+ setNameError ( '' ) ;
48+ newCompetitorInputRef . current . focus ( ) ;
49+ } else {
50+ addToast ( { title : 'Error' , message : 'Maximum of 64 competitors reached.' , duration : 3000 } ) ;
51+ }
4352 }
4453 } ;
4554
@@ -60,6 +69,10 @@ function TournamentBracketPage() {
6069
6170 const saveEdit = ( index ) => {
6271 const trimmedName = editingText . trim ( ) ;
72+ if ( trimmedName . length > 5 ) {
73+ addToast ( { title : 'Error' , message : 'Competitor name cannot exceed 5 characters.' , duration : 3000 } ) ;
74+ return ;
75+ }
6376 if ( competitors . includes ( trimmedName ) && competitors [ index ] !== trimmedName ) {
6477 addToast ( { title : 'Error' , message : 'Competitor names must be unique.' , duration : 3000 } ) ;
6578 return ;
@@ -122,10 +135,10 @@ function TournamentBracketPage() {
122135
123136 const [ champion , setChampion ] = useState ( null ) ;
124137
125- const advanceWinner = ( winner , roundIndex , matchIndex ) => {
138+ const advanceWinner = ( winner , loser , roundIndex , matchIndex ) => {
126139 if ( ! bracket || ! winner ) return ;
127140
128- setAdvancedMatches ( prev => ( { ...prev , [ `${ roundIndex } -${ matchIndex } ` ] : winner } ) ) ;
141+ setAdvancedMatches ( prev => ( { ...prev , [ `${ roundIndex } -${ matchIndex } ` ] : { winner, loser } } ) ) ;
129142
130143 if ( roundIndex === bracket . length - 1 ) {
131144 setChampion ( winner ) ;
@@ -206,7 +219,7 @@ function TournamentBracketPage() {
206219 const [ compactLayout , setCompactLayout ] = useState ( false ) ;
207220
208221 return (
209- < div className = "py-16 sm:py-24" >
222+ < div className = "py-16 sm:py-24 min-h-screen " >
210223 < div className = "mx-auto max-w-7xl px-6 lg:px-8 text-gray-300" >
211224 < Link
212225 to = "/apps"
@@ -222,9 +235,9 @@ function TournamentBracketPage() {
222235 < span className = "single-app-color" > tb</ span >
223236 </ h1 >
224237 < hr className = "border-gray-700" />
225- < div className = "flex justify-center items -center mt-8" >
238+ < div className = "flex flex-col justify -center mt-8" >
226239 < div
227- className = "group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-between relative transform transition-all duration-300 ease-in-out scale-105 overflow-hidden h-full w-full max-w-7xl"
240+ className = "group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-start relative w-full max-w-7xl flex-grow "
228241 style = { cardStyle }
229242 >
230243 < div
@@ -239,20 +252,24 @@ function TournamentBracketPage() {
239252 { ! tournamentStarted ? (
240253 < div >
241254 < div className = "mb-8" >
242- < h2 className = "text-2xl font-arvo font-normal mb-4" > Add Competitors</ h2 >
255+ < h2 className = "text-2xl font-arvo font-normal mb-4" > Add Competitors (max 64 competitors, 5 char limit) </ h2 >
243256 < div className = "flex gap-4" >
244257 < input
245258 type = "text"
246259 value = { newCompetitor }
247- onChange = { ( e ) => setNewCompetitor ( e . target . value ) }
260+ onChange = { ( e ) => {
261+ const value = e . target . value ;
262+ setNewCompetitor ( value ) ;
263+ setNewCompetitorCharLimitError ( value . length > 5 ) ;
264+ } }
248265 onKeyDown = { handleNewCompetitorKeyDown }
249266 placeholder = "Enter competitor name"
250- className = " bg-gray-800 text-white p-2 rounded-lg flex-grow"
267+ className = { ` bg-gray-800 text-white p-2 rounded-lg flex-grow ${ newCompetitorCharLimitError ? 'border-red-500 border-2' : '' } ` }
251268 ref = { newCompetitorInputRef }
252269 />
253270 < button
254271 onClick = { addCompetitor }
255- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
272+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
256273 ${ competitors . length >= 64
257274 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
258275 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
@@ -263,11 +280,12 @@ function TournamentBracketPage() {
263280 Add
264281 </ button >
265282 </ div >
283+ { newCompetitorCharLimitError && < p className = "text-red-500 mt-2" > Competitor name cannot exceed 5 characters.</ p > }
266284 { nameError && < p className = "text-red-500 mt-2" > { nameError } </ p > }
267285 { competitors . length >= 64 && < p className = "text-red-500 mt-2" > Maximum of 64 competitors reached.</ p > }
268286 </ div >
269287
270- < div >
288+ < div className = "flex-grow" >
271289 < h2 className = "text-2xl font-arvo font-normal mb-4" > Competitors ({ competitors . length } )</ h2 >
272290 < ul className = "space-y-2" >
273291 { competitors . map ( ( competitor , index ) => (
@@ -285,7 +303,7 @@ function TournamentBracketPage() {
285303 < div className = "flex gap-2" >
286304 { editingIndex === index ? (
287305 < button onClick = { ( ) => saveEdit ( index ) }
288- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
306+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
289307 ${ false // Save button is never disabled based on current logic
290308 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
291309 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
@@ -296,7 +314,7 @@ function TournamentBracketPage() {
296314 </ button >
297315 ) : (
298316 < button onClick = { ( ) => startEditing ( index , competitor ) }
299- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
317+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
300318 ${ false // Edit button is never disabled based on current logic
301319 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
302320 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
@@ -307,7 +325,7 @@ function TournamentBracketPage() {
307325 </ button >
308326 ) }
309327 < button onClick = { ( ) => deleteCompetitor ( index ) }
310- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
328+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
311329 ${ false // Delete button is never disabled based on current logic
312330 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
313331 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
@@ -325,7 +343,7 @@ function TournamentBracketPage() {
325343 < div className = "mt-8" >
326344 < button
327345 onClick = { startTournament }
328- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
346+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
329347 ${ competitors . length < 2
330348 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
331349 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
@@ -361,7 +379,7 @@ function TournamentBracketPage() {
361379 < div key = { roundIndex } className = { `flex flex-col ${ compactLayout ? 'space-y-2' : 'space-y-4' } min-w-max flex-shrink-0` } >
362380 < h3 className = "text-xl font-bold" > Round { roundIndex + 1 } </ h3 >
363381 { round . map ( ( match , matchIndex ) => (
364- < div key = { matchIndex } className = { `group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-between relative transform transition-all duration-300 ease-in-out overflow-hidden w-72 ${ compactLayout ? '' : 'h-full' } ` } style = { cardStyle } >
382+ < div key = { matchIndex } className = { `group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-between relative transform transition-all duration-300 ease-in-out overflow-hidden w-80 ${ compactLayout ? 'min-h-[100px] ' : 'h-full' } ` } style = { cardStyle } >
365383 < div className = "flex justify-between items-center mb-2" >
366384 < div className = "flex items-center gap-2" >
367385 < input
@@ -371,11 +389,11 @@ function TournamentBracketPage() {
371389 onChange = { ( e ) => handleScoreChange ( roundIndex , matchIndex , 0 , e . target . value ) }
372390 disabled = { ! match [ 0 ] || ! match [ 1 ] }
373391 />
374- < span > { match [ 0 ] || 'TBD' } </ span >
392+ < span className = { `break-words ${ match [ 1 ] === null ? 'text-article font-bold' : advancedMatches [ ` ${ roundIndex } - ${ matchIndex } ` ] ?. winner === match [ 0 ] ? 'text-article font-bold' : advancedMatches [ ` ${ roundIndex } - ${ matchIndex } ` ] ?. loser === match [ 0 ] ? 'text-gray-500 line-through' : '' } ` } > { match [ 0 ] || 'TBD' } </ span >
375393 </ div >
376394 < span > vs</ span >
377395 < div className = "flex items-center gap-2" >
378- < span > { match [ 1 ] || ( roundIndex === 0 ? 'Bye' : 'TBD' ) } </ span >
396+ < span className = { `break-words ${ match [ 1 ] === null ? 'text-gray-500 line-through' : advancedMatches [ ` ${ roundIndex } - ${ matchIndex } ` ] ?. winner === match [ 1 ] ? 'text-article font-bold' : advancedMatches [ ` ${ roundIndex } - ${ matchIndex } ` ] ?. loser === match [ 1 ] ? 'text-gray-500 line-through' : '' } ` } > { match [ 1 ] || ( roundIndex === 0 ? 'Bye' : 'TBD' ) } </ span >
379397 < input
380398 type = "number"
381399 className = "bg-gray-700 text-white p-1 rounded-lg w-16"
@@ -392,17 +410,18 @@ function TournamentBracketPage() {
392410 const score2 = scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] ;
393411 if ( score1 === undefined || score2 === undefined || score1 === '' || score2 === '' || score1 === score2 ) return ;
394412 const winner = score1 > score2 ? match [ 0 ] : match [ 1 ] ;
395- advanceWinner ( winner , roundIndex , matchIndex ) ;
413+ const loser = score1 > score2 ? match [ 1 ] : match [ 0 ] ;
414+ advanceWinner ( winner , loser , roundIndex , matchIndex ) ;
396415 } }
397- className = { `flex items-center justify-center gap-2 text-lg font-mono font-normal px-4 py-1 rounded-md border transition-colors duration-300 ease-in-out w-full mb-4
416+ className = { `flex items-center justify-center gap-2 text-lg font-mono font-normal px-4 py-1 rounded-md border transition-colors duration-300 ease-in-out w-full mb-4
398417 ${ advancedMatches [ `${ roundIndex } -${ matchIndex } ` ] || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] === undefined || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] === undefined || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] === '' || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] === '' || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] === scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ]
399418 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
400419 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
401420 } `}
402421 style = { buttonStyle }
403422 disabled = { advancedMatches [ `${ roundIndex } -${ matchIndex } ` ] || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] === undefined || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] === undefined || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] === '' || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] === '' || scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] === scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] }
404423 >
405- { advancedMatches [ `${ roundIndex } -${ matchIndex } ` ] ? `${ advancedMatches [ `${ roundIndex } -${ matchIndex } ` ] } advanced!` : ( roundIndex === bracket . length - 1 ? 'Set Champion' : 'Set Winner' ) }
424+ { advancedMatches [ `${ roundIndex } -${ matchIndex } ` ] ? `${ advancedMatches [ `${ roundIndex } -${ matchIndex } ` ] . winner } advanced!` : ( roundIndex === bracket . length - 1 ? 'Set Champion' : 'Set Winner' ) }
406425 </ button >
407426 ) }
408427 </ div >
@@ -412,25 +431,25 @@ function TournamentBracketPage() {
412431 </ div >
413432 { champion && (
414433 < div className = "mt-8 text-center" >
415- < h2 className = "text-3xl font-bold" > Champion!</ h2 >
434+ < h2 className = "text-3xl font-bold" > 🎉 Champion! 🎉 </ h2 >
416435 < p className = "text-xl font-bold text-yellow-400" > { champion } </ p >
417436 </ div >
418437 ) }
419438 < div className = "mt-8 flex gap-4 justify-center" >
420439 < button
421440 onClick = { resetScores }
422- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
441+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
423442 ${ false // Reset Scores button is never disabled based on current logic
424443 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
425444 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
426445 } `}
427446 style = { buttonStyle }
428447 >
429- Reset Scores
448+ Reset Matches
430449 </ button >
431450 < button
432451 onClick = { resetTournament }
433- className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
452+ className = { `flex items-center gap-2 text-lg font-mono font-normal px-4 py-2 rounded-md border transition-colors duration-300 ease-in-out
434453 ${ false // Reset Tournament button is never disabled based on current logic
435454 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
436455 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
@@ -450,4 +469,4 @@ function TournamentBracketPage() {
450469 ) ;
451470}
452471
453- export default TournamentBracketPage ;
472+ export default TournamentBracketPage ;
0 commit comments