Yaltopia-FIFA/app/(dashboard)/leagues/[leagueId]/competitions/[competitionId]/my-team/page.tsx
Kirubel-Kibru-Yaltopia 89440985f1
Some checks failed
Deploy to Cloudflare Workers / deploy (push) Has been cancelled
x
2026-05-24 21:46:10 +03:00

201 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { redirect } from "next/navigation";
import { createClient } from "@/lib/supabase/server";
import {
FormDonut,
GoalsTrendChart,
TopScorersChart,
StatCards,
} from "@/components/manager/TeamCharts";
import { GlassCard } from "@/components/ui/glass-card";
import { TeamBadge } from "@/components/teams/TeamBadge";
export default async function MyTeamPage({
params,
}: {
params: Promise<{ leagueId: string; competitionId: string }>;
}) {
const { leagueId, competitionId } = await params;
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) redirect("/login");
const { data: teamsInComp } = await supabase
.from("teams")
.select("id")
.eq("competition_id", competitionId);
const teamIds = teamsInComp?.map((t) => t.id) ?? [];
const { data: membership } = await supabase
.from("team_members")
.select("team_id, teams(*)")
.eq("user_id", user.id)
.eq("role", "manager")
.in("team_id", teamIds.length ? teamIds : ["00000000-0000-0000-0000-000000000000"])
.limit(1)
.maybeSingle();
if (!membership) {
return (
<p className="text-[var(--color-muted)]">
You are not a team manager in this competition.
</p>
);
}
const team = membership.teams as {
id: string;
name: string;
logo_path: string | null;
};
const { data: results } = await supabase
.from("team_match_results")
.select("*")
.eq("team_id", team.id)
.order("matchday", { ascending: true });
const { data: playerStats } = await supabase
.from("player_competition_stats")
.select("*")
.eq("team_id", team.id)
.eq("competition_id", competitionId)
.order("goals", { ascending: false });
const formCounts = { W: 0, D: 0, L: 0 };
results?.slice(-10).forEach((r) => {
if (r.result in formCounts) formCounts[r.result as keyof typeof formCounts]++;
});
const formData = Object.entries(formCounts).map(([name, value]) => ({
name,
value,
}));
const goalsTrend =
results?.map((r, i) => ({
matchday: r.matchday ?? i + 1,
gf: r.goals_for ?? 0,
ga: r.goals_against ?? 0,
})) ?? [];
const topScorers =
playerStats?.slice(0, 8).map((p) => ({
name: p.player_name,
goals: p.goals,
})) ?? [];
const topAssists =
playerStats
?.slice()
.sort((a, b) => b.assists - a.assists)
.slice(0, 8)
.map((p) => ({
name: p.player_name,
assists: p.assists,
})) ?? [];
const played = results?.length ?? 0;
const won = results?.filter((r) => r.result === "W").length ?? 0;
const drawn = results?.filter((r) => r.result === "D").length ?? 0;
const lost = results?.filter((r) => r.result === "L").length ?? 0;
const gf = results?.reduce((s, r) => s + (r.goals_for ?? 0), 0) ?? 0;
const ga = results?.reduce((s, r) => s + (r.goals_against ?? 0), 0) ?? 0;
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<TeamBadge name={team.name} logoPath={team.logo_path} size="lg" />
<a
href={`/leagues/${leagueId}/competitions/${competitionId}/teams/${team.id}/settings`}
className="text-sm text-cyan-400 hover:underline"
>
Team settings
</a>
</div>
<StatCards
stats={[
{ label: "Played", value: played },
{ label: "Won", value: won },
{ label: "GF", value: gf },
{ label: "GD", value: gf - ga },
]}
/>
<div className="grid gap-4 lg:grid-cols-2">
<FormDonut data={formData.filter((d) => d.value > 0)} />
<GoalsTrendChart data={goalsTrend} />
<TopScorersChart
data={topScorers}
dataKey="goals"
title="Top scorers"
/>
<TopScorersChart
data={topAssists}
dataKey="assists"
title="Top assists"
/>
</div>
<GlassCard title="Squad stats">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-white/10 text-left text-[var(--color-muted)]">
<th className="pb-2">Player</th>
<th className="pb-2 text-center">Apps</th>
<th className="pb-2 text-center">G</th>
<th className="pb-2 text-center">A</th>
<th className="pb-2 text-center">G+A</th>
</tr>
</thead>
<tbody>
{playerStats?.map((p) => (
<tr key={p.player_id} className="border-b border-white/5">
<td className="py-2">{p.player_name}</td>
<td className="py-2 text-center">{p.appearances}</td>
<td className="py-2 text-center">{p.goals}</td>
<td className="py-2 text-center">{p.assists}</td>
<td className="py-2 text-center text-cyan-400">
{p.goals + p.assists}
</td>
</tr>
))}
</tbody>
</table>
</GlassCard>
<GlassCard title="Recent results">
<ul className="space-y-2">
{results
?.slice()
.reverse()
.slice(0, 5)
.map((r) => (
<li
key={r.match_id}
className="flex items-center justify-between rounded-lg bg-white/5 px-3 py-2 text-sm"
>
<span>vs {r.opponent_name}</span>
<span>
{r.goals_for}{r.goals_against}{" "}
<span
className={
r.result === "W"
? "text-emerald-400"
: r.result === "L"
? "text-red-400"
: "text-amber-400"
}
>
{r.result}
</span>
</span>
</li>
))}
</ul>
</GlassCard>
</div>
);
}