refactor page to use services

This commit is contained in:
2025-12-18 15:58:09 +01:00
parent f54fa5de5b
commit fc386db06a
45 changed files with 2254 additions and 1292 deletions

View File

@@ -0,0 +1,71 @@
import { BaseApiClient } from '../base/BaseApiClient';
// DTOs
export type DriverDto = {
id: string;
name: string;
avatarUrl: string;
country: string;
totalRaces: number;
wins: number;
podiums: number;
rating: number;
globalRank: number;
consistency: number;
};
export type RaceDto = {
id: string;
track: string;
car: string;
scheduledAt: string; // ISO date string
isMyLeague: boolean;
leagueName?: string;
};
export type LeagueStandingDto = {
leagueId: string;
leagueName: string;
position: number;
points: number;
totalDrivers: number;
};
export type FeedItemDto = {
id: string;
type: string;
headline: string;
body: string | null;
timestamp: string; // ISO date string
ctaHref?: string;
ctaLabel?: string;
};
export type FriendDto = {
id: string;
name: string;
avatarUrl: string;
country: string;
};
export type DashboardOverviewDto = {
currentDriver: DriverDto;
nextRace: RaceDto | null;
upcomingRaces: RaceDto[];
leagueStandings: LeagueStandingDto[];
feedItems: FeedItemDto[];
friends: FriendDto[];
activeLeaguesCount: number;
};
/**
* Dashboard API Client
*
* Handles dashboard overview data aggregation.
*/
export class DashboardApiClient extends BaseApiClient {
/** Get dashboard overview data */
getDashboardOverview(): Promise<DashboardOverviewDto> {
return this.get<DashboardOverviewDto>('/dashboard/overview');
}
}

View File

@@ -1,6 +1,6 @@
import { BaseApiClient } from '../base/BaseApiClient';
// Import generated types
import type { CompleteOnboardingInputDTO, CompleteOnboardingOutputDTO, DriverRegistrationStatusDTO, DriverLeaderboardItemDTO } from '../../types/generated';
import type { CompleteOnboardingInputDTO, CompleteOnboardingOutputDTO, DriverRegistrationStatusDTO, DriverLeaderboardItemDTO, DriverProfileDTO } from '../../types/generated';
// TODO: Create proper DriverDTO in generated types
type DriverDTO = {
@@ -40,4 +40,14 @@ export class DriversApiClient extends BaseApiClient {
getRegistrationStatus(driverId: string, raceId: string): Promise<DriverRegistrationStatusDTO> {
return this.get<DriverRegistrationStatusDTO>(`/drivers/${driverId}/races/${raceId}/registration-status`);
}
/** Get driver by ID */
getDriver(driverId: string): Promise<DriverDTO | null> {
return this.get<DriverDTO | null>(`/drivers/${driverId}`);
}
/** Get driver profile with full details */
getDriverProfile(driverId: string): Promise<DriverProfileDTO> {
return this.get<DriverProfileDTO>(`/drivers/${driverId}/profile`);
}
}

View File

@@ -7,6 +7,7 @@ import { MediaApiClient } from './media/MediaApiClient';
import { AnalyticsApiClient } from './analytics/AnalyticsApiClient';
import { AuthApiClient } from './auth/AuthApiClient';
import { PaymentsApiClient } from './payments/PaymentsApiClient';
import { DashboardApiClient } from './dashboard/DashboardApiClient';
/**
* Main API Client
@@ -23,6 +24,7 @@ export class ApiClient {
public readonly analytics: AnalyticsApiClient;
public readonly auth: AuthApiClient;
public readonly payments: PaymentsApiClient;
public readonly dashboard: DashboardApiClient;
constructor(baseUrl: string) {
this.leagues = new LeaguesApiClient(baseUrl);
@@ -34,6 +36,7 @@ export class ApiClient {
this.analytics = new AnalyticsApiClient(baseUrl);
this.auth = new AuthApiClient(baseUrl);
this.payments = new PaymentsApiClient(baseUrl);
this.dashboard = new DashboardApiClient(baseUrl);
}
}

View File

@@ -49,4 +49,32 @@ export class LeaguesApiClient extends BaseApiClient {
removeMember(leagueId: string, performerDriverId: string, targetDriverId: string): Promise<{ success: boolean }> {
return this.patch<{ success: boolean }>(`/leagues/${leagueId}/members/${targetDriverId}/remove`, { performerDriverId });
}
/** Get league seasons */
getSeasons(leagueId: string): Promise<{ seasons: Array<{ id: string; status: string }> }> {
return this.get<{ seasons: Array<{ id: string; status: string }> }>(`/leagues/${leagueId}/seasons`);
}
/** Get season sponsorships */
getSeasonSponsorships(seasonId: string): Promise<{ sponsorships: Array<{ sponsorId: string; tier: string; status: string }> }> {
return this.get<{ sponsorships: Array<{ sponsorId: string; tier: string; status: string }> }>(`/seasons/${seasonId}/sponsorships`);
}
/** Get league config */
getLeagueConfig(leagueId: string): Promise<{ config: any }> {
return this.get<{ config: any }>(`/leagues/${leagueId}/config`);
}
/** Get league scoring presets */
getScoringPresets(): Promise<{ presets: any[] }> {
return this.get<{ presets: any[] }>(`/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,
});
}
}

View File

@@ -1,15 +1,15 @@
import { BaseApiClient } from '../base/BaseApiClient';
import type {
RequestAvatarGenerationInputDto,
RequestAvatarGenerationOutputDto,
UploadMediaInputDto,
UploadMediaOutputDto,
GetMediaOutputDto,
DeleteMediaOutputDto,
GetAvatarOutputDto,
UpdateAvatarInputDto,
UpdateAvatarOutputDto,
DeleteMediaOutputDto,
GetMediaOutputDto,
RequestAvatarGenerationInputDto,
RequestAvatarGenerationOutputDto,
UpdateAvatarInputDto,
UpdateAvatarOutputDto,
UploadMediaInputDto,
UploadMediaOutputDto,
} from '../../dtos';
import type { GetAvatarOutputDto } from '../../types/GetAvatarOutputDto';
import { BaseApiClient } from '../base/BaseApiClient';
/**
* Media API Client

View File

@@ -0,0 +1,33 @@
import { BaseApiClient } from '../base/BaseApiClient';
import type {
LeagueAdminProtestsDTO,
ApplyPenaltyCommandDTO,
RequestProtestDefenseCommandDTO,
} from '../../types';
/**
* Protests API Client
*
* Handles all protest-related API operations.
*/
export class ProtestsApiClient extends BaseApiClient {
/** Get protests for a league */
getLeagueProtests(leagueId: string): Promise<LeagueAdminProtestsDTO> {
return this.get<LeagueAdminProtestsDTO>(`/leagues/${leagueId}/protests`);
}
/** Get a specific protest for a league */
getLeagueProtest(leagueId: string, protestId: string): Promise<LeagueAdminProtestsDTO> {
return this.get<LeagueAdminProtestsDTO>(`/leagues/${leagueId}/protests/${protestId}`);
}
/** Apply a penalty */
applyPenalty(input: ApplyPenaltyCommandDTO): Promise<void> {
return this.post<void>('/races/penalties/apply', input);
}
/** Request protest defense */
requestDefense(input: RequestProtestDefenseCommandDTO): Promise<void> {
return this.post<void>('/races/protests/defense/request', input);
}
}

View File

@@ -39,4 +39,9 @@ export class SponsorsApiClient extends BaseApiClient {
getSponsorships(sponsorId: string): Promise<SponsorSponsorshipsDTO | null> {
return this.get<SponsorSponsorshipsDTO | null>(`/sponsors/${sponsorId}/sponsorships`);
}
/** Get sponsor by ID */
getSponsor(sponsorId: string): Promise<SponsorDTO | null> {
return this.get<SponsorDTO | null>(`/sponsors/${sponsorId}`);
}
}

View File

@@ -1,15 +1,16 @@
import { BaseApiClient } from '../base/BaseApiClient';
import { LeagueMemberDTO } from '@/lib/types/generated/LeagueMemberDTO';
import type {
AllTeamsDto,
TeamDetailsDto,
TeamMembersDto,
TeamJoinRequestsDto,
CreateTeamInputDto,
CreateTeamOutputDto,
DriverTeamDto,
TeamDetailsDto,
TeamJoinRequestsDto,
TeamMembersDto,
UpdateTeamInputDto,
UpdateTeamOutputDto,
DriverTeamDto,
} from '../../dtos';
import { BaseApiClient } from '../base/BaseApiClient';
/**
* Teams API Client
@@ -51,4 +52,9 @@ export class TeamsApiClient extends BaseApiClient {
getDriverTeam(driverId: string): Promise<DriverTeamDto | null> {
return this.get<DriverTeamDto | null>(`/teams/driver/${driverId}`);
}
/** Get membership for a driver in a team */
getMembership(teamId: string, driverId: string): Promise<LeagueMemberDTO | null> {
return this.get<LeagueMemberDTO | null>(`/teams/${teamId}/members/${driverId}`);
}
}