From 9c13a57804430d518546199f5fb3d9f342582edc Mon Sep 17 00:00:00 2001 From: Andres Date: Sun, 16 Jul 2023 23:23:46 +0200 Subject: [PATCH] add decks documentation --- .../common/pagination/pagination.dto.ts | 7 + src/main.ts | 2 +- src/modules/auth/auth.controller.ts | 30 ++-- src/modules/auth/dto/index.ts | 1 + src/modules/auth/dto/save-grade.dto.ts | 4 + src/modules/cards/entities/cards.entity.ts | 21 ++- .../cards/infrastructure/cards.repository.ts | 3 +- src/modules/decks/decks.controller.ts | 141 ++++++++++++------ src/modules/decks/dto/create-deck.dto.ts | 11 +- src/modules/decks/dto/get-all-decks.dto.ts | 11 +- src/modules/decks/dto/update-deck.dto.ts | 8 +- src/modules/decks/entities/deck.entity.ts | 27 +++- .../decks/infrastructure/decks.repository.ts | 25 +++- .../decks/use-cases/create-card-use-case.ts | 3 +- .../decks/use-cases/create-deck-use-case.ts | 3 +- .../use-cases/delete-deck-by-id-use-case.ts | 4 +- .../get-all-cards-in-deck-use-case.ts | 3 +- .../decks/use-cases/get-all-decks-use-case.ts | 3 +- .../get-random-card-in-deck-use-case.ts | 3 +- .../decks/use-cases/save-grade-use-case.ts | 4 +- .../decks/use-cases/update-deck-use-case.ts | 3 +- 21 files changed, 239 insertions(+), 78 deletions(-) create mode 100644 src/modules/auth/dto/save-grade.dto.ts diff --git a/src/infrastructure/common/pagination/pagination.dto.ts b/src/infrastructure/common/pagination/pagination.dto.ts index 5662d37..11b713e 100644 --- a/src/infrastructure/common/pagination/pagination.dto.ts +++ b/src/infrastructure/common/pagination/pagination.dto.ts @@ -12,3 +12,10 @@ export class PaginationDto { @IsNumber() itemsPerPage?: number } + +export class Pagination { + currentPage: number + itemsPerPage: number + totalPages: number + totalItems: number +} diff --git a/src/main.ts b/src/main.ts index cc6fca2..f9d8d1c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,7 +19,7 @@ async function bootstrap() { app.setGlobalPrefix('v1') const config = new DocumentBuilder() .setTitle('Flashcards') - .setDescription('The config API description') + .setDescription('Flashcards API') .setVersion('1.0') .addTag('Auth') .addTag('Decks') diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 12c8a00..48a27cc 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -52,7 +52,7 @@ import { export class AuthController { constructor(private commandBus: CommandBus) {} - @ApiOperation({ description: 'Retrieve current user data.' }) + @ApiOperation({ description: 'Retrieve current user data.', summary: 'Current user data' }) @ApiUnauthorizedResponse({ description: 'Not logged in' }) @ApiBadRequestResponse({ description: 'User not found' }) @UseGuards(JwtAuthGuard) @@ -63,7 +63,10 @@ export class AuthController { return await this.commandBus.execute(new GetCurrentUserDataCommand(userId)) } - @ApiOperation({ description: 'Sign in using email and password. Must have an account to do so.' }) + @ApiOperation({ + description: 'Sign in using email and password. Must have an account to do so.', + summary: 'Sign in using email and password. Must have an account to do so.', + }) @ApiUnauthorizedResponse({ description: 'Invalid credentials' }) @ApiBody({ type: LoginDto }) @HttpCode(HttpStatus.OK) @@ -90,7 +93,7 @@ export class AuthController { return { accessToken: req.user.data.accessToken } } - @ApiOperation({ description: 'Create a new user account' }) + @ApiOperation({ description: 'Create a new user account', summary: 'Create a new user account' }) @ApiBadRequestResponse({ description: 'Email already exists' }) @HttpCode(HttpStatus.CREATED) @Post('sign-up') @@ -98,7 +101,7 @@ export class AuthController { return await this.commandBus.execute(new CreateUserCommand(registrationData)) } - @ApiOperation({ description: 'Verify user email' }) + @ApiOperation({ description: 'Verify user email', summary: 'Verify user email' }) @ApiBadRequestResponse({ description: 'Email has already been verified' }) @ApiNotFoundResponse({ description: 'User not found' }) @ApiNoContentResponse({ description: 'Email verified successfully' }) @@ -108,7 +111,10 @@ export class AuthController { return await this.commandBus.execute(new VerifyEmailCommand(body.code)) } - @ApiOperation({ description: 'Send verification email again' }) + @ApiOperation({ + description: 'Send verification email again', + summary: 'Send verification email again', + }) @ApiBadRequestResponse({ description: 'Email has already been verified' }) @ApiNotFoundResponse({ description: 'User not found' }) @ApiNoContentResponse({ description: 'Verification email sent successfully' }) @@ -118,7 +124,7 @@ export class AuthController { return await this.commandBus.execute(new ResendVerificationEmailCommand(body.userId)) } - @ApiOperation({ description: 'Sign current user out' }) + @ApiOperation({ description: 'Sign current user out', summary: 'Sign current user out' }) @ApiUnauthorizedResponse({ description: 'Not logged in' }) @ApiNoContentResponse({ description: 'Logged out successfully' }) @HttpCode(HttpStatus.NO_CONTENT) @@ -136,7 +142,10 @@ export class AuthController { return null } - @ApiOperation({ description: 'Get new access token using refresh token' }) + @ApiOperation({ + description: 'Get new access token using refresh token', + summary: 'Get new access token using refresh token', + }) @ApiUnauthorizedResponse({ description: 'Invalid or missing refreshToken' }) @ApiNoContentResponse({ description: 'New tokens generated successfully' }) @HttpCode(HttpStatus.NO_CONTENT) @@ -165,7 +174,10 @@ export class AuthController { return null } - @ApiOperation({ description: 'Send password recovery email' }) + @ApiOperation({ + description: 'Send password recovery email', + summary: 'Send password recovery email', + }) @ApiBadRequestResponse({ description: 'Email has already been verified' }) @ApiNotFoundResponse({ description: 'User not found' }) @ApiNoContentResponse({ description: 'Password recovery email sent successfully' }) @@ -175,7 +187,7 @@ export class AuthController { return await this.commandBus.execute(new SendPasswordRecoveryEmailCommand(body.email)) } - @ApiOperation({ description: 'Reset password' }) + @ApiOperation({ description: 'Reset password', summary: 'Reset password' }) @ApiBadRequestResponse({ description: 'Password is required' }) @ApiNotFoundResponse({ description: 'Incorrect or expired password reset token' }) @ApiNoContentResponse({ description: 'Password reset successfully' }) diff --git a/src/modules/auth/dto/index.ts b/src/modules/auth/dto/index.ts index ba59596..af8790b 100644 --- a/src/modules/auth/dto/index.ts +++ b/src/modules/auth/dto/index.ts @@ -3,4 +3,5 @@ export * from './login.dto' export * from './recover-password.dto' export * from './registration.dto' export * from './resend-verification-email.dto' +export * from './save-grade.dto' export * from './update-auth.dto' diff --git a/src/modules/auth/dto/save-grade.dto.ts b/src/modules/auth/dto/save-grade.dto.ts new file mode 100644 index 0000000..de1bf03 --- /dev/null +++ b/src/modules/auth/dto/save-grade.dto.ts @@ -0,0 +1,4 @@ +export class SaveGradeDto { + cardId: string + grade: number +} diff --git a/src/modules/cards/entities/cards.entity.ts b/src/modules/cards/entities/cards.entity.ts index 4c092d2..012d5de 100644 --- a/src/modules/cards/entities/cards.entity.ts +++ b/src/modules/cards/entities/cards.entity.ts @@ -1 +1,20 @@ -export class Card {} +import { Pagination } from '../../../infrastructure/common/pagination/pagination.dto' + +export class Card { + id: string + deckId: string + userId: string + question: string + answer: string + shots: number + answerImg: string + questionImg: string + rating: number + created: Date + updated: Date +} + +export class PaginatedCards { + items: Card[] + pagination: Pagination +} diff --git a/src/modules/cards/infrastructure/cards.repository.ts b/src/modules/cards/infrastructure/cards.repository.ts index baa6ab7..f17b452 100644 --- a/src/modules/cards/infrastructure/cards.repository.ts +++ b/src/modules/cards/infrastructure/cards.repository.ts @@ -4,6 +4,7 @@ import { createPrismaOrderBy } from '../../../infrastructure/common/helpers/get- import { Pagination } from '../../../infrastructure/common/pagination/pagination.service' import { PrismaService } from '../../../prisma.service' import { CreateCardDto, GetAllCardsInDeckDto, UpdateCardDto } from '../dto' +import { PaginatedCards } from '../entities/cards.entity' @Injectable() export class CardsRepository { @@ -59,7 +60,7 @@ export class CardsRepository { itemsPerPage, orderBy, }: GetAllCardsInDeckDto - ) { + ): Promise { try { const where = { decks: { diff --git a/src/modules/decks/decks.controller.ts b/src/modules/decks/decks.controller.ts index c1e3a64..3ae8de4 100644 --- a/src/modules/decks/decks.controller.ts +++ b/src/modules/decks/decks.controller.ts @@ -3,6 +3,8 @@ import { Controller, Delete, Get, + HttpCode, + HttpStatus, Param, Patch, Post, @@ -15,14 +17,25 @@ import { } from '@nestjs/common' import { CommandBus } from '@nestjs/cqrs' import { FileFieldsInterceptor } from '@nestjs/platform-express' -import { ApiTags } from '@nestjs/swagger' +import { + ApiConsumes, + ApiNoContentResponse, + ApiNotFoundResponse, + ApiOkResponse, + ApiOperation, + ApiTags, + ApiUnauthorizedResponse, +} from '@nestjs/swagger' import { Pagination } from '../../infrastructure/common/pagination/pagination.service' +import { SaveGradeDto } from '../auth/dto' import { JwtAuthGuard } from '../auth/guards' import { CreateCardDto, GetAllCardsInDeckDto } from '../cards/dto' +import { Card, PaginatedCards } from '../cards/entities/cards.entity' import { DecksService } from './decks.service' import { UpdateDeckDto, CreateDeckDto, GetAllDecksDto } from './dto' +import { Deck, PaginatedDecks } from './entities/deck.entity' import { CreateDeckCommand, DeleteDeckByIdCommand, @@ -40,6 +53,20 @@ import { export class DecksController { constructor(private readonly decksService: DecksService, private commandBus: CommandBus) {} + @HttpCode(HttpStatus.PARTIAL_CONTENT) + @ApiOperation({ description: 'Retrieve paginated decks list.', summary: 'Paginated decks list' }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) + @UseGuards(JwtAuthGuard) + @Get() + findAll(@Query() query: GetAllDecksDto, @Req() req): Promise { + const finalQuery = Pagination.getPaginationData(query) + + return this.commandBus.execute(new GetAllDecksCommand({ ...finalQuery, userId: req.user.id })) + } + + @ApiConsumes('multipart/form-data') + @ApiOperation({ description: 'Create a deck', summary: 'Create a deck' }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) @UseGuards(JwtAuthGuard) @UseInterceptors(FileFieldsInterceptor([{ name: 'cover', maxCount: 1 }])) @Post() @@ -50,7 +77,7 @@ export class DecksController { cover: Express.Multer.File[] }, @Body() createDeckDto: CreateDeckDto - ) { + ): Promise { const userId = req.user.id return this.commandBus.execute( @@ -58,42 +85,64 @@ export class DecksController { ) } - @UseGuards(JwtAuthGuard) - @Get() - findAll(@Query() query: GetAllDecksDto, @Req() req) { - const finalQuery = Pagination.getPaginationData(query) - - return this.commandBus.execute(new GetAllDecksCommand({ ...finalQuery, userId: req.user.id })) - } - + @ApiOperation({ description: 'Retrieve a deck by id', summary: 'Retrieve a deck by id' }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) @UseGuards(JwtAuthGuard) @Get(':id') - findOne(@Param('id') id: string) { + findOne(@Param('id') id: string): Promise { return this.commandBus.execute(new GetDeckByIdCommand(id)) } + @ApiConsumes('multipart/form-data') + @ApiOperation({ description: 'Update a deck', summary: 'Update a deck' }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) + @ApiNotFoundResponse({ description: 'Deck not found' }) + @UseGuards(JwtAuthGuard) + @UseInterceptors(FileFieldsInterceptor([{ name: 'cover', maxCount: 1 }])) + @Patch(':id') + update( + @Param('id') id: string, + @UploadedFiles() + files: { + cover: Express.Multer.File[] + }, + @Body() updateDeckDto: UpdateDeckDto, + @Req() req + ): Promise { + return this.commandBus.execute( + new UpdateDeckCommand(id, updateDeckDto, req.user.id, files?.cover?.[0]) + ) + } + + @UseGuards(JwtAuthGuard) + @ApiOperation({ description: 'Delete a deck', summary: 'Delete a deck' }) + @ApiOkResponse({ description: 'Deck deleted', type: Deck }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) + @ApiNotFoundResponse({ description: 'Deck not found' }) + @Delete(':id') + remove(@Param('id') id: string, @Req() req): Promise { + return this.commandBus.execute(new DeleteDeckByIdCommand(id, req.user.id)) + } + @ApiOperation({ + description: 'Retrieve paginated cards in a deck', + summary: 'Retrieve cards in a deck', + }) @UseGuards(JwtAuthGuard) @Get(':id/cards') - findCardsInDeck(@Param('id') id: string, @Req() req, @Query() query: GetAllCardsInDeckDto) { + findCardsInDeck( + @Param('id') id: string, + @Req() req, + @Query() query: GetAllCardsInDeckDto + ): Promise { const finalQuery = Pagination.getPaginationData(query) return this.commandBus.execute(new GetAllCardsInDeckCommand(req.user.id, id, finalQuery)) } - @UseGuards(JwtAuthGuard) - @Get(':id/learn') - findRandomCardInDeck(@Param('id') id: string, @Req() req) { - return this.commandBus.execute(new GetRandomCardInDeckCommand(req.user.id, id)) - } - - @UseGuards(JwtAuthGuard) - @Post(':id/learn') - saveGrade(@Param('id') id: string, @Req() req, @Body() body: any) { - return this.commandBus.execute( - new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade }) - ) - } - + @ApiConsumes('multipart/form-data') + @ApiOperation({ description: 'Create card in a deck', summary: 'Create a card' }) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) + @ApiNotFoundResponse({ description: 'Deck not found' }) @UseGuards(JwtAuthGuard) @UseInterceptors( FileFieldsInterceptor([ @@ -108,32 +157,36 @@ export class DecksController { @UploadedFiles() files: { questionImg: Express.Multer.File[]; answerImg: Express.Multer.File[] }, @Body() card: CreateCardDto - ) { + ): Promise { return this.commandBus.execute( new CreateCardCommand(req.user.id, id, card, files.answerImg?.[0], files.questionImg?.[0]) ) } + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) @UseGuards(JwtAuthGuard) - @UseInterceptors(FileFieldsInterceptor([{ name: 'cover', maxCount: 1 }])) - @Patch(':id') - update( - @Param('id') id: string, - @UploadedFiles() - files: { - cover: Express.Multer.File[] - }, - @Body() updateDeckDto: UpdateDeckDto, - @Req() req - ) { - return this.commandBus.execute( - new UpdateDeckCommand(id, updateDeckDto, req.user.id, files?.cover?.[0]) - ) + @ApiOperation({ + description: 'Retrieve a random card in a deck. The cards priority is based on the grade', + summary: 'Retrieve a random card', + }) + @Get(':id/learn') + findRandomCardInDeck(@Param('id') id: string, @Req() req): Promise { + return this.commandBus.execute(new GetRandomCardInDeckCommand(req.user.id, id)) } @UseGuards(JwtAuthGuard) - @Delete(':id') - remove(@Param('id') id: string, @Req() req) { - return this.commandBus.execute(new DeleteDeckByIdCommand(id, req.user.id)) + @ApiUnauthorizedResponse({ description: 'Unauthorized' }) + @ApiNotFoundResponse({ description: 'Card not found' }) + @HttpCode(HttpStatus.NO_CONTENT) + @ApiNoContentResponse({ description: 'Grade saved' }) + @Post(':id/learn') + @ApiOperation({ + description: 'Save the grade of a card', + summary: 'Save the grade of a card', + }) + saveGrade(@Param('id') id: string, @Req() req, @Body() body: SaveGradeDto): Promise { + return this.commandBus.execute( + new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade }) + ) } } diff --git a/src/modules/decks/dto/create-deck.dto.ts b/src/modules/decks/dto/create-deck.dto.ts index 9271392..97904d9 100644 --- a/src/modules/decks/dto/create-deck.dto.ts +++ b/src/modules/decks/dto/create-deck.dto.ts @@ -1,18 +1,25 @@ +import { ApiHideProperty, ApiProperty } from '@nestjs/swagger' import { Transform } from 'class-transformer' import { IsBoolean, IsOptional, Length } from 'class-validator' export class CreateDeckDto { @Length(3, 30) name: string - + /** + * Cover image (binary) + */ @IsOptional() - @Length(0, 0) + @ApiProperty({ type: 'string', format: 'binary' }) cover?: string + /** + * Private decks are not visible to other users + */ @IsOptional() @IsBoolean() @Transform((val: string) => [true, 'true', 1, '1'].indexOf(val) > -1) isPrivate?: boolean + @ApiHideProperty() userId: string } diff --git a/src/modules/decks/dto/get-all-decks.dto.ts b/src/modules/decks/dto/get-all-decks.dto.ts index 9d800e1..9b8282d 100644 --- a/src/modules/decks/dto/get-all-decks.dto.ts +++ b/src/modules/decks/dto/get-all-decks.dto.ts @@ -1,3 +1,4 @@ +import { ApiHideProperty } from '@nestjs/swagger' import { IsUUID } from 'class-validator' import { PaginationDto } from '../../../infrastructure/common/pagination/pagination.dto' @@ -10,15 +11,23 @@ export class GetAllDecksDto extends PaginationDto { @IsOptionalOrEmptyString() maxCardsCount?: string + /** Search by deck name */ @IsOptionalOrEmptyString() name?: string + /** Filter by deck authorId */ @IsOptionalOrEmptyString() @IsUUID(4) authorId?: string - userId: string + @ApiHideProperty() + userId?: string + /** A string that represents the name of the field to order by and the order direction. + * The format is: "field_name-order_direction". + * Available directions: "asc" and "desc". + * @example "name-desc" + * */ @IsOrderBy() orderBy?: string | null } diff --git a/src/modules/decks/dto/update-deck.dto.ts b/src/modules/decks/dto/update-deck.dto.ts index b708743..6549330 100644 --- a/src/modules/decks/dto/update-deck.dto.ts +++ b/src/modules/decks/dto/update-deck.dto.ts @@ -1,4 +1,5 @@ import { PartialType } from '@nestjs/mapped-types' +import { ApiProperty } from '@nestjs/swagger' import { IsBoolean } from 'class-validator' import { IsOptionalOrEmptyString } from '../../../infrastructure/decorators' @@ -7,12 +8,13 @@ import { CreateDeckDto } from './create-deck.dto' export class UpdateDeckDto extends PartialType(CreateDeckDto) { @IsOptionalOrEmptyString() - name: string + name?: string @IsOptionalOrEmptyString() @IsBoolean() - isPrivate: boolean + isPrivate?: boolean @IsOptionalOrEmptyString() - cover: string + @ApiProperty({ type: 'string', format: 'binary' }) + cover?: string } diff --git a/src/modules/decks/entities/deck.entity.ts b/src/modules/decks/entities/deck.entity.ts index 1414ccc..b40feb3 100644 --- a/src/modules/decks/entities/deck.entity.ts +++ b/src/modules/decks/entities/deck.entity.ts @@ -1 +1,26 @@ -export class Deck {} +import { Pagination } from '../../../infrastructure/common/pagination/pagination.dto' + +export class Deck { + id: string + userId: string + name: string + isPrivate: boolean + shots: number + cover: string | null + rating: number + created: Date + updated: Date + cardsCount: number + author: DeckAuthor +} + +export class DeckAuthor { + id: string + name: string +} + +export class PaginatedDecks { + items: Deck[] + pagination: Pagination + maxCardsCount: number +} diff --git a/src/modules/decks/infrastructure/decks.repository.ts b/src/modules/decks/infrastructure/decks.repository.ts index 08a304a..9b14dcf 100644 --- a/src/modules/decks/infrastructure/decks.repository.ts +++ b/src/modules/decks/infrastructure/decks.repository.ts @@ -4,6 +4,7 @@ import { createPrismaOrderBy } from '../../../infrastructure/common/helpers/get- import { Pagination } from '../../../infrastructure/common/pagination/pagination.service' import { PrismaService } from '../../../prisma.service' import { GetAllDecksDto } from '../dto' +import { Deck, PaginatedDecks } from '../entities/deck.entity' @Injectable() export class DecksRepository { @@ -21,7 +22,7 @@ export class DecksRepository { userId: string cover?: string isPrivate?: boolean - }) { + }): Promise { try { return await this.prisma.deck.create({ data: { @@ -35,6 +36,14 @@ export class DecksRepository { cover, isPrivate, }, + include: { + author: { + select: { + id: true, + name: true, + }, + }, + }, }) } catch (e) { this.logger.error(e?.message) @@ -51,9 +60,7 @@ export class DecksRepository { minCardsCount, maxCardsCount, orderBy, - }: GetAllDecksDto) { - console.log(minCardsCount) - console.log(Number(minCardsCount)) + }: GetAllDecksDto): Promise { try { const where = { cardsCount: { @@ -163,13 +170,21 @@ export class DecksRepository { public async updateDeckById( id: string, data: { name?: string; cover?: string; isPrivate?: boolean } - ) { + ): Promise { try { return await this.prisma.deck.update({ where: { id, }, data, + include: { + author: { + select: { + id: true, + name: true, + }, + }, + }, }) } catch (e) { this.logger.error(e?.message) diff --git a/src/modules/decks/use-cases/create-card-use-case.ts b/src/modules/decks/use-cases/create-card-use-case.ts index 08ac692..9626c46 100644 --- a/src/modules/decks/use-cases/create-card-use-case.ts +++ b/src/modules/decks/use-cases/create-card-use-case.ts @@ -2,6 +2,7 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { FileUploadService } from '../../../infrastructure/file-upload-service/file-upload.service' import { CreateCardDto } from '../../cards/dto' +import { Card } from '../../cards/entities/cards.entity' import { CardsRepository } from '../../cards/infrastructure/cards.repository' export class CreateCardCommand { @@ -21,7 +22,7 @@ export class CreateCardHandler implements ICommandHandler { private readonly fileUploadService: FileUploadService ) {} - async execute(command: CreateCardCommand) { + async execute(command: CreateCardCommand): Promise { let questionImg, answerImg if (command.questionImg && command.answerImg) { diff --git a/src/modules/decks/use-cases/create-deck-use-case.ts b/src/modules/decks/use-cases/create-deck-use-case.ts index 2d30bb0..53823be 100644 --- a/src/modules/decks/use-cases/create-deck-use-case.ts +++ b/src/modules/decks/use-cases/create-deck-use-case.ts @@ -2,6 +2,7 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { FileUploadService } from '../../../infrastructure/file-upload-service/file-upload.service' import { CreateDeckDto } from '../dto' +import { Deck } from '../entities/deck.entity' import { DecksRepository } from '../infrastructure/decks.repository' export class CreateDeckCommand { @@ -15,7 +16,7 @@ export class CreateDeckHandler implements ICommandHandler { private readonly fileUploadService: FileUploadService ) {} - async execute(command: CreateDeckCommand) { + async execute(command: CreateDeckCommand): Promise { let cover if (command.cover) { diff --git a/src/modules/decks/use-cases/delete-deck-by-id-use-case.ts b/src/modules/decks/use-cases/delete-deck-by-id-use-case.ts index 262a965..57f4714 100644 --- a/src/modules/decks/use-cases/delete-deck-by-id-use-case.ts +++ b/src/modules/decks/use-cases/delete-deck-by-id-use-case.ts @@ -1,4 +1,4 @@ -import { BadRequestException, NotFoundException } from '@nestjs/common' +import { ForbiddenException, NotFoundException } from '@nestjs/common' import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { DecksRepository } from '../infrastructure/decks.repository' @@ -16,7 +16,7 @@ export class DeleteDeckByIdHandler implements ICommandHandler { const deck = await this.decksRepository.findDeckById(command.deckId) if (!deck) throw new NotFoundException(`Deck with id ${command.deckId} not found`) diff --git a/src/modules/decks/use-cases/get-all-decks-use-case.ts b/src/modules/decks/use-cases/get-all-decks-use-case.ts index 1109944..abcb07a 100644 --- a/src/modules/decks/use-cases/get-all-decks-use-case.ts +++ b/src/modules/decks/use-cases/get-all-decks-use-case.ts @@ -1,6 +1,7 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { GetAllDecksDto } from '../dto' +import { PaginatedDecks } from '../entities/deck.entity' import { DecksRepository } from '../infrastructure/decks.repository' export class GetAllDecksCommand { @@ -11,7 +12,7 @@ export class GetAllDecksCommand { export class GetAllDecksHandler implements ICommandHandler { constructor(private readonly deckRepository: DecksRepository) {} - async execute(command: GetAllDecksCommand) { + async execute(command: GetAllDecksCommand): Promise { return await this.deckRepository.findAllDecks(command.params) } } diff --git a/src/modules/decks/use-cases/get-random-card-in-deck-use-case.ts b/src/modules/decks/use-cases/get-random-card-in-deck-use-case.ts index c0aadd7..4434659 100644 --- a/src/modules/decks/use-cases/get-random-card-in-deck-use-case.ts +++ b/src/modules/decks/use-cases/get-random-card-in-deck-use-case.ts @@ -3,6 +3,7 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { Prisma } from '@prisma/client' import { pick } from 'remeda' +import { Card } from '../../cards/entities/cards.entity' import { CardsRepository } from '../../cards/infrastructure/cards.repository' import { DecksRepository } from '../infrastructure/decks.repository' @@ -19,7 +20,7 @@ export class GetRandomCardInDeckHandler implements ICommandHandler) { + private async getSmartRandomCard(cards: Array): Promise { const selectionPool: Array = [] cards.forEach(card => { diff --git a/src/modules/decks/use-cases/save-grade-use-case.ts b/src/modules/decks/use-cases/save-grade-use-case.ts index a55d31d..abd7b54 100644 --- a/src/modules/decks/use-cases/save-grade-use-case.ts +++ b/src/modules/decks/use-cases/save-grade-use-case.ts @@ -23,7 +23,7 @@ export class SaveGradeHandler implements ICommandHandler { private readonly gradesRepository: GradesRepository ) {} - async execute(command: SaveGradeCommand) { + async execute(command: SaveGradeCommand): Promise { const deck = await this.decksRepository.findDeckByCardId(command.args.cardId) if (!deck) @@ -33,7 +33,7 @@ export class SaveGradeHandler implements ICommandHandler { throw new ForbiddenException(`You can't save cards to a private deck that you don't own`) } - return await this.gradesRepository.createGrade({ + await this.gradesRepository.createGrade({ userId: command.userId, grade: command.args.grade, cardId: command.args.cardId, diff --git a/src/modules/decks/use-cases/update-deck-use-case.ts b/src/modules/decks/use-cases/update-deck-use-case.ts index 669b412..1cc98e7 100644 --- a/src/modules/decks/use-cases/update-deck-use-case.ts +++ b/src/modules/decks/use-cases/update-deck-use-case.ts @@ -3,6 +3,7 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { FileUploadService } from '../../../infrastructure/file-upload-service/file-upload.service' import { UpdateDeckDto } from '../dto' +import { Deck } from '../entities/deck.entity' import { DecksRepository } from '../infrastructure/decks.repository' export class UpdateDeckCommand { @@ -21,7 +22,7 @@ export class UpdateDeckHandler implements ICommandHandler { private readonly fileUploadService: FileUploadService ) {} - async execute(command: UpdateDeckCommand) { + async execute(command: UpdateDeckCommand): Promise { const deck = await this.deckRepository.findDeckById(command.deckId) if (!deck) {