refactor api modules
This commit is contained in:
@@ -3,7 +3,8 @@ import { vi } from 'vitest';
|
||||
import { TeamController } from './TeamController';
|
||||
import { TeamService } from './TeamService';
|
||||
import type { Request } from 'express';
|
||||
import { CreateTeamInputDTO, UpdateTeamInputDTO } from './dtos/CreateTeamInputDTO';
|
||||
import { CreateTeamInputDTO } from './dtos/CreateTeamInputDTO';
|
||||
import { UpdateTeamInput } from './dtos/TeamDto';
|
||||
|
||||
describe('TeamController', () => {
|
||||
let controller: TeamController;
|
||||
@@ -35,7 +36,7 @@ describe('TeamController', () => {
|
||||
|
||||
describe('getAll', () => {
|
||||
it('should return all teams', async () => {
|
||||
const result = { teams: [] };
|
||||
const result = { teams: [], totalCount: 0 };
|
||||
service.getAll.mockResolvedValue(result);
|
||||
|
||||
const response = await controller.getAll();
|
||||
@@ -49,12 +50,12 @@ describe('TeamController', () => {
|
||||
it('should return team details', async () => {
|
||||
const teamId = 'team-123';
|
||||
const userId = 'user-456';
|
||||
const result = { id: teamId, name: 'Team' };
|
||||
const result = { team: { id: teamId, name: 'Team', tag: 'TAG', description: 'Desc', ownerId: 'owner', leagues: [] }, membership: null, canManage: false };
|
||||
service.getDetails.mockResolvedValue(result);
|
||||
|
||||
const mockReq: Partial<Request> = { ['user']: { userId } };
|
||||
const mockReq = { user: { userId } } as any;
|
||||
|
||||
const response = await controller.getDetails(teamId, mockReq as Request);
|
||||
const response = await controller.getDetails(teamId, mockReq);
|
||||
|
||||
expect(service.getDetails).toHaveBeenCalledWith(teamId, userId);
|
||||
expect(response).toEqual(result);
|
||||
@@ -64,7 +65,7 @@ describe('TeamController', () => {
|
||||
describe('getMembers', () => {
|
||||
it('should return team members', async () => {
|
||||
const teamId = 'team-123';
|
||||
const result = { members: [] };
|
||||
const result = { members: [], totalCount: 0, ownerCount: 0, managerCount: 0, memberCount: 0 };
|
||||
service.getMembers.mockResolvedValue(result);
|
||||
|
||||
const response = await controller.getMembers(teamId);
|
||||
@@ -77,7 +78,7 @@ describe('TeamController', () => {
|
||||
describe('getJoinRequests', () => {
|
||||
it('should return join requests', async () => {
|
||||
const teamId = 'team-123';
|
||||
const result = { requests: [] };
|
||||
const result = { requests: [], pendingCount: 0, totalCount: 0 };
|
||||
service.getJoinRequests.mockResolvedValue(result);
|
||||
|
||||
const response = await controller.getJoinRequests(teamId);
|
||||
@@ -89,14 +90,14 @@ describe('TeamController', () => {
|
||||
|
||||
describe('create', () => {
|
||||
it('should create team', async () => {
|
||||
const input: CreateTeamInputDTO = { name: 'New Team' };
|
||||
const input: CreateTeamInputDTO = { name: 'New Team', tag: 'TAG' };
|
||||
const userId = 'user-123';
|
||||
const result = { teamId: 'team-456' };
|
||||
const result = { id: 'team-456', success: true };
|
||||
service.create.mockResolvedValue(result);
|
||||
|
||||
const mockReq: Partial<Request> = { ['user']: { userId } };
|
||||
const mockReq = { user: { userId } } as any;
|
||||
|
||||
const response = await controller.create(input, mockReq as Request);
|
||||
const response = await controller.create(input, mockReq);
|
||||
|
||||
expect(service.create).toHaveBeenCalledWith(input, userId);
|
||||
expect(response).toEqual(result);
|
||||
@@ -106,14 +107,14 @@ describe('TeamController', () => {
|
||||
describe('update', () => {
|
||||
it('should update team', async () => {
|
||||
const teamId = 'team-123';
|
||||
const input: UpdateTeamInputDTO = { name: 'Updated Team' };
|
||||
const userId = 'user-456';
|
||||
const input: UpdateTeamInput = { name: 'Updated Team', updatedBy: userId };
|
||||
const result = { success: true };
|
||||
service.update.mockResolvedValue(result);
|
||||
|
||||
const mockReq: Partial<Request> = { ['user']: { userId } };
|
||||
const mockReq = { user: { userId } } as any;
|
||||
|
||||
const response = await controller.update(teamId, input, mockReq as Request);
|
||||
const response = await controller.update(teamId, input, mockReq);
|
||||
|
||||
expect(service.update).toHaveBeenCalledWith(teamId, input, userId);
|
||||
expect(response).toEqual(result);
|
||||
@@ -123,7 +124,7 @@ describe('TeamController', () => {
|
||||
describe('getDriverTeam', () => {
|
||||
it('should return driver team', async () => {
|
||||
const driverId = 'driver-123';
|
||||
const result = { teamId: 'team-456' };
|
||||
const result = { team: { id: 'team-456', name: 'Team', tag: 'TAG', description: 'Desc', ownerId: 'owner', leagues: [] }, membership: { role: 'member' as const, joinedAt: '2023-01-01', isActive: true }, isOwner: false, canManage: false };
|
||||
service.getDriverTeam.mockResolvedValue(result);
|
||||
|
||||
const response = await controller.getDriverTeam(driverId);
|
||||
@@ -137,7 +138,7 @@ describe('TeamController', () => {
|
||||
it('should return team membership', async () => {
|
||||
const teamId = 'team-123';
|
||||
const driverId = 'driver-456';
|
||||
const result = { role: 'member' };
|
||||
const result = { role: 'member' as const, joinedAt: '2023-01-01', isActive: true };
|
||||
service.getMembership.mockResolvedValue(result);
|
||||
|
||||
const response = await controller.getMembership(teamId, driverId);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { GetTeamMembersOutputDTO } from './dtos/GetTeamMembersOutputDTO';
|
||||
import { GetTeamJoinRequestsOutputDTO } from './dtos/GetTeamJoinRequestsOutputDTO';
|
||||
import { CreateTeamInputDTO } from './dtos/CreateTeamInputDTO';
|
||||
import { CreateTeamOutputDTO } from './dtos/CreateTeamOutputDTO';
|
||||
import { UpdateTeamInputDTO } from './dtos/UpdateTeamInputDTO';
|
||||
import { UpdateTeamInput } from './dtos/TeamDto';
|
||||
import { UpdateTeamOutputDTO } from './dtos/UpdateTeamOutputDTO';
|
||||
import { GetDriverTeamOutputDTO } from './dtos/GetDriverTeamOutputDTO';
|
||||
import { GetTeamMembershipOutputDTO } from './dtos/GetTeamMembershipOutputDTO';
|
||||
@@ -22,8 +22,7 @@ export class TeamController {
|
||||
@ApiOperation({ summary: 'Get all teams' })
|
||||
@ApiResponse({ status: 200, description: 'List of all teams', type: GetAllTeamsOutputDTO })
|
||||
async getAll(): Promise<GetAllTeamsOutputDTO> {
|
||||
const presenter = await this.teamService.getAll();
|
||||
return presenter.responseModel;
|
||||
return await this.teamService.getAll();
|
||||
}
|
||||
|
||||
@Get(':teamId')
|
||||
@@ -31,43 +30,38 @@ export class TeamController {
|
||||
@ApiResponse({ status: 200, description: 'Team details', type: GetTeamDetailsOutputDTO })
|
||||
@ApiResponse({ status: 404, description: 'Team not found' })
|
||||
async getDetails(@Param('teamId') teamId: string, @Req() req: Request): Promise<GetTeamDetailsOutputDTO | null> {
|
||||
const userId = req['user']?.userId;
|
||||
const presenter = await this.teamService.getDetails(teamId, userId);
|
||||
return presenter.getResponseModel();
|
||||
const userId = (req as any)['user']?.userId;
|
||||
return await this.teamService.getDetails(teamId, userId);
|
||||
}
|
||||
|
||||
@Get(':teamId/members')
|
||||
@ApiOperation({ summary: 'Get team members' })
|
||||
@ApiResponse({ status: 200, description: 'Team members', type: GetTeamMembersOutputDTO })
|
||||
async getMembers(@Param('teamId') teamId: string): Promise<GetTeamMembersOutputDTO> {
|
||||
const presenter = await this.teamService.getMembers(teamId);
|
||||
return presenter.getResponseModel()!;
|
||||
return await this.teamService.getMembers(teamId);
|
||||
}
|
||||
|
||||
@Get(':teamId/join-requests')
|
||||
@ApiOperation({ summary: 'Get team join requests' })
|
||||
@ApiResponse({ status: 200, description: 'Team join requests', type: GetTeamJoinRequestsOutputDTO })
|
||||
async getJoinRequests(@Param('teamId') teamId: string): Promise<GetTeamJoinRequestsOutputDTO> {
|
||||
const presenter = await this.teamService.getJoinRequests(teamId);
|
||||
return presenter.getResponseModel()!;
|
||||
return await this.teamService.getJoinRequests(teamId);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new team' })
|
||||
@ApiResponse({ status: 201, description: 'Team created', type: CreateTeamOutputDTO })
|
||||
async create(@Body() input: CreateTeamInputDTO, @Req() req: Request): Promise<CreateTeamOutputDTO> {
|
||||
const userId = req['user']?.userId;
|
||||
const presenter = await this.teamService.create(input, userId);
|
||||
return presenter.responseModel;
|
||||
const userId = (req as any)['user']?.userId;
|
||||
return await this.teamService.create(input, userId);
|
||||
}
|
||||
|
||||
@Patch(':teamId')
|
||||
@ApiOperation({ summary: 'Update team' })
|
||||
@ApiResponse({ status: 200, description: 'Team updated', type: UpdateTeamOutputDTO })
|
||||
async update(@Param('teamId') teamId: string, @Body() input: UpdateTeamInputDTO, @Req() req: Request): Promise<UpdateTeamOutputDTO> {
|
||||
const userId = req['user']?.userId;
|
||||
const presenter = await this.teamService.update(teamId, input, userId);
|
||||
return presenter.responseModel;
|
||||
async update(@Param('teamId') teamId: string, @Body() input: UpdateTeamInput, @Req() req: Request): Promise<UpdateTeamOutputDTO> {
|
||||
const userId = (req as any)['user']?.userId;
|
||||
return await this.teamService.update(teamId, input, userId);
|
||||
}
|
||||
|
||||
@Get('driver/:driverId')
|
||||
@@ -75,8 +69,7 @@ export class TeamController {
|
||||
@ApiResponse({ status: 200, description: 'Driver\'s team', type: GetDriverTeamOutputDTO })
|
||||
@ApiResponse({ status: 404, description: 'Team not found' })
|
||||
async getDriverTeam(@Param('driverId') driverId: string): Promise<GetDriverTeamOutputDTO | null> {
|
||||
const presenter = await this.teamService.getDriverTeam(driverId);
|
||||
return presenter.getResponseModel();
|
||||
return await this.teamService.getDriverTeam(driverId);
|
||||
}
|
||||
|
||||
@Get(':teamId/members/:driverId')
|
||||
@@ -84,7 +77,6 @@ export class TeamController {
|
||||
@ApiResponse({ status: 200, description: 'Team membership', type: GetTeamMembershipOutputDTO })
|
||||
@ApiResponse({ status: 404, description: 'Membership not found' })
|
||||
async getMembership(@Param('teamId') teamId: string, @Param('driverId') driverId: string): Promise<GetTeamMembershipOutputDTO | null> {
|
||||
const presenter = await this.teamService.getMembership(teamId, driverId);
|
||||
return presenter.responseModel;
|
||||
return await this.teamService.getMembership(teamId, driverId);
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,6 @@ import { TeamService } from './TeamService';
|
||||
|
||||
// Import core interfaces
|
||||
import type { Logger } from '@core/shared/application/Logger';
|
||||
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
|
||||
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
|
||||
import type { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
|
||||
import type { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
||||
|
||||
// Import concrete in-memory implementations
|
||||
import { InMemoryTeamRepository } from '@adapters/racing/persistence/inmemory/InMemoryTeamRepository';
|
||||
@@ -15,15 +11,7 @@ import { InMemoryDriverRepository } from '@adapters/racing/persistence/inmemory/
|
||||
import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImageServiceAdapter';
|
||||
import { ConsoleLogger } from '@adapters/logging/ConsoleLogger';
|
||||
|
||||
// Import use cases
|
||||
import { GetAllTeamsUseCase } from '@core/racing/application/use-cases/GetAllTeamsUseCase';
|
||||
import { GetTeamDetailsUseCase } from '@core/racing/application/use-cases/GetTeamDetailsUseCase';
|
||||
import { GetTeamMembersUseCase } from '@core/racing/application/use-cases/GetTeamMembersUseCase';
|
||||
import { GetTeamJoinRequestsUseCase } from '@core/racing/application/use-cases/GetTeamJoinRequestsUseCase';
|
||||
import { CreateTeamUseCase } from '@core/racing/application/use-cases/CreateTeamUseCase';
|
||||
import { UpdateTeamUseCase } 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';
|
||||
// Use cases are imported and used directly in the service
|
||||
|
||||
// Define injection tokens
|
||||
export const TEAM_REPOSITORY_TOKEN = 'ITeamRepository';
|
||||
@@ -58,53 +46,5 @@ export const TeamProviders: Provider[] = [
|
||||
provide: LOGGER_TOKEN,
|
||||
useClass: ConsoleLogger,
|
||||
},
|
||||
// Use cases
|
||||
{
|
||||
provide: GetAllTeamsUseCase,
|
||||
useFactory: (teamRepo: ITeamRepository, membershipRepo: ITeamMembershipRepository, logger: Logger) =>
|
||||
new GetAllTeamsUseCase(teamRepo, membershipRepo, logger),
|
||||
inject: [TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetTeamDetailsUseCase,
|
||||
useFactory: (teamRepo: ITeamRepository, membershipRepo: ITeamMembershipRepository) =>
|
||||
new GetTeamDetailsUseCase(teamRepo, membershipRepo),
|
||||
inject: [TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetTeamMembersUseCase,
|
||||
useFactory: (membershipRepo: ITeamMembershipRepository, driverRepo: IDriverRepository, imageService: IImageServicePort, logger: Logger) =>
|
||||
new GetTeamMembersUseCase(membershipRepo, driverRepo, imageService, logger),
|
||||
inject: [TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, IMAGE_SERVICE_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetTeamJoinRequestsUseCase,
|
||||
useFactory: (membershipRepo: ITeamMembershipRepository, driverRepo: IDriverRepository, imageService: IImageServicePort, logger: Logger) =>
|
||||
new GetTeamJoinRequestsUseCase(membershipRepo, driverRepo, imageService, logger),
|
||||
inject: [TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, IMAGE_SERVICE_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: CreateTeamUseCase,
|
||||
useFactory: (teamRepo: ITeamRepository, membershipRepo: ITeamMembershipRepository) =>
|
||||
new CreateTeamUseCase(teamRepo, membershipRepo),
|
||||
inject: [TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: UpdateTeamUseCase,
|
||||
useFactory: (teamRepo: ITeamRepository, membershipRepo: ITeamMembershipRepository) =>
|
||||
new UpdateTeamUseCase(teamRepo, membershipRepo),
|
||||
inject: [TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetDriverTeamUseCase,
|
||||
useFactory: (teamRepo: ITeamRepository, membershipRepo: ITeamMembershipRepository, logger: Logger) =>
|
||||
new GetDriverTeamUseCase(teamRepo, membershipRepo, logger),
|
||||
inject: [TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GetTeamMembershipUseCase,
|
||||
useFactory: (membershipRepo: ITeamMembershipRepository, logger: Logger) =>
|
||||
new GetTeamMembershipUseCase(membershipRepo, logger),
|
||||
inject: [TEAM_MEMBERSHIP_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
// Use cases are created directly in the service
|
||||
];
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { TeamService } from './TeamService';
|
||||
import { GetAllTeamsUseCase } from '@core/racing/application/use-cases/GetAllTeamsUseCase';
|
||||
import { GetDriverTeamUseCase } from '@core/racing/application/use-cases/GetDriverTeamUseCase';
|
||||
@@ -11,20 +12,20 @@ import { DriverTeamViewModel } from './dtos/TeamDto';
|
||||
|
||||
describe('TeamService', () => {
|
||||
let service: TeamService;
|
||||
let getAllTeamsUseCase: jest.Mocked<GetAllTeamsUseCase>;
|
||||
let getDriverTeamUseCase: jest.Mocked<GetDriverTeamUseCase>;
|
||||
let getAllTeamsUseCase: ReturnType<typeof vi.mocked<GetAllTeamsUseCase>>;
|
||||
let getDriverTeamUseCase: ReturnType<typeof vi.mocked<GetDriverTeamUseCase>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockGetAllTeamsUseCase = {
|
||||
execute: jest.fn(),
|
||||
execute: vi.fn(),
|
||||
};
|
||||
const mockGetDriverTeamUseCase = {
|
||||
execute: jest.fn(),
|
||||
execute: vi.fn(),
|
||||
};
|
||||
const mockLogger = {
|
||||
debug: jest.fn(),
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
debug: vi.fn(),
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
@@ -61,11 +62,11 @@ describe('TeamService', () => {
|
||||
getAllTeamsUseCase.execute.mockResolvedValue(mockResult as any);
|
||||
|
||||
const mockPresenter = {
|
||||
present: jest.fn(),
|
||||
getViewModel: jest.fn().mockReturnValue({ teams: [], totalCount: 0 }),
|
||||
present: vi.fn(),
|
||||
getViewModel: vi.fn().mockReturnValue({ teams: [], totalCount: 0 }),
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(AllTeamsPresenter as any) = jest.fn().mockImplementation(() => mockPresenter);
|
||||
(AllTeamsPresenter as any) = vi.fn().mockImplementation(() => mockPresenter);
|
||||
|
||||
const result = await service.getAll();
|
||||
|
||||
@@ -81,11 +82,11 @@ describe('TeamService', () => {
|
||||
getDriverTeamUseCase.execute.mockResolvedValue(mockResult as any);
|
||||
|
||||
const mockPresenter = {
|
||||
present: jest.fn(),
|
||||
getViewModel: jest.fn().mockReturnValue({} as DriverTeamViewModel),
|
||||
present: vi.fn(),
|
||||
getViewModel: vi.fn().mockReturnValue({} as DriverTeamViewModel),
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(DriverTeamPresenter as any) = jest.fn().mockImplementation(() => mockPresenter);
|
||||
(DriverTeamPresenter as any) = vi.fn().mockImplementation(() => mockPresenter);
|
||||
|
||||
const result = await service.getDriverTeam('driver1');
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import type { Logger } from '@core/shared/application/Logger';
|
||||
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
|
||||
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
|
||||
import type { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepository';
|
||||
import type { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
||||
|
||||
// Use cases
|
||||
import { GetAllTeamsUseCase } from '@core/racing/application/use-cases/GetAllTeamsUseCase';
|
||||
@@ -38,7 +37,7 @@ import { CreateTeamPresenter } from './presenters/CreateTeamPresenter';
|
||||
import { UpdateTeamPresenter } from './presenters/UpdateTeamPresenter';
|
||||
|
||||
// Tokens
|
||||
import { TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, IMAGE_SERVICE_TOKEN, LOGGER_TOKEN } from './TeamProviders';
|
||||
import { TEAM_REPOSITORY_TOKEN, TEAM_MEMBERSHIP_REPOSITORY_TOKEN, DRIVER_REPOSITORY_TOKEN, LOGGER_TOKEN } from './TeamProviders';
|
||||
|
||||
@Injectable()
|
||||
export class TeamService {
|
||||
@@ -46,7 +45,6 @@ export class TeamService {
|
||||
@Inject(TEAM_REPOSITORY_TOKEN) private readonly teamRepository: ITeamRepository,
|
||||
@Inject(TEAM_MEMBERSHIP_REPOSITORY_TOKEN) private readonly membershipRepository: ITeamMembershipRepository,
|
||||
@Inject(DRIVER_REPOSITORY_TOKEN) private readonly driverRepository: IDriverRepository,
|
||||
@Inject(IMAGE_SERVICE_TOKEN) private readonly imageService: IImageServicePort,
|
||||
@Inject(LOGGER_TOKEN) private readonly logger: Logger,
|
||||
) {}
|
||||
|
||||
@@ -57,11 +55,11 @@ export class TeamService {
|
||||
const useCase = new GetAllTeamsUseCase(this.teamRepository, this.membershipRepository, this.logger, presenter);
|
||||
const result = await useCase.execute();
|
||||
if (result.isErr()) {
|
||||
this.logger.error('Error fetching all teams', result.error?.details?.message || 'Unknown error');
|
||||
this.logger.error('Error fetching all teams', new Error(result.error?.details?.message || 'Unknown error'));
|
||||
return { teams: [], totalCount: 0 };
|
||||
}
|
||||
|
||||
return presenter.responseModel;
|
||||
return presenter.getResponseModel()!;
|
||||
}
|
||||
|
||||
async getDetails(teamId: string, userId?: string): Promise<GetTeamDetailsOutputDTO | null> {
|
||||
@@ -75,14 +73,14 @@ export class TeamService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return presenter.getResponseModel();
|
||||
return presenter.getResponseModel()!;
|
||||
}
|
||||
|
||||
async getMembers(teamId: string): Promise<GetTeamMembersOutputDTO> {
|
||||
this.logger.debug(`[TeamService] Fetching team members for teamId: ${teamId}`);
|
||||
|
||||
const presenter = new TeamMembersPresenter();
|
||||
const useCase = new GetTeamMembersUseCase(this.membershipRepository, this.driverRepository, this.imageService, this.logger, presenter);
|
||||
const useCase = new GetTeamMembersUseCase(this.membershipRepository, this.driverRepository, this.teamRepository, this.logger, presenter);
|
||||
const result = await useCase.execute({ teamId });
|
||||
if (result.isErr()) {
|
||||
this.logger.error(`Error fetching team members for teamId: ${teamId}: ${result.error?.details?.message || 'Unknown error'}`);
|
||||
@@ -105,7 +103,7 @@ export class TeamService {
|
||||
const useCase = new GetTeamJoinRequestsUseCase(this.membershipRepository, this.driverRepository, this.teamRepository, presenter);
|
||||
const result = await useCase.execute({ teamId });
|
||||
if (result.isErr()) {
|
||||
this.logger.error(new Error(`Error fetching team join requests for teamId: ${teamId}: ${result.error?.details?.message || 'Unknown error'}`));
|
||||
this.logger.error(`Error fetching team join requests for teamId: ${teamId}`, new Error(result.error?.details?.message || 'Unknown error'));
|
||||
return {
|
||||
requests: [],
|
||||
pendingCount: 0,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsString, IsNotEmpty, IsOptional } from 'class-validator';
|
||||
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class CreateTeamInputDTO {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
|
||||
@@ -2,8 +2,8 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class CreateTeamOutputDTO {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
success: boolean;
|
||||
success!: boolean;
|
||||
}
|
||||
@@ -2,22 +2,22 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
class TeamListItemDTO {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
description!: string;
|
||||
|
||||
@ApiProperty()
|
||||
memberCount: number;
|
||||
memberCount!: number;
|
||||
|
||||
@ApiProperty({ type: [String] })
|
||||
leagues: string[];
|
||||
leagues!: string[];
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
specialization?: 'endurance' | 'sprint' | 'mixed';
|
||||
@@ -31,8 +31,8 @@ class TeamListItemDTO {
|
||||
|
||||
export class GetAllTeamsOutputDTO {
|
||||
@ApiProperty({ type: [TeamListItemDTO] })
|
||||
teams: TeamListItemDTO[];
|
||||
teams!: TeamListItemDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
totalCount!: number;
|
||||
}
|
||||
@@ -2,22 +2,22 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
class TeamDTO {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
description!: string;
|
||||
|
||||
@ApiProperty()
|
||||
ownerId: string;
|
||||
ownerId!: string;
|
||||
|
||||
@ApiProperty({ type: [String] })
|
||||
leagues: string[];
|
||||
leagues!: string[];
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
createdAt?: string;
|
||||
@@ -34,25 +34,25 @@ class TeamDTO {
|
||||
|
||||
class MembershipDTO {
|
||||
@ApiProperty()
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
role!: 'owner' | 'manager' | 'member';
|
||||
|
||||
@ApiProperty()
|
||||
joinedAt: string;
|
||||
joinedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
isActive: boolean;
|
||||
isActive!: boolean;
|
||||
}
|
||||
|
||||
export class GetDriverTeamOutputDTO {
|
||||
@ApiProperty({ type: TeamDTO })
|
||||
team: TeamDTO;
|
||||
team!: TeamDTO;
|
||||
|
||||
@ApiProperty({ type: MembershipDTO })
|
||||
membership: MembershipDTO;
|
||||
membership!: MembershipDTO;
|
||||
|
||||
@ApiProperty()
|
||||
isOwner: boolean;
|
||||
isOwner!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
canManage: boolean;
|
||||
canManage!: boolean;
|
||||
}
|
||||
@@ -2,22 +2,22 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
class TeamDTO {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
description!: string;
|
||||
|
||||
@ApiProperty()
|
||||
ownerId: string;
|
||||
ownerId!: string;
|
||||
|
||||
@ApiProperty({ type: [String] })
|
||||
leagues: string[];
|
||||
leagues!: string[];
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
createdAt?: string;
|
||||
@@ -34,22 +34,22 @@ class TeamDTO {
|
||||
|
||||
class MembershipDTO {
|
||||
@ApiProperty()
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
role!: 'owner' | 'manager' | 'member';
|
||||
|
||||
@ApiProperty()
|
||||
joinedAt: string;
|
||||
joinedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
isActive: boolean;
|
||||
isActive!: boolean;
|
||||
}
|
||||
|
||||
export class GetTeamDetailsOutputDTO {
|
||||
@ApiProperty({ type: TeamDTO })
|
||||
team: TeamDTO;
|
||||
team!: TeamDTO;
|
||||
|
||||
@ApiProperty({ type: MembershipDTO, nullable: true })
|
||||
membership: MembershipDTO | null;
|
||||
membership!: MembershipDTO | null;
|
||||
|
||||
@ApiProperty()
|
||||
canManage: boolean;
|
||||
canManage!: boolean;
|
||||
}
|
||||
@@ -2,34 +2,34 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
class TeamJoinRequestDTO {
|
||||
@ApiProperty()
|
||||
requestId: string;
|
||||
requestId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
driverId: string;
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
driverName: string;
|
||||
driverName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
teamId: string;
|
||||
teamId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
status: 'pending' | 'approved' | 'rejected';
|
||||
status!: 'pending' | 'approved' | 'rejected';
|
||||
|
||||
@ApiProperty()
|
||||
requestedAt: string;
|
||||
requestedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
avatarUrl: string;
|
||||
avatarUrl!: string;
|
||||
}
|
||||
|
||||
export class GetTeamJoinRequestsOutputDTO {
|
||||
@ApiProperty({ type: [TeamJoinRequestDTO] })
|
||||
requests: TeamJoinRequestDTO[];
|
||||
requests!: TeamJoinRequestDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
pendingCount: number;
|
||||
pendingCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
totalCount!: number;
|
||||
}
|
||||
@@ -2,37 +2,37 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
class TeamMemberDTO {
|
||||
@ApiProperty()
|
||||
driverId: string;
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
driverName: string;
|
||||
driverName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
role!: 'owner' | 'manager' | 'member';
|
||||
|
||||
@ApiProperty()
|
||||
joinedAt: string;
|
||||
joinedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
isActive: boolean;
|
||||
isActive!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
avatarUrl: string;
|
||||
avatarUrl!: string;
|
||||
}
|
||||
|
||||
export class GetTeamMembersOutputDTO {
|
||||
@ApiProperty({ type: [TeamMemberDTO] })
|
||||
members: TeamMemberDTO[];
|
||||
members!: TeamMemberDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
totalCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
ownerCount: number;
|
||||
ownerCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
managerCount: number;
|
||||
managerCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
memberCount: number;
|
||||
memberCount!: number;
|
||||
}
|
||||
@@ -2,11 +2,11 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class GetTeamMembershipOutputDTO {
|
||||
@ApiProperty()
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
role!: 'owner' | 'manager' | 'member';
|
||||
|
||||
@ApiProperty()
|
||||
joinedAt: string;
|
||||
joinedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
isActive: boolean;
|
||||
isActive!: boolean;
|
||||
}
|
||||
@@ -4,31 +4,31 @@ export type SkillLevel = 'beginner' | 'intermediate' | 'advanced' | 'pro';
|
||||
|
||||
class TeamLeaderboardItemDTO {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
memberCount: number;
|
||||
memberCount!: number;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
rating: number | null;
|
||||
rating!: number | null;
|
||||
|
||||
@ApiProperty()
|
||||
totalWins: number;
|
||||
totalWins!: number;
|
||||
|
||||
@ApiProperty()
|
||||
totalRaces: number;
|
||||
totalRaces!: number;
|
||||
|
||||
@ApiProperty({ enum: ['beginner', 'intermediate', 'advanced', 'pro'] })
|
||||
performanceLevel: SkillLevel;
|
||||
performanceLevel!: SkillLevel;
|
||||
|
||||
@ApiProperty()
|
||||
isRecruiting: boolean;
|
||||
isRecruiting!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
createdAt: string;
|
||||
createdAt!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
description?: string;
|
||||
@@ -45,14 +45,14 @@ class TeamLeaderboardItemDTO {
|
||||
|
||||
export class GetTeamsLeaderboardOutputDTO {
|
||||
@ApiProperty({ type: [TeamLeaderboardItemDTO] })
|
||||
teams: TeamLeaderboardItemDTO[];
|
||||
teams!: TeamLeaderboardItemDTO[];
|
||||
|
||||
@ApiProperty()
|
||||
recruitingCount: number;
|
||||
recruitingCount!: number;
|
||||
|
||||
@ApiProperty({ type: 'object', additionalProperties: { type: 'array', items: { $ref: '#/components/schemas/TeamLeaderboardItemDTO' } } })
|
||||
groupsBySkillLevel: Record<SkillLevel, TeamLeaderboardItemDTO[]>;
|
||||
groupsBySkillLevel!: Record<SkillLevel, TeamLeaderboardItemDTO[]>;
|
||||
|
||||
@ApiProperty({ type: [TeamLeaderboardItemDTO] })
|
||||
topTeams: TeamLeaderboardItemDTO[];
|
||||
topTeams!: TeamLeaderboardItemDTO[];
|
||||
}
|
||||
@@ -3,22 +3,22 @@ import { IsString, IsNotEmpty, IsBoolean, IsOptional } from 'class-validator';
|
||||
|
||||
export class TeamListItemViewModel {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
description!: string;
|
||||
|
||||
@ApiProperty()
|
||||
memberCount: number;
|
||||
memberCount!: number;
|
||||
|
||||
@ApiProperty({ type: [String] })
|
||||
leagues: string[];
|
||||
leagues!: string[];
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
specialization?: 'endurance' | 'sprint' | 'mixed';
|
||||
@@ -32,30 +32,30 @@ export class TeamListItemViewModel {
|
||||
|
||||
export class AllTeamsViewModel {
|
||||
@ApiProperty({ type: [TeamListItemViewModel] })
|
||||
teams: TeamListItemViewModel[];
|
||||
teams!: TeamListItemViewModel[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
totalCount!: number;
|
||||
}
|
||||
|
||||
export class TeamViewModel {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
id!: string;
|
||||
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
description!: string;
|
||||
|
||||
@ApiProperty()
|
||||
ownerId: string;
|
||||
ownerId!: string;
|
||||
|
||||
@ApiProperty({ type: [String] })
|
||||
leagues: string[];
|
||||
leagues!: string[];
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
createdAt?: string;
|
||||
@@ -85,131 +85,131 @@ export enum MembershipStatus {
|
||||
|
||||
export class MembershipViewModel {
|
||||
@ApiProperty()
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
role!: 'owner' | 'manager' | 'member';
|
||||
|
||||
@ApiProperty()
|
||||
joinedAt: string;
|
||||
joinedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
isActive: boolean;
|
||||
isActive!: boolean;
|
||||
}
|
||||
|
||||
export class DriverTeamViewModel {
|
||||
@ApiProperty({ type: TeamViewModel })
|
||||
team: TeamViewModel;
|
||||
team!: TeamViewModel;
|
||||
|
||||
@ApiProperty({ type: MembershipViewModel })
|
||||
membership: MembershipViewModel;
|
||||
membership!: MembershipViewModel;
|
||||
|
||||
@ApiProperty()
|
||||
isOwner: boolean;
|
||||
isOwner!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
canManage: boolean;
|
||||
canManage!: boolean;
|
||||
}
|
||||
|
||||
export class GetDriverTeamQuery {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
teamId: string;
|
||||
teamId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
driverId: string;
|
||||
driverId!: string;
|
||||
}
|
||||
|
||||
export class TeamDetailsViewModel {
|
||||
@ApiProperty({ type: TeamViewModel })
|
||||
team: TeamViewModel;
|
||||
team!: TeamViewModel;
|
||||
|
||||
@ApiProperty({ type: MembershipViewModel, nullable: true })
|
||||
membership: MembershipViewModel | null;
|
||||
membership!: MembershipViewModel | null;
|
||||
|
||||
@ApiProperty()
|
||||
canManage: boolean;
|
||||
canManage!: boolean;
|
||||
}
|
||||
|
||||
export class TeamMemberViewModel {
|
||||
@ApiProperty()
|
||||
driverId: string;
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
driverName: string;
|
||||
driverName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
role: 'owner' | 'manager' | 'member';
|
||||
role!: 'owner' | 'manager' | 'member';
|
||||
|
||||
@ApiProperty()
|
||||
joinedAt: string;
|
||||
joinedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
isActive: boolean;
|
||||
isActive!: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
avatarUrl: string;
|
||||
avatarUrl!: string;
|
||||
}
|
||||
|
||||
export class TeamMembersViewModel {
|
||||
@ApiProperty({ type: [TeamMemberViewModel] })
|
||||
members: TeamMemberViewModel[];
|
||||
members!: TeamMemberViewModel[];
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
totalCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
ownerCount: number;
|
||||
ownerCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
managerCount: number;
|
||||
managerCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
memberCount: number;
|
||||
memberCount!: number;
|
||||
}
|
||||
|
||||
export class TeamJoinRequestViewModel {
|
||||
@ApiProperty()
|
||||
requestId: string;
|
||||
requestId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
driverId: string;
|
||||
driverId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
driverName: string;
|
||||
driverName!: string;
|
||||
|
||||
@ApiProperty()
|
||||
teamId: string;
|
||||
teamId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
status: 'pending' | 'approved' | 'rejected';
|
||||
status!: 'pending' | 'approved' | 'rejected';
|
||||
|
||||
@ApiProperty()
|
||||
requestedAt: string;
|
||||
requestedAt!: string;
|
||||
|
||||
@ApiProperty()
|
||||
avatarUrl: string;
|
||||
avatarUrl!: string;
|
||||
}
|
||||
|
||||
export class TeamJoinRequestsViewModel {
|
||||
@ApiProperty({ type: [TeamJoinRequestViewModel] })
|
||||
requests: TeamJoinRequestViewModel[];
|
||||
requests!: TeamJoinRequestViewModel[];
|
||||
|
||||
@ApiProperty()
|
||||
pendingCount: number;
|
||||
pendingCount!: number;
|
||||
|
||||
@ApiProperty()
|
||||
totalCount: number;
|
||||
totalCount!: number;
|
||||
}
|
||||
|
||||
export class CreateTeamInput {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
name!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
tag: string;
|
||||
tag!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@@ -218,17 +218,17 @@ export class CreateTeamInput {
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
ownerId: string;
|
||||
ownerId!: string;
|
||||
}
|
||||
|
||||
export class CreateTeamOutput {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
teamId: string;
|
||||
teamId!: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success: boolean;
|
||||
success!: boolean;
|
||||
}
|
||||
|
||||
export class UpdateTeamInput {
|
||||
@@ -254,19 +254,19 @@ export class UpdateTeamInput {
|
||||
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
updatedBy: string;
|
||||
updatedBy!: string;
|
||||
}
|
||||
|
||||
export class UpdateTeamOutput {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success: boolean;
|
||||
success!: boolean;
|
||||
}
|
||||
|
||||
export class ApproveTeamJoinRequestInput {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
requestId: string;
|
||||
requestId!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@@ -277,13 +277,13 @@ export class ApproveTeamJoinRequestInput {
|
||||
export class ApproveTeamJoinRequestOutput {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success: boolean;
|
||||
success!: boolean;
|
||||
}
|
||||
|
||||
export class RejectTeamJoinRequestInput {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
requestId: string;
|
||||
requestId!: string;
|
||||
|
||||
@ApiProperty({ required: false })
|
||||
@IsOptional()
|
||||
@@ -294,5 +294,5 @@ export class RejectTeamJoinRequestInput {
|
||||
export class RejectTeamJoinRequestOutput {
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
success: boolean;
|
||||
success!: boolean;
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class UpdateTeamOutputDTO {
|
||||
@ApiProperty()
|
||||
success: boolean;
|
||||
success!: boolean;
|
||||
}
|
||||
@@ -16,4 +16,11 @@ export class TeamMembershipPresenter implements UseCaseOutputPort<GetTeamMembers
|
||||
getResponseModel(): GetTeamMembershipOutputDTO | null {
|
||||
return this.result;
|
||||
}
|
||||
|
||||
get responseModel(): GetTeamMembershipOutputDTO {
|
||||
if (!this.result) {
|
||||
throw new Error('Presenter not presented');
|
||||
}
|
||||
return this.result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +1,90 @@
|
||||
import type { TeamsLeaderboardOutputPort } from '@core/racing/application/ports/output/TeamsLeaderboardOutputPort';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import type { GetTeamsLeaderboardResult } from '@core/racing/application/use-cases/GetTeamsLeaderboardUseCase';
|
||||
import type { GetTeamsLeaderboardOutputDTO } from '../dtos/GetTeamsLeaderboardOutputDTO';
|
||||
|
||||
export class TeamsLeaderboardPresenter {
|
||||
export class TeamsLeaderboardPresenter implements UseCaseOutputPort<GetTeamsLeaderboardResult> {
|
||||
private result: GetTeamsLeaderboardOutputDTO | null = null;
|
||||
|
||||
reset() {
|
||||
this.result = null;
|
||||
}
|
||||
|
||||
async present(outputPort: TeamsLeaderboardOutputPort): Promise<void> {
|
||||
present(result: GetTeamsLeaderboardResult): void {
|
||||
this.result = {
|
||||
teams: outputPort.teams.map(team => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
memberCount: team.memberCount,
|
||||
rating: team.rating,
|
||||
totalWins: team.totalWins,
|
||||
totalRaces: team.totalRaces,
|
||||
performanceLevel: team.performanceLevel,
|
||||
isRecruiting: team.isRecruiting,
|
||||
createdAt: team.createdAt.toISOString(),
|
||||
description: team.description,
|
||||
specialization: team.specialization,
|
||||
region: team.region,
|
||||
languages: team.languages,
|
||||
teams: result.items.map(item => ({
|
||||
id: item.team.id,
|
||||
name: item.team.name.toString(),
|
||||
memberCount: item.memberCount,
|
||||
rating: item.rating,
|
||||
totalWins: item.totalWins,
|
||||
totalRaces: item.totalRaces,
|
||||
performanceLevel: item.performanceLevel,
|
||||
isRecruiting: item.isRecruiting,
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
description: item.team.description?.toString() || '',
|
||||
})),
|
||||
recruitingCount: outputPort.recruitingCount,
|
||||
recruitingCount: result.recruitingCount,
|
||||
groupsBySkillLevel: {
|
||||
beginner: outputPort.groupsBySkillLevel.beginner.map(team => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
memberCount: team.memberCount,
|
||||
rating: team.rating,
|
||||
totalWins: team.totalWins,
|
||||
totalRaces: team.totalRaces,
|
||||
performanceLevel: team.performanceLevel,
|
||||
isRecruiting: team.isRecruiting,
|
||||
createdAt: team.createdAt.toISOString(),
|
||||
description: team.description,
|
||||
specialization: team.specialization,
|
||||
region: team.region,
|
||||
languages: team.languages,
|
||||
beginner: result.groupsBySkillLevel.beginner.map(item => ({
|
||||
id: item.team.id,
|
||||
name: item.team.name.toString(),
|
||||
memberCount: item.memberCount,
|
||||
rating: item.rating,
|
||||
totalWins: item.totalWins,
|
||||
totalRaces: item.totalRaces,
|
||||
performanceLevel: item.performanceLevel,
|
||||
isRecruiting: item.isRecruiting,
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
description: item.team.description?.toString() || '',
|
||||
})),
|
||||
intermediate: outputPort.groupsBySkillLevel.intermediate.map(team => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
memberCount: team.memberCount,
|
||||
rating: team.rating,
|
||||
totalWins: team.totalWins,
|
||||
totalRaces: team.totalRaces,
|
||||
performanceLevel: team.performanceLevel,
|
||||
isRecruiting: team.isRecruiting,
|
||||
createdAt: team.createdAt.toISOString(),
|
||||
description: team.description,
|
||||
specialization: team.specialization,
|
||||
region: team.region,
|
||||
languages: team.languages,
|
||||
intermediate: result.groupsBySkillLevel.intermediate.map(item => ({
|
||||
id: item.team.id,
|
||||
name: item.team.name.toString(),
|
||||
memberCount: item.memberCount,
|
||||
rating: item.rating,
|
||||
totalWins: item.totalWins,
|
||||
totalRaces: item.totalRaces,
|
||||
performanceLevel: item.performanceLevel,
|
||||
isRecruiting: item.isRecruiting,
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
description: item.team.description?.toString() || '',
|
||||
})),
|
||||
advanced: outputPort.groupsBySkillLevel.advanced.map(team => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
memberCount: team.memberCount,
|
||||
rating: team.rating,
|
||||
totalWins: team.totalWins,
|
||||
totalRaces: team.totalRaces,
|
||||
performanceLevel: team.performanceLevel,
|
||||
isRecruiting: team.isRecruiting,
|
||||
createdAt: team.createdAt.toISOString(),
|
||||
description: team.description,
|
||||
specialization: team.specialization,
|
||||
region: team.region,
|
||||
languages: team.languages,
|
||||
advanced: result.groupsBySkillLevel.advanced.map(item => ({
|
||||
id: item.team.id,
|
||||
name: item.team.name.toString(),
|
||||
memberCount: item.memberCount,
|
||||
rating: item.rating,
|
||||
totalWins: item.totalWins,
|
||||
totalRaces: item.totalRaces,
|
||||
performanceLevel: item.performanceLevel,
|
||||
isRecruiting: item.isRecruiting,
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
description: item.team.description?.toString() || '',
|
||||
})),
|
||||
pro: outputPort.groupsBySkillLevel.pro.map(team => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
memberCount: team.memberCount,
|
||||
rating: team.rating,
|
||||
totalWins: team.totalWins,
|
||||
totalRaces: team.totalRaces,
|
||||
performanceLevel: team.performanceLevel,
|
||||
isRecruiting: team.isRecruiting,
|
||||
createdAt: team.createdAt.toISOString(),
|
||||
description: team.description,
|
||||
specialization: team.specialization,
|
||||
region: team.region,
|
||||
languages: team.languages,
|
||||
pro: result.groupsBySkillLevel.pro.map(item => ({
|
||||
id: item.team.id,
|
||||
name: item.team.name.toString(),
|
||||
memberCount: item.memberCount,
|
||||
rating: item.rating,
|
||||
totalWins: item.totalWins,
|
||||
totalRaces: item.totalRaces,
|
||||
performanceLevel: item.performanceLevel,
|
||||
isRecruiting: item.isRecruiting,
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
description: item.team.description?.toString() || '',
|
||||
})),
|
||||
},
|
||||
topTeams: outputPort.topTeams.map(team => ({
|
||||
id: team.id,
|
||||
name: team.name,
|
||||
memberCount: team.memberCount,
|
||||
rating: team.rating,
|
||||
totalWins: team.totalWins,
|
||||
totalRaces: team.totalRaces,
|
||||
performanceLevel: team.performanceLevel,
|
||||
isRecruiting: team.isRecruiting,
|
||||
createdAt: team.createdAt.toISOString(),
|
||||
description: team.description,
|
||||
specialization: team.specialization,
|
||||
region: team.region,
|
||||
languages: team.languages,
|
||||
topTeams: result.topItems.map(item => ({
|
||||
id: item.team.id,
|
||||
name: item.team.name.toString(),
|
||||
memberCount: item.memberCount,
|
||||
rating: item.rating,
|
||||
totalWins: item.totalWins,
|
||||
totalRaces: item.totalRaces,
|
||||
performanceLevel: item.performanceLevel,
|
||||
isRecruiting: item.isRecruiting,
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
description: item.team.description?.toString() || '',
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user