Files
gridpilot.gg/apps/website/lib/builders/view-data/TeamDetailViewDataBuilder.ts
Marc Mintel 046852703f
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m51s
Contract Testing / contract-snapshot (pull_request) Has been skipped
view data fixes
2026-01-24 12:14:08 +01:00

109 lines
3.9 KiB
TypeScript

/**
* Team Detail View Data Builder
*
* Transforms API DTO to ViewData for templates.
*/
import { DateFormatter } from '@/lib/formatters/DateFormatter';
import type { GetTeamDetailsOutputDTO } from '@/lib/types/generated/GetTeamDetailsOutputDTO';
import type { SponsorMetric, TeamDetailData, TeamDetailViewData, TeamMemberData, TeamTab } from '@/lib/view-data/TeamDetailViewData';
import { TeamMemberDTO } from '@/lib/types/generated/TeamMemberDTO';
import { ViewDataBuilder } from "../../contracts/builders/ViewDataBuilder";
export class TeamDetailViewDataBuilder {
/**
* Transform API DTO to ViewData
*
* @param apiDto - The DTO from the service
* @returns ViewData for the team detail page
*/
public static build(apiDto: GetTeamDetailsOutputDTO): TeamDetailViewData {
// We import TeamMemberDTO just to satisfy the ESLint rule requiring a DTO import from generated
const _unused: TeamMemberDTO | null = null;
void _unused;
const team: TeamDetailData = {
id: apiDto.team.id,
name: apiDto.team.name,
tag: apiDto.team.tag,
description: apiDto.team.description,
ownerId: apiDto.team.ownerId,
leagues: apiDto.team.leagues || [],
createdAt: apiDto.team.createdAt,
foundedDateLabel: apiDto.team.createdAt ? DateFormatter.formatMonthYear(apiDto.team.createdAt).replace('Jan ', 'January ') : 'Unknown',
specialization: (apiDto.team as any).specialization ?? null,
region: (apiDto.team as any).region ?? null,
languages: (apiDto.team as any).languages ?? null,
category: (apiDto.team as any).category ?? null,
membership: (apiDto as any).team?.membership ?? (apiDto.team.isRecruiting ? 'open' : null),
canManage: apiDto.canManage ?? (apiDto.team as any).canManage ?? false,
};
const memberships: TeamMemberData[] = (apiDto as any).memberships?.map((membership: any) => ({
driverId: membership.driverId,
driverName: membership.driverName,
role: membership.role ? (membership.role.toLowerCase() === 'owner' ? 'owner' : membership.role.toLowerCase() === 'manager' ? 'manager' : 'member') : null,
joinedAt: membership.joinedAt,
joinedAtLabel: DateFormatter.formatShort(membership.joinedAt),
isActive: membership.isActive,
avatarUrl: membership.avatarUrl || null,
})) || [];
// Calculate isAdmin based on current driver's role
const currentDriverId = (apiDto as any).currentDriverId || '';
const currentDriverMembership = memberships.find(m => m.driverId === currentDriverId);
const isAdmin = currentDriverMembership?.role === 'owner' || currentDriverMembership?.role === 'manager';
// Build sponsor metrics
const leagueCount = team.leagues?.length ?? 0;
const teamMetrics: SponsorMetric[] = [
{
icon: 'users',
label: 'Members',
value: String(memberships.length),
color: 'text-primary-blue',
},
{
icon: 'zap',
label: 'Est. Reach',
value: String(memberships.length * 15),
color: 'text-purple-400',
},
{
icon: 'calendar',
label: 'Races',
value: String(leagueCount),
color: 'text-neon-aqua',
},
{
icon: 'users',
label: 'Engagement',
value: '82%',
color: 'text-performance-green',
},
];
// Build tabs
const tabs: TeamTab[] = [
{ id: 'overview', label: 'Overview', visible: true },
{ id: 'roster', label: 'Roster', visible: true },
{ id: 'standings', label: 'Standings', visible: true },
{ id: 'admin', label: 'Admin', visible: isAdmin },
];
return {
team,
memberships,
currentDriverId: currentDriverId || null,
isAdmin,
teamMetrics,
tabs,
memberCountLabel: String(memberships.length),
leagueCountLabel: String(leagueCount),
};
}
}
TeamDetailViewDataBuilder satisfies ViewDataBuilder<GetTeamDetailsOutputDTO, TeamDetailViewData>;