This commit is contained in:
2026-01-08 21:36:15 +01:00
parent 05cf3bafd2
commit d689df0270
23 changed files with 25233 additions and 88 deletions

View File

@@ -1,4 +1,4 @@
import { Controller, Get, Post, Patch, Body, Req, Param, Inject } from '@nestjs/common';
import { Controller, Get, Post, Patch, Body, Req, Param, Inject, NotFoundException } from '@nestjs/common';
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
import { Public } from '../auth/Public';
@@ -37,9 +37,13 @@ export class TeamController {
@ApiOperation({ summary: 'Get team details' })
@ApiResponse({ status: 200, description: 'Team details', type: GetTeamDetailsOutputDTO })
@ApiResponse({ status: 404, description: 'Team not found' })
async getDetails(@Param('teamId') teamId: string, @Req() req: RequestWithUser): Promise<GetTeamDetailsOutputDTO | null> {
async getDetails(@Param('teamId') teamId: string, @Req() req: RequestWithUser): Promise<GetTeamDetailsOutputDTO> {
const userId = req.user?.userId;
return await this.teamService.getDetails(teamId, userId);
const result = await this.teamService.getDetails(teamId, userId);
if (!result) {
throw new NotFoundException('Team not found');
}
return result;
}
@Public()
@@ -90,4 +94,15 @@ export class TeamController {
async getMembership(@Param('teamId') teamId: string, @Param('driverId') driverId: string): Promise<GetTeamMembershipOutputDTO | null> {
return await this.teamService.getMembership(teamId, driverId);
}
}
@Post(':teamId/join')
@ApiOperation({ summary: 'Join a team (actor derived from session)' })
@ApiResponse({ status: 200, description: 'Joined team successfully' })
async joinTeam(
@Param('teamId') teamId: string,
@Req() req: RequestWithUser,
): Promise<Record<string, unknown>> {
const userId = req.user?.userId;
return await this.teamService.joinTeam(teamId, userId);
}
}

View File

@@ -25,6 +25,7 @@ import { CreateTeamUseCase, CreateTeamInput } from '@core/racing/application/use
import { UpdateTeamUseCase, UpdateTeamInput } from '@core/racing/application/use-cases/UpdateTeamUseCase';
import { GetDriverTeamUseCase } from '@core/racing/application/use-cases/GetDriverTeamUseCase';
import { GetTeamMembershipUseCase } from '@core/racing/application/use-cases/GetTeamMembershipUseCase';
import { JoinTeamUseCase } from '@core/racing/application/use-cases/JoinTeamUseCase';
// Tokens
import { TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LOGGER_TOKEN, TEAM_STATS_REPOSITORY_TOKEN } from './TeamTokens';
@@ -307,4 +308,22 @@ export class TeamService {
isActive: value.membership.isActive,
} : null;
}
}
async joinTeam(teamId: string, userId?: string): Promise<Record<string, unknown>> {
this.logger.debug(`[TeamService] Joining team ${teamId} for user ${userId}`);
if (!userId) {
throw new Error('User ID is required');
}
const useCase = new JoinTeamUseCase(this.teamRepository, this.membershipRepository, this.logger);
const result = await useCase.execute({ teamId, driverId: userId });
if (result.isErr()) {
const error = result.error;
this.logger.error(`Error joining team ${teamId}: ${error?.details?.message || 'Unknown error'}`);
return { success: false, error: error?.details?.message || 'Unknown error' };
}
return { success: true };
}
}