mirror of
https://github.com/ershisan99/flashcards-api.git
synced 2025-12-16 20:59:26 +00:00
fix grade orderby
This commit is contained in:
@@ -1,6 +1,22 @@
|
||||
type OrderByDirection = 'asc' | 'desc'
|
||||
|
||||
export function createPrismaOrderBy(input: string | null) {
|
||||
const { key, direction, relation, field } = getOrderByObject(input)
|
||||
|
||||
if (relation && field) {
|
||||
return {
|
||||
[relation]: {
|
||||
[field]: direction,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[key]: direction as OrderByDirection,
|
||||
}
|
||||
}
|
||||
|
||||
export function getOrderByObject(input: string) {
|
||||
if (!input || input === 'null') {
|
||||
return undefined
|
||||
}
|
||||
@@ -18,13 +34,14 @@ export function createPrismaOrderBy(input: string | null) {
|
||||
const [relation, field] = key.split('.')
|
||||
|
||||
return {
|
||||
[relation]: {
|
||||
[field]: direction,
|
||||
},
|
||||
relation,
|
||||
field,
|
||||
direction,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[key]: direction as OrderByDirection,
|
||||
key,
|
||||
direction: direction as OrderByDirection,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export class Card {
|
||||
}
|
||||
|
||||
export class PaginatedCards {
|
||||
items: Omit<Card, 'userId' | 'rating'>[]
|
||||
items: Array<Omit<Card, 'userId' | 'rating'> & { grade: number }>
|
||||
pagination: Pagination
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common'
|
||||
|
||||
import { createPrismaOrderBy } from '../../../infrastructure/common/helpers/get-order-by-object'
|
||||
import {
|
||||
createPrismaOrderBy,
|
||||
getOrderByObject,
|
||||
} from '../../../infrastructure/common/helpers/get-order-by-object'
|
||||
import { Pagination } from '../../../infrastructure/common/pagination/pagination.service'
|
||||
import { PrismaService } from '../../../prisma.service'
|
||||
import { CreateCardDto, GetAllCardsInDeckDto, UpdateCardDto } from '../dto'
|
||||
import { PaginatedCardsWithGrade } from '../entities/cards.entity'
|
||||
import { CardWithGrade, PaginatedCardsWithGrade } from '../entities/cards.entity'
|
||||
|
||||
@Injectable()
|
||||
export class CardsRepository {
|
||||
@@ -74,27 +77,70 @@ export class CardsRepository {
|
||||
contains: answer || undefined,
|
||||
},
|
||||
}
|
||||
const result = await this.prisma.$transaction([
|
||||
this.prisma.card.count({ where }),
|
||||
this.prisma.card.findMany({
|
||||
orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' },
|
||||
where,
|
||||
include: {
|
||||
grades: {
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
grade: true,
|
||||
|
||||
const { key, direction } = getOrderByObject(orderBy)
|
||||
|
||||
if (key === 'grade') {
|
||||
const start = (currentPage - 1) * itemsPerPage
|
||||
|
||||
const sqlQuery = `
|
||||
SELECT c.*, g.grade as userGrade
|
||||
FROM card AS c
|
||||
LEFT JOIN grade AS g ON c.id = g.cardId AND g.userId = ?
|
||||
WHERE c.deckId = ? AND
|
||||
(c.question LIKE ? OR c.answer LIKE ?)
|
||||
ORDER BY g.grade ${direction}
|
||||
LIMIT ?, ?
|
||||
`
|
||||
|
||||
const cardsRaw = (await this.prisma.$queryRawUnsafe(
|
||||
sqlQuery,
|
||||
userId,
|
||||
deckId,
|
||||
`%${question || ''}%`,
|
||||
`%${answer || ''}%`,
|
||||
start,
|
||||
itemsPerPage
|
||||
)) satisfies Array<any>
|
||||
|
||||
const cards: CardWithGrade[] = cardsRaw.map(({ userGrade, ...card }) => ({
|
||||
...card,
|
||||
grades: [
|
||||
{
|
||||
grade: userGrade,
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
const totalCount = await this.prisma.card.count({ where })
|
||||
|
||||
return Pagination.transformPaginationData([totalCount, cards], {
|
||||
currentPage,
|
||||
itemsPerPage,
|
||||
})
|
||||
} else {
|
||||
const result = await this.prisma.$transaction([
|
||||
this.prisma.card.count({ where }),
|
||||
this.prisma.card.findMany({
|
||||
orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' },
|
||||
where,
|
||||
include: {
|
||||
grades: {
|
||||
where: {
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
grade: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
skip: (currentPage - 1) * itemsPerPage,
|
||||
take: itemsPerPage,
|
||||
}),
|
||||
])
|
||||
skip: (currentPage - 1) * itemsPerPage,
|
||||
take: itemsPerPage,
|
||||
}),
|
||||
])
|
||||
|
||||
return Pagination.transformPaginationData(result, { currentPage, itemsPerPage })
|
||||
return Pagination.transformPaginationData(result, { currentPage, itemsPerPage })
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error(e?.message)
|
||||
throw new InternalServerErrorException(e?.message)
|
||||
|
||||
@@ -194,19 +194,12 @@ export class DecksController {
|
||||
summary: 'Save the grade of a card',
|
||||
})
|
||||
async saveGrade(@Param('id') deckId: string, @Req() req, @Body() body: SaveGradeDto) {
|
||||
const promises = [
|
||||
this.commandBus.execute(new GetRandomCardInDeckCommand(req.user.id, deckId, body.cardId)),
|
||||
this.commandBus.execute(
|
||||
new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade })
|
||||
),
|
||||
]
|
||||
const saved = await this.commandBus.execute(
|
||||
new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade })
|
||||
)
|
||||
|
||||
try {
|
||||
const [card] = await Promise.all(promises)
|
||||
|
||||
return card
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
return await this.commandBus.execute(
|
||||
new GetRandomCardInDeckCommand(req.user.id, saved.deckId, saved.id)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
|
||||
'created',
|
||||
'updated',
|
||||
'shots',
|
||||
'grade',
|
||||
]
|
||||
)
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user