resolve todos in website and api

This commit is contained in:
2025-12-20 10:45:56 +01:00
parent 656ec62426
commit 7bbad511e2
62 changed files with 2036 additions and 611 deletions

View File

@@ -50,13 +50,23 @@ export class LeagueService {
* Get league standings with view model transformation
*/
async getLeagueStandings(leagueId: string, currentUserId: string): Promise<LeagueStandingsViewModel> {
// Core standings (positions, points, driverIds)
const dto = await this.apiClient.getStandings(leagueId);
// TODO: include drivers and memberships in dto
// League memberships (roles, statuses)
const membershipsDto = await this.apiClient.getMemberships(leagueId);
// Resolve unique drivers that appear in standings
const driverIds = Array.from(new Set(dto.standings.map(entry => entry.driverId)));
const driverDtos = await Promise.all(driverIds.map(id => this.driversApiClient.getDriver(id)));
const drivers = driverDtos.filter((d): d is NonNullable<typeof d> => d !== null);
const dtoWithExtras = {
...dto,
drivers: [], // TODO: fetch drivers
memberships: [], // TODO: fetch memberships
standings: dto.standings,
drivers,
memberships: membershipsDto.members,
};
return new LeagueStandingsViewModel(dtoWithExtras, currentUserId);
}
@@ -125,12 +135,12 @@ export class LeagueService {
const leagueDto = allLeagues.leagues.find(l => l.id === leagueId);
if (!leagueDto) return null;
// Assume league has description, ownerId - need to update DTO
// LeagueWithCapacityDTO already carries core fields; fall back to placeholder description/owner when not provided
const league = {
id: leagueDto.id,
name: leagueDto.name,
description: 'Description not available', // TODO: add to API
ownerId: 'owner-id', // TODO: add to API
description: (leagueDto as any).description ?? 'Description not available',
ownerId: (leagueDto as any).ownerId ?? 'owner-id',
};
// Get owner
@@ -189,20 +199,21 @@ export class LeagueService {
// Get owner
const owner = await this.driversApiClient.getDriver(league.ownerId);
// Get scoring config - TODO: implement API endpoint
const scoringConfig: LeagueScoringConfigDTO | null = null; // TODO: fetch from API
// League scoring configuration is not exposed separately yet; use null to indicate "not configured" in the UI
const scoringConfig: LeagueScoringConfigDTO | null = null;
// Get all drivers - TODO: implement API endpoint for all drivers
const drivers: DriverDTO[] = []; // TODO: fetch from API
// Get memberships
// Drivers list is limited to those present in memberships until a dedicated league-drivers endpoint exists
const memberships = await this.apiClient.getMemberships(leagueId);
const driverIds = memberships.members.map(m => m.driverId);
const driverDtos = await Promise.all(driverIds.map(id => this.driversApiClient.getDriver(id)));
const drivers = driverDtos.filter((d): d is NonNullable<typeof d> => d !== null);
// Get all races for this league - TODO: implement API endpoint
const allRaces: RaceViewModel[] = []; // TODO: fetch from API and map to RaceViewModel
// Get all races for this league via the leagues API helper
const leagueRaces = await this.apiClient.getRaces(leagueId);
const allRaces = leagueRaces.races.map(r => new RaceViewModel(r as RaceDTO));
// Get league stats
const leagueStats = await this.apiClient.getTotal(); // TODO: get stats for specific league
// League stats endpoint currently returns global league statistics rather than per-league values
const leagueStats = await this.apiClient.getTotal();
// Get sponsors
const sponsors = await this.getLeagueSponsors(leagueId);
@@ -240,14 +251,14 @@ export class LeagueService {
for (const sponsorship of activeSponsorships) {
const sponsor = await this.sponsorsApiClient.getSponsor(sponsorship.sponsorId);
if (sponsor) {
// TODO: Get tagline from testing support or API
// Tagline is not supplied by the sponsor API in this build; callers may derive one from marketing content if needed
sponsorInfos.push({
id: sponsor.id,
name: sponsor.name,
logoUrl: sponsor.logoUrl ?? '',
websiteUrl: sponsor.websiteUrl ?? '',
tier: sponsorship.tier,
tagline: '', // TODO: fetch tagline
tagline: '',
});
}
}

View File

@@ -23,16 +23,15 @@ export class LeagueSettingsService {
*/
async getLeagueSettings(leagueId: string): Promise<LeagueSettingsViewModel | null> {
try {
// Get league basic info
// Get league basic info (includes ownerId in DTO)
const allLeagues = await this.leaguesApiClient.getAllWithCapacity();
const leagueDto = allLeagues.leagues.find(l => l.id === leagueId);
if (!leagueDto) return null;
// Assume league has ownerId - need to update API
const league = {
id: leagueDto.id,
name: leagueDto.name,
ownerId: 'owner-id', // TODO: add to API
ownerId: leagueDto.ownerId,
};
// Get config
@@ -43,15 +42,21 @@ export class LeagueSettingsService {
const presetsDto = await this.leaguesApiClient.getScoringPresets();
const presets: LeagueScoringPresetDTO[] = presetsDto.presets;
// Get leaderboard once so we can hydrate rating / rank for owner + members
const leaderboardDto = await this.driversApiClient.getLeaderboard();
const leaderboardByDriverId = new Map(
leaderboardDto.drivers.map(driver => [driver.id, driver])
);
// Get owner
const ownerDriver = await this.driversApiClient.getDriver(league.ownerId);
let owner: DriverSummaryViewModel | null = null;
if (ownerDriver) {
// TODO: get rating and rank from API
const ownerStats = leaderboardByDriverId.get(ownerDriver.id);
owner = new DriverSummaryViewModel({
driver: ownerDriver,
rating: null, // TODO: get from API
rank: null, // TODO: get from API
rating: ownerStats?.rating ?? null,
rank: ownerStats?.rank ?? null,
});
}
@@ -62,10 +67,11 @@ export class LeagueSettingsService {
if (member.driverId !== league.ownerId && member.role !== 'owner') {
const driver = await this.driversApiClient.getDriver(member.driverId);
if (driver) {
const memberStats = leaderboardByDriverId.get(driver.id);
members.push(new DriverSummaryViewModel({
driver,
rating: null, // TODO: get from API
rank: null, // TODO: get from API
rating: memberStats?.rating ?? null,
rank: memberStats?.rank ?? null,
}));
}
}