Skip to content

Commit e5d4d1a

Browse files
committed
feat: allow creating one or many participants
1 parent 42b4b88 commit e5d4d1a

File tree

4 files changed

+47
-10
lines changed

4 files changed

+47
-10
lines changed

apps/backend/src/research/participants/participants.controller.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
import { Body, Controller, Delete, Get, Param, Patch, Post } from "@nestjs/common";
22
import { ParticipantsService } from "./participants.service";
3-
import { ApiNotFoundResponse, ApiOperation, ApiTags, ApiUnprocessableEntityResponse } from "@nestjs/swagger";
3+
import {
4+
ApiBody,
5+
ApiExtraModels,
6+
ApiNotFoundResponse,
7+
ApiOperation,
8+
ApiTags,
9+
ApiUnprocessableEntityResponse,
10+
getSchemaPath,
11+
} from "@nestjs/swagger";
412
import { ParticipantCreationDto, ParticipantMutationDto, ParticipantResponseDto } from "./participant.dto";
513
import { ErrorResponseDto } from "../../common/dto/error.dto";
614
import { Roles } from "../../system/users/roles.decorator";
715
import { UserRole } from "../../system/users/user.entity";
816
import { QuestionnairesService } from "../questionnaires/questionnaires.service";
17+
import { OneOrMany } from "../../types";
918

1019
@ApiTags("Participants")
20+
@ApiExtraModels(ParticipantCreationDto)
1121
@Controller("participants")
1222
export class ParticipantsController {
1323
constructor(
@@ -18,7 +28,27 @@ export class ParticipantsController {
1828
@Post()
1929
@ApiOperation({ summary: "Create a participant" })
2030
@ApiUnprocessableEntityResponse({ description: "Unique id constraint violation", type: ErrorResponseDto })
21-
create(@Body() participant: ParticipantCreationDto): Promise<ParticipantResponseDto> {
31+
@ApiBody({
32+
schema: {
33+
oneOf: [
34+
{ $ref: getSchemaPath(ParticipantCreationDto) },
35+
{
36+
type: "array",
37+
items: { $ref: getSchemaPath(ParticipantCreationDto) },
38+
},
39+
],
40+
},
41+
examples: {
42+
single: { value: { id: 1, birthday: "2024-11-01T00:05:02.718Z" } },
43+
multiple: {
44+
value: [
45+
{ id: 1, birthday: "2024-11-01T00:05:02.718Z" },
46+
{ id: 2, birthday: "2024-11-01T00:05:02.718Z" },
47+
],
48+
},
49+
},
50+
})
51+
create(@Body() participant: OneOrMany<ParticipantCreationDto>): Promise<ParticipantResponseDto[]> {
2252
return this.participantService.create(participant);
2353
}
2454

apps/backend/src/research/participants/participants.service.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Injectable, UnprocessableEntityException } from "@nestjs/common";
33
import { EntityManager, EntityRepository, FilterQuery, UniqueConstraintViolationException } from "@mikro-orm/core";
44
import { ParticipantCreationDto, ParticipantMutationDto } from "./participant.dto";
55
import { Participant } from "./participant.entity";
6+
import { OneOrMany } from "../../types";
67

78
@Injectable()
89
export class ParticipantsService {
@@ -12,20 +13,25 @@ export class ParticipantsService {
1213
private readonly em: EntityManager
1314
) {}
1415

15-
async create(participantCreationDto: ParticipantCreationDto) {
16-
const participant = new Participant();
17-
participant.birthday = participantCreationDto.birthday;
16+
async create(participantCreationDto: OneOrMany<ParticipantCreationDto>) {
17+
const participantDtos = Array.isArray(participantCreationDto) ? participantCreationDto : [participantCreationDto];
18+
const participants = participantDtos.map((dto) => {
19+
const participant = new Participant();
20+
participant.id = dto.id;
21+
participant.birthday = dto.birthday;
22+
return participant;
23+
});
1824

1925
try {
20-
await this.em.persist(participant).flush();
26+
await this.em.persist(participants).flush();
2127
} catch (e) {
2228
if (e instanceof UniqueConstraintViolationException) {
2329
throw new UnprocessableEntityException("Participant with this id already exists");
2430
}
2531
throw e;
2632
}
2733

28-
return participant.toObject();
34+
return participants.map((p) => p.toObject());
2935
}
3036

3137
async findAll() {

apps/backend/src/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ declare global {
2626
? T[S]
2727
: never;
2828
}
29+
30+
export type OneOrMany<T> = T | T[];

apps/frontend/src/api.gen.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,6 @@ export interface components {
619619
* @example 2024-11-01T00:05:02.718Z
620620
*/
621621
birthday?: string;
622-
latestQuestionnaire?: components["schemas"]["QuestionnaireListResponseDto"];
623622
};
624623
ParticipantResponseDto: {
625624
/**
@@ -1604,7 +1603,7 @@ export interface operations {
16041603
};
16051604
requestBody: {
16061605
content: {
1607-
"application/json": components["schemas"]["ParticipantCreationDto"];
1606+
"application/json": components["schemas"]["ParticipantCreationDto"] | components["schemas"]["ParticipantCreationDto"][];
16081607
};
16091608
};
16101609
responses: {
@@ -1613,7 +1612,7 @@ export interface operations {
16131612
[name: string]: unknown;
16141613
};
16151614
content: {
1616-
"application/json": components["schemas"]["ParticipantResponseDto"];
1615+
"application/json": components["schemas"]["ParticipantResponseDto"][];
16171616
};
16181617
};
16191618
/** @description Unique id constraint violation */

0 commit comments

Comments
 (0)