diff --git a/e2e/cucumber/features/tournament-schedule.feature b/e2e/cucumber/features/tournament-schedule.feature index 548b2ff..b28d9e9 100644 --- a/e2e/cucumber/features/tournament-schedule.feature +++ b/e2e/cucumber/features/tournament-schedule.feature @@ -11,7 +11,7 @@ Feature: Tournament Schedule Then I should see "Schedule" And I should see the "Generate Schedule" button - @happy-path @tournament @issue-7 @wip + @happy-path @tournament @issue-7 Scenario: Tournament admin generates round-robin schedule Given I am logged in as a tournament admin And a tournament exists with 4 teams @@ -21,7 +21,7 @@ Feature: Tournament Schedule And I should see round 1 matchups And I should see round 2 matchups - @happy-path @tournament @issue-7 @wip + @happy-path @tournament @issue-7 Scenario: Tournament admin views schedule with bye rounds Given I am logged in as a tournament admin And a tournament exists with 5 teams @@ -30,7 +30,7 @@ Feature: Tournament Schedule Then I should see a bye round for one team And each team should play every other team exactly once - @happy-path @tournament @issue-7 @wip + @happy-path @tournament @issue-7 Scenario: Tournament admin clicks on a matchup to enter results Given I am logged in as a tournament admin And a tournament has a generated schedule diff --git a/justfile b/justfile index 5de1e11..679b98d 100644 --- a/justfile +++ b/justfile @@ -212,8 +212,6 @@ help: clean: @echo "Cleaning project..." rm -rf node_modules .next dist - @echo "Cleaning Docker artifacts..." - docker system prune -f # Generate Prisma client prisma-generate: diff --git a/src/app/admin/tournaments/[id]/schedule/page.tsx b/src/app/admin/tournaments/[id]/schedule/page.tsx index 0ea0a32..370e695 100644 --- a/src/app/admin/tournaments/[id]/schedule/page.tsx +++ b/src/app/admin/tournaments/[id]/schedule/page.tsx @@ -2,6 +2,8 @@ import { prisma } from "@/lib/prisma" import Navigation from "@/components/Navigation" import Link from "next/link" import { notFound } from "next/navigation" +import { ScheduleGenerator } from "@/components/ScheduleGenerator" +import { ScheduleDisplay } from "@/components/ScheduleDisplay" interface PageProps { params: Promise<{ @@ -27,6 +29,21 @@ export default async function TournamentSchedulePage({ params }: PageProps) { player: true, }, }, + rounds: { + orderBy: { roundNumber: "asc" }, + include: { + bracketMatchups: { + orderBy: { bracketPosition: "asc" }, + include: { + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, + match: true, + }, + }, + }, + }, }, }) @@ -34,6 +51,9 @@ export default async function TournamentSchedulePage({ params }: PageProps) { notFound() } + const teamCount = tournament.participants.length + const existingRounds = tournament.rounds.length + return (
@@ -53,22 +73,31 @@ export default async function TournamentSchedulePage({ params }: PageProps) { Schedule - {tournament.name} -
+

Tournament Schedule

-
-

- No schedule has been generated yet. Click "Generate Schedule" to create round matchups. -

+ {existingRounds > 0 ? ( + + ) : ( +

+ No schedule has been generated yet. Click "Generate Schedule" to create round matchups. +

+ )} + +
+ +
) -} \ No newline at end of file +} diff --git a/src/components/ScheduleDisplay.tsx b/src/components/ScheduleDisplay.tsx new file mode 100644 index 0000000..a57bbe7 --- /dev/null +++ b/src/components/ScheduleDisplay.tsx @@ -0,0 +1,98 @@ +"use client" + +import Link from "next/link" + +interface Player { + id: number + name: string +} + +interface BracketMatchup { + id: number + player1P1: Player | null + player1P2: Player | null + player2P1: Player | null + player2P2: Player | null + match: { id: number } | null + bracketPosition: number | null + status: string +} + +interface TournamentRound { + id: number + roundNumber: number + status: string + bracketMatchups: BracketMatchup[] +} + +export function ScheduleDisplay({ rounds }: { rounds: TournamentRound[] }) { + return ( +
+ {rounds.map((round) => ( +
+

+ Round {round.roundNumber} + + ({round.status}) + +

+ +
+ {round.bracketMatchups.map((matchup) => { + const team1 = [ + matchup.player1P1?.name, + matchup.player1P2?.name, + ] + .filter(Boolean) + .join(" + ") + + const team2 = [ + matchup.player2P1?.name, + matchup.player2P2?.name, + ] + .filter(Boolean) + .join(" + ") + + const content = ( +
+
+ + {team1 || "TBD"} + + vs + + {team2 || "TBD"} + +
+
+ {matchup.status === "pending" ? ( + Pending + ) : matchup.match ? ( + Completed + ) : ( + {matchup.status} + )} +
+
+ ) + + if (matchup.match) { + return ( + + {content} + + ) + } + + return
{content}
+ })} +
+
+ ))} +
+ ) +}