Files
gridpilot.gg/apps/website/lib/api/leagues/LeaguesApiClient.ts
2025-12-28 21:02:32 +01:00

197 lines
10 KiB
TypeScript

import { BaseApiClient } from '../base/BaseApiClient';
import type { AllLeaguesWithCapacityDTO } from '../../types/generated/AllLeaguesWithCapacityDTO';
import type { TotalLeaguesDTO } from '../../types/generated/TotalLeaguesDTO';
import type { LeagueStandingsDTO } from '../../types/generated/LeagueStandingsDTO';
import type { LeagueScheduleDTO } from '../../types/generated/LeagueScheduleDTO';
import type { LeagueMembershipsDTO } from '../../types/generated/LeagueMembershipsDTO';
import type { CreateLeagueInputDTO } from '../../types/generated/CreateLeagueInputDTO';
import type { CreateLeagueOutputDTO } from '../../types/generated/CreateLeagueOutputDTO';
import type { SponsorshipDetailDTO } from '../../types/generated/SponsorshipDetailDTO';
import type { RaceDTO } from '../../types/generated/RaceDTO';
import type { GetLeagueAdminConfigOutputDTO } from '../../types/generated/GetLeagueAdminConfigOutputDTO';
import type { LeagueScoringPresetDTO } from '../../types/generated/LeagueScoringPresetDTO';
import type { LeagueSeasonSummaryDTO } from '../../types/generated/LeagueSeasonSummaryDTO';
import type { CreateLeagueScheduleRaceInputDTO } from '../../types/generated/CreateLeagueScheduleRaceInputDTO';
import type { CreateLeagueScheduleRaceOutputDTO } from '../../types/generated/CreateLeagueScheduleRaceOutputDTO';
import type { UpdateLeagueScheduleRaceInputDTO } from '../../types/generated/UpdateLeagueScheduleRaceInputDTO';
import type { LeagueScheduleRaceMutationSuccessDTO } from '../../types/generated/LeagueScheduleRaceMutationSuccessDTO';
import type { LeagueSeasonSchedulePublishOutputDTO } from '../../types/generated/LeagueSeasonSchedulePublishOutputDTO';
import type { LeagueRosterMemberDTO } from '../../types/generated/LeagueRosterMemberDTO';
import type { LeagueRosterJoinRequestDTO } from '../../types/generated/LeagueRosterJoinRequestDTO';
import type { ApproveJoinRequestOutputDTO } from '../../types/generated/ApproveJoinRequestOutputDTO';
import type { RejectJoinRequestOutputDTO } from '../../types/generated/RejectJoinRequestOutputDTO';
import type { UpdateLeagueMemberRoleOutputDTO } from '../../types/generated/UpdateLeagueMemberRoleOutputDTO';
import type { RemoveLeagueMemberOutputDTO } from '../../types/generated/RemoveLeagueMemberOutputDTO';
import type { AllLeaguesWithCapacityAndScoringDTO } from '../../types/AllLeaguesWithCapacityAndScoringDTO';
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null;
}
function isRaceDTO(value: unknown): value is RaceDTO {
if (!isRecord(value)) return false;
return typeof value.id === 'string' && typeof value.name === 'string' && typeof value.date === 'string';
}
function parseRaceDTOArray(value: unknown): RaceDTO[] {
if (!Array.isArray(value)) return [];
return value.filter(isRaceDTO);
}
/**
* Leagues API Client
*
* Handles all league-related API operations.
*/
export class LeaguesApiClient extends BaseApiClient {
/** Get all leagues with capacity information */
getAllWithCapacity(): Promise<AllLeaguesWithCapacityDTO> {
return this.get<AllLeaguesWithCapacityDTO>('/leagues/all-with-capacity');
}
/** Get all leagues with capacity + scoring summary (for leagues page filters) */
getAllWithCapacityAndScoring(): Promise<AllLeaguesWithCapacityAndScoringDTO> {
return this.get<AllLeaguesWithCapacityAndScoringDTO>('/leagues/all-with-capacity-and-scoring');
}
/** Get total number of leagues */
getTotal(): Promise<TotalLeaguesDTO> {
return this.get<TotalLeaguesDTO>('/leagues/total-leagues');
}
/** Get league standings */
getStandings(leagueId: string): Promise<LeagueStandingsDTO> {
return this.get<LeagueStandingsDTO>(`/leagues/${leagueId}/standings`);
}
/** Get league schedule */
getSchedule(leagueId: string, seasonId?: string): Promise<LeagueScheduleDTO> {
const qs = seasonId ? `?seasonId=${encodeURIComponent(seasonId)}` : '';
return this.get<LeagueScheduleDTO>(`/leagues/${leagueId}/schedule${qs}`);
}
/** Get league memberships */
getMemberships(leagueId: string): Promise<LeagueMembershipsDTO> {
return this.get<LeagueMembershipsDTO>(`/leagues/${leagueId}/memberships`);
}
/** Create a new league */
create(input: CreateLeagueInputDTO): Promise<CreateLeagueOutputDTO> {
return this.post<CreateLeagueOutputDTO>('/leagues', input);
}
/** Remove a member from league */
removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<{ success: boolean }> {
return this.patch<{ success: boolean }>(`/leagues/${leagueId}/members/${targetDriverId}/remove`, { performerDriverId });
}
/** Update a member's role in league */
updateMemberRole(leagueId: string, performerDriverId: string, targetDriverId: string, newRole: string): Promise<{ success: boolean }> {
return this.patch<{ success: boolean }>(`/leagues/${leagueId}/members/${targetDriverId}/role`, { performerDriverId, newRole });
}
/** Get league seasons */
getSeasons(leagueId: string): Promise<LeagueSeasonSummaryDTO[]> {
return this.get<LeagueSeasonSummaryDTO[]>(`/leagues/${leagueId}/seasons`);
}
/** Get season sponsorships */
getSeasonSponsorships(seasonId: string): Promise<{ sponsorships: SponsorshipDetailDTO[] }> {
return this.get<{ sponsorships: SponsorshipDetailDTO[] }>(`/leagues/seasons/${seasonId}/sponsorships`);
}
/** Get league config */
getLeagueConfig(leagueId: string): Promise<GetLeagueAdminConfigOutputDTO> {
return this.get<GetLeagueAdminConfigOutputDTO>(`/leagues/${leagueId}/config`);
}
/** Get league scoring presets */
getScoringPresets(): Promise<{ presets: LeagueScoringPresetDTO[] }> {
return this.get<{ presets: LeagueScoringPresetDTO[] }>(`/leagues/scoring-presets`);
}
/** Transfer league ownership */
transferOwnership(leagueId: string, currentOwnerId: string, newOwnerId: string): Promise<{ success: boolean }> {
return this.post<{ success: boolean }>(`/leagues/${leagueId}/transfer-ownership`, {
currentOwnerId,
newOwnerId,
});
}
/** Publish a league season schedule (admin/owner only; actor derived from session) */
publishSeasonSchedule(leagueId: string, seasonId: string): Promise<LeagueSeasonSchedulePublishOutputDTO> {
return this.post<LeagueSeasonSchedulePublishOutputDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/publish`, {});
}
/** Unpublish a league season schedule (admin/owner only; actor derived from session) */
unpublishSeasonSchedule(leagueId: string, seasonId: string): Promise<LeagueSeasonSchedulePublishOutputDTO> {
return this.post<LeagueSeasonSchedulePublishOutputDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/unpublish`, {});
}
/** Create a schedule race for a league season (admin/owner only; actor derived from session) */
createSeasonScheduleRace(
leagueId: string,
seasonId: string,
input: CreateLeagueScheduleRaceInputDTO,
): Promise<CreateLeagueScheduleRaceOutputDTO> {
const { example: _example, ...payload } = input;
return this.post<CreateLeagueScheduleRaceOutputDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races`, payload);
}
/** Update a schedule race for a league season (admin/owner only; actor derived from session) */
updateSeasonScheduleRace(
leagueId: string,
seasonId: string,
raceId: string,
input: UpdateLeagueScheduleRaceInputDTO,
): Promise<LeagueScheduleRaceMutationSuccessDTO> {
const { example: _example, ...payload } = input;
return this.patch<LeagueScheduleRaceMutationSuccessDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races/${raceId}`, payload);
}
/** Delete a schedule race for a league season (admin/owner only; actor derived from session) */
deleteSeasonScheduleRace(
leagueId: string,
seasonId: string,
raceId: string,
): Promise<LeagueScheduleRaceMutationSuccessDTO> {
return this.delete<LeagueScheduleRaceMutationSuccessDTO>(`/leagues/${leagueId}/seasons/${seasonId}/schedule/races/${raceId}`);
}
/** Get races for a league */
async getRaces(leagueId: string): Promise<{ races: RaceDTO[] }> {
const response = await this.get<{ races?: unknown }>(`/leagues/${leagueId}/races`);
return { races: parseRaceDTOArray(response?.races) };
}
/** Admin roster: list current members (admin/owner only; actor derived from session) */
getAdminRosterMembers(leagueId: string): Promise<LeagueRosterMemberDTO[]> {
return this.get<LeagueRosterMemberDTO[]>(`/leagues/${leagueId}/admin/roster/members`);
}
/** Admin roster: list pending join requests (admin/owner only; actor derived from session) */
getAdminRosterJoinRequests(leagueId: string): Promise<LeagueRosterJoinRequestDTO[]> {
return this.get<LeagueRosterJoinRequestDTO[]>(`/leagues/${leagueId}/admin/roster/join-requests`);
}
/** Admin roster: approve a join request (admin/owner only; actor derived from session) */
approveRosterJoinRequest(leagueId: string, joinRequestId: string): Promise<ApproveJoinRequestOutputDTO> {
return this.post<ApproveJoinRequestOutputDTO>(`/leagues/${leagueId}/admin/roster/join-requests/${joinRequestId}/approve`, {});
}
/** Admin roster: reject a join request (admin/owner only; actor derived from session) */
rejectRosterJoinRequest(leagueId: string, joinRequestId: string): Promise<RejectJoinRequestOutputDTO> {
return this.post<RejectJoinRequestOutputDTO>(`/leagues/${leagueId}/admin/roster/join-requests/${joinRequestId}/reject`, {});
}
/** Admin roster: update member role (admin/owner only; actor derived from session) */
updateRosterMemberRole(leagueId: string, targetDriverId: string, newRole: string): Promise<UpdateLeagueMemberRoleOutputDTO> {
return this.patch<UpdateLeagueMemberRoleOutputDTO>(`/leagues/${leagueId}/admin/roster/members/${targetDriverId}/role`, { newRole });
}
/** Admin roster: remove member (admin/owner only; actor derived from session) */
removeRosterMember(leagueId: string, targetDriverId: string): Promise<RemoveLeagueMemberOutputDTO> {
return this.patch<RemoveLeagueMemberOutputDTO>(`/leagues/${leagueId}/admin/roster/members/${targetDriverId}/remove`, {});
}
}