-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
32f9819
commit 9b2368e
Showing
22 changed files
with
627 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
src/api/dashboard/controllers/club-dashboard.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Controller, Get, NotFoundException, Param, ParseIntPipe, Query, Version } from '@nestjs/common'; | ||
import { ApiNotFoundResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger'; | ||
import { MemberDashboardDTOV1, WeeklyNumericRankingInputV2 } from '../dto/member-dashboard.dto'; | ||
import { MemberDashboardService } from '../services/member-dashboard.service'; | ||
import { ClubDashboardDTOV1 } from '../dto/club-dashboard.dto'; | ||
import { ClubDashboardService } from '../services/club-dashboard.service'; | ||
|
||
@ApiTags('Dashboards') | ||
@Controller({ | ||
path: 'dashboard/club', | ||
version: '1', | ||
}) | ||
export class ClubDashboardController { | ||
constructor( | ||
private readonly clubDashboardService: ClubDashboardService, | ||
) { | ||
} | ||
|
||
@Get(':uniqueIndex') | ||
@ApiOkResponse({ | ||
type: ClubDashboardDTOV1, | ||
description: 'The information to be displayed on the club dashboard', | ||
}) | ||
@ApiNotFoundResponse({ | ||
description: 'No info found for given club', | ||
}) | ||
@Version('1') | ||
async clubDashboardV1( | ||
@Param('uniqueIndex') id: string, | ||
): Promise<ClubDashboardDTOV1> { | ||
const clubDasboard = await this.clubDashboardService.getDashboard(id); | ||
if (!clubDasboard) { | ||
throw new NotFoundException(`No member found for id ${id}`); | ||
} | ||
return clubDasboard; | ||
} | ||
|
||
} |
41 changes: 41 additions & 0 deletions
41
src/api/dashboard/controllers/division-dashboard.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Controller, Get, NotFoundException, Param, ParseIntPipe, Query, Version } from "@nestjs/common"; | ||
import { ApiNotFoundResponse, ApiOkResponse, ApiTags } from "@nestjs/swagger"; | ||
import { MemberDashboardDTOV1, WeeklyNumericRankingInputV2 } from "../dto/member-dashboard.dto"; | ||
import { MemberService } from "src/services/members/member.service"; | ||
import { getSimplifiedPlayerCategory } from "../../member/helpers/player-category-helpers"; | ||
import { EloMemberService } from "src/services/members/elo-member.service"; | ||
import { MemberDashboardService } from "../services/member-dashboard.service"; | ||
import { DivisionDashboardDTOV1 } from '../dto/division-dashboard.dto'; | ||
import { DivisionDashboardService } from '../services/division-dashboard.service'; | ||
|
||
@ApiTags('Dashboards') | ||
@Controller({ | ||
path: 'dashboard/division', | ||
version: '1', | ||
}) | ||
export class DivisionDashboardController { | ||
constructor( | ||
private readonly divisionDashboardService: DivisionDashboardService, | ||
){ | ||
} | ||
|
||
@Get(':divisionId') | ||
@ApiOkResponse({ | ||
type: DivisionDashboardDTOV1, | ||
description: 'The information to be displayed on the division dashboard', | ||
}) | ||
@ApiNotFoundResponse({ | ||
description: 'No info found for given division', | ||
}) | ||
@Version('1') | ||
async memberDashboardV1( | ||
@Param('divisionId', ParseIntPipe) id: number, | ||
): Promise<DivisionDashboardDTOV1> { | ||
const divisionDashboardDTOV1 = await this.divisionDashboardService.getDashboard(id); | ||
if(!divisionDashboardDTOV1) { | ||
throw new NotFoundException(`No division found for id ${id}`); | ||
} | ||
return divisionDashboardDTOV1; | ||
} | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
src/api/dashboard/controllers/member-dashboard.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Controller, Get, NotFoundException, Param, ParseIntPipe, Query, Version } from '@nestjs/common'; | ||
import { ApiNotFoundResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger'; | ||
import { MemberDashboardDTOV1, WeeklyNumericRankingInputV2 } from '../dto/member-dashboard.dto'; | ||
import { MemberDashboardService } from '../services/member-dashboard.service'; | ||
|
||
@ApiTags('Dashboards') | ||
@Controller({ | ||
path: 'dashboard/member', | ||
version: '1', | ||
}) | ||
export class MemberDashboardController { | ||
constructor( | ||
private readonly memberDashboardService: MemberDashboardService, | ||
) { | ||
} | ||
|
||
@Get(':uniqueIndex') | ||
@ApiOkResponse({ | ||
type: MemberDashboardDTOV1, | ||
description: 'The information to be displayed on the members dashboard', | ||
}) | ||
@ApiNotFoundResponse({ | ||
description: 'No info found for given player', | ||
}) | ||
@Version('1') | ||
async memberDashboardV1( | ||
@Param('uniqueIndex', ParseIntPipe) id: number, | ||
@Query() params: WeeklyNumericRankingInputV2, | ||
): Promise<MemberDashboardDTOV1> { | ||
const memberDashboard = await this.memberDashboardService.getDashboard(id, params.category); | ||
if (!memberDashboard) { | ||
throw new NotFoundException(`No member found for id ${id}`); | ||
} | ||
return memberDashboard; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { CommonModule } from '../../common/common.module'; | ||
import { ServicesModule } from '../../services/services.module'; | ||
import { MemberDashboardController } from './controllers/member-dashboard.controller'; | ||
import { MemberDashboardService } from './services/member-dashboard.service'; | ||
import { DivisionDashboardService } from './services/division-dashboard.service'; | ||
import { DivisionDashboardController } from './controllers/division-dashboard.controller'; | ||
import { ClubDashboardService } from './services/club-dashboard.service'; | ||
import { ClubDashboardController } from './controllers/club-dashboard.controller'; | ||
|
||
@Module({ | ||
imports: [CommonModule, ServicesModule], | ||
controllers: [MemberDashboardController, DivisionDashboardController, ClubDashboardController], | ||
providers: [MemberDashboardService, DivisionDashboardService, ClubDashboardService], | ||
}) | ||
export class DashboardModule { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
import { ClubEntry, MemberEntry, TeamEntry, TeamMatchesEntry } from '../../../entity/tabt-soap/TabTAPI_Port'; | ||
import { ResponseDTO } from './common.dto'; | ||
|
||
export class ClubDashboardDTOV1 { | ||
@ApiProperty({ type: ClubEntry}) | ||
club: ResponseDTO<ClubEntry>; | ||
@ApiProperty({type: MemberEntry, isArray: true}) | ||
members: ResponseDTO<MemberEntry[]>; | ||
@ApiProperty({type: TeamEntry, isArray: true}) | ||
teams: ResponseDTO<TeamEntry[]>; | ||
@ApiProperty({type: 'object', additionalProperties: {type: 'array', additionalProperties: {type: '#/components/TeamMatchEntry'}} , description: 'key is the week name'}) | ||
matches: ResponseDTO<{ | ||
[weekName: number]: TeamMatchesEntry[] | ||
}> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export enum RESPONSE_STATUS { | ||
SUCCESS = 'SUCCESS', | ||
ERROR = 'ERROR', | ||
WARNING = 'WARNING', | ||
} | ||
|
||
export class ResponseDTO<T> { | ||
constructor( | ||
public readonly status: RESPONSE_STATUS, | ||
public readonly payload: T | undefined, | ||
public readonly error?: string, | ||
) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { DivisionEntry, RankingEntry } from '../../../entity/tabt-soap/TabTAPI_Port'; | ||
import { WinLossSummaryDTOV1 } from './member-dashboard.dto'; | ||
import { ResponseDTO } from './common.dto'; | ||
|
||
export class DivisionMemberDashboardDTOV1 extends WinLossSummaryDTOV1 { | ||
member: { | ||
lastname: string; | ||
firstname: string; | ||
ranking: string; | ||
clubName: string; | ||
}; | ||
} | ||
|
||
export class DivisionDashboardDTOV1 { | ||
division: ResponseDTO<DivisionEntry>; | ||
ranking: ResponseDTO<RankingEntry[]>; | ||
playersStats: ResponseDTO<DivisionMemberDashboardDTOV1[]>; | ||
} |
20 changes: 20 additions & 0 deletions
20
src/api/dashboard/dto/mappers/division-member-dashboard-dto-v1.mapper.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { DivisionMemberDashboardDTOV1 } from '../division-dashboard.dto'; | ||
import { MemberResults } from '../../../../common/dto/member-ranking.dto'; | ||
|
||
export class DivisionMemberDashboardDTOV1Mapper { | ||
static mapMemberResults(memberResult: MemberResults): DivisionMemberDashboardDTOV1{ | ||
return { | ||
member:{ | ||
lastname: memberResult.lastName, | ||
firstname: memberResult.firstName, | ||
ranking: memberResult.ranking, | ||
clubName: '' | ||
}, | ||
count: memberResult.played, | ||
victories: memberResult.win, | ||
defeats: memberResult.lose, | ||
victoriesPct: memberResult.winPourcentage, | ||
defeatsPct: memberResult.losePourcentage, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { ApiPropertyOptional } from '@nestjs/swagger'; | ||
import { MemberEntry, MemberEntryResultEntry, TeamMatchesEntry } from '../../../entity/tabt-soap/TabTAPI_Port'; | ||
import { PLAYER_CATEGORY, WeeklyNumericRankingV3 } from '../../member/dto/member.dto'; | ||
import { IsEnum } from 'class-validator'; | ||
import { ResponseDTO } from './common.dto'; | ||
|
||
|
||
export class MemberDashboardDTOV1 { | ||
constructor( | ||
public member: ResponseDTO<MemberEntry>, | ||
public numericRankingResponse: ResponseDTO<WeeklyNumericRankingV3>, | ||
public latestTeamMatches: ResponseDTO<TeamMatchesEntry[]>, | ||
public stats: ResponseDTO<MemberStatsDTOV1>, | ||
) { | ||
} | ||
} | ||
|
||
export class MemberStatsDTOV1 { | ||
tieBreaks: WinLossSummaryDTOV1; | ||
matches: WinLossSummaryDTOV1; | ||
perRanking: RankingWinLossDTOV1[]; | ||
} | ||
|
||
export class WinLossSummaryDTOV1 { | ||
count: number; | ||
victories?: number; | ||
defeats?: number; | ||
victoriesPct?: number; | ||
defeatsPct?: number; | ||
} | ||
|
||
export class RankingWinLossDTOV1 extends WinLossSummaryDTOV1 { | ||
ranking: string; | ||
players: MemberEntryResultEntry[] | ||
} | ||
|
||
export class WeeklyNumericRankingInputV2 { | ||
@ApiPropertyOptional({ enum: PLAYER_CATEGORY}) | ||
@IsEnum(PLAYER_CATEGORY) | ||
category?: PLAYER_CATEGORY; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export interface DashboardServiceInterface<T> { | ||
getDashboard(...args: any[]): Promise<T>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { Injectable, NotFoundException } from '@nestjs/common'; | ||
import { ClubService } from '../../../services/clubs/club.service'; | ||
import { DashboardServiceInterface } from '../interfaces/dashboard-service.interface'; | ||
import { DivisionMemberDashboardDTOV1 } from '../dto/division-dashboard.dto'; | ||
import { MatchesMembersRankerService } from '../../../services/matches/matches-members-ranker.service'; | ||
import { DivisionMemberDashboardDTOV1Mapper } from '../dto/mappers/division-member-dashboard-dto-v1.mapper'; | ||
import { ClubDashboardDTOV1 } from '../dto/club-dashboard.dto'; | ||
import { MemberService } from '../../../services/members/member.service'; | ||
import { MatchService } from '../../../services/matches/match.service'; | ||
import { ClubTeamService } from '../../../services/clubs/club-team.service'; | ||
import { ClubEntry, MemberEntry, TeamEntry, TeamMatchesEntry } from '../../../entity/tabt-soap/TabTAPI_Port'; | ||
import { RESPONSE_STATUS, ResponseDTO } from '../dto/common.dto'; | ||
|
||
@Injectable() | ||
export class ClubDashboardService implements DashboardServiceInterface<ClubDashboardDTOV1> { | ||
|
||
constructor( | ||
private readonly clubService: ClubService, | ||
private readonly matchesMembersRankerService: MatchesMembersRankerService, | ||
private readonly memberService: MemberService, | ||
private readonly matchService: MatchService, | ||
private readonly clubTeamService: ClubTeamService, | ||
) { | ||
} | ||
|
||
async getDashboard(clubUniqueIndex: string): Promise<ClubDashboardDTOV1> { | ||
const club = await this.getClub(clubUniqueIndex); | ||
if (!club.payload) { | ||
return { | ||
club: new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, 'No club found for given id'), | ||
members: new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, 'No club found for given id'), | ||
teams: new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, 'No club found for given id'), | ||
matches: new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, 'No club found for given id'), | ||
} | ||
} | ||
|
||
|
||
const [members, teams, matches] = await Promise.all([ | ||
this.getClubMembers(clubUniqueIndex), | ||
this.getClubTeams(clubUniqueIndex), | ||
this.getClubMatchesGrouped(clubUniqueIndex), | ||
]); | ||
|
||
|
||
return { | ||
club, | ||
members, | ||
teams, | ||
matches, | ||
}; | ||
} | ||
|
||
async getPlayersStats(divisionId: number): Promise<DivisionMemberDashboardDTOV1[]> { | ||
const results = await this.matchesMembersRankerService.getMembersRankingFromDivision(divisionId); | ||
// map the results to the DTO | ||
return results.map(DivisionMemberDashboardDTOV1Mapper.mapMemberResults); | ||
}; | ||
|
||
private async getClubsMembers(clubUniqueIndex: string): Promise<ResponseDTO<MemberEntry[]>> { | ||
try { | ||
const members = await this.memberService.getMembers({ Club: clubUniqueIndex }); | ||
return new ResponseDTO(RESPONSE_STATUS.SUCCESS, members); | ||
} catch (error) { | ||
return new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, error.message); | ||
} | ||
} | ||
|
||
private async getClub(clubUniqueIndex: string): Promise<ResponseDTO<ClubEntry>> { | ||
try { | ||
const clubs = await this.clubService.getClubs({ Club: clubUniqueIndex }); | ||
if(!clubs?.[0]) { | ||
return new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, 'No club found for given id'); | ||
} | ||
return new ResponseDTO(RESPONSE_STATUS.SUCCESS, clubs[0]); | ||
} catch (error) { | ||
return new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, error.message); | ||
} | ||
} | ||
|
||
private async getClubMembers(clubUniqueIndex: string): Promise<ResponseDTO<MemberEntry[]>> { | ||
try { | ||
const members = await this.memberService.getMembers({ Club: clubUniqueIndex }); | ||
return new ResponseDTO(RESPONSE_STATUS.SUCCESS, members); | ||
} catch (error) { | ||
return new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, error.message); | ||
} | ||
} | ||
|
||
private async getClubTeams(clubUniqueIndex: string): Promise<ResponseDTO<TeamEntry[]>> { | ||
try { | ||
const teams = await this.clubTeamService.getClubsTeams({ Club: clubUniqueIndex }); | ||
return new ResponseDTO(RESPONSE_STATUS.SUCCESS, teams); | ||
} catch (error) { | ||
return new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, error.message); | ||
} | ||
} | ||
|
||
|
||
private async getClubMatchesGrouped(clubUniqueIndex: string): Promise<ResponseDTO<{ [weekname: number]: TeamMatchesEntry[] }>> { | ||
try { | ||
const matches = await this.matchService.getMatches({ Club: clubUniqueIndex }); | ||
const reduced = matches.reduce<{ [weekName: number]: TeamMatchesEntry[] }>((acc, currentValue) => { | ||
const weekName = Number(currentValue.WeekName); | ||
if (acc[weekName]) { | ||
acc[weekName].push(currentValue); | ||
} else { | ||
acc[weekName] = [currentValue]; | ||
} | ||
return acc; | ||
}, {}); | ||
return new ResponseDTO(RESPONSE_STATUS.SUCCESS, reduced); | ||
} catch (error) { | ||
return new ResponseDTO(RESPONSE_STATUS.ERROR, undefined, error.message | ||
|
||
) | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.