Skip to content

Commit

Permalink
search athletes by name
Browse files Browse the repository at this point in the history
  • Loading branch information
nimarion committed Jun 17, 2024
1 parent ded9396 commit c3171eb
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 4 deletions.
15 changes: 15 additions & 0 deletions src/athletes/athlete.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,18 @@ export class Athlete {
@ApiProperty({ nullable: true, type: Number })
athleteRepresentativeId: number | null;
}

export class AthleteSearchResult {
@ApiProperty()
id: number;
@ApiProperty()
country: string;
@ApiProperty()
firstname: string;
@ApiProperty()
lastname: string;
@ApiProperty({ nullable: true, enum: ['MALE', 'FEMALE'] })
sex: 'MALE' | 'FEMALE' | null;
@ApiProperty({ nullable: true, type: Date })
birthdate: Date | null;
}
16 changes: 15 additions & 1 deletion src/athletes/athlete.query.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import { gql } from 'graphql-request';

const ATHLETE_QUERY = gql`
export const ATHLETE_SEARCH_QUERY = gql`
query SearchCompetitors($name: String) {
searchCompetitors(query: $name) {
aaAthleteId
familyName
givenName
birthDate
disciplines
gender
country
}
}
`;

export const ATHLETE_QUERY = gql`
query Query($id: Int) {
getSingleCompetitor(id: $id) {
basicData {
Expand Down
19 changes: 18 additions & 1 deletion src/athletes/athletes.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@nestjs/common';
import { AthletesService } from './athletes.service';
import { ApiOkResponse, ApiNotFoundResponse, ApiQuery } from '@nestjs/swagger';
import { Athlete, Performance } from './athlete.dto';
import { Athlete, AthleteSearchResult, Performance } from './athlete.dto';
import { ResultsService } from './results/result.service';

@Controller('athletes')
Expand All @@ -18,6 +18,23 @@ export class AthletesController {
private readonly resultsService: ResultsService,
) {}

@Get('/search')
@ApiOkResponse({
type: AthleteSearchResult,
})
async searchAthlete(
@Query('name') name: string,
): Promise<AthleteSearchResult[]> {
if (!name) {
throw new NotFoundException();
}
const athlete = await this.athletesService.searchAthlete(name);
if (!athlete) {
throw new NotFoundException();
}
return athlete;
}

@Get(':id')
@ApiOkResponse({
description: 'Returns the athlete profile',
Expand Down
59 changes: 57 additions & 2 deletions src/athletes/athletes.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
import { GraphQLClient } from 'graphql-request';
import { z } from 'zod';
import * as Sentry from '@sentry/node';
import { Athlete } from './athlete.dto';
import ATHLETE_QUERY from './athlete.query';
import { Athlete, AthleteSearchResult } from './athlete.dto';
import ATHLETE_QUERY, { ATHLETE_SEARCH_QUERY } from './athlete.query';
import { Athlete as AthleteSchema } from './athlete.zod';
import parseVenue from './venue.utils';
import mapDisciplineToCode from 'src/discipline.utils';
Expand All @@ -16,6 +16,61 @@ export class AthletesService {
this.graphQLClient = new GraphQLClient(process.env.STELLATE_ENDPOINT);
}

async searchAthlete(name: string): Promise<AthleteSearchResult[] | null> {
try {
const data = await this.graphQLClient.request(ATHLETE_SEARCH_QUERY, {
name,
});
console.log(data);
const response = z
.object({
searchCompetitors: z.array(
z.object({
aaAthleteId: z.string(),
familyName: z.string(),
givenName: z.string(),
birthDate: z
.string()
.nullable()
.transform((val) => {
if (!val) return null;
const date = new Date(val);
date.setMinutes(date.getMinutes() - date.getTimezoneOffset());
return date;
}),
gender: z.string(),
country: z.string(),
}),
),
})
.parse(data);
if (response.searchCompetitors.length === 0) {
return null;
}
return response.searchCompetitors.map((item) => {
console.log(item.gender, item.gender in ['Men', 'Women']);
const sex =
item.gender === 'Men'
? 'MALE'
: item.gender === 'Women'
? 'FEMALE'
: null;
return {
id: Number(item.aaAthleteId),
country: item.country,
firstname: item.givenName,
lastname: formatLastname(item.familyName),
birthdate: item.birthDate,
sex,
};
});
} catch (error) {
console.error(error);
Sentry.captureException(error);
}
return null;
}

async getAthlete(id: number): Promise<Athlete | null> {
try {
const data = await this.graphQLClient.request(
Expand Down

0 comments on commit c3171eb

Please sign in to comment.