refactor core presenters

This commit is contained in:
2025-12-19 19:42:19 +01:00
parent 8116fe888f
commit 94fc538f44
228 changed files with 2817 additions and 3097 deletions

View File

@@ -0,0 +1,18 @@
import type { League } from '../../../domain/entities/League';
import type { Season } from '../../../domain/entities/season/Season';
import type { LeagueScoringConfig } from '../../../domain/entities/LeagueScoringConfig';
import type { Game } from '../../../domain/entities/Game';
import type { LeagueScoringPresetOutputPort } from './LeagueScoringPresetOutputPort';
export interface LeagueEnrichedData {
league: League;
usedDriverSlots: number;
season?: Season;
scoringConfig?: LeagueScoringConfig;
game?: Game;
preset?: LeagueScoringPresetOutputPort;
}
export interface AllLeaguesWithCapacityAndScoringOutputPort {
leagues: LeagueEnrichedData[];
}

View File

@@ -0,0 +1,6 @@
import type { League } from '../../domain/entities/League';
export interface AllLeaguesWithCapacityOutputPort {
leagues: League[];
memberCounts: Record<string, number>;
}

View File

@@ -0,0 +1,22 @@
export type AllRacesStatus = 'scheduled' | 'running' | 'completed' | 'cancelled' | 'all';
export interface AllRacesListItem {
id: string;
track: string;
car: string;
scheduledAt: string;
status: 'scheduled' | 'running' | 'completed' | 'cancelled';
leagueId: string;
leagueName: string;
strengthOfField: number | null;
}
export interface AllRacesFilterOptions {
statuses: { value: AllRacesStatus; label: string }[];
leagues: { id: string; name: string }[];
}
export interface AllRacesPageOutputPort {
races: AllRacesListItem[];
filters: AllRacesFilterOptions;
}

View File

@@ -0,0 +1,4 @@
export interface ApproveLeagueJoinRequestOutputPort {
success: boolean;
message: string;
}

View File

@@ -0,0 +1,3 @@
export interface CompleteDriverOnboardingOutputPort {
driverId: string;
}

View File

@@ -0,0 +1,4 @@
export interface CreateLeagueOutputPort {
leagueId: string;
success: boolean;
}

View File

@@ -0,0 +1,85 @@
import type { FeedItemType } from '@core/social/domain/types/FeedItemType';
export interface DashboardDriverSummaryOutputPort {
id: string;
name: string;
country: string;
avatarUrl: string;
rating: number | null;
globalRank: number | null;
totalRaces: number;
wins: number;
podiums: number;
consistency: number | null;
}
export interface DashboardRaceSummaryOutputPort {
id: string;
leagueId: string;
leagueName: string;
track: string;
car: string;
scheduledAt: string;
status: 'scheduled' | 'running' | 'completed' | 'cancelled';
isMyLeague: boolean;
}
export interface DashboardRecentResultOutputPort {
raceId: string;
raceName: string;
leagueId: string;
leagueName: string;
finishedAt: string;
position: number;
incidents: number;
}
export interface DashboardLeagueStandingSummaryOutputPort {
leagueId: string;
leagueName: string;
position: number;
totalDrivers: number;
points: number;
}
export interface DashboardFeedItemSummaryOutputPort {
id: string;
type: FeedItemType;
headline: string;
body?: string;
timestamp: string;
ctaLabel?: string;
ctaHref?: string;
}
export interface DashboardFeedSummaryOutputPort {
notificationCount: number;
items: DashboardFeedItemSummaryOutputPort[];
}
export interface DashboardFriendSummaryOutputPort {
id: string;
name: string;
country: string;
avatarUrl: string;
}
export interface DashboardOverviewOutputPort {
currentDriver: DashboardDriverSummaryOutputPort | null;
myUpcomingRaces: DashboardRaceSummaryOutputPort[];
otherUpcomingRaces: DashboardRaceSummaryOutputPort[];
/**
* All upcoming races for the driver, already sorted by scheduledAt ascending.
*/
upcomingRaces: DashboardRaceSummaryOutputPort[];
/**
* Count of distinct leagues that are currently "active" for the driver,
* based on upcoming races and league standings.
*/
activeLeaguesCount: number;
nextRace: DashboardRaceSummaryOutputPort | null;
recentResults: DashboardRecentResultOutputPort[];
leagueStandingsSummaries: DashboardLeagueStandingSummaryOutputPort[];
feedSummary: DashboardFeedSummaryOutputPort;
friends: DashboardFriendSummaryOutputPort[];
}

View File

@@ -0,0 +1,5 @@
export interface DriverRegistrationStatusOutputPort {
isRegistered: boolean;
raceId: string;
driverId: string;
}

View File

@@ -1,4 +1,5 @@
export interface GetDriverTeamOutputPort {
export interface DriverTeamOutputPort {
driverId: string;
team: {
id: string;
name: string;
@@ -9,9 +10,10 @@ export interface GetDriverTeamOutputPort {
createdAt: Date;
};
membership: {
driverId: string;
teamId: string;
role: 'member' | 'captain' | 'admin';
driverId: string;
role: 'owner' | 'manager' | 'driver';
status: 'active' | 'pending' | 'none';
joinedAt: Date;
};
}

View File

@@ -0,0 +1,22 @@
import type { SkillLevel } from '../../domain/services/SkillLevelService';
export interface DriverLeaderboardItemOutputPort {
id: string;
name: string;
rating: number;
skillLevel: SkillLevel;
nationality: string;
racesCompleted: number;
wins: number;
podiums: number;
isActive: boolean;
rank: number;
avatarUrl: string;
}
export interface DriversLeaderboardOutputPort {
drivers: DriverLeaderboardItemOutputPort[];
totalRaces: number;
totalWins: number;
activeCount: number;
}

View File

@@ -0,0 +1,13 @@
export interface GetAllRacesOutputPort {
races: {
id: string;
leagueId: string;
track: string;
car: string;
status: 'scheduled' | 'running' | 'completed' | 'cancelled';
scheduledAt: string;
strengthOfField: number | null;
leagueName: string;
}[];
totalCount: number;
}

View File

@@ -7,5 +7,7 @@ export interface GetAllTeamsOutputPort {
ownerId: string;
leagues: string[];
createdAt: Date;
memberCount: number;
}>;
totalCount?: number;
}

View File

@@ -1,7 +1,4 @@
export interface GetLeagueAdminOutputPort {
league: {
id: string;
ownerId: string;
};
// Additional data would be populated by combining multiple use cases
leagueId: string;
ownerId: string;
}

View File

@@ -1,13 +1,12 @@
export interface LeagueJoinRequestOutputPort {
id: string;
leagueId: string;
driverId: string;
requestedAt: Date;
message: string;
driver: { id: string; name: string } | null;
}
export interface GetLeagueJoinRequestsOutputPort {
joinRequests: Array<{
id: string;
leagueId: string;
driverId: string;
requestedAt: Date;
message?: string;
driver: {
id: string;
name: string;
};
}>;
joinRequests: LeagueJoinRequestOutputPort[];
}

View File

@@ -1,10 +1,14 @@
export interface LeagueMembershipOutputPort {
driverId: string;
driver: { id: string; name: string };
role: string;
joinedAt: Date;
}
export interface LeagueMembershipsOutputPort {
members: LeagueMembershipOutputPort[];
}
export interface GetLeagueMembershipsOutputPort {
memberships: Array<{
id: string;
leagueId: string;
driverId: string;
role: 'member' | 'admin' | 'owner';
joinedAt: Date;
}>;
drivers: { id: string; name: string }[];
memberships: LeagueMembershipsOutputPort;
}

View File

@@ -1,3 +1,9 @@
export interface LeagueOwnerSummaryOutputPort {
driver: { id: string; iracingId: string; name: string; country: string; bio: string | undefined; joinedAt: string };
rating: number;
rank: number;
}
export interface GetLeagueOwnerSummaryOutputPort {
summary: { driver: { id: string; name: string }; rating: number; rank: number } | null;
summary: LeagueOwnerSummaryOutputPort | null;
}

View File

@@ -1,20 +1,47 @@
export interface ProtestOutputPort {
id: string;
raceId: string;
protestingDriverId: string;
accusedDriverId: string;
incident: { lap: number; description: string; timeInRace: number | undefined };
comment: string | undefined;
proofVideoUrl: string | undefined;
status: string;
reviewedBy: string | undefined;
decisionNotes: string | undefined;
filedAt: string;
reviewedAt: string | undefined;
defense: { statement: string; videoUrl: string | undefined; submittedAt: string } | undefined;
defenseRequestedAt: string | undefined;
defenseRequestedBy: string | undefined;
}
export interface RaceOutputPort {
id: string;
leagueId: string;
scheduledAt: string;
track: string;
trackId: string | undefined;
car: string;
carId: string | undefined;
sessionType: string;
status: string;
strengthOfField: number | undefined;
registeredCount: number | undefined;
maxParticipants: number | undefined;
}
export interface DriverOutputPort {
id: string;
iracingId: string;
name: string;
country: string;
bio: string | undefined;
joinedAt: string;
}
export interface GetLeagueProtestsOutputPort {
protests: Array<{
id: string;
raceId: string;
protestingDriverId: string;
accusedDriverId: string;
submittedAt: Date;
description: string;
status: string;
}>;
races: Array<{
id: string;
name: string;
date: string;
}>;
drivers: Array<{
id: string;
name: string;
}>;
protests: ProtestOutputPort[];
racesById: Record<string, RaceOutputPort>;
driversById: Record<string, DriverOutputPort>;
}

View File

@@ -0,0 +1,13 @@
export interface LeagueSeasonSummaryOutputPort {
seasonId: string;
name: string;
status: string;
startDate: Date;
endDate: Date;
isPrimary: boolean;
isParallelActive: boolean;
}
export interface GetLeagueSeasonsOutputPort {
seasons: LeagueSeasonSummaryOutputPort[];
}

View File

@@ -0,0 +1,10 @@
export interface GetSponsorsOutputPort {
sponsors: {
id: string;
name: string;
contactEmail: string;
websiteUrl: string | undefined;
logoUrl: string | undefined;
createdAt: Date;
}[];
}

View File

@@ -0,0 +1,10 @@
export interface GetSponsorshipPricingOutputPort {
entityType: string;
entityId: string;
pricing: {
id: string;
level: string;
price: number;
currency: string;
}[];
}

View File

@@ -9,9 +9,9 @@ export interface GetTeamDetailsOutputPort {
createdAt: Date;
};
membership: {
driverId: string;
teamId: string;
role: 'member' | 'captain' | 'admin';
role: 'owner' | 'manager' | 'member';
joinedAt: Date;
isActive: boolean;
} | null;
canManage: boolean;
}

View File

@@ -0,0 +1,3 @@
export interface GetTotalLeaguesOutputPort {
totalLeagues: number;
}

View File

@@ -0,0 +1,3 @@
export interface GetTotalRacesOutputPort {
totalRaces: number;
}

View File

@@ -0,0 +1,8 @@
export interface ImportRaceResultsApiOutputPort {
success: boolean;
raceId: string;
leagueId: string;
driversProcessed: number;
resultsRecorded: number;
errors?: string[];
}

View File

@@ -0,0 +1,5 @@
export interface JoinLeagueOutputPort {
membershipId: string;
leagueId: string;
status: string;
}

View File

@@ -1,4 +1,4 @@
export interface LeagueDriverSeasonStatsOutputPort {
export interface LeagueDriverSeasonStatsItemOutputPort {
leagueId: string;
driverId: string;
position: number;
@@ -17,4 +17,9 @@ export interface LeagueDriverSeasonStatsOutputPort {
avgFinish: number | null;
rating: number | null;
ratingChange: number | null;
}
export interface LeagueDriverSeasonStatsOutputPort {
leagueId: string;
stats: LeagueDriverSeasonStatsItemOutputPort[];
}

View File

@@ -0,0 +1,11 @@
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 LeagueFullConfigOutputPort {
league: League;
activeSeason?: Season;
scoringConfig?: LeagueScoringConfig;
game?: Game;
}

View File

@@ -1,18 +1,12 @@
import type { ChampionshipConfig } from '../../domain/types/ChampionshipConfig';
import type { LeagueScoringPresetOutputPort } from './LeagueScoringPresetOutputPort';
export interface LeagueScoringConfigOutputPort {
leagueId: string;
seasonId: string;
gameId: string;
gameName: string;
scoringPresetId?: string;
scoringPresetName?: string;
dropPolicySummary: string;
championships: Array<{
id: string;
name: string;
type: 'driver' | 'team' | 'nations' | 'trophy';
sessionTypes: string[];
pointsPreview: Array<{ sessionType: string; position: number; points: number }>;
bonusSummary: string[];
dropPolicyDescription: string;
}>;
preset?: LeagueScoringPresetOutputPort;
championships: ChampionshipConfig[];
}

View File

@@ -0,0 +1,5 @@
import type { LeagueScoringPresetOutputPort } from './LeagueScoringPresetOutputPort';
export interface LeagueScoringPresetsOutputPort {
presets: LeagueScoringPresetOutputPort[];
}

View File

@@ -0,0 +1,10 @@
export interface StandingItemOutputPort {
driverId: string;
driver: { id: string; name: string };
points: number;
rank: number;
}
export interface LeagueStandingsOutputPort {
standings: StandingItemOutputPort[];
}

View File

@@ -0,0 +1,5 @@
export interface LeagueStatsOutputPort {
totalMembers: number;
totalRaces: number;
averageRating: number;
}

View File

@@ -0,0 +1,24 @@
import type { SponsorableEntityType } from '../../domain/entities/SponsorshipRequest';
import type { SponsorshipTier } from '../../domain/entities/SeasonSponsorship';
export interface PendingSponsorshipRequestOutput {
id: string;
sponsorId: string;
sponsorName: string;
sponsorLogo?: string;
tier: SponsorshipTier;
offeredAmount: number;
currency: string;
formattedAmount: string;
message?: string;
createdAt: Date;
platformFee: number;
netAmount: number;
}
export interface PendingSponsorshipRequestsOutputPort {
entityType: SponsorableEntityType;
entityId: string;
requests: PendingSponsorshipRequestOutput[];
totalCount: number;
}

View File

@@ -0,0 +1,57 @@
export interface ProfileOverviewOutputPort {
driver: {
id: string;
name: string;
country: string;
avatarUrl: string;
iracingId: string | null;
joinedAt: Date;
rating: number | null;
globalRank: number | null;
consistency: number | null;
bio: string | null;
totalDrivers: number | null;
};
stats: {
totalRaces: number;
wins: number;
podiums: number;
dnfs: number;
avgFinish: number | null;
bestFinish: number | null;
worstFinish: number | null;
finishRate: number | null;
winRate: number | null;
podiumRate: number | null;
percentile: number | null;
rating: number | null;
consistency: number | null;
overallRank: number | null;
} | null;
finishDistribution: {
totalRaces: number;
wins: number;
podiums: number;
topTen: number;
dnfs: number;
other: number;
} | null;
teamMemberships: {
teamId: string;
teamName: string;
teamTag: string | null;
role: string;
joinedAt: Date;
isCurrent: boolean;
}[];
socialSummary: {
friendsCount: number;
friends: {
id: string;
name: string;
country: string;
avatarUrl: string;
}[];
};
extendedProfile: null;
}

View File

@@ -0,0 +1,15 @@
import type { Race } from '../../../domain/entities/Race';
import type { League } from '../../../domain/entities/League';
import type { RaceRegistration } from '../../../domain/entities/RaceRegistration';
import type { Driver } from '../../../domain/entities/Driver';
import type { Result } from '../../../domain/entities/result/Result';
export interface RaceDetailOutputPort {
race: Race;
league: League | null;
registrations: RaceRegistration[];
drivers: Driver[];
userResult: Result | null;
isUserRegistered: boolean;
canRegister: boolean;
}

View File

@@ -0,0 +1,7 @@
import type { Penalty } from '../../../domain/entities/Penalty';
import type { Driver } from '../../../domain/entities/Driver';
export interface RacePenaltiesOutputPort {
penalties: Penalty[];
drivers: Driver[];
}

View File

@@ -0,0 +1,7 @@
import type { Protest } from '../../../domain/entities/Protest';
import type { Driver } from '../../../domain/entities/Driver';
export interface RaceProtestsOutputPort {
protests: Protest[];
drivers: Driver[];
}

View File

@@ -0,0 +1,5 @@
import type { RaceRegistration } from '../../../domain/entities/RaceRegistration';
export interface RaceRegistrationsOutputPort {
registrations: RaceRegistration[];
}

View File

@@ -0,0 +1,16 @@
import type { Race } from '../../../domain/entities/Race';
import type { League } from '../../../domain/entities/League';
import type { Result } from '../../../domain/entities/result/Result';
import type { Driver } from '../../../domain/entities/Driver';
import type { Penalty } from '../../../domain/entities/Penalty';
export interface RaceResultsDetailOutputPort {
race: Race;
league: League | null;
results: Result[];
drivers: Driver[];
penalties: Penalty[];
pointsSystem?: Record<number, number>;
fastestLapTime?: number;
currentDriverId?: string;
}

View File

@@ -0,0 +1,12 @@
export interface RaceWithSOFOutputPort {
id: string;
leagueId: string;
track: string;
car: string;
scheduledAt: Date;
status: 'scheduled' | 'running' | 'completed' | 'cancelled';
strengthOfField: number | null;
registeredCount: number;
maxParticipants: number;
participantCount: number;
}

View File

@@ -0,0 +1,14 @@
export interface RacesPageOutputPort {
page: number;
pageSize: number;
totalCount: number;
races: {
id: string;
leagueId: string;
track: string;
car: string;
scheduledAt: Date;
status: 'scheduled' | 'running' | 'completed' | 'cancelled';
strengthOfField: number | null;
}[];
}

View File

@@ -0,0 +1,4 @@
export interface RejectLeagueJoinRequestOutputPort {
success: boolean;
message: string;
}

View File

@@ -0,0 +1,3 @@
export interface RemoveLeagueMemberOutputPort {
success: boolean;
}

View File

@@ -0,0 +1,30 @@
export interface SponsoredLeagueOutput {
id: string;
name: string;
tier: 'main' | 'secondary';
drivers: number;
races: number;
impressions: number;
status: 'active' | 'upcoming' | 'completed';
}
export interface SponsorDashboardOutputPort {
sponsorId: string;
sponsorName: string;
metrics: {
impressions: number;
impressionsChange: number;
uniqueViewers: number;
viewersChange: number;
races: number;
drivers: number;
exposure: number;
exposureChange: number;
};
sponsoredLeagues: SponsoredLeagueOutput[];
investment: {
activeSponsorships: number;
totalInvestment: number;
costPerThousandViews: number;
};
}

View File

@@ -0,0 +1,46 @@
import type { SponsorshipTier, SponsorshipStatus } from '../../domain/entities/SeasonSponsorship';
export interface SponsorshipDetailOutput {
id: string;
leagueId: string;
leagueName: string;
seasonId: string;
seasonName: string;
seasonStartDate?: Date;
seasonEndDate?: Date;
tier: SponsorshipTier;
status: SponsorshipStatus;
pricing: {
amount: number;
currency: string;
};
platformFee: {
amount: number;
currency: string;
};
netAmount: {
amount: number;
currency: string;
};
metrics: {
drivers: number;
races: number;
completedRaces: number;
impressions: number;
};
createdAt: Date;
activatedAt?: Date;
}
export interface SponsorSponsorshipsOutputPort {
sponsorId: string;
sponsorName: string;
sponsorships: SponsorshipDetailOutput[];
summary: {
totalSponsorships: number;
activeSponsorships: number;
totalInvestment: number;
totalPlatformFees: number;
currency: string;
};
}

View File

@@ -0,0 +1,13 @@
export interface TeamJoinRequestsOutputPort {
requests: {
requestId: string;
driverId: string;
driverName: string;
teamId: string;
status: 'pending' | 'approved' | 'rejected';
requestedAt: Date;
avatarUrl: string;
}[];
pendingCount: number;
totalCount: number;
}

View File

@@ -0,0 +1,14 @@
export interface TeamMembersOutputPort {
members: {
driverId: string;
driverName: string;
role: 'owner' | 'manager' | 'member';
joinedAt: Date;
isActive: boolean;
avatarUrl: string;
}[];
totalCount: number;
ownerCount: number;
managerCount: number;
memberCount: number;
}

View File

@@ -0,0 +1,50 @@
export type SkillLevel = 'beginner' | 'intermediate' | 'advanced' | 'pro';
export interface TeamsLeaderboardOutputPort {
teams: {
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[];
}[];
recruitingCount: number;
groupsBySkillLevel: Record<SkillLevel, {
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[];
}[]>;
topTeams: {
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[];
}[];
}

View File

@@ -0,0 +1,3 @@
export interface TotalDriversOutputPort {
totalDrivers: number;
}

View File

@@ -0,0 +1,3 @@
export interface TransferLeagueOwnershipOutputPort {
success: boolean;
}

View File

@@ -0,0 +1,3 @@
export interface UpdateLeagueMemberRoleOutputPort {
success: boolean;
}