resolve manual DTOs
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
import type { DriverDTO } from '../types/DriverDTO';
|
||||
import type { GetDriverOutputDTO } from '../types/generated/GetDriverOutputDTO';
|
||||
|
||||
/**
|
||||
* View Model for driver summary with rating and rank
|
||||
* Transform from DTO to ViewModel with UI fields
|
||||
*/
|
||||
export class DriverSummaryViewModel {
|
||||
driver: DriverDTO;
|
||||
driver: GetDriverOutputDTO;
|
||||
rating: number | null;
|
||||
rank: number | null;
|
||||
|
||||
constructor(dto: {
|
||||
driver: DriverDTO;
|
||||
driver: GetDriverOutputDTO;
|
||||
rating?: number | null;
|
||||
rank?: number | null;
|
||||
}) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { GetDriverTeamOutputDTO } from '@/lib/types/generated/GetDriverTeamOutputDTO';
|
||||
|
||||
/**
|
||||
* View Model for Driver's Team
|
||||
*
|
||||
@@ -6,21 +8,22 @@
|
||||
export class DriverTeamViewModel {
|
||||
teamId: string;
|
||||
teamName: string;
|
||||
tag: string;
|
||||
role: string;
|
||||
isOwner: boolean;
|
||||
canManage: boolean;
|
||||
|
||||
constructor(dto: { teamId: string; teamName: string; role: string }) {
|
||||
this.teamId = dto.teamId;
|
||||
this.teamName = dto.teamName;
|
||||
this.role = dto.role;
|
||||
constructor(dto: GetDriverTeamOutputDTO) {
|
||||
this.teamId = dto.team.id;
|
||||
this.teamName = dto.team.name;
|
||||
this.tag = dto.team.tag;
|
||||
this.role = dto.membership.role;
|
||||
this.isOwner = dto.isOwner;
|
||||
this.canManage = dto.canManage;
|
||||
}
|
||||
|
||||
/** UI-specific: Display role */
|
||||
get displayRole(): string {
|
||||
return this.role.charAt(0).toUpperCase() + this.role.slice(1);
|
||||
}
|
||||
|
||||
/** UI-specific: Is owner */
|
||||
get isOwner(): boolean {
|
||||
return this.role === 'owner';
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
// TODO: Create ImportRaceResultsSummaryDTO in apps/website/lib/types/generated when available
|
||||
interface ImportRaceResultsSummaryDTO {
|
||||
success: boolean;
|
||||
raceId: string;
|
||||
importedCount: number;
|
||||
errors: string[];
|
||||
driversProcessed: number;
|
||||
resultsRecorded: number;
|
||||
errors?: string[];
|
||||
}
|
||||
|
||||
export class ImportRaceResultsSummaryViewModel {
|
||||
success: boolean;
|
||||
raceId: string;
|
||||
importedCount: number;
|
||||
driversProcessed: number;
|
||||
resultsRecorded: number;
|
||||
errors: string[];
|
||||
|
||||
constructor(dto: ImportRaceResultsSummaryDTO) {
|
||||
this.success = dto.success;
|
||||
this.raceId = dto.raceId;
|
||||
this.importedCount = dto.importedCount;
|
||||
this.errors = dto.errors;
|
||||
this.driversProcessed = dto.driversProcessed;
|
||||
this.resultsRecorded = dto.resultsRecorded;
|
||||
this.errors = dto.errors || [];
|
||||
}
|
||||
|
||||
// TODO: Add additional UI-specific fields when DTO is available
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { LeagueStatsDTO } from '../types/generated/LeagueStatsDTO';
|
||||
import { LeagueMembershipsDTO } from '../types/generated/LeagueMembershipsDTO';
|
||||
import { LeagueScheduleDTO } from '../types/generated/LeagueScheduleDTO';
|
||||
import { LeagueStandingsDTO } from '../types/generated/LeagueStandingsDTO';
|
||||
import { DriverDTO } from '../types/DriverDTO';
|
||||
import { GetDriverOutputDTO } from '../types/generated/GetDriverOutputDTO';
|
||||
import { RaceDTO } from '../types/generated/RaceDTO';
|
||||
import { LeagueScoringConfigDTO } from '../types/LeagueScoringConfigDTO';
|
||||
import { RaceViewModel } from './RaceViewModel';
|
||||
@@ -20,7 +20,7 @@ export interface SponsorInfo {
|
||||
|
||||
// Driver summary for management section
|
||||
export interface DriverSummary {
|
||||
driver: DriverDTO;
|
||||
driver: GetDriverOutputDTO;
|
||||
rating: number | null;
|
||||
rank: number | null;
|
||||
}
|
||||
@@ -50,13 +50,13 @@ export class LeagueDetailPageViewModel {
|
||||
};
|
||||
|
||||
// Owner info
|
||||
owner: DriverDTO | null;
|
||||
owner: GetDriverOutputDTO | null;
|
||||
|
||||
// Scoring configuration
|
||||
scoringConfig: LeagueScoringConfigDTO | null;
|
||||
|
||||
// Drivers and memberships
|
||||
drivers: DriverDTO[];
|
||||
drivers: GetDriverOutputDTO[];
|
||||
memberships: LeagueMembershipWithRole[];
|
||||
|
||||
// Races
|
||||
@@ -93,9 +93,9 @@ export class LeagueDetailPageViewModel {
|
||||
|
||||
constructor(
|
||||
league: LeagueWithCapacityDTO,
|
||||
owner: DriverDTO | null,
|
||||
owner: GetDriverOutputDTO | null,
|
||||
scoringConfig: LeagueScoringConfigDTO | null,
|
||||
drivers: DriverDTO[],
|
||||
drivers: GetDriverOutputDTO[],
|
||||
memberships: LeagueMembershipsDTO,
|
||||
allRaces: RaceViewModel[],
|
||||
leagueStats: LeagueStatsDTO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { LeagueScoringPresetDTO } from '../types/LeagueScoringPresetDTO';
|
||||
import type { LeagueScoringPresetDTO } from '@core/racing/application/ports/LeagueScoringPresetProvider';
|
||||
|
||||
/**
|
||||
* View Model for league scoring presets
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { LeagueConfigFormModel } from '../types/LeagueConfigFormModel';
|
||||
import type { LeagueScoringPresetDTO } from '../types/LeagueScoringPresetDTO';
|
||||
import type { LeagueConfigFormModel } from '@core/racing/application';
|
||||
import type { LeagueScoringPresetDTO } from '@core/racing/application/ports/LeagueScoringPresetProvider';
|
||||
import { LeagueScoringPresetsViewModel } from './LeagueScoringPresetsViewModel';
|
||||
import { DriverSummaryViewModel } from './DriverSummaryViewModel';
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { LeagueStandingDTO } from '../types/generated/LeagueStandingDTO';
|
||||
import { StandingEntryViewModel } from './StandingEntryViewModel';
|
||||
import { DriverDTO } from '../types/DriverDTO';
|
||||
import { GetDriverOutputDTO } from '../types/generated/GetDriverOutputDTO';
|
||||
import { LeagueMembership } from '../types/LeagueMembership';
|
||||
|
||||
export class LeagueStandingsViewModel {
|
||||
standings: StandingEntryViewModel[];
|
||||
drivers: DriverDTO[];
|
||||
drivers: GetDriverOutputDTO[];
|
||||
memberships: LeagueMembership[];
|
||||
|
||||
constructor(dto: { standings: LeagueStandingDTO[]; drivers: DriverDTO[]; memberships: LeagueMembership[] }, currentUserId: string, previousStandings?: LeagueStandingDTO[]) {
|
||||
constructor(dto: { standings: LeagueStandingDTO[]; drivers: GetDriverOutputDTO[]; 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;
|
||||
|
||||
@@ -6,9 +6,9 @@ describe('MediaViewModel', () => {
|
||||
const dto = {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image' as const,
|
||||
category: 'avatar' as const,
|
||||
uploadedAt: new Date('2023-01-15'),
|
||||
type: 'image',
|
||||
category: 'avatar',
|
||||
uploadedAt: '2023-01-15T00:00:00.000Z',
|
||||
size: 2048000,
|
||||
};
|
||||
|
||||
@@ -26,8 +26,8 @@ describe('MediaViewModel', () => {
|
||||
const dto = {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image' as const,
|
||||
uploadedAt: new Date('2023-01-15'),
|
||||
type: 'image',
|
||||
uploadedAt: '2023-01-15T00:00:00.000Z',
|
||||
};
|
||||
|
||||
const viewModel = new MediaViewModel(dto);
|
||||
@@ -41,7 +41,7 @@ describe('MediaViewModel', () => {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
expect(viewModel.formattedSize).toBe('Unknown');
|
||||
@@ -52,7 +52,7 @@ describe('MediaViewModel', () => {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
size: 512000, // 500 KB
|
||||
});
|
||||
|
||||
@@ -64,7 +64,7 @@ describe('MediaViewModel', () => {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
size: 2048000, // 2 MB
|
||||
});
|
||||
|
||||
@@ -76,7 +76,7 @@ describe('MediaViewModel', () => {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
size: 1024, // 1 KB
|
||||
});
|
||||
|
||||
@@ -88,7 +88,7 @@ describe('MediaViewModel', () => {
|
||||
id: 'media-123',
|
||||
url: 'https://example.com/video.mp4',
|
||||
type: 'video',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
size: 104857600, // 100 MB
|
||||
});
|
||||
|
||||
@@ -100,19 +100,19 @@ describe('MediaViewModel', () => {
|
||||
id: '1',
|
||||
url: 'image.jpg',
|
||||
type: 'image',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
});
|
||||
const videoVm = new MediaViewModel({
|
||||
id: '2',
|
||||
url: 'video.mp4',
|
||||
type: 'video',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
});
|
||||
const docVm = new MediaViewModel({
|
||||
id: '3',
|
||||
url: 'doc.pdf',
|
||||
type: 'document',
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
expect(imageVm.type).toBe('image');
|
||||
@@ -129,7 +129,7 @@ describe('MediaViewModel', () => {
|
||||
url: 'https://example.com/image.jpg',
|
||||
type: 'image',
|
||||
category,
|
||||
uploadedAt: new Date(),
|
||||
uploadedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
expect(viewModel.category).toBe(category);
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
// Note: No generated DTO available for Media yet
|
||||
interface MediaDTO {
|
||||
id: string;
|
||||
url: string;
|
||||
type: 'image' | 'video' | 'document';
|
||||
category?: 'avatar' | 'team-logo' | 'league-cover' | 'race-result';
|
||||
uploadedAt: Date;
|
||||
size?: number;
|
||||
}
|
||||
import type { GetMediaOutputDTO } from '../types/generated';
|
||||
|
||||
/**
|
||||
* Media View Model
|
||||
@@ -21,12 +13,12 @@ export class MediaViewModel {
|
||||
uploadedAt: Date;
|
||||
size?: number;
|
||||
|
||||
constructor(dto: MediaDTO) {
|
||||
constructor(dto: GetMediaOutputDTO) {
|
||||
this.id = dto.id;
|
||||
this.url = dto.url;
|
||||
this.type = dto.type;
|
||||
this.uploadedAt = dto.uploadedAt;
|
||||
if (dto.category !== undefined) this.category = dto.category;
|
||||
this.type = dto.type as 'image' | 'video' | 'document';
|
||||
this.uploadedAt = new Date(dto.uploadedAt);
|
||||
if (dto.category !== undefined) this.category = dto.category as 'avatar' | 'team-logo' | 'league-cover' | 'race-result';
|
||||
if (dto.size !== undefined) this.size = dto.size;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,70 +1,53 @@
|
||||
import { TeamMemberViewModel } from './TeamMemberViewModel';
|
||||
|
||||
// Note: No generated DTO available for TeamDetails yet
|
||||
interface DriverDTO {
|
||||
id: string;
|
||||
name: string;
|
||||
avatarUrl?: string;
|
||||
iracingId?: string;
|
||||
rating?: number;
|
||||
}
|
||||
interface TeamMemberDTO {
|
||||
driverId: string;
|
||||
driver?: DriverDTO;
|
||||
role: string;
|
||||
joinedAt: string;
|
||||
}
|
||||
interface TeamDetailsDTO {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
logoUrl?: string;
|
||||
memberCount: number;
|
||||
ownerId: string;
|
||||
members: TeamMemberDTO[];
|
||||
}
|
||||
import type { GetTeamDetailsOutputDTO } from '@/lib/types/generated/GetTeamDetailsOutputDTO';
|
||||
|
||||
export class TeamDetailsViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
tag: string;
|
||||
description?: string;
|
||||
logoUrl?: string;
|
||||
memberCount: number;
|
||||
ownerId: string;
|
||||
members: TeamMemberViewModel[];
|
||||
|
||||
leagues: string[];
|
||||
createdAt?: string;
|
||||
specialization?: string;
|
||||
region?: string;
|
||||
languages?: string[];
|
||||
membership: { role: string; joinedAt: string; isActive: boolean } | null;
|
||||
canManage: boolean;
|
||||
private currentUserId: string;
|
||||
|
||||
constructor(dto: TeamDetailsDTO, currentUserId: string) {
|
||||
this.id = dto.id;
|
||||
this.name = dto.name;
|
||||
this.description = dto.description;
|
||||
this.logoUrl = dto.logoUrl;
|
||||
this.memberCount = dto.memberCount;
|
||||
this.ownerId = dto.ownerId;
|
||||
this.members = dto.members.map(m => new TeamMemberViewModel(m, currentUserId, dto.ownerId));
|
||||
constructor(dto: GetTeamDetailsOutputDTO, currentUserId: string) {
|
||||
this.id = dto.team.id;
|
||||
this.name = dto.team.name;
|
||||
this.tag = dto.team.tag;
|
||||
this.description = dto.team.description;
|
||||
this.ownerId = dto.team.ownerId;
|
||||
this.leagues = dto.team.leagues;
|
||||
this.createdAt = dto.team.createdAt;
|
||||
this.specialization = dto.team.specialization;
|
||||
this.region = dto.team.region;
|
||||
this.languages = dto.team.languages;
|
||||
this.membership = dto.membership;
|
||||
this.canManage = dto.canManage;
|
||||
this.currentUserId = currentUserId;
|
||||
}
|
||||
|
||||
/** UI-specific: Whether current user is owner */
|
||||
get isOwner(): boolean {
|
||||
return this.currentUserId === this.ownerId;
|
||||
return this.membership?.role === 'owner';
|
||||
}
|
||||
|
||||
/** UI-specific: Whether can add members */
|
||||
get canAddMembers(): boolean {
|
||||
return this.isOwner && this.memberCount < 10; // Assuming max 10
|
||||
/** UI-specific: Whether can manage team */
|
||||
get canManage(): boolean {
|
||||
return this.canManage;
|
||||
}
|
||||
|
||||
/** UI-specific: Member management actions available */
|
||||
get memberActionsAvailable(): boolean {
|
||||
return this.isOwner;
|
||||
/** UI-specific: Whether current user is member */
|
||||
get isMember(): boolean {
|
||||
return this.membership !== null;
|
||||
}
|
||||
|
||||
/** UI-specific: Team status */
|
||||
get teamStatus(): string {
|
||||
if (this.memberCount < 5) return 'Recruiting';
|
||||
if (this.memberCount < 10) return 'Active';
|
||||
return 'Full';
|
||||
/** UI-specific: Current user's role */
|
||||
get userRole(): string {
|
||||
return this.membership?.role || 'none';
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,23 @@
|
||||
// Note: No generated DTO available for TeamMember yet
|
||||
interface DriverDTO {
|
||||
id: string;
|
||||
name: string;
|
||||
avatarUrl?: string;
|
||||
iracingId?: string;
|
||||
rating?: number;
|
||||
}
|
||||
|
||||
interface TeamMemberDTO {
|
||||
driverId: string;
|
||||
driver?: DriverDTO;
|
||||
role: string;
|
||||
joinedAt: string;
|
||||
}
|
||||
import type { TeamMemberDTO } from '@/lib/types/generated/GetTeamMembersOutputDTO';
|
||||
|
||||
export class TeamMemberViewModel {
|
||||
driverId: string;
|
||||
driver?: any;
|
||||
role: string;
|
||||
driverName: string;
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
joinedAt: string;
|
||||
isActive: boolean;
|
||||
avatarUrl: string;
|
||||
|
||||
private currentUserId: string;
|
||||
private teamOwnerId: string;
|
||||
|
||||
constructor(dto: TeamMemberDTO, currentUserId: string, teamOwnerId: string) {
|
||||
Object.assign(this, dto);
|
||||
this.driverId = dto.driverId;
|
||||
this.driverName = dto.driverName;
|
||||
this.role = dto.role;
|
||||
this.joinedAt = dto.joinedAt;
|
||||
this.isActive = dto.isActive;
|
||||
this.avatarUrl = dto.avatarUrl;
|
||||
this.currentUserId = currentUserId;
|
||||
this.teamOwnerId = teamOwnerId;
|
||||
}
|
||||
@@ -33,7 +26,7 @@ export class TeamMemberViewModel {
|
||||
get roleBadgeVariant(): string {
|
||||
switch (this.role) {
|
||||
case 'owner': return 'primary';
|
||||
case 'captain': return 'secondary';
|
||||
case 'manager': return 'secondary';
|
||||
case 'member': return 'default';
|
||||
default: return 'default';
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
// Note: No generated DTO available for TeamSummary yet
|
||||
interface TeamSummaryDTO {
|
||||
id: string;
|
||||
name: string;
|
||||
logoUrl?: string;
|
||||
memberCount: number;
|
||||
rating: number;
|
||||
}
|
||||
import type { TeamListItemDTO } from '@/lib/types/generated/GetAllTeamsOutputDTO';
|
||||
|
||||
export class TeamSummaryViewModel {
|
||||
id: string;
|
||||
name: string;
|
||||
logoUrl?: string;
|
||||
tag: string;
|
||||
memberCount: number;
|
||||
rating: number;
|
||||
description?: string;
|
||||
totalWins: number = 0;
|
||||
totalRaces: number = 0;
|
||||
@@ -21,23 +13,20 @@ export class TeamSummaryViewModel {
|
||||
specialization?: string;
|
||||
region?: string;
|
||||
languages: string[] = [];
|
||||
leagues: string[] = [];
|
||||
|
||||
private maxMembers = 10; // Assuming max members
|
||||
|
||||
constructor(dto: TeamSummaryDTO & { description?: string; totalWins?: number; totalRaces?: number; performanceLevel?: string; isRecruiting?: boolean; specialization?: string; region?: string; languages?: string[] }) {
|
||||
constructor(dto: TeamListItemDTO) {
|
||||
this.id = dto.id;
|
||||
this.name = dto.name;
|
||||
if (dto.logoUrl !== undefined) this.logoUrl = dto.logoUrl;
|
||||
this.tag = dto.tag;
|
||||
this.memberCount = dto.memberCount;
|
||||
this.rating = dto.rating;
|
||||
this.description = dto.description;
|
||||
this.totalWins = dto.totalWins ?? 0;
|
||||
this.totalRaces = dto.totalRaces ?? 0;
|
||||
this.performanceLevel = dto.performanceLevel ?? '';
|
||||
this.isRecruiting = dto.isRecruiting ?? false;
|
||||
this.specialization = dto.specialization;
|
||||
this.region = dto.region;
|
||||
this.languages = dto.languages ?? [];
|
||||
this.leagues = dto.leagues;
|
||||
}
|
||||
|
||||
/** UI-specific: Whether team is full */
|
||||
@@ -45,9 +34,9 @@ export class TeamSummaryViewModel {
|
||||
return this.memberCount >= this.maxMembers;
|
||||
}
|
||||
|
||||
/** UI-specific: Rating display */
|
||||
get ratingDisplay(): string {
|
||||
return this.rating.toFixed(0);
|
||||
/** UI-specific: Tag display */
|
||||
get tagDisplay(): string {
|
||||
return `[${this.tag}]`;
|
||||
}
|
||||
|
||||
/** UI-specific: Member count display */
|
||||
|
||||
Reference in New Issue
Block a user