remove core from pages

This commit is contained in:
2025-12-18 19:14:50 +01:00
parent 9814d9682c
commit 4a3087ae35
35 changed files with 552 additions and 354 deletions

View File

@@ -6,6 +6,7 @@ import { LeagueStandingsDTO } from '../types/generated/LeagueStandingsDTO';
import { DriverDTO } from '../types/DriverDTO';
import { RaceDTO } from '../types/generated/RaceDTO';
import { LeagueScoringConfigDTO } from '../types/LeagueScoringConfigDTO';
import { RaceViewModel } from './RaceViewModel';
// Sponsor info type
export interface SponsorInfo {
@@ -59,8 +60,8 @@ export class LeagueDetailPageViewModel {
memberships: LeagueMembershipWithRole[];
// Races
allRaces: RaceDTO[];
runningRaces: RaceDTO[];
allRaces: RaceViewModel[];
runningRaces: RaceViewModel[];
// Stats
averageSOF: number | null;
@@ -96,7 +97,7 @@ export class LeagueDetailPageViewModel {
scoringConfig: LeagueScoringConfigDTO | null,
drivers: DriverDTO[],
memberships: LeagueMembershipsDTO,
allRaces: RaceDTO[],
allRaces: RaceViewModel[],
leagueStats: LeagueStatsDTO,
sponsors: SponsorInfo[]
) {

View File

@@ -1,6 +1,5 @@
import type { LeagueConfigFormModel } from '../types/LeagueConfigFormModel';
import type { LeagueScoringPresetDTO } from '../types/LeagueScoringPresetDTO';
import type { DriverDTO } from '../types/DriverDTO';
import { LeagueScoringPresetsViewModel } from './LeagueScoringPresetsViewModel';
import { DriverSummaryViewModel } from './DriverSummaryViewModel';
@@ -17,7 +16,7 @@ export class LeagueSettingsViewModel {
config: LeagueConfigFormModel;
presets: LeagueScoringPresetDTO[];
owner: DriverSummaryViewModel | null;
members: DriverDTO[];
members: DriverSummaryViewModel[];
constructor(dto: {
league: {
@@ -28,7 +27,7 @@ export class LeagueSettingsViewModel {
config: LeagueConfigFormModel;
presets: LeagueScoringPresetDTO[];
owner: DriverSummaryViewModel | null;
members: DriverDTO[];
members: DriverSummaryViewModel[];
}) {
this.league = dto.league;
this.config = dto.config;

View File

@@ -1,20 +1,21 @@
import { LeagueStandingDTO } from '../types/generated/LeagueStandingDTO';
import { StandingEntryViewModel } from './StandingEntryViewModel';
import { DriverDTO } from '../types/DriverDTO';
import { LeagueMembership } from '../types/LeagueMembership';
export class LeagueStandingsViewModel {
standings: StandingEntryViewModel[];
drivers: DriverDTO[];
memberships: LeagueMembership[];
constructor(dto: { standings: LeagueStandingDTO[] }, currentUserId: string, previousStandings?: LeagueStandingDTO[]) {
constructor(dto: { standings: LeagueStandingDTO[]; drivers: DriverDTO[]; memberships: LeagueMembership[] }, currentUserId: string, previousStandings?: LeagueStandingDTO[]) {
const leaderPoints = dto.standings[0]?.points || 0;
this.standings = dto.standings.map((entry, index) => {
const nextPoints = dto.standings[index + 1]?.points || entry.points;
const previousPosition = previousStandings?.find(p => p.driverId === entry.driverId)?.position;
return new StandingEntryViewModel(entry, leaderPoints, nextPoints, currentUserId, previousPosition);
});
this.drivers = dto.drivers;
this.memberships = dto.memberships;
}
// Note: The generated DTO doesn't have these fields
// These will need to be added when the OpenAPI spec is updated
drivers: any[] = [];
memberships: any[] = [];
}

View File

@@ -0,0 +1,13 @@
import { DriverSummaryDTO } from '../types/generated/LeagueAdminProtestsDTO';
export class ProtestDriverViewModel {
constructor(private readonly dto: DriverSummaryDTO) {}
get id(): string {
return this.dto.id;
}
get name(): string {
return this.dto.name;
}
}

View File

@@ -11,6 +11,9 @@ export class ProtestViewModel {
accusedDriverId: string;
description: string;
submittedAt: string;
status: string;
reviewedAt?: string;
decisionNotes?: string;
constructor(dto: ProtestDTO) {
this.id = dto.id;
@@ -19,6 +22,10 @@ export class ProtestViewModel {
this.accusedDriverId = dto.accusedDriverId;
this.description = dto.description;
this.submittedAt = dto.submittedAt;
// TODO: Add these fields to DTO when available
this.status = 'pending';
this.reviewedAt = undefined;
this.decisionNotes = undefined;
}
/** UI-specific: Formatted submitted date */
@@ -26,8 +33,8 @@ export class ProtestViewModel {
return new Date(this.submittedAt).toLocaleString();
}
/** UI-specific: Status display - placeholder since status not in current DTO */
/** UI-specific: Status display */
get statusDisplay(): string {
return 'Pending'; // TODO: Update when status is added to DTO
return 'Pending';
}
}

View File

@@ -0,0 +1,34 @@
import { RaceDTO } from '../types/generated/RaceDTO';
export class RaceViewModel {
constructor(private readonly dto: RaceDTO, private readonly _status?: string, private readonly _registeredCount?: number, private readonly _strengthOfField?: number) {}
get id(): string {
return this.dto.id;
}
get name(): string {
return this.dto.name;
}
get date(): string {
return this.dto.date;
}
get status(): string | undefined {
return this._status;
}
get registeredCount(): number | undefined {
return this._registeredCount;
}
get strengthOfField(): number | undefined {
return this._strengthOfField;
}
/** UI-specific: Formatted date */
get formattedDate(): string {
return new Date(this.date).toLocaleDateString();
}
}

View File

@@ -0,0 +1,54 @@
import { PendingRequestDTO } from '@/components/sponsors/PendingSponsorshipRequests';
export class SponsorshipRequestViewModel {
id: string;
sponsorId: string;
sponsorName: string;
sponsorLogo?: string;
tier: 'main' | 'secondary';
offeredAmount: number;
currency: string;
formattedAmount: string;
message?: string;
createdAt: Date;
platformFee: number;
netAmount: number;
constructor(dto: PendingRequestDTO) {
this.id = dto.id;
this.sponsorId = dto.sponsorId;
this.sponsorName = dto.sponsorName;
this.sponsorLogo = dto.sponsorLogo;
this.tier = dto.tier;
this.offeredAmount = dto.offeredAmount;
this.currency = dto.currency;
this.formattedAmount = dto.formattedAmount;
this.message = dto.message;
this.createdAt = dto.createdAt;
this.platformFee = dto.platformFee;
this.netAmount = dto.netAmount;
}
/** UI-specific: Formatted date */
get formattedDate(): string {
return this.createdAt.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
});
}
/** UI-specific: Net amount in dollars */
get netAmountDollars(): string {
return `$${(this.netAmount / 100).toFixed(2)}`;
}
/** UI-specific: Tier display */
get tierDisplay(): string {
return this.tier === 'main' ? 'Main Sponsor' : 'Secondary';
}
/** UI-specific: Tier badge variant */
get tierBadgeVariant(): 'primary' | 'secondary' {
return this.tier === 'main' ? 'primary' : 'secondary';
}
}