website cleanup

This commit is contained in:
2025-12-24 21:44:58 +01:00
parent 9b683a59d3
commit d78854a4c6
277 changed files with 6141 additions and 2693 deletions

View File

@@ -1,9 +1,9 @@
import { BaseApiClient } from '../base/BaseApiClient';
import { AuthSessionDTO } from '../../types/generated/AuthSessionDTO';
import { LoginParams } from '../../types/generated/LoginParams';
import { SignupParams } from '../../types/generated/SignupParams';
import { LoginWithIracingCallbackParams } from '../../types/generated/LoginWithIracingCallbackParams';
import { IracingAuthRedirectResult } from '../../types/generated/IracingAuthRedirectResult';
import { LoginParamsDTO } from '../../types/generated/LoginParamsDTO';
import { SignupParamsDTO } from '../../types/generated/SignupParamsDTO';
import { LoginWithIracingCallbackParamsDTO } from '../../types/generated/LoginWithIracingCallbackParamsDTO';
import { IracingAuthRedirectResultDTO } from '../../types/generated/IracingAuthRedirectResultDTO';
/**
* Auth API Client
@@ -12,12 +12,12 @@ import { IracingAuthRedirectResult } from '../../types/generated/IracingAuthRedi
*/
export class AuthApiClient extends BaseApiClient {
/** Sign up with email */
signup(params: SignupParams): Promise<AuthSessionDTO> {
signup(params: SignupParamsDTO): Promise<AuthSessionDTO> {
return this.post<AuthSessionDTO>('/auth/signup', params);
}
/** Login with email */
login(params: LoginParams): Promise<AuthSessionDTO> {
login(params: LoginParamsDTO): Promise<AuthSessionDTO> {
return this.post<AuthSessionDTO>('/auth/login', params);
}
@@ -32,13 +32,22 @@ export class AuthApiClient extends BaseApiClient {
}
/** Start iRacing auth redirect */
startIracingAuthRedirect(returnTo?: string): Promise<IracingAuthRedirectResult> {
startIracingAuthRedirect(returnTo?: string): Promise<IracingAuthRedirectResultDTO> {
const query = returnTo ? `?returnTo=${encodeURIComponent(returnTo)}` : '';
return this.get<IracingAuthRedirectResult>(`/auth/iracing/start${query}`);
return this.get<IracingAuthRedirectResultDTO>(`/auth/iracing/start${query}`);
}
/**
* Convenience: build iRacing auth start URL.
* Used by AuthService for view-layer navigation.
*/
getIracingAuthUrl(returnTo?: string): string {
const query = returnTo ? `?returnTo=${encodeURIComponent(returnTo)}` : '';
return `${this.baseUrl}/auth/iracing/start${query}`;
}
/** Login with iRacing callback */
loginWithIracingCallback(params: LoginWithIracingCallbackParams): Promise<AuthSessionDTO> {
loginWithIracingCallback(params: LoginWithIracingCallbackParamsDTO): Promise<AuthSessionDTO> {
const query = new URLSearchParams();
query.append('code', params.code);
query.append('state', params.state);
@@ -47,4 +56,4 @@ export class AuthApiClient extends BaseApiClient {
}
return this.get<AuthSessionDTO>(`/auth/iracing/callback?${query.toString()}`);
}
}
}

View File

@@ -9,7 +9,7 @@ import { Logger } from '../../interfaces/Logger';
import { ErrorReporter } from '../../interfaces/ErrorReporter';
export class BaseApiClient {
private baseUrl: string;
protected baseUrl: string;
private errorReporter: ErrorReporter;
private logger: Logger;
@@ -19,12 +19,16 @@ export class BaseApiClient {
this.logger = logger;
}
protected async request<T>(method: string, path: string, data?: object): Promise<T> {
protected async request<T>(method: string, path: string, data?: object | FormData): Promise<T> {
this.logger.info(`${method} ${path}`);
const headers: HeadersInit = {
'Content-Type': 'application/json',
};
const isFormData = typeof FormData !== 'undefined' && data instanceof FormData;
const headers: HeadersInit = isFormData
? {}
: {
'Content-Type': 'application/json',
};
const config: RequestInit = {
method,
@@ -33,7 +37,7 @@ export class BaseApiClient {
};
if (data) {
config.body = JSON.stringify(data);
config.body = isFormData ? data : JSON.stringify(data);
}
const response = await fetch(`${this.baseUrl}${path}`, config);
@@ -45,7 +49,10 @@ export class BaseApiClient {
} catch {
// Keep default error message
}
const error = new Error(errorData.message || `API request failed with status ${response.status}`);
const error = new Error(
errorData.message || `API request failed with status ${response.status}`,
) as Error & { status?: number };
error.status = response.status;
this.errorReporter.report(error);
throw error;
}
@@ -76,4 +83,4 @@ export class BaseApiClient {
protected patch<T>(path: string, data: object): Promise<T> {
return this.request<T>('PATCH', path, data);
}
}
}

View File

@@ -1,28 +1,5 @@
import { BaseApiClient } from '../base/BaseApiClient';
import {
DashboardDriverSummaryDTO,
DashboardRaceSummaryDTO,
DashboardLeagueStandingSummaryDTO,
DashboardFeedItemSummaryDTO,
DashboardFriendSummaryDTO,
DashboardRecentResultDTO,
} from '../../types/generated';
// Define DashboardOverviewDTO using generated types
export type DashboardOverviewDto = {
currentDriver: DashboardDriverSummaryDTO | null;
myUpcomingRaces: DashboardRaceSummaryDTO[];
otherUpcomingRaces: DashboardRaceSummaryDTO[];
upcomingRaces: DashboardRaceSummaryDTO[];
activeLeaguesCount: number;
nextRace: DashboardRaceSummaryDTO | null;
recentResults: DashboardRecentResultDTO[];
leagueStandingsSummaries: DashboardLeagueStandingSummaryDTO[];
feedSummary: {
feedItems: DashboardFeedItemSummaryDTO[];
};
friends: DashboardFriendSummaryDTO[];
};
import type { DashboardOverviewDTO } from '../../types/generated/DashboardOverviewDTO';
/**
* Dashboard API Client
@@ -31,7 +8,7 @@ export type DashboardOverviewDto = {
*/
export class DashboardApiClient extends BaseApiClient {
/** Get dashboard overview data */
getDashboardOverview(): Promise<DashboardOverviewDto> {
return this.get<DashboardOverviewDto>('/dashboard/overview');
getDashboardOverview(): Promise<DashboardOverviewDTO> {
return this.get<DashboardOverviewDTO>('/dashboard/overview');
}
}
}

View File

@@ -1,6 +1,10 @@
import { BaseApiClient } from '../base/BaseApiClient';
// Import generated types
import type { CompleteOnboardingInputDTO, CompleteOnboardingOutputDTO, DriverRegistrationStatusDTO, DriverLeaderboardItemDTO, DriverProfileDTO, GetDriverOutputDTO } from '../../types/generated';
import type { CompleteOnboardingInputDTO } from '../../types/generated/CompleteOnboardingInputDTO';
import type { CompleteOnboardingOutputDTO } from '../../types/generated/CompleteOnboardingOutputDTO';
import type { DriverRegistrationStatusDTO } from '../../types/generated/DriverRegistrationStatusDTO';
import type { DriverLeaderboardItemDTO } from '../../types/generated/DriverLeaderboardItemDTO';
import type { GetDriverOutputDTO } from '../../types/generated/GetDriverOutputDTO';
import type { GetDriverProfileOutputDTO } from '../../types/generated/GetDriverProfileOutputDTO';
type DriversLeaderboardDto = {
drivers: DriverLeaderboardItemDTO[];
@@ -38,12 +42,12 @@ export class DriversApiClient extends BaseApiClient {
}
/** Get driver profile with full details */
getDriverProfile(driverId: string): Promise<DriverProfileDTO> {
return this.get<DriverProfileDTO>(`/drivers/${driverId}/profile`);
getDriverProfile(driverId: string): Promise<GetDriverProfileOutputDTO> {
return this.get<GetDriverProfileOutputDTO>(`/drivers/${driverId}/profile`);
}
/** Update current driver profile */
updateProfile(updates: { bio?: string; country?: string }): Promise<GetDriverOutputDTO> {
return this.put<GetDriverOutputDTO>('/drivers/profile', updates);
}
}
}

View File

@@ -1,15 +1,16 @@
import { BaseApiClient } from '../base/BaseApiClient';
import type {
AllLeaguesWithCapacityDto,
LeagueStatsDto,
LeagueStandingsDto,
LeagueScheduleDto,
LeagueMembershipsDto,
CreateLeagueInputDto,
CreateLeagueOutputDto,
SponsorshipDetailDTO,
RaceDTO,
} from '../../dtos';
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';
/**
* Leagues API Client
@@ -18,33 +19,33 @@ import type {
*/
export class LeaguesApiClient extends BaseApiClient {
/** Get all leagues with capacity information */
getAllWithCapacity(): Promise<AllLeaguesWithCapacityDto> {
return this.get<AllLeaguesWithCapacityDto>('/leagues/all-with-capacity');
getAllWithCapacity(): Promise<AllLeaguesWithCapacityDTO> {
return this.get<AllLeaguesWithCapacityDTO>('/leagues/all-with-capacity');
}
/** Get total number of leagues */
getTotal(): Promise<LeagueStatsDto> {
return this.get<LeagueStatsDto>('/leagues/total-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`);
getStandings(leagueId: string): Promise<LeagueStandingsDTO> {
return this.get<LeagueStandingsDTO>(`/leagues/${leagueId}/standings`);
}
/** Get league schedule */
getSchedule(leagueId: string): Promise<LeagueScheduleDto> {
return this.get<LeagueScheduleDto>(`/leagues/${leagueId}/schedule`);
getSchedule(leagueId: string): Promise<LeagueScheduleDTO> {
return this.get<LeagueScheduleDTO>(`/leagues/${leagueId}/schedule`);
}
/** Get league memberships */
getMemberships(leagueId: string): Promise<LeagueMembershipsDto> {
return this.get<LeagueMembershipsDto>(`/leagues/${leagueId}/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);
create(input: CreateLeagueInputDTO): Promise<CreateLeagueOutputDTO> {
return this.post<CreateLeagueOutputDTO>('/leagues', input);
}
/** Remove a member from league */
@@ -58,8 +59,8 @@ export class LeaguesApiClient extends BaseApiClient {
}
/** 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`);
getSeasons(leagueId: string): Promise<LeagueSeasonSummaryDTO[]> {
return this.get<LeagueSeasonSummaryDTO[]>(`/leagues/${leagueId}/seasons`);
}
/** Get season sponsorships */
@@ -68,13 +69,13 @@ export class LeaguesApiClient extends BaseApiClient {
}
/** Get league config */
getLeagueConfig(leagueId: string): Promise<{ config: any }> {
return this.get<{ config: any }>(`/leagues/${leagueId}/config`);
getLeagueConfig(leagueId: string): Promise<GetLeagueAdminConfigOutputDTO> {
return this.get<GetLeagueAdminConfigOutputDTO>(`/leagues/${leagueId}/config`);
}
/** Get league scoring presets */
getScoringPresets(): Promise<{ presets: any[] }> {
return this.get<{ presets: any[] }>(`/leagues/scoring-presets`);
getScoringPresets(): Promise<{ presets: LeagueScoringPresetDTO[] }> {
return this.get<{ presets: LeagueScoringPresetDTO[] }>(`/leagues/scoring-presets`);
}
/** Transfer league ownership */
@@ -89,4 +90,4 @@ export class LeaguesApiClient extends BaseApiClient {
getRaces(leagueId: string): Promise<{ races: RaceDTO[] }> {
return this.get<{ races: RaceDTO[] }>(`/leagues/${leagueId}/races`);
}
}
}

View File

@@ -1,13 +1,11 @@
import type {
DeleteMediaOutputDTO,
GetMediaOutputDTO,
RequestAvatarGenerationInputDTO,
RequestAvatarGenerationOutputDTO,
UpdateAvatarInputDTO,
UpdateAvatarOutputDTO,
UploadMediaOutputDTO,
} from '../generated';
import type { GetAvatarOutputDTO } from '../generated';
import type { DeleteMediaOutputDTO } from '../../types/generated/DeleteMediaOutputDTO';
import type { GetAvatarOutputDTO } from '../../types/generated/GetAvatarOutputDTO';
import type { GetMediaOutputDTO } from '../../types/generated/GetMediaOutputDTO';
import type { RequestAvatarGenerationInputDTO } from '../../types/generated/RequestAvatarGenerationInputDTO';
import type { RequestAvatarGenerationOutputDTO } from '../../types/generated/RequestAvatarGenerationOutputDTO';
import type { UpdateAvatarInputDTO } from '../../types/generated/UpdateAvatarInputDTO';
import type { UpdateAvatarOutputDTO } from '../../types/generated/UpdateAvatarOutputDTO';
import type { UploadMediaOutputDTO } from '../../types/generated/UploadMediaOutputDTO';
import { BaseApiClient } from '../base/BaseApiClient';
/**
@@ -51,4 +49,4 @@ export class MediaApiClient extends BaseApiClient {
updateAvatar(input: UpdateAvatarInputDTO): Promise<UpdateAvatarOutputDTO> {
return this.put<UpdateAvatarOutputDTO>(`/media/avatar/${input.driverId}`, { avatarUrl: input.avatarUrl });
}
}
}

View File

@@ -1,8 +1,14 @@
import { BaseApiClient } from '../base/BaseApiClient';
import type { PaymentDto, MembershipFeeDto, MemberPaymentDto, PrizeDto, WalletDto, TransactionDto, UpdatePaymentStatusInputDTO } from '../types/generated';
import type { MembershipFeeDTO } from '../../types/generated/MembershipFeeDTO';
import type { MemberPaymentDTO } from '../../types/generated/MemberPaymentDTO';
import type { PaymentDTO } from '../../types/generated/PaymentDTO';
import type { PrizeDTO } from '../../types/generated/PrizeDTO';
import type { TransactionDTO } from '../../types/generated/TransactionDTO';
import type { UpdatePaymentStatusInputDTO } from '../../types/generated/UpdatePaymentStatusInputDTO';
import type { WalletDTO } from '../../types/generated/WalletDTO';
// Define missing types that are not fully generated
type GetPaymentsOutputDto = { payments: PaymentDto[] };
type GetPaymentsOutputDto = { payments: PaymentDTO[] };
type CreatePaymentInputDto = {
type: 'sponsorship' | 'membership_fee';
amount: number;
@@ -11,15 +17,15 @@ type CreatePaymentInputDto = {
leagueId: string;
seasonId?: string;
};
type CreatePaymentOutputDto = { payment: PaymentDto };
type CreatePaymentOutputDto = { payment: PaymentDTO };
type GetMembershipFeesOutputDto = {
fee: MembershipFeeDto | null;
payments: MemberPaymentDto[]
fee: MembershipFeeDTO | null;
payments: MemberPaymentDTO[]
};
type GetPrizesOutputDto = { prizes: PrizeDto[] };
type GetPrizesOutputDto = { prizes: PrizeDTO[] };
type GetWalletOutputDto = {
wallet: WalletDto;
transactions: TransactionDto[]
wallet: WalletDTO;
transactions: TransactionDTO[]
};
type ProcessWalletTransactionInputDto = {
leagueId: string;
@@ -30,8 +36,8 @@ type ProcessWalletTransactionInputDto = {
referenceType?: 'sponsorship' | 'membership_fee' | 'prize';
};
type ProcessWalletTransactionOutputDto = {
wallet: WalletDto;
transaction: TransactionDto
wallet: WalletDTO;
transaction: TransactionDTO
};
type UpdateMemberPaymentInputDto = {
feeId: string;
@@ -39,16 +45,16 @@ type UpdateMemberPaymentInputDto = {
status?: 'pending' | 'paid' | 'overdue';
paidAt?: Date | string;
};
type UpdateMemberPaymentOutputDto = { payment: MemberPaymentDto };
type GetWalletTransactionsOutputDto = { transactions: TransactionDto[] };
type UpdatePaymentStatusOutputDto = { payment: PaymentDto };
type UpdateMemberPaymentOutputDto = { payment: MemberPaymentDTO };
type GetWalletTransactionsOutputDto = { transactions: TransactionDTO[] };
type UpdatePaymentStatusOutputDto = { payment: PaymentDTO };
type UpsertMembershipFeeInputDto = {
leagueId: string;
seasonId?: string;
type: 'season' | 'monthly' | 'per_race';
amount: number;
};
type UpsertMembershipFeeOutputDto = { fee: MembershipFeeDto };
type UpsertMembershipFeeOutputDto = { fee: MembershipFeeDTO };
type CreatePrizeInputDto = {
leagueId: string;
seasonId: string;
@@ -58,12 +64,12 @@ type CreatePrizeInputDto = {
type: 'cash' | 'merchandise' | 'other';
description?: string;
};
type CreatePrizeOutputDto = { prize: PrizeDto };
type CreatePrizeOutputDto = { prize: PrizeDTO };
type AwardPrizeInputDto = {
prizeId: string;
driverId: string;
};
type AwardPrizeOutputDto = { prize: PrizeDto };
type AwardPrizeOutputDto = { prize: PrizeDTO };
type DeletePrizeInputDto = { prizeId: string };
type DeletePrizeOutputDto = { success: boolean };
@@ -149,4 +155,4 @@ export class PaymentsApiClient extends BaseApiClient {
processWalletTransaction(input: ProcessWalletTransactionInputDto): Promise<ProcessWalletTransactionOutputDto> {
return this.post<ProcessWalletTransactionOutputDto>('/payments/wallets/transactions', input);
}
}
}

View File

@@ -1,11 +1,9 @@
import { BaseApiClient } from '../base/BaseApiClient';
import type {
LeagueAdminProtestsDTO,
ApplyPenaltyCommandDTO,
RequestProtestDefenseCommandDTO,
ReviewProtestCommandDTO,
} from '../../types/generated';
import type { RaceProtestsDTO } from '../../types';
import type { ApplyPenaltyCommandDTO } from '../../types/generated/ApplyPenaltyCommandDTO';
import type { LeagueAdminProtestsDTO } from '../../types/generated/LeagueAdminProtestsDTO';
import type { RaceProtestsDTO } from '../../types/generated/RaceProtestsDTO';
import type { RequestProtestDefenseCommandDTO } from '../../types/generated/RequestProtestDefenseCommandDTO';
import type { ReviewProtestCommandDTO } from '../../types/generated/ReviewProtestCommandDTO';
/**
* Protests API Client
@@ -42,4 +40,4 @@ export class ProtestsApiClient extends BaseApiClient {
getRaceProtests(raceId: string): Promise<RaceProtestsDTO> {
return this.get<RaceProtestsDTO>(`/races/${raceId}/protests`);
}
}
}

View File

@@ -11,6 +11,7 @@ import type { RaceDetailLeagueDTO } from '../../types/generated/RaceDetailLeague
import type { RaceDetailEntryDTO } from '../../types/generated/RaceDetailEntryDTO';
import type { RaceDetailRegistrationDTO } from '../../types/generated/RaceDetailRegistrationDTO';
import type { RaceDetailUserResultDTO } from '../../types/generated/RaceDetailUserResultDTO';
import type { FileProtestCommandDTO } from '../../types/generated/FileProtestCommandDTO';
// Define missing types
type RacesPageDataDTO = { races: RacesPageDataRaceDTO[] };
@@ -42,8 +43,9 @@ export class RacesApiClient extends BaseApiClient {
}
/** Get races page data */
getPageData(): Promise<RacesPageDataDTO> {
return this.get<RacesPageDataDTO>('/races/page-data');
getPageData(leagueId?: string): Promise<RacesPageDataDTO> {
const query = leagueId ? `?leagueId=${encodeURIComponent(leagueId)}` : '';
return this.get<RacesPageDataDTO>(`/races/page-data${query}`);
}
/** Get race detail */
@@ -90,4 +92,9 @@ export class RacesApiClient extends BaseApiClient {
reopen(raceId: string): Promise<void> {
return this.post<void>(`/races/${raceId}/reopen`, {});
}
}
/** File a protest */
fileProtest(input: FileProtestCommandDTO): Promise<void> {
return this.post<void>('/races/protests/file', input);
}
}