Some checks failed
Deploy to Cloudflare Workers / deploy (push) Has been cancelled
96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
import { notFound } from "next/navigation";
|
|
import { createClient } from "@/lib/supabase/server";
|
|
import { GlassCard } from "@/components/ui/glass-card";
|
|
import { CompetitionDraftPanel } from "@/components/competitions/competition-draft-panel";
|
|
import { StandingsTable } from "@/components/standings/StandingsTable";
|
|
import { TeamBadge } from "@/components/teams/TeamBadge";
|
|
import Link from "next/link";
|
|
|
|
export default async function CompetitionPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ leagueId: string; competitionId: string }>;
|
|
}) {
|
|
const { leagueId, competitionId } = await params;
|
|
const supabase = await createClient();
|
|
|
|
const { data: competition } = await supabase
|
|
.from("competitions")
|
|
.select("*")
|
|
.eq("id", competitionId)
|
|
.single();
|
|
|
|
if (!competition) notFound();
|
|
|
|
const { data: teams } = await supabase
|
|
.from("teams")
|
|
.select("*")
|
|
.eq("competition_id", competitionId)
|
|
.order("name");
|
|
|
|
const { data: standings } = await supabase
|
|
.from("competition_standings")
|
|
.select("*")
|
|
.eq("competition_id", competitionId);
|
|
|
|
const { data: upcoming } = await supabase
|
|
.from("matches")
|
|
.select(
|
|
`*, home:home_team_id(name, logo_path), away:away_team_id(name, logo_path)`
|
|
)
|
|
.eq("competition_id", competitionId)
|
|
.in("status", ["scheduled", "schedule_pending", "schedule_confirmed"])
|
|
.order("scheduled_at")
|
|
.limit(5);
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="flex flex-wrap items-center justify-between gap-4">
|
|
<h1 className="text-2xl font-bold">{competition.name}</h1>
|
|
</div>
|
|
|
|
{competition.status === "draft" && (
|
|
<CompetitionDraftPanel
|
|
competitionId={competitionId}
|
|
initialTeams={teams ?? []}
|
|
/>
|
|
)}
|
|
|
|
{competition.tournament_mode === "league" && standings && standings.length > 0 && (
|
|
<GlassCard title="Standings">
|
|
<StandingsTable standings={standings} />
|
|
</GlassCard>
|
|
)}
|
|
|
|
<GlassCard title="Upcoming fixtures">
|
|
<ul className="space-y-3">
|
|
{upcoming?.map((m) => {
|
|
const home = m.home as { name: string; logo_path: string | null };
|
|
const away = m.away as { name: string; logo_path: string | null };
|
|
return (
|
|
<li key={m.id}>
|
|
<Link
|
|
href={`/leagues/${leagueId}/competitions/${competitionId}/matches/${m.id}`}
|
|
className="flex items-center justify-between rounded-lg border border-white/10 p-3 transition-colors hover:bg-white/5"
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<TeamBadge name={home?.name} logoPath={home?.logo_path} size="sm" />
|
|
<span className="text-[var(--color-muted)]">vs</span>
|
|
<TeamBadge name={away?.name} logoPath={away?.logo_path} size="sm" />
|
|
</div>
|
|
<span className="text-xs text-[var(--color-muted)] capitalize">
|
|
{m.status.replace(/_/g, " ")}
|
|
</span>
|
|
</Link>
|
|
</li>
|
|
);
|
|
})}
|
|
{(!upcoming || upcoming.length === 0) && (
|
|
<p className="text-sm text-[var(--color-muted)]">No upcoming fixtures</p>
|
|
)}
|
|
</ul>
|
|
</GlassCard>
|
|
</div>
|
|
);
|
|
}
|