Some checks failed
Deploy to Cloudflare Workers / deploy (push) Has been cancelled
97 lines
3.4 KiB
TypeScript
97 lines
3.4 KiB
TypeScript
import { createClient } from "@/lib/supabase/server";
|
|
import { getCurrentProfile } from "@/lib/auth/profile";
|
|
import { PageHeader } from "@/components/dashboard/page-header";
|
|
import { GlassCard } from "@/components/ui/glass-card";
|
|
import Link from "next/link";
|
|
import { parseLeagueRules, defaultLeagueRules } from "@/lib/rules/schema";
|
|
|
|
export default async function ManagerRulesPage() {
|
|
const supabase = await createClient();
|
|
const ctx = await getCurrentProfile();
|
|
|
|
const { data: memberships } = await supabase
|
|
.from("team_members")
|
|
.select("teams(competition_id, competitions(league_id, name, leagues(name)))")
|
|
.eq("user_id", ctx!.user.id)
|
|
.eq("role", "manager");
|
|
|
|
const leagueIds = new Set<string>();
|
|
const leagueNames = new Map<string, string>();
|
|
|
|
memberships?.forEach((m) => {
|
|
const team = m.teams as {
|
|
competitions: { league_id: string; leagues: { name: string } | null } | null;
|
|
} | null;
|
|
const leagueId = team?.competitions?.league_id;
|
|
const name = team?.competitions?.leagues?.name;
|
|
if (leagueId) {
|
|
leagueIds.add(leagueId);
|
|
if (name) leagueNames.set(leagueId, name);
|
|
}
|
|
});
|
|
|
|
const rulesBlocks = await Promise.all(
|
|
[...leagueIds].map(async (leagueId) => {
|
|
const { data: latest } = await supabase
|
|
.from("league_rules")
|
|
.select("rules, version")
|
|
.eq("league_id", leagueId)
|
|
.order("version", { ascending: false })
|
|
.limit(1)
|
|
.single();
|
|
const rules = latest?.rules
|
|
? parseLeagueRules(latest.rules)
|
|
: defaultLeagueRules;
|
|
return { leagueId, name: leagueNames.get(leagueId) ?? "League", rules, version: latest?.version ?? 0 };
|
|
})
|
|
);
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<PageHeader
|
|
title="Rules"
|
|
description="Scoring and format for leagues you participate in"
|
|
/>
|
|
{rulesBlocks.length === 0 ? (
|
|
<GlassCard>
|
|
<p className="text-sm text-[var(--color-muted)]">
|
|
No league rules available yet. You need to be assigned as a team manager.
|
|
</p>
|
|
</GlassCard>
|
|
) : (
|
|
rulesBlocks.map((block) => (
|
|
<GlassCard
|
|
key={block.leagueId}
|
|
title={`${block.name} · v${block.version}`}
|
|
>
|
|
<dl className="grid gap-3 text-sm sm:grid-cols-2">
|
|
<div>
|
|
<dt className="text-[var(--color-muted)]">Win points</dt>
|
|
<dd className="font-medium">{block.rules.points_win}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="text-[var(--color-muted)]">Draw points</dt>
|
|
<dd className="font-medium">{block.rules.points_draw}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="text-[var(--color-muted)]">Format</dt>
|
|
<dd className="font-medium capitalize">{block.rules.round_robin_format}</dd>
|
|
</div>
|
|
<div>
|
|
<dt className="text-[var(--color-muted)]">Auto-qualify (CL)</dt>
|
|
<dd className="font-medium">{block.rules.auto_qualify_count}</dd>
|
|
</div>
|
|
</dl>
|
|
<Link
|
|
href={`/leagues/${block.leagueId}/rules`}
|
|
className="mt-4 inline-block text-sm text-cyan-400 hover:underline"
|
|
>
|
|
View full rules page
|
|
</Link>
|
|
</GlassCard>
|
|
))
|
|
)}
|
|
</div>
|
|
);
|
|
}
|