Some checks failed
Deploy to Cloudflare Workers / deploy (push) Has been cancelled
134 lines
4.1 KiB
TypeScript
134 lines
4.1 KiB
TypeScript
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
|
|
export type ManagerCompetitionRow = {
|
|
competition_id: string;
|
|
competition_name: string;
|
|
league_id: string;
|
|
league_name: string;
|
|
tournament_mode: "league" | "cup";
|
|
team_id: string;
|
|
team_name: string;
|
|
team_nickname: string | null;
|
|
team_icon: string | null;
|
|
points: number;
|
|
goals_for: number;
|
|
goals_against: number;
|
|
goal_difference: number;
|
|
played: number;
|
|
};
|
|
|
|
export async function getManagerCompetitions(
|
|
supabase: SupabaseClient,
|
|
userId: string,
|
|
mode?: "league" | "cup"
|
|
) {
|
|
const { data: memberships, error: mErr } = await supabase
|
|
.from("team_members")
|
|
.select("team_id, teams(id, name, nickname, icon, competition_id)")
|
|
.eq("user_id", userId)
|
|
.eq("role", "manager");
|
|
|
|
if (mErr) throw new Error(mErr.message);
|
|
if (!memberships?.length) return [] as ManagerCompetitionRow[];
|
|
|
|
const rows: ManagerCompetitionRow[] = [];
|
|
|
|
for (const m of memberships) {
|
|
const team = m.teams as {
|
|
id: string;
|
|
name: string;
|
|
nickname: string | null;
|
|
icon: string | null;
|
|
competition_id: string;
|
|
};
|
|
if (!team?.competition_id) continue;
|
|
|
|
const { data: comp } = await supabase
|
|
.from("competitions")
|
|
.select("id, name, tournament_mode, league_id, leagues(name)")
|
|
.eq("id", team.competition_id)
|
|
.single();
|
|
|
|
if (!comp) continue;
|
|
if (mode && comp.tournament_mode !== mode) continue;
|
|
|
|
const { data: standing } = await supabase
|
|
.from("competition_standings")
|
|
.select("points, goals_for, goals_against, goal_difference, played")
|
|
.eq("competition_id", team.competition_id)
|
|
.eq("team_id", team.id)
|
|
.maybeSingle();
|
|
|
|
const league = comp.leagues as { name: string } | null;
|
|
|
|
rows.push({
|
|
competition_id: comp.id,
|
|
competition_name: comp.name,
|
|
league_id: comp.league_id,
|
|
league_name: league?.name ?? "League",
|
|
tournament_mode: comp.tournament_mode as "league" | "cup",
|
|
team_id: team.id,
|
|
team_name: team.name,
|
|
team_nickname: team.nickname,
|
|
team_icon: team.icon,
|
|
points: standing?.points ?? 0,
|
|
goals_for: standing?.goals_for ?? 0,
|
|
goals_against: standing?.goals_against ?? 0,
|
|
goal_difference: standing?.goal_difference ?? 0,
|
|
played: standing?.played ?? 0,
|
|
});
|
|
}
|
|
|
|
return rows;
|
|
}
|
|
|
|
export async function getManagerDashboard(
|
|
supabase: SupabaseClient,
|
|
userId: string
|
|
) {
|
|
const { data: memberships } = await supabase
|
|
.from("team_members")
|
|
.select("team_id, teams(competition_id)")
|
|
.eq("user_id", userId)
|
|
.eq("role", "manager");
|
|
|
|
const teamIds = memberships?.map((m) => m.team_id) ?? [];
|
|
if (teamIds.length === 0) {
|
|
return { nextFixture: null, recentResults: [], stats: null };
|
|
}
|
|
|
|
const teamFilter = teamIds.join(",");
|
|
const { data: nextFixture } = await supabase
|
|
.from("matches")
|
|
.select(
|
|
`id, scheduled_at, proposed_scheduled_at, status, home_team_id, away_team_id,
|
|
home:home_team_id(name, nickname, icon),
|
|
away:away_team_id(name, nickname, icon),
|
|
competitions(name, leagues(name))`
|
|
)
|
|
.or(`home_team_id.in.(${teamFilter}),away_team_id.in.(${teamFilter})`)
|
|
.in("status", ["scheduled", "schedule_pending", "schedule_confirmed"])
|
|
.order("scheduled_at", { ascending: true, nullsFirst: false })
|
|
.limit(1)
|
|
.maybeSingle();
|
|
|
|
const { data: recentResults } = await supabase
|
|
.from("team_match_results")
|
|
.select("*")
|
|
.in("team_id", teamIds)
|
|
.order("scheduled_at", { ascending: false })
|
|
.limit(8);
|
|
|
|
const wins = recentResults?.filter((r) => r.result === "W").length ?? 0;
|
|
const draws = recentResults?.filter((r) => r.result === "D").length ?? 0;
|
|
const losses = recentResults?.filter((r) => r.result === "L").length ?? 0;
|
|
const goalsFor =
|
|
recentResults?.reduce((s, r) => s + (r.goals_for ?? 0), 0) ?? 0;
|
|
|
|
return {
|
|
nextFixture,
|
|
recentResults: recentResults ?? [],
|
|
stats: { wins, draws, losses, goalsFor, played: recentResults?.length ?? 0 },
|
|
};
|
|
}
|