Yaltopia-FIFA/lib/api/client.ts
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

214 lines
7.0 KiB
TypeScript

/** Browser client for Next.js API routes */
type ApiResponse<T> = { success: true; data: T } | { success: false; error: string };
export async function apiFetch<T>(
path: string,
options?: RequestInit
): Promise<T> {
const res = await fetch(path, {
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
credentials: "same-origin",
});
let json: ApiResponse<T>;
try {
json = await res.json();
} catch {
throw new Error(`API ${path} returned invalid JSON (${res.status})`);
}
if (!json.success) {
throw new Error(json.error || `Request failed (${res.status})`);
}
return json.data;
}
export const api = {
health: () => apiFetch<{ status: string; supabase: boolean }>("/api/health"),
leagues: {
list: () => apiFetch<unknown[]>("/api/leagues"),
create: (body: { name: string; description?: string }) =>
apiFetch<unknown>("/api/leagues", {
method: "POST",
body: JSON.stringify(body),
}),
get: (leagueId: string) => apiFetch<unknown>(`/api/leagues/${leagueId}`),
createCompetition: (
leagueId: string,
body: { name: string; tournament_mode: "league" | "cup"; timezone?: string }
) =>
apiFetch<unknown>(`/api/leagues/${leagueId}/competitions`, {
method: "POST",
body: JSON.stringify(body),
}),
saveRules: (leagueId: string, rules: object) =>
apiFetch<void>(`/api/leagues/${leagueId}/rules`, {
method: "POST",
body: JSON.stringify({ rules }),
}),
delete: (leagueId: string) =>
apiFetch<void>(`/api/leagues/${leagueId}`, { method: "DELETE" }),
assignMaster: (leagueId: string, email: string) =>
apiFetch<void>(`/api/leagues/${leagueId}/masters`, {
method: "POST",
body: JSON.stringify({ email }),
}),
listMasters: (leagueId: string) =>
apiFetch<unknown[]>(`/api/leagues/${leagueId}/masters`),
},
competitions: {
get: (id: string) => apiFetch<unknown>(`/api/competitions/${id}`),
activate: (id: string) =>
apiFetch<void>(`/api/competitions/${id}/activate`, { method: "POST" }),
generateFixtures: (id: string) =>
apiFetch<unknown>(`/api/competitions/${id}/fixtures`, { method: "POST" }),
standings: (id: string) =>
apiFetch<unknown[]>(`/api/competitions/${id}/standings`),
matches: (id: string) =>
apiFetch<unknown[]>(`/api/competitions/${id}/matches`),
pendingResults: (id: string) =>
apiFetch<unknown[]>(`/api/competitions/${id}/pending-results`),
transfers: (id: string) =>
apiFetch<unknown[]>(`/api/competitions/${id}/transfers`),
dashboard: (id: string) =>
apiFetch<{ results: unknown[]; playerStats: unknown[] }>(
`/api/competitions/${id}/dashboard`
),
listTeams: (id: string) =>
apiFetch<unknown[]>(`/api/competitions/${id}/teams`),
createTeam: (
id: string,
body: { name: string; nickname?: string; icon?: string }
) =>
apiFetch<unknown>(`/api/competitions/${id}/teams`, {
method: "POST",
body: JSON.stringify(body),
}),
addRoster: (
id: string,
body: { teamId: string; playerId: string }
) =>
apiFetch<void>(`/api/competitions/${id}/roster`, {
method: "POST",
body: JSON.stringify(body),
}),
transfer: (
id: string,
body: { playerId: string; fromTeamId: string; toTeamId: string }
) =>
apiFetch<void>(`/api/competitions/${id}/transfers`, {
method: "POST",
body: JSON.stringify(body),
}),
},
teams: {
delete: (teamId: string) =>
apiFetch<void>(`/api/teams/${teamId}`, { method: "DELETE" }),
update: (teamId: string, body: { home_stadium_name?: string; logo_path?: string; nickname?: string; icon?: string }) =>
apiFetch<unknown>(`/api/teams/${teamId}`, {
method: "PATCH",
body: JSON.stringify(body),
}),
setAvailability: (
teamId: string,
windows: { day_of_week: number; start_time?: string; end_time?: string }[]
) =>
apiFetch<void>(`/api/teams/${teamId}/availability`, {
method: "PUT",
body: JSON.stringify({ windows }),
}),
},
players: {
list: () => apiFetch<unknown[]>("/api/players"),
create: (body: { display_name: string; external_id?: string }) =>
apiFetch<unknown>("/api/players", {
method: "POST",
body: JSON.stringify(body),
}),
setStatus: (playerId: string, status: "active" | "inactive") =>
apiFetch<void>(`/api/players/${playerId}`, {
method: "PATCH",
body: JSON.stringify({ status }),
}),
},
matches: {
get: (matchId: string) => apiFetch<unknown>(`/api/matches/${matchId}`),
proposeSchedule: (matchId: string, scheduledAt: string) =>
apiFetch<void>(`/api/matches/${matchId}/schedule`, {
method: "POST",
body: JSON.stringify({ action: "propose", scheduledAt }),
}),
signSchedule: (matchId: string, teamId: string) =>
apiFetch<void>(`/api/matches/${matchId}/schedule`, {
method: "POST",
body: JSON.stringify({ action: "sign", teamId }),
}),
submitResult: (
matchId: string,
body: { teamId: string; homeScore: number; awayScore: number }
) =>
apiFetch<void>(`/api/matches/${matchId}/results`, {
method: "POST",
body: JSON.stringify({ action: "submit", ...body }),
}),
approveResult: (matchId: string) =>
apiFetch<void>(`/api/matches/${matchId}/results`, {
method: "POST",
body: JSON.stringify({ action: "approve" }),
}),
setResult: (
matchId: string,
body: { homeScore: number; awayScore: number; note?: string }
) =>
apiFetch<void>(`/api/matches/${matchId}/results`, {
method: "POST",
body: JSON.stringify({ action: "set", ...body }),
}),
},
manager: {
dashboard: () => apiFetch<unknown>("/api/manager/dashboard"),
competitions: (mode?: "league" | "cup") =>
apiFetch<unknown[]>(
`/api/manager/competitions${mode ? `?mode=${mode}` : ""}`
),
calendar: (from: string, to: string) =>
apiFetch<unknown[]>(
`/api/manager/calendar?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`
),
},
master: {
calendar: (from: string, to: string) =>
apiFetch<unknown[]>(
`/api/master/calendar?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`
),
},
issues: {
list: (asMaster?: boolean) =>
apiFetch<unknown[]>(`/api/issues${asMaster ? "?as=master" : ""}`),
create: (body: {
leagueId: string;
competitionId?: string;
subject: string;
body: string;
}) =>
apiFetch<unknown>("/api/issues", {
method: "POST",
body: JSON.stringify(body),
}),
},
};