From 52da77d57bdc39be73a3e825f6bcbe9f52de9cac Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Fri, 3 Apr 2026 21:03:57 -0700 Subject: [PATCH] refactor(ui): update components to use new player field names --- src/app/admin/tournaments/[id]/page.tsx | 65 ++++---------- .../admin/tournaments/[id]/results/page.tsx | 12 +-- .../admin/tournaments/[id]/schedule/page.tsx | 30 +++---- src/app/matches/[id]/page.tsx | 88 ++++++++++--------- src/app/matches/page.tsx | 12 +-- src/app/page.tsx | 12 +-- src/app/players/[id]/profile/page.tsx | 48 +++++----- src/app/players/[id]/schedule/page.tsx | 60 ++++++------- src/components/TeamsSection.tsx | 78 ++++++++++------ 9 files changed, 193 insertions(+), 212 deletions(-) diff --git a/src/app/admin/tournaments/[id]/page.tsx b/src/app/admin/tournaments/[id]/page.tsx index 1c6255a..e9cc8bb 100644 --- a/src/app/admin/tournaments/[id]/page.tsx +++ b/src/app/admin/tournaments/[id]/page.tsx @@ -40,28 +40,14 @@ export default async function TournamentDetailPage({ params }: PageProps) { player: true, }, }, - teams: { - include: { - player1: true, - player2: true, - }, - }, rounds: { include: { bracketMatchups: { include: { - team1: { - include: { - player1: true, - player2: true, - }, - }, - team2: { - include: { - player1: true, - player2: true, - }, - }, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, match: true, }, }, @@ -86,28 +72,14 @@ export default async function TournamentDetailPage({ params }: PageProps) { player: true, }, }, - teams: { - include: { - player1: true, - player2: true, - }, - }, rounds: { include: { bracketMatchups: { include: { - team1: { - include: { - player1: true, - player2: true, - }, - }, - team2: { - include: { - player1: true, - player2: true, - }, - }, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, match: true, }, }, @@ -120,10 +92,10 @@ export default async function TournamentDetailPage({ params }: PageProps) { const matches = await prisma.match.findMany({ where: { eventId: tournamentId }, include: { - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "desc" }, }) @@ -204,12 +176,6 @@ export default async function TournamentDetailPage({ params }: PageProps) { {tournament.participants.length}

-
-

Teams

-

- {tournament.teams.length} -

-

Rounds

@@ -217,7 +183,7 @@ export default async function TournamentDetailPage({ params }: PageProps) {

-

Matches

+

Matchups

{matches.length}

@@ -287,7 +253,6 @@ export default async function TournamentDetailPage({ params }: PageProps) { {/* Teams Section */} ({ id: p.player.id, name: p.player.name, @@ -317,8 +282,8 @@ export default async function TournamentDetailPage({ params }: PageProps) { {match.playedAt?.toLocaleDateString()}

- {match.team1P1.name} + {match.team1P2.name} vs{" "} - {match.team2P1.name} + {match.team2P2.name} + {match.player1P1?.name} + {match.player1P2?.name} vs{" "} + {match.player2P1?.name} + {match.player2P2?.name}

diff --git a/src/app/admin/tournaments/[id]/results/page.tsx b/src/app/admin/tournaments/[id]/results/page.tsx index 6ba41e5..ed68d6f 100644 --- a/src/app/admin/tournaments/[id]/results/page.tsx +++ b/src/app/admin/tournaments/[id]/results/page.tsx @@ -38,10 +38,10 @@ export default async function TournamentResultsPage({ params }: PageProps) { const matches = await prisma.match.findMany({ where: { eventId: tournamentId }, include: { - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "desc" }, }) @@ -114,8 +114,8 @@ export default async function TournamentResultsPage({ params }: PageProps) { {match.playedAt?.toLocaleDateString()}

- {match.team1P1.name} + {match.team1P2.name} vs{" "} - {match.team2P1.name} + {match.team2P2.name} + {match.player1P1?.name} + {match.player1P2?.name} vs{" "} + {match.player2P1?.name} + {match.player2P2?.name}

diff --git a/src/app/admin/tournaments/[id]/schedule/page.tsx b/src/app/admin/tournaments/[id]/schedule/page.tsx index a6fea79..34a3f7a 100644 --- a/src/app/admin/tournaments/[id]/schedule/page.tsx +++ b/src/app/admin/tournaments/[id]/schedule/page.tsx @@ -34,23 +34,15 @@ export default async function TournamentSchedulePage({ params }: PageProps) { const tournament = await prisma.event.findUnique({ where: { id: tournamentId }, include: { - teams: { - include: { - player1: true, - player2: true, - }, - }, rounds: { orderBy: { roundNumber: "asc" }, include: { bracketMatchups: { include: { - team1: { - include: { player1: true, player2: true }, - }, - team2: { - include: { player1: true, player2: true }, - }, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, match: true, }, }, @@ -94,7 +86,7 @@ export default async function TournamentSchedulePage({ params }: PageProps) {

Tournament Schedule

- {tournament.name} — {tournament.teams.length} teams + {tournament.name}

@@ -106,7 +98,7 @@ export default async function TournamentSchedulePage({ params }: PageProps) {
)} @@ -128,11 +120,11 @@ export default async function TournamentSchedulePage({ params }: PageProps) { ) : (
{round.bracketMatchups.map((matchup) => { - const team1Name = matchup.team1 - ? `${matchup.team1.player1.name} + ${matchup.team1.player2.name}` + const team1Name = matchup.player1P1 && matchup.player1P2 + ? `${matchup.player1P1.name} + ${matchup.player1P2.name}` : "TBD" - const team2Name = matchup.team2 - ? `${matchup.team2.player1.name} + ${matchup.team2.player2.name}` + const team2Name = matchup.player2P1 && matchup.player2P2 + ? `${matchup.player2P1.name} + ${matchup.player2P2.name}` : "TBD" return ( @@ -208,7 +200,7 @@ export default async function TournamentSchedulePage({ params }: PageProps) {
)} diff --git a/src/app/matches/[id]/page.tsx b/src/app/matches/[id]/page.tsx index e333b83..12e41a6 100644 --- a/src/app/matches/[id]/page.tsx +++ b/src/app/matches/[id]/page.tsx @@ -22,10 +22,10 @@ export default async function MatchDetailPage({ params }: PageProps) { const match = await prisma.match.findUnique({ where: { id: matchId }, include: { - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, event: true, eloSnapshots: { include: { @@ -93,13 +93,13 @@ export default async function MatchDetailPage({ params }: PageProps) {

- {match.team1P1.name} + {match.player1P1?.name}

- Elo: {match.team1P1.currentElo} - {eloChanges[match.team1P1.id] !== undefined && ( - = 0 ? "text-green-600 ml-1" : "text-red-600 ml-1"}> - ({eloChanges[match.team1P1.id] >= 0 ? "+" : ""}{eloChanges[match.team1P1.id]}) + Elo: {match.player1P1?.currentElo} + {match.player1P1 && eloChanges[match.player1P1.id] !== undefined && ( + = 0 ? "text-green-600 ml-1" : "text-red-600 ml-1"}> + ({eloChanges[match.player1P1.id] >= 0 ? "+" : ""}{eloChanges[match.player1P1.id]}) )}

@@ -112,13 +112,13 @@ export default async function MatchDetailPage({ params }: PageProps) {
Team 1

- {match.team1P2.name} + {match.player1P2?.name}

- Elo: {match.team1P2.currentElo} - {eloChanges[match.team1P2.id] !== undefined && ( - = 0 ? "text-green-600 ml-1" : "text-red-600 ml-1"}> - ({eloChanges[match.team1P2.id] >= 0 ? "+" : ""}{eloChanges[match.team1P2.id]}) + Elo: {match.player1P2?.currentElo} + {match.player1P2 && eloChanges[match.player1P2.id] !== undefined && ( + = 0 ? "text-green-600 ml-1" : "text-red-600 ml-1"}> + ({eloChanges[match.player1P2.id] >= 0 ? "+" : ""}{eloChanges[match.player1P2.id]}) )}

@@ -129,13 +129,13 @@ export default async function MatchDetailPage({ params }: PageProps) {

- {match.team2P1.name} + {match.player2P1?.name}

- Elo: {match.team2P1.currentElo} - {eloChanges[match.team2P1.id] !== undefined && ( - = 0 ? "text-green-600" : "text-red-600"}> - ({eloChanges[match.team2P1.id] >= 0 ? "+" : ""}{eloChanges[match.team2P1.id]}) + Elo: {match.player2P1?.currentElo} + {match.player2P1 && eloChanges[match.player2P1.id] !== undefined && ( + = 0 ? "text-green-600" : "text-red-600"}> + ({eloChanges[match.player2P1.id] >= 0 ? "+" : ""}{eloChanges[match.player2P1.id]}) )}

@@ -146,13 +146,13 @@ export default async function MatchDetailPage({ params }: PageProps) {

- {match.team2P2.name} + {match.player2P2?.name}

- Elo: {match.team2P2.currentElo} - {eloChanges[match.team2P2.id] !== undefined && ( - = 0 ? "text-green-600" : "text-red-600"}> - ({eloChanges[match.team2P2.id] >= 0 ? "+" : ""}{eloChanges[match.team2P2.id]}) + Elo: {match.player2P2?.currentElo} + {match.player2P2 && eloChanges[match.player2P2.id] !== undefined && ( + = 0 ? "text-green-600" : "text-red-600"}> + ({eloChanges[match.player2P2.id] >= 0 ? "+" : ""}{eloChanges[match.player2P2.id]}) )}

@@ -246,16 +246,20 @@ export default async function MatchDetailPage({ params }: PageProps) {

Team 1

- {match.team1P1.name} - = 0 ? "text-green-600" : "text-red-600"}> - {eloChanges[match.team1P1.id] >= 0 ? "+" : ""}{eloChanges[match.team1P1.id]} - + {match.player1P1?.name} + {match.player1P1 && ( + = 0 ? "text-green-600" : "text-red-600"}> + {eloChanges[match.player1P1.id] >= 0 ? "+" : ""}{eloChanges[match.player1P1.id]} + + )}
- {match.team1P2.name} - = 0 ? "text-green-600" : "text-red-600"}> - {eloChanges[match.team1P2.id] >= 0 ? "+" : ""}{eloChanges[match.team1P2.id]} - + {match.player1P2?.name} + {match.player1P2 && ( + = 0 ? "text-green-600" : "text-red-600"}> + {eloChanges[match.player1P2.id] >= 0 ? "+" : ""}{eloChanges[match.player1P2.id]} + + )}
@@ -265,16 +269,20 @@ export default async function MatchDetailPage({ params }: PageProps) {

Team 2

- {match.team2P1.name} - = 0 ? "text-green-600" : "text-red-600"}> - {eloChanges[match.team2P1.id] >= 0 ? "+" : ""}{eloChanges[match.team2P1.id]} - + {match.player2P1?.name} + {match.player2P1 && ( + = 0 ? "text-green-600" : "text-red-600"}> + {eloChanges[match.player2P1.id] >= 0 ? "+" : ""}{eloChanges[match.player2P1.id]} + + )}
- {match.team2P2.name} - = 0 ? "text-green-600" : "text-red-600"}> - {eloChanges[match.team2P2.id] >= 0 ? "+" : ""}{eloChanges[match.team2P2.id]} - + {match.player2P2?.name} + {match.player2P2 && ( + = 0 ? "text-green-600" : "text-red-600"}> + {eloChanges[match.player2P2.id] >= 0 ? "+" : ""}{eloChanges[match.player2P2.id]} + + )}
diff --git a/src/app/matches/page.tsx b/src/app/matches/page.tsx index 0a301e0..95a1d16 100644 --- a/src/app/matches/page.tsx +++ b/src/app/matches/page.tsx @@ -25,10 +25,10 @@ export default async function MatchesListPage() { orderBy: { createdAt: "desc" }, take: 50, include: { - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, event: true, }, }); @@ -84,10 +84,10 @@ export default async function MatchesListPage() { #{match.id} - {match.team1P1.name} & {match.team1P2.name} + {match.player1P1?.name} & {match.player1P2?.name} - {match.team2P1.name} & {match.team2P2.name} + {match.player2P1?.name} & {match.player2P2?.name} {match.team1Score} diff --git a/src/app/page.tsx b/src/app/page.tsx index e8a9998..b52596e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -24,10 +24,10 @@ export default async function Home() { include: { matches: { include: { - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "desc" }, }, @@ -178,7 +178,7 @@ export default async function Home() {
- {match.team1P1.name} & {match.team1P2.name} + {match.player1P1?.name} & {match.player1P2?.name}
{match.team1Score} @@ -187,7 +187,7 @@ export default async function Home() {
vs
- {match.team2P1.name} & {match.team2P2.name} + {match.player2P1?.name} & {match.player2P2?.name}
{match.team2Score} diff --git a/src/app/players/[id]/profile/page.tsx b/src/app/players/[id]/profile/page.tsx index 445760c..bf72608 100644 --- a/src/app/players/[id]/profile/page.tsx +++ b/src/app/players/[id]/profile/page.tsx @@ -64,17 +64,17 @@ export default async function PlayerProfilePage({ params }: PageProps) { const recentMatches = await prisma.match.findMany({ where: { OR: [ - { team1P1Id: playerId }, - { team1P2Id: playerId }, - { team2P1Id: playerId }, - { team2P2Id: playerId }, + { player1P1Id: playerId }, + { player1P2Id: playerId }, + { player2P1Id: playerId }, + { player2P2Id: playerId }, ], }, include: { - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, event: true, }, orderBy: { playedAt: "desc" }, @@ -247,18 +247,18 @@ export default async function PlayerProfilePage({ params }: PageProps) { {recentMatches.map((match) => { - const isTeam1 = match.team1P1Id === playerId || match.team1P2Id === playerId; + const isTeam1 = match.player1P1Id === playerId || match.player1P2Id === playerId; const teamWon = isTeam1 ? match.team1Score > match.team2Score : match.team2Score > match.team1Score; const teamScore = isTeam1 ? match.team1Score : match.team2Score; const opponentScore = isTeam1 ? match.team2Score : match.team1Score; const teammate = isTeam1 - ? (match.team1P1Id === playerId ? match.team1P2 : match.team1P1) - : (match.team2P1Id === playerId ? match.team2P2 : match.team2P1); + ? (match.player1P1Id === playerId ? match.player1P2 : match.player1P1) + : (match.player2P1Id === playerId ? match.player2P2 : match.player2P1); const opponents = isTeam1 - ? [match.team2P1, match.team2P2] - : [match.team1P1, match.team1P2]; + ? [match.player2P1, match.player2P2] + : [match.player1P1, match.player1P2]; return ( @@ -276,21 +276,23 @@ export default async function PlayerProfilePage({ params }: PageProps) { {match.event?.name || "N/A"} - - {teammate.name} - + {teammate && ( + + {teammate.name} + + )} - {opponents.map((opponent, index) => ( - + {opponents.filter(o => o !== null).map((opponent, index) => ( + - {opponent.name} + {opponent?.name} {index < opponents.length - 1 ? ", " : ""} diff --git a/src/app/players/[id]/schedule/page.tsx b/src/app/players/[id]/schedule/page.tsx index 46f2932..8372598 100644 --- a/src/app/players/[id]/schedule/page.tsx +++ b/src/app/players/[id]/schedule/page.tsx @@ -27,10 +27,10 @@ export default async function PlayerSchedulePage({ params }: PageProps) { where: { playedAt: { gte: new Date() } }, include: { event: true, - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "asc" }, }, @@ -38,10 +38,10 @@ export default async function PlayerSchedulePage({ params }: PageProps) { where: { playedAt: { gte: new Date() } }, include: { event: true, - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "asc" }, }, @@ -49,10 +49,10 @@ export default async function PlayerSchedulePage({ params }: PageProps) { where: { playedAt: { gte: new Date() } }, include: { event: true, - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "asc" }, }, @@ -60,10 +60,10 @@ export default async function PlayerSchedulePage({ params }: PageProps) { where: { playedAt: { gte: new Date() } }, include: { event: true, - team1P1: true, - team1P2: true, - team2P1: true, - team2P2: true, + player1P1: true, + player1P2: true, + player2P1: true, + player2P2: true, }, orderBy: { playedAt: "asc" }, }, @@ -94,12 +94,6 @@ export default async function PlayerSchedulePage({ params }: PageProps) { }, include: { participants: true, - teams: { - include: { - player1: true, - player2: true, - }, - }, }, }) @@ -125,13 +119,13 @@ export default async function PlayerSchedulePage({ params }: PageProps) {
{upcomingMatches.map((match) => { const team1Players = [ - match.team1P1.name, - match.team1P2.name, - ].join(" + ") + match.player1P1?.name, + match.player1P2?.name, + ].filter(Boolean).join(" + ") const team2Players = [ - match.team2P1.name, - match.team2P2.name, - ].join(" + ") + match.player2P1?.name, + match.player2P2?.name, + ].filter(Boolean).join(" + ") return (
{activeTournaments.map((tournament) => { - const playerTeam = tournament.teams.find( - (team) => - team.player1Id === playerId || team.player2Id === playerId + // Since teams are now ephemeral, just check if player is a participant + const isParticipant = tournament.participants.some( + (p) => p.playerId === playerId ) return ( @@ -192,9 +186,9 @@ export default async function PlayerSchedulePage({ params }: PageProps) {

{tournament.format} - {tournament.status}

- {playerTeam && ( + {isParticipant && (

- Team: {playerTeam.player1.name} + {playerTeam.player2.name} + Participant in tournament

)}
diff --git a/src/components/TeamsSection.tsx b/src/components/TeamsSection.tsx index eeee568..5d860ad 100644 --- a/src/components/TeamsSection.tsx +++ b/src/components/TeamsSection.tsx @@ -18,7 +18,6 @@ interface Team { interface TeamsSectionProps { tournamentId: number - teams: Team[] participants: Player[] teamDurability: string partnerRotation: string @@ -30,14 +29,13 @@ type PartnerRotationOption = 'none' | 'minimize_repeat' | 'maximize_even' | 'elo export default function TeamsSection({ tournamentId, - teams: initialTeams, participants, teamDurability: initialTeamDurability, partnerRotation: initialPartnerRotation, allowByes: initialAllowByes, }: TeamsSectionProps) { const router = useRouter() - const [teams, setTeams] = useState(initialTeams) + const [teams, setTeams] = useState([]) const [teamDurability, setTeamDurability] = useState(initialTeamDurability as TeamDurabilityOption) const [partnerRotation, setPartnerRotation] = useState(initialPartnerRotation as PartnerRotationOption) const [allowByes, setAllowByes] = useState(initialAllowByes) @@ -85,9 +83,9 @@ export default function TeamsSection({ } } - const handleGenerateTeams = async () => { + const handleGenerateSchedule = async () => { if (participants.length < 2) { - setError("At least 2 participants are required to generate teams") + setError("At least 2 participants are required to generate a schedule") return } @@ -101,31 +99,58 @@ export default function TeamsSection({ setIsGenerating(true) try { - const response = await fetch(`/api/tournaments/${tournamentId}/teams/generate`, { + const response = await fetch(`/api/tournaments/${tournamentId}/schedule`, { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - teamDurability, - partnerRotation, - allowByes, - }), }) if (!response.ok) { try { const errorData = await response.json() - setError(errorData.error || "Failed to generate teams") + setError(errorData.error || "Failed to generate schedule") } catch { - setError(`Failed to generate teams: ${response.status} ${response.statusText}`) + setError(`Failed to generate schedule: ${response.status} ${response.statusText}`) } + setIsGenerating(false) return } const data = await response.json() - setTeams(data.teams) - setSuccess(`Successfully generated ${data.teams.length} teams!`) + // Update teams from the generated schedule + // Extract teams from round matchups + const generatedTeams: Team[] = [] + for (const round of data.rounds) { + for (const matchup of round.bracketMatchups) { + // Add unique teams + const team1 = { + id: 0, + teamName: `${matchup.player1P1.name} & ${matchup.player1P2.name}`, + player1: matchup.player1P1, + player2: matchup.player1P2, + } + const team2 = { + id: 0, + teamName: `${matchup.player2P1.name} & ${matchup.player2P2.name}`, + player1: matchup.player2P1, + player2: matchup.player2P2, + } + + // Check if team already exists + const existingTeam1 = generatedTeams.find( + t => t.player1.id === team1.player1.id && t.player2.id === team1.player2.id + ) + if (!existingTeam1) generatedTeams.push(team1) + + const existingTeam2 = generatedTeams.find( + t => t.player1.id === team2.player1.id && t.player2.id === team2.player2.id + ) + if (!existingTeam2) generatedTeams.push(team2) + } + } + setTeams(generatedTeams) + setSuccess(`Successfully generated ${data.roundsCreated} rounds with ${data.matchupsCreated} matchups!`) router.refresh() } catch (err) { if (err instanceof Error) { @@ -139,7 +164,7 @@ export default function TeamsSection({ } const handleDeleteTeams = async () => { - if (!confirm("Are you sure you want to delete all teams? This will also delete the schedule.")) { + if (!confirm("Are you sure you want to delete the schedule? This will remove all rounds and matchups.")) { return } @@ -148,28 +173,23 @@ export default function TeamsSection({ setIsGenerating(true) try { - // First delete schedule if exists - await fetch(`/api/tournaments/${tournamentId}/schedule`, { - method: "DELETE", - }) - - // Then delete teams - const response = await fetch(`/api/tournaments/${tournamentId}/teams`, { + // Delete schedule (which includes matchups/rounds) + const response = await fetch(`/api/tournaments/${tournamentId}/schedule`, { method: "DELETE", }) if (!response.ok) { try { const errorData = await response.json() - setError(errorData.error || "Failed to delete teams") + setError(errorData.error || "Failed to delete schedule") } catch { - setError(`Failed to delete teams: ${response.status} ${response.statusText}`) + setError(`Failed to delete schedule: ${response.status} ${response.statusText}`) } return } setTeams([]) - setSuccess("Teams deleted successfully!") + setSuccess("Schedule deleted successfully!") router.refresh() } catch (err) { if (err instanceof Error) { @@ -349,11 +369,11 @@ export default function TeamsSection({ {/* Team Generation Controls */}
{teams.length > 0 && ( @@ -362,7 +382,7 @@ export default function TeamsSection({ disabled={isGenerating} className="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 disabled:opacity-50 text-sm" > - Delete All Teams + Delete Schedule )}