feat: update docs for favorites

This commit is contained in:
2024-05-30 20:59:27 +02:00
parent aba09f5367
commit 5a1d375ada
11 changed files with 47 additions and 21 deletions

View File

@@ -37,7 +37,12 @@ import { Card, CardWithGrade, PaginatedCardsWithGrade } from '../cards/entities/
import { CreateDeckDto, GetAllDecksDto, UpdateDeckDto } from './dto' import { CreateDeckDto, GetAllDecksDto, UpdateDeckDto } from './dto'
import { GetRandomCardDto } from './dto/get-random-card.dto' import { GetRandomCardDto } from './dto/get-random-card.dto'
import { Deck, PaginatedDecks, PaginatedDecksWithMaxCardsCount } from './entities/deck.entity' import {
Deck,
DeckWithFavorites,
PaginatedDecks,
PaginatedDecksWithMaxCardsCount,
} from './entities/deck.entity'
import { MinMaxCards } from './entities/min-max-cards.entity' import { MinMaxCards } from './entities/min-max-cards.entity'
import { import {
AddDeckToFavoritesCommand, AddDeckToFavoritesCommand,
@@ -130,8 +135,8 @@ export class DecksController {
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@Get(':id') @Get(':id')
@ApiBearerAuth() @ApiBearerAuth()
findOne(@Param('id') id: string): Promise<Deck> { findOne(@Param('id') id: string, @Req() req): Promise<DeckWithFavorites> {
return this.commandBus.execute(new GetDeckByIdCommand(id)) return this.commandBus.execute(new GetDeckByIdCommand(id, req.user.id))
} }
@ApiConsumes('multipart/form-data') @ApiConsumes('multipart/form-data')
@@ -259,7 +264,7 @@ export class DecksController {
description: 'Add deck to favorites', description: 'Add deck to favorites',
summary: 'Add deck to favorites', summary: 'Add deck to favorites',
}) })
async addToFavorites(@Req() req, @Param('id') deckId: string): Promise<CardWithGrade> { async addToFavorites(@Req() req, @Param('id') deckId: string): Promise<void> {
return await this.commandBus.execute(new AddDeckToFavoritesCommand(req.user.id, deckId)) return await this.commandBus.execute(new AddDeckToFavoritesCommand(req.user.id, deckId))
} }
@@ -267,13 +272,13 @@ export class DecksController {
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@ApiUnauthorizedResponse({ description: 'Unauthorized' }) @ApiUnauthorizedResponse({ description: 'Unauthorized' })
@HttpCode(HttpStatus.NO_CONTENT) @HttpCode(HttpStatus.NO_CONTENT)
@ApiNoContentResponse({ description: 'Added to favorites' }) @ApiNoContentResponse({ description: 'Removed from favorites' })
@Delete(':id/favorite') @Delete(':id/favorite')
@ApiOperation({ @ApiOperation({
description: 'Add deck to favorites', description: 'Remove deck from favorites',
summary: 'Add deck to favorites', summary: 'Remove deck from favorites',
}) })
async removeFromFavorites(@Req() req, @Param('id') deckId: string): Promise<CardWithGrade> { async removeFromFavorites(@Req() req, @Param('id') deckId: string): Promise<void> {
return await this.commandBus.execute(new RemoveDeckFromFavoritesCommand(req.user.id, deckId)) return await this.commandBus.execute(new RemoveDeckFromFavoritesCommand(req.user.id, deckId))
} }
} }

View File

@@ -15,18 +15,26 @@ export class DeckWithAuthor extends Deck {
author: DeckAuthor author: DeckAuthor
} }
export class DeckWithAuthorAndFavorites extends DeckWithAuthor {
isFavorite: boolean
}
export class DeckWithFavorites extends Deck {
isFavorite: boolean
}
export class DeckAuthor { export class DeckAuthor {
id: string id: string
name: string name: string
} }
export class PaginatedDecksWithMaxCardsCount { export class PaginatedDecksWithMaxCardsCount {
items: DeckWithAuthor[] items: DeckWithAuthorAndFavorites[]
pagination: Pagination pagination: Pagination
maxCardsCount: number maxCardsCount: number
} }
export class PaginatedDecks { export class PaginatedDecks {
items: DeckWithAuthor[] items: DeckWithAuthorAndFavorites[]
pagination: Pagination pagination: Pagination
} }

View File

@@ -263,7 +263,7 @@ export class DecksRepository {
} }
} }
public async findDeckById(id: string): Promise<Deck> { public async findDeckById(id: string, userId: string): Promise<any> {
try { try {
const result = await this.prisma.deck.findUnique({ const result = await this.prisma.deck.findUnique({
where: { where: {
@@ -275,10 +275,20 @@ export class DecksRepository {
card: true, card: true,
}, },
}, },
favoritedBy: {
where: {
userId,
},
},
}, },
}) })
return omit({ ...result, cardsCount: result._count.card }, ['_count']) const isFavorite = result.favoritedBy.length > 0
return omit({ ...result, cardsCount: result._count.card, isFavorite }, [
'_count',
'favoritedBy',
])
} catch (e) { } catch (e) {
this.logger.error(e?.message) this.logger.error(e?.message)
throw new InternalServerErrorException(e?.message) throw new InternalServerErrorException(e?.message)

View File

@@ -15,7 +15,7 @@ export class AddDeckToFavoritesHandler implements ICommandHandler<AddDeckToFavor
constructor(private readonly decksRepository: DecksRepository) {} constructor(private readonly decksRepository: DecksRepository) {}
async execute(command: AddDeckToFavoritesCommand): Promise<void> { async execute(command: AddDeckToFavoritesCommand): Promise<void> {
const deck = await this.decksRepository.findDeckById(command.deckId) const deck = await this.decksRepository.findDeckById(command.deckId, command.userId)
if (!deck) { if (!deck) {
throw new NotFoundException(`Deck with id ${command.deckId} not found`) throw new NotFoundException(`Deck with id ${command.deckId} not found`)

View File

@@ -28,7 +28,7 @@ export class CreateCardHandler implements ICommandHandler<CreateCardCommand> {
async execute(command: CreateCardCommand): Promise<Card> { async execute(command: CreateCardCommand): Promise<Card> {
let questionImg, answerImg let questionImg, answerImg
const deck = await this.decksRepository.findDeckById(command.deckId) const deck = await this.decksRepository.findDeckById(command.deckId, command.userId)
if (!deck) { if (!deck) {
throw new NotFoundException(`Deck with id ${command.deckId} not found`) throw new NotFoundException(`Deck with id ${command.deckId} not found`)

View File

@@ -15,7 +15,7 @@ export class DeleteDeckByIdHandler implements ICommandHandler<DeleteDeckByIdComm
constructor(private readonly deckRepository: DecksRepository) {} constructor(private readonly deckRepository: DecksRepository) {}
async execute(command: DeleteDeckByIdCommand) { async execute(command: DeleteDeckByIdCommand) {
const deck = await this.deckRepository.findDeckById(command.id) const deck = await this.deckRepository.findDeckById(command.id, command.userId)
if (!deck) throw new NotFoundException(`Deck with id ${command.id} not found`) if (!deck) throw new NotFoundException(`Deck with id ${command.id} not found`)
if (deck.userId !== command.userId) { if (deck.userId !== command.userId) {

View File

@@ -56,7 +56,7 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
} }
async execute(command: GetAllCardsInDeckCommand): Promise<PaginatedCards> { async execute(command: GetAllCardsInDeckCommand): Promise<PaginatedCards> {
const deck = await this.decksRepository.findDeckById(command.deckId) const deck = await this.decksRepository.findDeckById(command.deckId, command.userId)
if (!deck) throw new NotFoundException(`Deck with id ${command.deckId} not found`) if (!deck) throw new NotFoundException(`Deck with id ${command.deckId} not found`)

View File

@@ -3,7 +3,10 @@ import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'
import { DecksRepository } from '../infrastructure/decks.repository' import { DecksRepository } from '../infrastructure/decks.repository'
export class GetDeckByIdCommand { export class GetDeckByIdCommand {
constructor(public readonly id: string) {} constructor(
public readonly id: string,
public readonly userId: string
) {}
} }
@CommandHandler(GetDeckByIdCommand) @CommandHandler(GetDeckByIdCommand)
@@ -11,6 +14,6 @@ export class GetDeckByIdHandler implements ICommandHandler<GetDeckByIdCommand> {
constructor(private readonly deckRepository: DecksRepository) {} constructor(private readonly deckRepository: DecksRepository) {}
async execute(command: GetDeckByIdCommand) { async execute(command: GetDeckByIdCommand) {
return await this.deckRepository.findDeckById(command.id) return await this.deckRepository.findDeckById(command.id, command.userId)
} }
} }

View File

@@ -22,7 +22,7 @@ export class GetRandomCardInDeckHandler implements ICommandHandler<GetRandomCard
) {} ) {}
async execute(command: GetRandomCardInDeckCommand) { async execute(command: GetRandomCardInDeckCommand) {
const deck = await this.decksRepository.findDeckById(command.deckId) const deck = await this.decksRepository.findDeckById(command.deckId, command.userId)
if (!deck) throw new NotFoundException(`Deck with id ${command.deckId} not found`) if (!deck) throw new NotFoundException(`Deck with id ${command.deckId} not found`)

View File

@@ -17,7 +17,7 @@ export class RemoveDeckFromFavoritesHandler
constructor(private readonly decksRepository: DecksRepository) {} constructor(private readonly decksRepository: DecksRepository) {}
async execute(command: RemoveDeckFromFavoritesCommand): Promise<void> { async execute(command: RemoveDeckFromFavoritesCommand): Promise<void> {
const deck = await this.decksRepository.findDeckById(command.deckId) const deck = await this.decksRepository.findDeckById(command.deckId, command.userId)
if (!deck) { if (!deck) {
throw new NotFoundException(`Deck with id ${command.deckId} not found`) throw new NotFoundException(`Deck with id ${command.deckId} not found`)

View File

@@ -23,7 +23,7 @@ export class UpdateDeckHandler implements ICommandHandler<UpdateDeckCommand> {
) {} ) {}
async execute(command: UpdateDeckCommand): Promise<Deck> { async execute(command: UpdateDeckCommand): Promise<Deck> {
const deck = await this.deckRepository.findDeckById(command.deckId) const deck = await this.deckRepository.findDeckById(command.deckId, command.userId)
if (!deck) { if (!deck) {
throw new NotFoundException(`Deck with id ${command.deckId} not found`) throw new NotFoundException(`Deck with id ${command.deckId} not found`)