@@ -153,7 +153,7 @@ function TournamentBracketPage() {
153153 }
154154
155155 setBracket ( newBracket ) ;
156- handleByes ( newBracket ) ;
156+ handleByes ( newBracket , { } ) ;
157157 } ;
158158
159159 const [ champion , setChampion ] = useState ( null ) ;
@@ -212,12 +212,12 @@ function TournamentBracketPage() {
212212 setScores ( newScores ) ;
213213 } ;
214214
215- const handleByes = ( currentBracket ) => {
215+ const handleByes = ( currentBracket , initialAdvancedMatches = { } ) => {
216216 if ( ! currentBracket ) return ;
217217
218218 const newBracket = JSON . parse ( JSON . stringify ( currentBracket ) ) ;
219219 let changed = false ;
220- let updatedAdvancedMatches = { ...advancedMatches } ; // Create a mutable copy
220+ let updatedAdvancedMatches = { ...initialAdvancedMatches } ; // Create a mutable copy
221221
222222 newBracket [ 0 ] . forEach ( ( match , matchIndex ) => {
223223 if ( match [ 0 ] && match [ 1 ] === null ) {
@@ -263,12 +263,12 @@ function TournamentBracketPage() {
263263 < span className = "separator-color" > ::</ span >
264264 < span className = "apps-color" > apps</ span >
265265 < span className = "separator-color" > ::</ span >
266- < span className = "single-app-color" > tb </ span >
266+ < span className = "single-app-color" > tournament-brackets </ span >
267267 </ h1 >
268268 < hr className = "border-gray-700" />
269269 < div className = "flex flex-col justify-center mt-8" >
270270 < div
271- className = "group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-start relative w-full max-w-7xl flex-grow"
271+ className = "group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-start relative w-full flex-grow"
272272 style = { cardStyle }
273273 >
274274 < div
@@ -281,111 +281,129 @@ function TournamentBracketPage() {
281281 > </ div >
282282 < div className = "relative z-10" >
283283 { ! tournamentStarted ? (
284- < div >
285- < div className = "mb-8" >
286- < h2 className = "text-2xl font-arvo font-normal mb-4" > Add Competitors (max 64 competitors, 5 char limit)</ h2 >
287- < div className = "flex gap-4" >
288- < input
289- type = "text"
290- value = { newCompetitor }
291- onChange = { ( e ) => {
292- const value = e . target . value ;
293- setNewCompetitor ( value ) ;
294- setNewCompetitorCharLimitError ( value . length > 5 ) ;
295- } }
296- onKeyDown = { handleNewCompetitorKeyDown }
297- placeholder = "Enter competitor name"
298- className = { `bg-gray-800 text-white p-2 rounded-lg flex-grow ${ newCompetitorCharLimitError ? 'border-red-500 border-2' : '' } ` }
299- ref = { newCompetitorInputRef }
300- />
301- < button
302- onClick = { addCompetitor }
303- 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
304- ${ competitors . length >= 64
305- ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
306- : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
307- } `}
308- style = { buttonStyle }
309- disabled = { competitors . length >= 64 }
310- >
311- Add
312- </ button >
284+ < >
285+ < div >
286+ < div className = "mb-8" >
287+ < h2 className = "text-2xl font-arvo font-normal mb-4" > Add Competitors (max 64 competitors, 5 char limit)</ h2 >
288+ < div className = "flex gap-4" >
289+ < input
290+ type = "text"
291+ value = { newCompetitor }
292+ onChange = { ( e ) => {
293+ const value = e . target . value ;
294+ setNewCompetitor ( value ) ;
295+ setNewCompetitorCharLimitError ( value . length > 5 ) ;
296+ } }
297+ onKeyDown = { handleNewCompetitorKeyDown }
298+ placeholder = "Enter competitor name"
299+ className = { `bg-gray-800 text-white p-2 rounded-lg flex-grow ${ newCompetitorCharLimitError ? 'border-red-500 border-2' : '' } ` }
300+ ref = { newCompetitorInputRef }
301+ />
302+ < button
303+ onClick = { addCompetitor }
304+ 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
305+ ${ competitors . length >= 64
306+ ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
307+ : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
308+ } `}
309+ style = { buttonStyle }
310+ disabled = { competitors . length >= 64 }
311+ >
312+ Add
313+ </ button >
314+ </ div >
315+ { newCompetitorCharLimitError && < p className = "text-red-500 mt-2" > Competitor name cannot exceed 5 characters.</ p > }
316+ { nameError && < p className = "text-red-500 mt-2" > { nameError } </ p > }
317+ { competitors . length >= 64 && < p className = "text-red-500 mt-2" > Maximum of 64 competitors reached.</ p > }
313318 </ div >
314- { newCompetitorCharLimitError && < p className = "text-red-500 mt-2" > Competitor name cannot exceed 5 characters.</ p > }
315- { nameError && < p className = "text-red-500 mt-2" > { nameError } </ p > }
316- { competitors . length >= 64 && < p className = "text-red-500 mt-2" > Maximum of 64 competitors reached.</ p > }
317- </ div >
318319
319- < div className = "flex-grow" >
320- < h2 className = "text-2xl font-arvo font-normal mb-4" > Competitors ({ competitors . length } )</ h2 >
321- < ul className = "space-y-2" >
322- { competitors . map ( ( competitor , index ) => (
323- < li key = { index } className = "flex items-center justify-between bg-gray-800 p-2 rounded-lg" >
324- { editingIndex === index ? (
325- < input
326- type = "text"
327- value = { editingText }
328- onChange = { ( e ) => setEditingText ( e . target . value ) }
329- className = "bg-gray-700 text-white p-1 rounded-lg flex-grow"
330- />
331- ) : (
332- < span > { competitor } </ span >
333- ) }
334- < div className = "flex gap-2" >
320+ < div className = "flex-grow" >
321+ < h2 className = "text-2xl font-arvo font-normal mb-4" > Competitors ({ competitors . length } )</ h2 >
322+ < ul className = "space-y-2" >
323+ { competitors . map ( ( competitor , index ) => (
324+ < li key = { index } className = "flex items-center justify-between bg-gray-800 p-2 rounded-lg" >
335325 { editingIndex === index ? (
336- < button onClick = { ( ) => saveEdit ( index ) }
337- 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
338- ${ false // Save button is never disabled based on current logic
339- ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
340- : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
341- } `}
342- style = { buttonStyle }
343- >
344- Save
345- </ button >
326+ < input
327+ type = "text"
328+ value = { editingText }
329+ onChange = { ( e ) => setEditingText ( e . target . value ) }
330+ className = "bg-gray-700 text-white p-1 rounded-lg flex-grow"
331+ />
346332 ) : (
347- < button onClick = { ( ) => startEditing ( index , competitor ) }
333+ < span > { competitor } </ span >
334+ ) }
335+ < div className = "flex gap-2" >
336+ { editingIndex === index ? (
337+ < button onClick = { ( ) => saveEdit ( index ) }
338+ 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
339+ ${ false // Save button is never disabled based on current logic
340+ ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
341+ : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
342+ } `}
343+ style = { buttonStyle }
344+ >
345+ Save
346+ </ button >
347+ ) : (
348+ < button onClick = { ( ) => startEditing ( index , competitor ) }
349+ 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
350+ ${ false // Edit button is never disabled based on current logic
351+ ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
352+ : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
353+ } `}
354+ style = { buttonStyle }
355+ >
356+ Edit
357+ </ button >
358+ ) }
359+ < button onClick = { ( ) => deleteCompetitor ( index ) }
348360 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
349- ${ false // Edit button is never disabled based on current logic
361+ ${ false // Delete button is never disabled based on current logic
350362 ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
351363 : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
352364 } `}
353365 style = { buttonStyle }
354366 >
355- Edit
367+ Delete
356368 </ button >
357- ) }
358- < button onClick = { ( ) => deleteCompetitor ( index ) }
359- 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
360- ${ false // Delete button is never disabled based on current logic
361- ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
362- : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
363- } `}
364- style = { buttonStyle }
365- >
366- Delete
367- </ button >
368- </ div >
369- </ li >
370- ) ) }
371- </ ul >
369+ </ div >
370+ </ li >
371+ ) ) }
372+ </ ul >
373+ </ div >
374+
375+ < div className = "mt-8" >
376+ < button
377+ onClick = { startTournament }
378+ 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
379+ ${ competitors . length < 2
380+ ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
381+ : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
382+ } `}
383+ style = { buttonStyle }
384+ disabled = { competitors . length < 2 }
385+ >
386+ Start Tournament
387+ </ button >
388+ </ div >
372389 </ div >
373390
374391 < div className = "mt-8" >
375- < button
376- onClick = { startTournament }
377- 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
378- ${ competitors . length < 2
379- ? 'bg-gray-600 text-gray-400 cursor-not-allowed'
380- : `bg-[${ colors . app } ] text-white hover:bg-[${ colors . app } ]`
381- } `}
382- style = { buttonStyle }
383- disabled = { competitors . length < 2 }
384- >
385- Start Tournament
386- </ button >
392+ < h2 className = "text-2xl font-arvo font-normal mb-4" > How it works</ h2 >
393+ < p className = "text-gray-400" >
394+ ✦ This tournament bracket generator creates a single-elimination bracket. < br />
395+ ✦ The number of rounds and BYEs are automatically calculated based on the number of competitors. < br />
396+ ✦ Competitors are randomly seeded. < br />
397+ ✦ Enter scores for each match to advance the winner to the next round. < br />
398+ < br />
399+ As an example, for 20 teams: < br />
400+ ✦ The next power of 2 greater than or equal to 20 is 32 (2^5). < br />
401+ ✦ The number of BYEs is calculated as bracketSize - numCompetitors. < br />
402+ ✦ Therefore, 32 - 20 = 12 BYEs. < br />
403+ ✦ There will be 12 BYEs for 20 teams. < br />
404+ </ p >
387405 </ div >
388- </ div >
406+ </ >
389407 ) : (
390408 < div >
391409 < div className = "flex items-center justify-between mb-4" >
@@ -405,7 +423,7 @@ function TournamentBracketPage() {
405423 < div className = "ml-3 text-gray-300" > Compact Layout</ div >
406424 </ label >
407425 </ div >
408- < div className = "flex space-x-4 overflow-x-auto pb-4" >
426+ < div className = "flex space-x-4 overflow-x-auto pb-4 px-4 " >
409427 { bracket && bracket . map ( ( round , roundIndex ) => (
410428 < div key = { roundIndex } className = { `flex flex-col ${ compactLayout ? 'space-y-2' : 'space-y-4' } min-w-max flex-shrink-0 ${ roundIndex === currentRoundIndex ? 'border-2 border-yellow-400 p-2 rounded-lg' : '' } ` } >
411429 < h3 className = "text-xl font-bold" > Round { roundIndex + 1 } </ h3 >
@@ -437,9 +455,9 @@ function TournamentBracketPage() {
437455 { match [ 0 ] && match [ 1 ] && (
438456 < button
439457 onClick = { ( ) => {
440- const score1 = scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] ;
441- const score2 = scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] ;
442- if ( score1 === undefined || score2 === undefined || score1 === '' || score2 === '' || score1 === score2 ) return ;
458+ const score1 = parseInt ( scores [ roundIndex ] ?. [ matchIndex ] ?. [ 0 ] , 10 ) ;
459+ const score2 = parseInt ( scores [ roundIndex ] ?. [ matchIndex ] ?. [ 1 ] , 10 ) ;
460+ if ( isNaN ( score1 ) || isNaN ( score2 ) || score1 === score2 ) return ;
443461 const winner = score1 > score2 ? match [ 0 ] : match [ 1 ] ;
444462 const loser = score1 > score2 ? match [ 1 ] : match [ 0 ] ;
445463 advanceWinner ( winner , loser , roundIndex , matchIndex ) ;
0 commit comments