mirror of
https://github.com/ershisan99/flashcards-api.git
synced 2025-12-16 20:59:26 +00:00
fix learn endpoint
This commit is contained in:
@@ -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())
|
||||||
|
|||||||
@@ -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', {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 }>
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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',
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user