Some checks failed
Deploy to Cloudflare Workers / deploy (push) Has been cancelled
125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
import { notFound } from "next/navigation";
|
||
import { createClient } from "@/lib/supabase/server";
|
||
import { MatchActions } from "./match-actions";
|
||
import { GlassCard } from "@/components/ui/glass-card";
|
||
import { TeamBadge } from "@/components/teams/TeamBadge";
|
||
|
||
export default async function MatchPage({
|
||
params,
|
||
}: {
|
||
params: Promise<{ leagueId: string; competitionId: string; matchId: string }>;
|
||
}) {
|
||
const { leagueId, competitionId, matchId } = await params;
|
||
const supabase = await createClient();
|
||
const {
|
||
data: { user },
|
||
} = await supabase.auth.getUser();
|
||
|
||
const { data: match } = await supabase
|
||
.from("matches")
|
||
.select(
|
||
`*, home:home_team_id(id, name, logo_path), away:away_team_id(id, name, logo_path)`
|
||
)
|
||
.eq("id", matchId)
|
||
.single();
|
||
|
||
if (!match) notFound();
|
||
|
||
const home = match.home as { id: string; name: string; logo_path: string | null };
|
||
const away = match.away as { id: string; name: string; logo_path: string | null };
|
||
|
||
const { data: submissions } = await supabase
|
||
.from("match_result_submissions")
|
||
.select("*, teams(name)")
|
||
.eq("match_id", matchId);
|
||
|
||
const { data: signatures } = await supabase
|
||
.from("match_signatures")
|
||
.select("team_id, teams(name)")
|
||
.eq("match_id", matchId);
|
||
|
||
let userTeamId: string | null = null;
|
||
if (user) {
|
||
const { data: tm } = await supabase
|
||
.from("team_members")
|
||
.select("team_id")
|
||
.eq("user_id", user.id)
|
||
.in("team_id", [home.id, away.id])
|
||
.limit(1)
|
||
.single();
|
||
userTeamId = tm?.team_id ?? null;
|
||
}
|
||
|
||
const { data: isLeagueManager } = user
|
||
? await supabase
|
||
.from("competition_league_managers")
|
||
.select("id")
|
||
.eq("competition_id", competitionId)
|
||
.eq("user_id", user.id)
|
||
.maybeSingle()
|
||
: { data: null };
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<GlassCard>
|
||
<div className="flex flex-wrap items-center justify-center gap-8 py-4">
|
||
<TeamBadge name={home.name} logoPath={home.logo_path} size="lg" />
|
||
<div className="text-center">
|
||
<p className="text-3xl font-bold">
|
||
{match.status === "completed"
|
||
? `${match.home_score} – ${match.away_score}`
|
||
: "vs"}
|
||
</p>
|
||
<p className="mt-1 text-sm capitalize text-[var(--color-muted)]">
|
||
{match.status.replace(/_/g, " ")}
|
||
</p>
|
||
{match.venue && (
|
||
<p className="mt-1 text-xs text-[var(--color-muted)]">{match.venue}</p>
|
||
)}
|
||
</div>
|
||
<TeamBadge name={away.name} logoPath={away.logo_path} size="lg" />
|
||
</div>
|
||
</GlassCard>
|
||
|
||
<div className="grid gap-4 lg:grid-cols-2">
|
||
<GlassCard title="Schedule signatures">
|
||
<ul className="text-sm">
|
||
{signatures?.map((s) => (
|
||
<li key={s.team_id} className="text-emerald-400">
|
||
✓ {(s.teams as { name: string })?.name} signed
|
||
</li>
|
||
))}
|
||
{(!signatures || signatures.length === 0) && (
|
||
<li className="text-[var(--color-muted)]">No signatures yet</li>
|
||
)}
|
||
</ul>
|
||
</GlassCard>
|
||
|
||
<GlassCard title="Result submissions">
|
||
<ul className="space-y-2 text-sm">
|
||
{submissions?.map((s) => (
|
||
<li key={s.team_id}>
|
||
{(s.teams as { name: string })?.name}: {s.home_score}–{s.away_score}
|
||
</li>
|
||
))}
|
||
{(!submissions || submissions.length === 0) && (
|
||
<li className="text-[var(--color-muted)]">No submissions yet</li>
|
||
)}
|
||
</ul>
|
||
</GlassCard>
|
||
</div>
|
||
|
||
<MatchActions
|
||
matchId={matchId}
|
||
homeTeamId={home.id}
|
||
awayTeamId={away.id}
|
||
userTeamId={userTeamId}
|
||
status={match.status}
|
||
resultStatus={match.result_status}
|
||
isLeagueManager={!!isLeagueManager}
|
||
proposedAt={match.proposed_scheduled_at}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|