wip
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import type { League } from '../../domain/entities/League';
|
||||
import type { Season } from '../../domain/entities/Season';
|
||||
import type { LeagueScoringConfig } from '../../domain/entities/LeagueScoringConfig';
|
||||
import type { Game } from '../../domain/entities/Game';
|
||||
import type { LeagueScoringPresetDTO } from '../ports/LeagueScoringPresetProvider';
|
||||
|
||||
export interface LeagueSummaryViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
createdAt: Date;
|
||||
maxDrivers: number;
|
||||
usedDriverSlots: number;
|
||||
maxTeams?: number;
|
||||
usedTeamSlots?: number;
|
||||
structureSummary: string;
|
||||
scoringPatternSummary?: string;
|
||||
timingSummary: string;
|
||||
scoring?: {
|
||||
gameId: string;
|
||||
gameName: string;
|
||||
primaryChampionshipType: string;
|
||||
scoringPresetId: string;
|
||||
scoringPresetName: string;
|
||||
dropPolicySummary: string;
|
||||
scoringPatternSummary: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AllLeaguesWithCapacityAndScoringViewModel {
|
||||
leagues: LeagueSummaryViewModel[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface LeagueEnrichedData {
|
||||
league: League;
|
||||
usedDriverSlots: number;
|
||||
season?: Season;
|
||||
scoringConfig?: LeagueScoringConfig;
|
||||
game?: Game;
|
||||
preset?: LeagueScoringPresetDTO;
|
||||
}
|
||||
|
||||
export interface IAllLeaguesWithCapacityAndScoringPresenter {
|
||||
present(enrichedLeagues: LeagueEnrichedData[]): AllLeaguesWithCapacityAndScoringViewModel;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { League } from '../../domain/entities/League';
|
||||
|
||||
export interface LeagueWithCapacityViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
settings: {
|
||||
maxDrivers: number;
|
||||
sessionDuration?: number;
|
||||
visibility?: string;
|
||||
};
|
||||
createdAt: string;
|
||||
socialLinks?: {
|
||||
discordUrl?: string;
|
||||
youtubeUrl?: string;
|
||||
websiteUrl?: string;
|
||||
};
|
||||
usedSlots: number;
|
||||
}
|
||||
|
||||
export interface AllLeaguesWithCapacityViewModel {
|
||||
leagues: LeagueWithCapacityViewModel[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface IAllLeaguesWithCapacityPresenter {
|
||||
present(
|
||||
leagues: League[],
|
||||
memberCounts: Map<string, number>
|
||||
): AllLeaguesWithCapacityViewModel;
|
||||
}
|
||||
22
packages/racing/application/presenters/IAllTeamsPresenter.ts
Normal file
22
packages/racing/application/presenters/IAllTeamsPresenter.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { Team } from '../../domain/entities/Team';
|
||||
|
||||
export interface TeamListItemViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
memberCount: number;
|
||||
leagues: string[];
|
||||
specialization?: 'endurance' | 'sprint' | 'mixed';
|
||||
region?: string;
|
||||
languages?: string[];
|
||||
}
|
||||
|
||||
export interface AllTeamsViewModel {
|
||||
teams: TeamListItemViewModel[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface IAllTeamsPresenter {
|
||||
present(teams: Team[]): AllTeamsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export interface DriverRegistrationStatusViewModel {
|
||||
isRegistered: boolean;
|
||||
raceId: string;
|
||||
driverId: string;
|
||||
}
|
||||
|
||||
export interface IDriverRegistrationStatusPresenter {
|
||||
present(
|
||||
isRegistered: boolean,
|
||||
raceId: string,
|
||||
driverId: string
|
||||
): DriverRegistrationStatusViewModel;
|
||||
getViewModel(): DriverRegistrationStatusViewModel;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Team, TeamMembership } from '../../domain/entities/Team';
|
||||
|
||||
export interface DriverTeamViewModel {
|
||||
team: {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
specialization?: 'endurance' | 'sprint' | 'mixed';
|
||||
region?: string;
|
||||
languages?: string[];
|
||||
};
|
||||
membership: {
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
joinedAt: string;
|
||||
isActive: boolean;
|
||||
};
|
||||
isOwner: boolean;
|
||||
canManage: boolean;
|
||||
}
|
||||
|
||||
export interface IDriverTeamPresenter {
|
||||
present(
|
||||
team: Team,
|
||||
membership: TeamMembership,
|
||||
driverId: string
|
||||
): DriverTeamViewModel;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { Driver } from '../../domain/entities/Driver';
|
||||
import type { SkillLevel } from '../../domain/services/SkillLevelService';
|
||||
|
||||
export type { SkillLevel };
|
||||
|
||||
export interface DriverLeaderboardItemViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
rating: number;
|
||||
skillLevel: SkillLevel;
|
||||
nationality: string;
|
||||
racesCompleted: number;
|
||||
wins: number;
|
||||
podiums: number;
|
||||
isActive: boolean;
|
||||
rank: number;
|
||||
avatarUrl: string;
|
||||
}
|
||||
|
||||
export interface DriversLeaderboardViewModel {
|
||||
drivers: DriverLeaderboardItemViewModel[];
|
||||
totalRaces: number;
|
||||
totalWins: number;
|
||||
activeCount: number;
|
||||
}
|
||||
|
||||
export interface IDriversLeaderboardPresenter {
|
||||
present(
|
||||
drivers: Driver[],
|
||||
rankings: Array<{ driverId: string; rating: number; overallRank: number }>,
|
||||
stats: Record<string, { rating: number; wins: number; podiums: number; totalRaces: number; overallRank: number }>,
|
||||
avatarUrls: Record<string, string>
|
||||
): DriversLeaderboardViewModel;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { GetEntitySponsorshipPricingResultDTO } from '../use-cases/GetEntitySponsorshipPricingQuery';
|
||||
|
||||
export interface IEntitySponsorshipPricingPresenter {
|
||||
present(data: GetEntitySponsorshipPricingResultDTO | null): void;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
export interface LeagueDriverSeasonStatsItemViewModel {
|
||||
leagueId: string;
|
||||
driverId: string;
|
||||
position: number;
|
||||
driverName: string;
|
||||
teamId?: string;
|
||||
teamName?: string;
|
||||
totalPoints: number;
|
||||
basePoints: number;
|
||||
penaltyPoints: number;
|
||||
bonusPoints: number;
|
||||
pointsPerRace: number;
|
||||
racesStarted: number;
|
||||
racesFinished: number;
|
||||
dnfs: number;
|
||||
noShows: number;
|
||||
avgFinish: number | null;
|
||||
rating: number | null;
|
||||
ratingChange: number | null;
|
||||
}
|
||||
|
||||
export interface LeagueDriverSeasonStatsViewModel {
|
||||
leagueId: string;
|
||||
stats: LeagueDriverSeasonStatsItemViewModel[];
|
||||
}
|
||||
|
||||
export interface ILeagueDriverSeasonStatsPresenter {
|
||||
present(
|
||||
leagueId: string,
|
||||
standings: Array<{
|
||||
driverId: string;
|
||||
position: number;
|
||||
points: number;
|
||||
racesCompleted: number;
|
||||
}>,
|
||||
penalties: Map<string, { baseDelta: number; bonusDelta: number }>,
|
||||
driverResults: Map<string, Array<{ position: number }>>,
|
||||
driverRatings: Map<string, { rating: number | null; ratingChange: number | null }>
|
||||
): LeagueDriverSeasonStatsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { League } from '../../domain/entities/League';
|
||||
import type { Season } from '../../domain/entities/Season';
|
||||
import type { LeagueScoringConfig } from '../../domain/entities/LeagueScoringConfig';
|
||||
import type { Game } from '../../domain/entities/Game';
|
||||
|
||||
export interface LeagueConfigFormViewModel {
|
||||
leagueId: string;
|
||||
basics: {
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
gameId: string;
|
||||
};
|
||||
structure: {
|
||||
mode: string;
|
||||
maxDrivers: number;
|
||||
maxTeams?: number;
|
||||
driversPerTeam?: number;
|
||||
multiClassEnabled: boolean;
|
||||
};
|
||||
championships: {
|
||||
enableDriverChampionship: boolean;
|
||||
enableTeamChampionship: boolean;
|
||||
enableNationsChampionship: boolean;
|
||||
enableTrophyChampionship: boolean;
|
||||
};
|
||||
scoring: {
|
||||
patternId?: string;
|
||||
customScoringEnabled: boolean;
|
||||
};
|
||||
dropPolicy: {
|
||||
strategy: string;
|
||||
n?: number;
|
||||
};
|
||||
timings: {
|
||||
practiceMinutes: number;
|
||||
qualifyingMinutes: number;
|
||||
sprintRaceMinutes?: number;
|
||||
mainRaceMinutes: number;
|
||||
sessionCount: number;
|
||||
roundsPlanned: number;
|
||||
};
|
||||
stewarding: {
|
||||
decisionMode: string;
|
||||
requireDefense: boolean;
|
||||
defenseTimeLimit: number;
|
||||
voteTimeLimit: number;
|
||||
protestDeadlineHours: number;
|
||||
stewardingClosesHours: number;
|
||||
notifyAccusedOnProtest: boolean;
|
||||
notifyOnVoteRequired: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface LeagueFullConfigData {
|
||||
league: League;
|
||||
activeSeason?: Season;
|
||||
scoringConfig?: LeagueScoringConfig;
|
||||
game?: Game;
|
||||
}
|
||||
|
||||
export interface ILeagueFullConfigPresenter {
|
||||
present(data: LeagueFullConfigData): LeagueConfigFormViewModel;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { LeagueSchedulePreviewDTO } from '../dto/LeagueScheduleDTO';
|
||||
|
||||
export interface ILeagueSchedulePreviewPresenter {
|
||||
present(data: LeagueSchedulePreviewDTO): void;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { ChampionshipConfig } from '../../domain/value-objects/ChampionshipConfig';
|
||||
import type { LeagueScoringPresetDTO } from '../ports/LeagueScoringPresetProvider';
|
||||
|
||||
export interface LeagueScoringChampionshipViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
sessionTypes: string[];
|
||||
pointsPreview: Array<{ sessionType: string; position: number; points: number }>;
|
||||
bonusSummary: string[];
|
||||
dropPolicyDescription: string;
|
||||
}
|
||||
|
||||
export interface LeagueScoringConfigViewModel {
|
||||
leagueId: string;
|
||||
seasonId: string;
|
||||
gameId: string;
|
||||
gameName: string;
|
||||
scoringPresetId?: string;
|
||||
scoringPresetName?: string;
|
||||
dropPolicySummary: string;
|
||||
championships: LeagueScoringChampionshipViewModel[];
|
||||
}
|
||||
|
||||
export interface LeagueScoringConfigData {
|
||||
leagueId: string;
|
||||
seasonId: string;
|
||||
gameId: string;
|
||||
gameName: string;
|
||||
scoringPresetId?: string;
|
||||
preset?: LeagueScoringPresetDTO;
|
||||
championships: ChampionshipConfig[];
|
||||
}
|
||||
|
||||
export interface ILeagueScoringConfigPresenter {
|
||||
present(data: LeagueScoringConfigData): LeagueScoringConfigViewModel;
|
||||
getViewModel(): LeagueScoringConfigViewModel;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { LeagueScoringPresetDTO } from '../ports/LeagueScoringPresetProvider';
|
||||
|
||||
export interface LeagueScoringPresetsViewModel {
|
||||
presets: LeagueScoringPresetDTO[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface ILeagueScoringPresetsPresenter {
|
||||
present(presets: LeagueScoringPresetDTO[]): LeagueScoringPresetsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { Standing } from '../../domain/entities/Standing';
|
||||
|
||||
export interface StandingItemViewModel {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
seasonId: string;
|
||||
driverId: string;
|
||||
position: number;
|
||||
points: number;
|
||||
wins: number;
|
||||
podiums: number;
|
||||
racesCompleted: number;
|
||||
}
|
||||
|
||||
export interface LeagueStandingsViewModel {
|
||||
leagueId: string;
|
||||
standings: StandingItemViewModel[];
|
||||
}
|
||||
|
||||
export interface ILeagueStandingsPresenter {
|
||||
present(standings: Standing[]): LeagueStandingsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
export interface LeagueStatsViewModel {
|
||||
leagueId: string;
|
||||
totalRaces: number;
|
||||
completedRaces: number;
|
||||
scheduledRaces: number;
|
||||
averageSOF: number | null;
|
||||
highestSOF: number | null;
|
||||
lowestSOF: number | null;
|
||||
}
|
||||
|
||||
export interface ILeagueStatsPresenter {
|
||||
present(
|
||||
leagueId: string,
|
||||
totalRaces: number,
|
||||
completedRaces: number,
|
||||
scheduledRaces: number,
|
||||
sofValues: number[]
|
||||
): LeagueStatsViewModel;
|
||||
getViewModel(): LeagueStatsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { GetPendingSponsorshipRequestsResultDTO } from '../use-cases/GetPendingSponsorshipRequestsQuery';
|
||||
|
||||
export interface IPendingSponsorshipRequestsPresenter {
|
||||
present(data: GetPendingSponsorshipRequestsResultDTO): void;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { PenaltyType, PenaltyStatus } from '../../domain/entities/Penalty';
|
||||
|
||||
export interface RacePenaltyViewModel {
|
||||
id: string;
|
||||
raceId: string;
|
||||
driverId: string;
|
||||
driverName: string;
|
||||
type: PenaltyType;
|
||||
value?: number;
|
||||
reason: string;
|
||||
protestId?: string;
|
||||
issuedBy: string;
|
||||
issuedByName: string;
|
||||
status: PenaltyStatus;
|
||||
description: string;
|
||||
issuedAt: string;
|
||||
appliedAt?: string;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export interface RacePenaltiesViewModel {
|
||||
penalties: RacePenaltyViewModel[];
|
||||
}
|
||||
|
||||
export interface IRacePenaltiesPresenter {
|
||||
present(
|
||||
penalties: Array<{
|
||||
id: string;
|
||||
raceId: string;
|
||||
driverId: string;
|
||||
type: PenaltyType;
|
||||
value?: number;
|
||||
reason: string;
|
||||
protestId?: string;
|
||||
issuedBy: string;
|
||||
status: PenaltyStatus;
|
||||
issuedAt: Date;
|
||||
appliedAt?: Date;
|
||||
notes?: string;
|
||||
getDescription(): string;
|
||||
}>,
|
||||
driverMap: Map<string, string>
|
||||
): RacePenaltiesViewModel;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { ProtestStatus, ProtestIncident } from '../../domain/entities/Protest';
|
||||
|
||||
export interface RaceProtestViewModel {
|
||||
id: string;
|
||||
raceId: string;
|
||||
protestingDriverId: string;
|
||||
protestingDriverName: string;
|
||||
accusedDriverId: string;
|
||||
accusedDriverName: string;
|
||||
incident: ProtestIncident;
|
||||
comment?: string;
|
||||
proofVideoUrl?: string;
|
||||
status: ProtestStatus;
|
||||
reviewedBy?: string;
|
||||
reviewedByName?: string;
|
||||
decisionNotes?: string;
|
||||
filedAt: string;
|
||||
reviewedAt?: string;
|
||||
}
|
||||
|
||||
export interface RaceProtestsViewModel {
|
||||
protests: RaceProtestViewModel[];
|
||||
}
|
||||
|
||||
export interface IRaceProtestsPresenter {
|
||||
present(
|
||||
protests: Array<{
|
||||
id: string;
|
||||
raceId: string;
|
||||
protestingDriverId: string;
|
||||
accusedDriverId: string;
|
||||
incident: ProtestIncident;
|
||||
comment?: string;
|
||||
proofVideoUrl?: string;
|
||||
status: ProtestStatus;
|
||||
reviewedBy?: string;
|
||||
decisionNotes?: string;
|
||||
filedAt: Date;
|
||||
reviewedAt?: Date;
|
||||
}>,
|
||||
driverMap: Map<string, string>
|
||||
): RaceProtestsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface RaceRegistrationsViewModel {
|
||||
registeredDriverIds: string[];
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface IRaceRegistrationsPresenter {
|
||||
present(registeredDriverIds: string[]): RaceRegistrationsViewModel;
|
||||
getViewModel(): RaceRegistrationsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
export interface RaceWithSOFViewModel {
|
||||
id: string;
|
||||
leagueId: string;
|
||||
scheduledAt: string;
|
||||
track: string;
|
||||
trackId: string;
|
||||
car: string;
|
||||
carId: string;
|
||||
sessionType: string;
|
||||
status: string;
|
||||
strengthOfField: number | null;
|
||||
registeredCount: number;
|
||||
maxParticipants: number;
|
||||
participantCount: number;
|
||||
}
|
||||
|
||||
export interface IRaceWithSOFPresenter {
|
||||
present(
|
||||
raceId: string,
|
||||
leagueId: string,
|
||||
scheduledAt: Date,
|
||||
track: string,
|
||||
trackId: string,
|
||||
car: string,
|
||||
carId: string,
|
||||
sessionType: string,
|
||||
status: string,
|
||||
strengthOfField: number | null,
|
||||
registeredCount: number,
|
||||
maxParticipants: number,
|
||||
participantCount: number
|
||||
): RaceWithSOFViewModel;
|
||||
getViewModel(): RaceWithSOFViewModel;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
export interface RaceListItemViewModel {
|
||||
id: string;
|
||||
track: string;
|
||||
car: string;
|
||||
scheduledAt: string;
|
||||
status: 'scheduled' | 'running' | 'completed' | 'cancelled';
|
||||
leagueId: string;
|
||||
leagueName: string;
|
||||
strengthOfField: number | null;
|
||||
isUpcoming: boolean;
|
||||
isLive: boolean;
|
||||
isPast: boolean;
|
||||
}
|
||||
|
||||
export interface RacesPageViewModel {
|
||||
races: RaceListItemViewModel[];
|
||||
stats: {
|
||||
total: number;
|
||||
scheduled: number;
|
||||
running: number;
|
||||
completed: number;
|
||||
};
|
||||
liveRaces: RaceListItemViewModel[];
|
||||
upcomingThisWeek: RaceListItemViewModel[];
|
||||
recentResults: RaceListItemViewModel[];
|
||||
}
|
||||
|
||||
export interface IRacesPagePresenter {
|
||||
present(races: any[]): void;
|
||||
getViewModel(): RacesPageViewModel;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { SponsoredLeagueDTO, SponsorDashboardDTO } from '../use-cases/GetSponsorDashboardQuery';
|
||||
|
||||
export interface ISponsorDashboardPresenter {
|
||||
present(data: SponsorDashboardDTO | null): void;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { SponsorSponsorshipsDTO } from '../use-cases/GetSponsorSponsorshipsQuery';
|
||||
|
||||
export interface ISponsorSponsorshipsPresenter {
|
||||
present(data: SponsorSponsorshipsDTO | null): void;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { Team, TeamMembership } from '../../domain/entities/Team';
|
||||
|
||||
export interface TeamDetailsViewModel {
|
||||
team: {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
leagues: string[];
|
||||
specialization?: 'endurance' | 'sprint' | 'mixed';
|
||||
region?: string;
|
||||
languages?: string[];
|
||||
};
|
||||
membership: {
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
joinedAt: string;
|
||||
isActive: boolean;
|
||||
} | null;
|
||||
canManage: boolean;
|
||||
}
|
||||
|
||||
export interface ITeamDetailsPresenter {
|
||||
present(
|
||||
team: Team,
|
||||
membership: TeamMembership | null,
|
||||
driverId: string
|
||||
): TeamDetailsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { TeamJoinRequest } from '../../domain/entities/Team';
|
||||
|
||||
export interface TeamJoinRequestViewModel {
|
||||
requestId: string;
|
||||
driverId: string;
|
||||
driverName: string;
|
||||
teamId: string;
|
||||
status: 'pending' | 'approved' | 'rejected';
|
||||
requestedAt: string;
|
||||
avatarUrl: string;
|
||||
}
|
||||
|
||||
export interface TeamJoinRequestsViewModel {
|
||||
requests: TeamJoinRequestViewModel[];
|
||||
pendingCount: number;
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface ITeamJoinRequestsPresenter {
|
||||
present(
|
||||
requests: TeamJoinRequest[],
|
||||
driverNames: Record<string, string>,
|
||||
avatarUrls: Record<string, string>
|
||||
): TeamJoinRequestsViewModel;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { TeamMembership } from '../../domain/entities/Team';
|
||||
|
||||
export interface TeamMemberViewModel {
|
||||
driverId: string;
|
||||
driverName: string;
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
joinedAt: string;
|
||||
isActive: boolean;
|
||||
avatarUrl: string;
|
||||
}
|
||||
|
||||
export interface TeamMembersViewModel {
|
||||
members: TeamMemberViewModel[];
|
||||
totalCount: number;
|
||||
ownerCount: number;
|
||||
managerCount: number;
|
||||
memberCount: number;
|
||||
}
|
||||
|
||||
export interface ITeamMembersPresenter {
|
||||
present(
|
||||
memberships: TeamMembership[],
|
||||
driverNames: Record<string, string>,
|
||||
avatarUrls: Record<string, string>
|
||||
): TeamMembersViewModel;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
export type SkillLevel = 'beginner' | 'intermediate' | 'advanced' | 'pro';
|
||||
|
||||
export interface TeamLeaderboardItemViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
memberCount: number;
|
||||
rating: number | null;
|
||||
totalWins: number;
|
||||
totalRaces: number;
|
||||
performanceLevel: SkillLevel;
|
||||
isRecruiting: boolean;
|
||||
createdAt: Date;
|
||||
description?: string;
|
||||
specialization?: 'endurance' | 'sprint' | 'mixed';
|
||||
region?: string;
|
||||
languages?: string[];
|
||||
}
|
||||
|
||||
export interface TeamsLeaderboardViewModel {
|
||||
teams: TeamLeaderboardItemViewModel[];
|
||||
recruitingCount: number;
|
||||
}
|
||||
|
||||
export interface ITeamsLeaderboardPresenter {
|
||||
present(teams: any[], recruitingCount: number): void;
|
||||
getViewModel(): TeamsLeaderboardViewModel;
|
||||
}
|
||||
Reference in New Issue
Block a user