- {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
)}
| |