fix learn endpoint

This commit is contained in:
2023-07-21 16:44:18 +02:00
parent 5fdd8b5bb1
commit a943838622
8 changed files with 72 additions and 9 deletions

View File

@@ -125,9 +125,9 @@ model deck {
model grade { model grade {
id String @id @default(cuid()) id String @id @default(cuid())
deckId String @unique deckId String
cardId String @unique cardId String @unique
userId String @unique userId String
grade Int grade Int
shots Int shots Int
created DateTime @default(now()) created DateTime @default(now())

View File

@@ -159,7 +159,9 @@ export class AuthController {
@Res({ passthrough: true }) res: ExpressResponse @Res({ passthrough: true }) res: ExpressResponse
): Promise<void> { ): Promise<void> {
if (!accessToken) throw new UnauthorizedException() if (!accessToken) throw new UnauthorizedException()
await this.commandBus.execute(new LogoutCommand(accessToken)) await this.commandBus.execute(new LogoutCommand(accessToken))
res.clearCookie('accessToken', { httpOnly: true, sameSite: 'none', secure: true }) res.clearCookie('accessToken', { httpOnly: true, sameSite: 'none', secure: true })
res.clearCookie('refreshToken', { res.clearCookie('refreshToken', {

View File

@@ -1,4 +1,11 @@
import { IsNumber, IsString, Max, Min } from 'class-validator'
export class SaveGradeDto { export class SaveGradeDto {
@IsString()
cardId: string cardId: string
@IsNumber()
@Max(5)
@Min(1)
grade: number grade: number
} }

View File

@@ -9,6 +9,8 @@ export class Card {
shots: number shots: number
answerImg: string answerImg: string
questionImg: string questionImg: string
questionVideo: string
answerVideo: string
rating: number rating: number
created: Date created: Date
updated: Date updated: Date
@@ -18,3 +20,11 @@ export class PaginatedCards {
items: Card[] items: Card[]
pagination: Pagination pagination: Pagination
} }
export class PaginatedCardsWithGrade {
pagination: Pagination
items: CardWithGrade[]
}
export class CardWithGrade extends Card {
grades?: Array<{ grade: number }>
}

View File

@@ -4,7 +4,7 @@ import { createPrismaOrderBy } from '../../../infrastructure/common/helpers/get-
import { Pagination } from '../../../infrastructure/common/pagination/pagination.service' import { Pagination } from '../../../infrastructure/common/pagination/pagination.service'
import { PrismaService } from '../../../prisma.service' import { PrismaService } from '../../../prisma.service'
import { CreateCardDto, GetAllCardsInDeckDto, UpdateCardDto } from '../dto' import { CreateCardDto, GetAllCardsInDeckDto, UpdateCardDto } from '../dto'
import { PaginatedCards } from '../entities/cards.entity' import { PaginatedCardsWithGrade } from '../entities/cards.entity'
@Injectable() @Injectable()
export class CardsRepository { export class CardsRepository {
@@ -53,6 +53,7 @@ export class CardsRepository {
async findCardsByDeckId( async findCardsByDeckId(
deckId: string, deckId: string,
userId: string,
{ {
answer = undefined, answer = undefined,
question = undefined, question = undefined,
@@ -60,7 +61,7 @@ export class CardsRepository {
itemsPerPage, itemsPerPage,
orderBy, orderBy,
}: GetAllCardsInDeckDto }: GetAllCardsInDeckDto
): Promise<PaginatedCards> { ): Promise<PaginatedCardsWithGrade> {
try { try {
const where = { const where = {
decks: { decks: {
@@ -78,6 +79,16 @@ export class CardsRepository {
this.prisma.card.findMany({ this.prisma.card.findMany({
orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' }, orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' },
where, where,
include: {
grades: {
where: {
userId,
},
select: {
grade: true,
},
},
},
skip: (currentPage - 1) * itemsPerPage, skip: (currentPage - 1) * itemsPerPage,
take: itemsPerPage, take: itemsPerPage,
}), }),

View File

@@ -22,9 +22,7 @@ export class GradesRepository {
try { try {
return await this.prisma.grade.upsert({ return await this.prisma.grade.upsert({
where: { where: {
userId,
cardId, cardId,
deckId,
}, },
update: { update: {
grade, grade,

View File

@@ -1,8 +1,9 @@
import { ForbiddenException, NotFoundException } from '@nestjs/common' import { ForbiddenException, NotFoundException } from '@nestjs/common'
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs' import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'
import { omit } from 'remeda'
import { GetAllCardsInDeckDto } from '../../cards/dto' import { GetAllCardsInDeckDto } from '../../cards/dto'
import { PaginatedCards } from '../../cards/entities/cards.entity' import { PaginatedCards, PaginatedCardsWithGrade } from '../../cards/entities/cards.entity'
import { CardsRepository } from '../../cards/infrastructure/cards.repository' import { CardsRepository } from '../../cards/infrastructure/cards.repository'
import { DecksRepository } from '../infrastructure/decks.repository' import { DecksRepository } from '../infrastructure/decks.repository'
@@ -20,6 +21,24 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
private readonly cardsRepository: CardsRepository, private readonly cardsRepository: CardsRepository,
private readonly decksRepository: DecksRepository private readonly decksRepository: DecksRepository
) {} ) {}
private transformGrade(cards: PaginatedCardsWithGrade): PaginatedCards {
return {
...cards,
items: cards.items.map(card => {
if (card.grades.length === 0) return omit({ ...card, grade: 0 }, ['grades'])
const grade = card.grades.reduce((acc, grade) => acc + grade.grade, 0) / card.grades.length
return omit(
{
...card,
grade,
},
['grades']
)
}),
}
}
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)
@@ -29,7 +48,12 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
if (deck.userId !== command.userId && deck.isPrivate) { if (deck.userId !== command.userId && deck.isPrivate) {
throw new ForbiddenException(`You can't get a private deck that you don't own`) throw new ForbiddenException(`You can't get a private deck that you don't own`)
} }
const cards = await this.cardsRepository.findCardsByDeckId(
command.deckId,
command.userId,
command.params
)
return await this.cardsRepository.findCardsByDeckId(command.deckId, command.params) return this.transformGrade(cards)
} }
} }

View File

@@ -56,6 +56,17 @@ export class GetRandomCardInDeckHandler implements ICommandHandler<GetRandomCard
) )
const smartRandomCard = await this.getSmartRandomCard(cards) const smartRandomCard = await this.getSmartRandomCard(cards)
return pick(smartRandomCard, ['id', 'question', 'answer', 'deckId']) return pick(smartRandomCard, [
'id',
'question',
'answer',
'deckId',
'questionImg',
'answerImg',
'questionVideo',
'answerVideo',
'created',
'updated',
])
} }
} }