fix grade orderby

This commit is contained in:
2023-08-07 16:40:21 +02:00
parent dab78cd2a1
commit 2b7b967382
5 changed files with 95 additions and 38 deletions

View File

@@ -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,
}
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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)
)
}
}

View File

@@ -42,6 +42,7 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
'created',
'updated',
'shots',
'grade',
]
)
),