116 lines
3.8 KiB
TypeScript
116 lines
3.8 KiB
TypeScript
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
|
|
import { Result } from '@/lib/contracts/Result';
|
|
import { TeamService } from '@/lib/services/teams/TeamService';
|
|
import { TeamDetailViewDataBuilder } from '@/lib/builders/view-data/TeamDetailViewDataBuilder';
|
|
import type { TeamDetailViewData } from '@/lib/view-data/TeamDetailViewData';
|
|
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
|
|
import { SessionGateway } from '@/lib/gateways/SessionGateway';
|
|
import type { TeamMemberViewModel } from '@/lib/view-models/TeamMemberViewModel';
|
|
|
|
/**
|
|
* TeamDetailPageDto - Raw serializable data for team detail page
|
|
* Contains only raw data, no derived/computed properties
|
|
*/
|
|
export interface TeamDetailPageDto {
|
|
team: {
|
|
id: string;
|
|
name: string;
|
|
tag: string;
|
|
description?: string;
|
|
ownerId: string;
|
|
leagues: string[];
|
|
createdAt?: string;
|
|
specialization?: string;
|
|
region?: string;
|
|
languages?: string[];
|
|
category?: string;
|
|
membership?: {
|
|
role: string;
|
|
joinedAt: string;
|
|
isActive: boolean;
|
|
} | null;
|
|
canManage: boolean;
|
|
};
|
|
memberships: Array<{
|
|
driverId: string;
|
|
driverName: string;
|
|
role: 'owner' | 'manager' | 'member';
|
|
joinedAt: string;
|
|
isActive: boolean;
|
|
avatarUrl: string;
|
|
}>;
|
|
currentDriverId: string;
|
|
}
|
|
|
|
/**
|
|
* TeamDetailPageQuery - Server-side composition for team detail page
|
|
*/
|
|
export class TeamDetailPageQuery implements PageQuery<TeamDetailViewData, string> {
|
|
async execute(teamId: string): Promise<Result<TeamDetailViewData, PresentationError>> {
|
|
// Get session to determine current driver (optional for public view)
|
|
const sessionGateway = new SessionGateway();
|
|
const session = await sessionGateway.getSession();
|
|
|
|
const currentDriverId = session?.user?.primaryDriverId || '';
|
|
const service = new TeamService();
|
|
|
|
// Fetch team details
|
|
const teamResult = await service.getTeamDetails(teamId, currentDriverId);
|
|
|
|
if (teamResult.isErr()) {
|
|
return Result.err(mapToPresentationError(teamResult.getError()));
|
|
}
|
|
|
|
const teamData = teamResult.unwrap();
|
|
|
|
// Fetch team members
|
|
const membersResult = await service.getTeamMembers(teamId, currentDriverId, teamData.team.ownerId);
|
|
|
|
if (membersResult.isErr()) {
|
|
return Result.err(mapToPresentationError(membersResult.getError()));
|
|
}
|
|
|
|
const membersData = membersResult.unwrap();
|
|
|
|
// Transform to raw serializable DTO
|
|
const dto: TeamDetailPageDto = {
|
|
team: {
|
|
id: teamData.team.id,
|
|
name: teamData.team.name,
|
|
tag: teamData.team.tag,
|
|
description: teamData.team.description,
|
|
ownerId: teamData.team.ownerId,
|
|
leagues: teamData.team.leagues,
|
|
createdAt: teamData.team.createdAt,
|
|
specialization: (teamData.team as any).specialization,
|
|
region: (teamData.team as any).region,
|
|
languages: (teamData.team as any).languages,
|
|
category: teamData.team.category,
|
|
membership: teamData.membership ? {
|
|
role: teamData.membership.role,
|
|
joinedAt: teamData.membership.joinedAt,
|
|
isActive: teamData.membership.isActive,
|
|
} : null,
|
|
canManage: teamData.canManage,
|
|
},
|
|
memberships: membersData.map((member: TeamMemberViewModel) => ({
|
|
driverId: member.driverId,
|
|
driverName: member.driverName,
|
|
role: member.role,
|
|
joinedAt: member.joinedAt,
|
|
isActive: member.isActive,
|
|
avatarUrl: member.avatarUrl,
|
|
})),
|
|
currentDriverId,
|
|
};
|
|
|
|
const viewData = TeamDetailViewDataBuilder.build(dto);
|
|
return Result.ok(viewData);
|
|
}
|
|
|
|
static async execute(teamId: string): Promise<Result<TeamDetailViewData, PresentationError>> {
|
|
const query = new TeamDetailPageQuery();
|
|
return query.execute(teamId);
|
|
}
|
|
}
|