Skip to content

Commit ed4eef4

Browse files
committed
fix: tournament brackets
1 parent 9c6baa0 commit ed4eef4

File tree

2 files changed

+120
-102
lines changed

2 files changed

+120
-102
lines changed

src/components/Sidebar.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ const Sidebar = ({ isOpen, toggleSidebar, toggleModal }) => {
228228
<span className="flex items-center gap-2 font-sans text-white">
229229
<AlienIcon size={16} />
230230
<span>Extras</span>
231-
<LinkIcon size={16} className="text-emerald-200"/>
231+
<LinkIcon size={16} className="text-rose-400"/>
232232

233233
</span>
234234

@@ -259,7 +259,7 @@ const Sidebar = ({ isOpen, toggleSidebar, toggleModal }) => {
259259
<span className="flex items-center gap-2 font-sans text-white">
260260
<JoystickIcon size={16} />
261261
<span>Games</span>
262-
<ArrowSquareOutIcon size={16} className="text-emerald-200"/>
262+
<ArrowSquareOutIcon size={16} className="text-rose-400"/>
263263
</span>
264264
<CaretDownIcon
265265
size={20}
@@ -301,7 +301,7 @@ const Sidebar = ({ isOpen, toggleSidebar, toggleModal }) => {
301301
<span className="flex items-center gap-2 font-sans text-white">
302302
<AnchorIcon size={16} />
303303
<span>External Links</span>
304-
<ArrowSquareOutIcon size={16} className="text-emerald-200"/>
304+
<ArrowSquareOutIcon size={16} className="text-rose-400"/>
305305
</span>
306306

307307
<CaretDownIcon

src/pages/apps/TournamentBracketPage.js

Lines changed: 117 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)