Files
gridpilot.gg/apps/website/lib/services/leagues/LeagueService.ts
2025-12-18 14:26:17 +01:00

96 lines
3.4 KiB
TypeScript

import { LeaguesApiClient } from "@/lib/api/leagues/LeaguesApiClient";
import { CreateLeagueInputDTO } from "@/lib/types/generated/CreateLeagueInputDTO";
import { LeagueWithCapacityDTO } from "@/lib/types/generated/LeagueWithCapacityDTO";
import { CreateLeagueViewModel } from "@/lib/view-models/CreateLeagueViewModel";
import { LeagueMembershipsViewModel } from "@/lib/view-models/LeagueMembershipsViewModel";
import { LeagueScheduleViewModel } from "@/lib/view-models/LeagueScheduleViewModel";
import { LeagueStandingsViewModel } from "@/lib/view-models/LeagueStandingsViewModel";
import { LeagueStatsViewModel } from "@/lib/view-models/LeagueStatsViewModel";
import { LeagueSummaryViewModel } from "@/lib/view-models/LeagueSummaryViewModel";
import { RemoveMemberViewModel } from "@/lib/view-models/RemoveMemberViewModel";
import { SubmitBlocker, ThrottleBlocker } from "@/lib/blockers";
/**
* League Service
*
* Orchestrates league operations by coordinating API calls and view model creation.
* All dependencies are injected via constructor.
*/
export class LeagueService {
private readonly submitBlocker = new SubmitBlocker();
private readonly throttle = new ThrottleBlocker(500);
constructor(
private readonly apiClient: LeaguesApiClient
) {}
/**
* Get all leagues with view model transformation
*/
async getAllLeagues(): Promise<LeagueSummaryViewModel[]> {
const dto = await this.apiClient.getAllWithCapacity();
return dto.leagues.map((league: LeagueWithCapacityDTO) => new LeagueSummaryViewModel(league));
}
/**
* Get league standings with view model transformation
*/
async getLeagueStandings(leagueId: string, currentUserId: string): Promise<LeagueStandingsViewModel> {
const dto = await this.apiClient.getStandings(leagueId);
// TODO: include drivers and memberships in dto
const dtoWithExtras = {
...dto,
drivers: [], // TODO: fetch drivers
memberships: [], // TODO: fetch memberships
};
return new LeagueStandingsViewModel(dtoWithExtras, currentUserId);
}
/**
* Get league statistics
*/
async getLeagueStats(): Promise<LeagueStatsViewModel> {
const dto = await this.apiClient.getTotal();
return new LeagueStatsViewModel(dto);
}
/**
* Get league schedule
*/
async getLeagueSchedule(leagueId: string): Promise<LeagueScheduleViewModel> {
const dto = await this.apiClient.getSchedule(leagueId);
return new LeagueScheduleViewModel(dto);
}
/**
* Get league memberships
*/
async getLeagueMemberships(leagueId: string, currentUserId: string): Promise<LeagueMembershipsViewModel> {
const dto = await this.apiClient.getMemberships(leagueId);
return new LeagueMembershipsViewModel(dto, currentUserId);
}
/**
* Create a new league
*/
async createLeague(input: CreateLeagueInputDTO): Promise<void> {
if (!this.submitBlocker.canExecute() || !this.throttle.canExecute()) return;
this.submitBlocker.block();
this.throttle.block();
try {
await this.apiClient.create(input);
} finally {
this.submitBlocker.release();
}
}
/**
* Remove a member from league
*/
async removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<RemoveMemberViewModel> {
const dto = await this.apiClient.removeMember(leagueId, performerDriverId, targetDriverId);
return new RemoveMemberViewModel(dto);
}
}