website refactor
This commit is contained in:
@@ -1,30 +1,44 @@
|
||||
import { Result } from '@/lib/contracts/Result';
|
||||
import { Service, DomainError } from '@/lib/contracts/services/Service';
|
||||
import { RulebookApiDto } from '@/lib/types/tbd/RulebookApiDto';
|
||||
import { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';
|
||||
import { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';
|
||||
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
|
||||
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
|
||||
|
||||
export class LeagueRulebookService implements Service {
|
||||
private apiClient: LeaguesApiClient;
|
||||
|
||||
constructor() {
|
||||
const baseUrl = getWebsiteApiBaseUrl();
|
||||
this.apiClient = new LeaguesApiClient(
|
||||
baseUrl,
|
||||
new ConsoleErrorReporter(),
|
||||
new ConsoleLogger()
|
||||
);
|
||||
}
|
||||
|
||||
async getRulebookData(leagueId: string): Promise<Result<RulebookApiDto, DomainError>> {
|
||||
// Mock data since backend not implemented
|
||||
const mockData: RulebookApiDto = {
|
||||
leagueId,
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: 'Custom Rules',
|
||||
championships: [
|
||||
{
|
||||
type: 'driver',
|
||||
try {
|
||||
const config = await this.apiClient.getLeagueConfig(leagueId);
|
||||
|
||||
const mockData: RulebookApiDto = {
|
||||
leagueId,
|
||||
scoringConfig: {
|
||||
gameName: 'iRacing',
|
||||
scoringPresetName: config.form?.scoring?.type || 'Standard',
|
||||
championships: (config.form?.championships || []).map((c: any) => ({
|
||||
type: c.type || 'driver',
|
||||
sessionTypes: ['Race'],
|
||||
pointsPreview: [
|
||||
{ sessionType: 'Race', position: 1, points: 25 },
|
||||
{ sessionType: 'Race', position: 2, points: 20 },
|
||||
{ sessionType: 'Race', position: 3, points: 16 },
|
||||
],
|
||||
bonusSummary: ['Pole Position: +1', 'Fastest Lap: +1'],
|
||||
}
|
||||
],
|
||||
dropPolicySummary: 'All results count',
|
||||
},
|
||||
};
|
||||
return Result.ok(mockData);
|
||||
pointsPreview: [],
|
||||
bonusSummary: [],
|
||||
})),
|
||||
dropPolicySummary: config.form?.dropPolicy?.strategy || 'All results count',
|
||||
},
|
||||
};
|
||||
return Result.ok(mockData);
|
||||
} catch (error: unknown) {
|
||||
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to fetch rulebook' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,45 @@
|
||||
import { Result } from '@/lib/contracts/Result';
|
||||
import { Service, DomainError } from '@/lib/contracts/services/Service';
|
||||
import { LeagueScheduleApiDto } from '@/lib/types/tbd/LeagueScheduleApiDto';
|
||||
import { LeaguesApiClient } from '@/lib/api/leagues/LeaguesApiClient';
|
||||
import { ConsoleErrorReporter } from '@/lib/infrastructure/logging/ConsoleErrorReporter';
|
||||
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
|
||||
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
|
||||
|
||||
export class LeagueScheduleService implements Service {
|
||||
private apiClient: LeaguesApiClient;
|
||||
|
||||
constructor() {
|
||||
const baseUrl = getWebsiteApiBaseUrl();
|
||||
this.apiClient = new LeaguesApiClient(
|
||||
baseUrl,
|
||||
new ConsoleErrorReporter(),
|
||||
new ConsoleLogger()
|
||||
);
|
||||
}
|
||||
|
||||
async getScheduleData(leagueId: string): Promise<Result<LeagueScheduleApiDto, DomainError>> {
|
||||
// Mock data since backend not implemented
|
||||
const mockData: LeagueScheduleApiDto = {
|
||||
leagueId,
|
||||
races: [
|
||||
{
|
||||
id: 'race-1',
|
||||
name: 'Round 1 - Monza',
|
||||
date: '2024-10-15T14:00:00Z',
|
||||
track: 'Monza Circuit',
|
||||
car: 'Ferrari SF90',
|
||||
sessionType: 'Race',
|
||||
},
|
||||
{
|
||||
id: 'race-2',
|
||||
name: 'Round 2 - Silverstone',
|
||||
date: '2024-10-22T13:00:00Z',
|
||||
track: 'Silverstone Circuit',
|
||||
car: 'Mercedes W10',
|
||||
sessionType: 'Race',
|
||||
},
|
||||
{
|
||||
id: 'race-3',
|
||||
name: 'Round 3 - Spa-Francorchamps',
|
||||
date: '2024-10-29T12:00:00Z',
|
||||
track: 'Circuit de Spa-Francorchamps',
|
||||
car: 'Red Bull RB15',
|
||||
sessionType: 'Race',
|
||||
},
|
||||
],
|
||||
};
|
||||
return Result.ok(mockData);
|
||||
try {
|
||||
const data = await this.apiClient.getSchedule(leagueId);
|
||||
|
||||
// Map LeagueScheduleDTO to LeagueScheduleApiDto
|
||||
const apiDto: LeagueScheduleApiDto = {
|
||||
leagueId,
|
||||
races: data.races.map(race => ({
|
||||
id: race.id,
|
||||
name: race.name,
|
||||
date: race.date,
|
||||
track: (race as any).track || 'TBA',
|
||||
car: (race as any).car || 'TBA',
|
||||
sessionType: (race as any).sessionType || 'Race',
|
||||
status: (race as any).status || 'scheduled',
|
||||
strengthOfField: (race as any).strengthOfField,
|
||||
})),
|
||||
};
|
||||
|
||||
return Result.ok(apiDto);
|
||||
} catch (error: unknown) {
|
||||
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to fetch schedule' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ import type { LeagueSeasonSchedulePublishOutputDTO } from '@/lib/types/generated
|
||||
import type { LeagueRosterMemberDTO } from '@/lib/types/generated/LeagueRosterMemberDTO';
|
||||
import type { LeagueMembershipsDTO } from '@/lib/types/generated/LeagueMembershipsDTO';
|
||||
import type { GetTeamDetailsOutputDTO } from '@/lib/types/generated/GetTeamDetailsOutputDTO';
|
||||
import type { GetDriverOutputDTO } from '@/lib/types/generated/GetDriverOutputDTO';
|
||||
import type { RaceDTO } from '@/lib/types/generated/RaceDTO';
|
||||
import type { LeagueScoringConfigDTO } from '@/lib/types/generated/LeagueScoringConfigDTO';
|
||||
import { TeamMemberViewModel } from '@/lib/view-models/TeamMemberViewModel';
|
||||
import { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
|
||||
import { TeamDetailsViewModel } from '@/lib/view-models/TeamDetailsViewModel';
|
||||
@@ -45,7 +48,11 @@ export interface LeagueRosterAdminData {
|
||||
|
||||
export interface LeagueDetailData {
|
||||
league: LeagueWithCapacityAndScoringDTO;
|
||||
apiDto: AllLeaguesWithCapacityAndScoringDTO;
|
||||
owner: GetDriverOutputDTO | null;
|
||||
scoringConfig: LeagueScoringConfigDTO | null;
|
||||
memberships: LeagueMembershipsDTO;
|
||||
races: RaceDTO[];
|
||||
sponsors: any[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,24 +65,28 @@ export interface LeagueDetailData {
|
||||
@injectable()
|
||||
export class LeagueService implements Service {
|
||||
private apiClient: LeaguesApiClient;
|
||||
private driversApiClient?: DriversApiClient;
|
||||
private sponsorsApiClient?: SponsorsApiClient;
|
||||
private racesApiClient?: RacesApiClient;
|
||||
private driversApiClient: DriversApiClient;
|
||||
private sponsorsApiClient: SponsorsApiClient;
|
||||
private racesApiClient: RacesApiClient;
|
||||
|
||||
constructor(@unmanaged() apiClient?: LeaguesApiClient) {
|
||||
const baseUrl = getWebsiteApiBaseUrl();
|
||||
const logger = new ConsoleLogger();
|
||||
const errorReporter = new EnhancedErrorReporter(logger, {
|
||||
showUserNotifications: false,
|
||||
logToConsole: true,
|
||||
reportToExternal: isProductionEnvironment(),
|
||||
});
|
||||
|
||||
if (apiClient) {
|
||||
this.apiClient = apiClient;
|
||||
} else {
|
||||
const baseUrl = getWebsiteApiBaseUrl();
|
||||
const logger = new ConsoleLogger();
|
||||
const errorReporter = new EnhancedErrorReporter(logger, {
|
||||
showUserNotifications: false,
|
||||
logToConsole: true,
|
||||
reportToExternal: isProductionEnvironment(),
|
||||
});
|
||||
this.apiClient = new LeaguesApiClient(baseUrl, errorReporter, logger);
|
||||
}
|
||||
// Optional clients can be initialized if needed
|
||||
|
||||
this.driversApiClient = new DriversApiClient(baseUrl, errorReporter, logger);
|
||||
this.sponsorsApiClient = new SponsorsApiClient(baseUrl, errorReporter, logger);
|
||||
this.racesApiClient = new RacesApiClient(baseUrl, errorReporter, logger);
|
||||
}
|
||||
|
||||
async getLeagueStandings(leagueId: string): Promise<any> {
|
||||
@@ -143,7 +154,11 @@ export class LeagueService implements Service {
|
||||
|
||||
async getLeagueDetailData(leagueId: string): Promise<Result<LeagueDetailData, DomainError>> {
|
||||
try {
|
||||
const apiDto = await this.apiClient.getAllWithCapacityAndScoring();
|
||||
const [apiDto, memberships, racesResponse] = await Promise.all([
|
||||
this.apiClient.getAllWithCapacityAndScoring(),
|
||||
this.apiClient.getMemberships(leagueId),
|
||||
this.apiClient.getRaces(leagueId),
|
||||
]);
|
||||
|
||||
if (!apiDto || !apiDto.leagues) {
|
||||
return Result.err({ type: 'notFound', message: 'Leagues not found' });
|
||||
@@ -153,10 +168,40 @@ export class LeagueService implements Service {
|
||||
if (!league) {
|
||||
return Result.err({ type: 'notFound', message: 'League not found' });
|
||||
}
|
||||
|
||||
// Fetch owner if ownerId exists
|
||||
let owner: GetDriverOutputDTO | null = null;
|
||||
if (league.ownerId) {
|
||||
owner = await this.driversApiClient.getDriver(league.ownerId);
|
||||
}
|
||||
|
||||
// Fetch scoring config if available
|
||||
let scoringConfig: LeagueScoringConfigDTO | null = null;
|
||||
try {
|
||||
const config = await this.apiClient.getLeagueConfig(leagueId);
|
||||
if (config.form?.scoring) {
|
||||
// Map form scoring to LeagueScoringConfigDTO if possible, or just use partial
|
||||
scoringConfig = {
|
||||
leagueId,
|
||||
seasonId: '', // Not available in this context
|
||||
gameId: '',
|
||||
gameName: '',
|
||||
scoringPresetId: (config.form.scoring as any).presetId,
|
||||
dropPolicySummary: '',
|
||||
championships: [],
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to fetch league scoring config', e);
|
||||
}
|
||||
|
||||
return Result.ok({
|
||||
league,
|
||||
apiDto,
|
||||
owner,
|
||||
scoringConfig,
|
||||
memberships,
|
||||
races: racesResponse.races,
|
||||
sponsors: [], // Sponsors integration can be added here
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
console.error('LeagueService.getLeagueDetailData failed:', error);
|
||||
|
||||
@@ -18,72 +18,51 @@ export class LeagueStandingsService implements Service {
|
||||
);
|
||||
}
|
||||
|
||||
async getStandingsData(_: string): Promise<Result<{ standings: LeagueStandingsApiDto; memberships: LeagueMembershipsApiDto }, DomainError>> {
|
||||
// Mock data since backend may not be implemented
|
||||
const mockStandings: LeagueStandingsApiDto = {
|
||||
standings: [
|
||||
{
|
||||
driverId: 'driver1',
|
||||
driver: {
|
||||
id: 'driver1',
|
||||
name: 'John Doe',
|
||||
iracingId: '12345',
|
||||
country: 'US',
|
||||
joinedAt: new Date().toISOString(),
|
||||
},
|
||||
points: 100,
|
||||
position: 1,
|
||||
wins: 2,
|
||||
podiums: 3,
|
||||
races: 5,
|
||||
},
|
||||
{
|
||||
driverId: 'driver2',
|
||||
driver: {
|
||||
id: 'driver2',
|
||||
name: 'Jane Smith',
|
||||
iracingId: '67890',
|
||||
country: 'UK',
|
||||
joinedAt: new Date().toISOString(),
|
||||
},
|
||||
points: 80,
|
||||
position: 2,
|
||||
wins: 1,
|
||||
podiums: 2,
|
||||
races: 5,
|
||||
},
|
||||
],
|
||||
};
|
||||
async getStandingsData(leagueId: string): Promise<Result<{ standings: LeagueStandingsApiDto; memberships: LeagueMembershipsApiDto }, DomainError>> {
|
||||
try {
|
||||
const [standingsData, membershipsData] = await Promise.all([
|
||||
this.apiClient.getStandings(leagueId),
|
||||
this.apiClient.getMemberships(leagueId),
|
||||
]);
|
||||
|
||||
const mockMemberships: LeagueMembershipsApiDto = {
|
||||
members: [
|
||||
{
|
||||
driverId: 'driver1',
|
||||
// Map LeagueStandingsDTO to LeagueStandingsApiDto
|
||||
const standings: LeagueStandingsApiDto = {
|
||||
standings: standingsData.standings.map(s => ({
|
||||
driverId: s.driverId,
|
||||
driver: {
|
||||
id: 'driver1',
|
||||
name: 'John Doe',
|
||||
iracingId: '12345',
|
||||
country: 'US',
|
||||
joinedAt: new Date().toISOString(),
|
||||
id: s.driver.id,
|
||||
name: s.driver.name,
|
||||
iracingId: s.driver.iracingId,
|
||||
country: s.driver.country,
|
||||
joinedAt: s.driver.joinedAt,
|
||||
},
|
||||
role: 'member',
|
||||
joinedAt: new Date().toISOString(),
|
||||
},
|
||||
{
|
||||
driverId: 'driver2',
|
||||
driver: {
|
||||
id: 'driver2',
|
||||
name: 'Jane Smith',
|
||||
iracingId: '67890',
|
||||
country: 'UK',
|
||||
joinedAt: new Date().toISOString(),
|
||||
},
|
||||
role: 'member',
|
||||
joinedAt: new Date().toISOString(),
|
||||
},
|
||||
],
|
||||
};
|
||||
points: s.points,
|
||||
position: s.position,
|
||||
wins: s.wins,
|
||||
podiums: s.podiums,
|
||||
races: s.races,
|
||||
})),
|
||||
};
|
||||
|
||||
return Result.ok({ standings: mockStandings, memberships: mockMemberships });
|
||||
// Map LeagueMembershipsDTO to LeagueMembershipsApiDto
|
||||
const memberships: LeagueMembershipsApiDto = {
|
||||
members: (membershipsData.members || []).map(m => ({
|
||||
driverId: m.driverId,
|
||||
driver: {
|
||||
id: m.driver.id,
|
||||
name: m.driver.name,
|
||||
iracingId: m.driver.iracingId,
|
||||
country: m.driver.country,
|
||||
joinedAt: m.driver.joinedAt,
|
||||
},
|
||||
role: m.role as any,
|
||||
joinedAt: m.joinedAt,
|
||||
})),
|
||||
};
|
||||
|
||||
return Result.ok({ standings, memberships });
|
||||
} catch (error: unknown) {
|
||||
return Result.err({ type: 'serverError', message: (error as Error).message || 'Failed to fetch standings' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user