103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
'use client';
|
|
|
|
/**
|
|
* LeagueStandingsPresenter
|
|
* Pure client-side presenter for LeagueStandingsTemplate
|
|
* Converts ViewModels to ViewData
|
|
*/
|
|
|
|
import type { Presenter } from '@/lib/contracts/presenters/Presenter';
|
|
import type { LeagueMembership } from '@/lib/types/LeagueMembership';
|
|
import type { DriverData, LeagueMembershipData, LeagueStandingsViewData, StandingEntryData } from '@/lib/view-data/LeagueStandingsViewData';
|
|
import type { DriverViewModel } from '@/lib/view-models/DriverViewModel';
|
|
import type { StandingEntryViewModel } from '@/lib/view-models/StandingEntryViewModel';
|
|
|
|
interface LeagueStandingsInput {
|
|
standings: StandingEntryViewModel[];
|
|
drivers: DriverViewModel[];
|
|
memberships: LeagueMembership[];
|
|
leagueId: string;
|
|
currentDriverId: string | null;
|
|
isAdmin: boolean;
|
|
}
|
|
|
|
export class LeagueStandingsPresenter implements Presenter<LeagueStandingsInput, LeagueStandingsViewData> {
|
|
/**
|
|
* Convert StandingEntryViewModel to StandingEntryData
|
|
*/
|
|
private static convertStanding(standing: StandingEntryViewModel): StandingEntryData {
|
|
return {
|
|
driverId: standing.driverId,
|
|
position: standing.position,
|
|
totalPoints: standing.points,
|
|
racesFinished: standing.races,
|
|
racesStarted: standing.races,
|
|
avgFinish: null, // Not available in current ViewModel
|
|
penaltyPoints: 0, // Not available in current ViewModel
|
|
bonusPoints: 0, // Not available in current ViewModel
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert DriverViewModel to DriverData
|
|
*/
|
|
private static convertDriver(driver: DriverViewModel): DriverData {
|
|
return {
|
|
id: driver.id,
|
|
name: driver.name,
|
|
avatarUrl: driver.avatarUrl,
|
|
iracingId: driver.iracingId,
|
|
rating: driver.rating,
|
|
country: driver.country,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert LeagueMembership to LeagueMembershipData
|
|
*/
|
|
private static convertMembership(membership: LeagueMembership): LeagueMembershipData {
|
|
return {
|
|
driverId: membership.driverId,
|
|
leagueId: membership.leagueId,
|
|
role: membership.role,
|
|
joinedAt: membership.joinedAt,
|
|
status: membership.status,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Transform input to output
|
|
*/
|
|
present(input: LeagueStandingsInput): LeagueStandingsViewData {
|
|
return {
|
|
standings: input.standings.map(s => LeagueStandingsPresenter.convertStanding(s)),
|
|
drivers: input.drivers.map(d => LeagueStandingsPresenter.convertDriver(d)),
|
|
memberships: input.memberships.map(m => LeagueStandingsPresenter.convertMembership(m)),
|
|
leagueId: input.leagueId,
|
|
currentDriverId: input.currentDriverId,
|
|
isAdmin: input.isAdmin,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Static helper for backward compatibility
|
|
*/
|
|
static createViewData(
|
|
standings: StandingEntryViewModel[],
|
|
drivers: DriverViewModel[],
|
|
memberships: LeagueMembership[],
|
|
leagueId: string,
|
|
currentDriverId: string | null,
|
|
isAdmin: boolean
|
|
): LeagueStandingsViewData {
|
|
const presenter = new LeagueStandingsPresenter();
|
|
return presenter.present({
|
|
standings,
|
|
drivers,
|
|
memberships,
|
|
leagueId,
|
|
currentDriverId,
|
|
isAdmin,
|
|
});
|
|
}
|
|
} |