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'
|
type OrderByDirection = 'asc' | 'desc'
|
||||||
|
|
||||||
export function createPrismaOrderBy(input: string | null) {
|
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') {
|
if (!input || input === 'null') {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
@@ -18,13 +34,14 @@ export function createPrismaOrderBy(input: string | null) {
|
|||||||
const [relation, field] = key.split('.')
|
const [relation, field] = key.split('.')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[relation]: {
|
relation,
|
||||||
[field]: direction,
|
field,
|
||||||
},
|
direction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[key]: direction as OrderByDirection,
|
key,
|
||||||
|
direction: direction as OrderByDirection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PaginatedCards {
|
export class PaginatedCards {
|
||||||
items: Omit<Card, 'userId' | 'rating'>[]
|
items: Array<Omit<Card, 'userId' | 'rating'> & { grade: number }>
|
||||||
pagination: Pagination
|
pagination: Pagination
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common'
|
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 { 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 { PaginatedCardsWithGrade } from '../entities/cards.entity'
|
import { CardWithGrade, PaginatedCardsWithGrade } from '../entities/cards.entity'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CardsRepository {
|
export class CardsRepository {
|
||||||
@@ -74,27 +77,70 @@ export class CardsRepository {
|
|||||||
contains: answer || undefined,
|
contains: answer || undefined,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const result = await this.prisma.$transaction([
|
|
||||||
this.prisma.card.count({ where }),
|
const { key, direction } = getOrderByObject(orderBy)
|
||||||
this.prisma.card.findMany({
|
|
||||||
orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' },
|
if (key === 'grade') {
|
||||||
where,
|
const start = (currentPage - 1) * itemsPerPage
|
||||||
include: {
|
|
||||||
grades: {
|
const sqlQuery = `
|
||||||
where: {
|
SELECT c.*, g.grade as userGrade
|
||||||
userId,
|
FROM card AS c
|
||||||
},
|
LEFT JOIN grade AS g ON c.id = g.cardId AND g.userId = ?
|
||||||
select: {
|
WHERE c.deckId = ? AND
|
||||||
grade: true,
|
(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,
|
||||||
skip: (currentPage - 1) * itemsPerPage,
|
take: itemsPerPage,
|
||||||
take: itemsPerPage,
|
}),
|
||||||
}),
|
])
|
||||||
])
|
|
||||||
|
|
||||||
return Pagination.transformPaginationData(result, { currentPage, itemsPerPage })
|
return Pagination.transformPaginationData(result, { currentPage, itemsPerPage })
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(e?.message)
|
this.logger.error(e?.message)
|
||||||
throw new InternalServerErrorException(e?.message)
|
throw new InternalServerErrorException(e?.message)
|
||||||
|
|||||||
@@ -194,19 +194,12 @@ export class DecksController {
|
|||||||
summary: 'Save the grade of a card',
|
summary: 'Save the grade of a card',
|
||||||
})
|
})
|
||||||
async saveGrade(@Param('id') deckId: string, @Req() req, @Body() body: SaveGradeDto) {
|
async saveGrade(@Param('id') deckId: string, @Req() req, @Body() body: SaveGradeDto) {
|
||||||
const promises = [
|
const saved = await this.commandBus.execute(
|
||||||
this.commandBus.execute(new GetRandomCardInDeckCommand(req.user.id, deckId, body.cardId)),
|
new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade })
|
||||||
this.commandBus.execute(
|
)
|
||||||
new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade })
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
try {
|
return await this.commandBus.execute(
|
||||||
const [card] = await Promise.all(promises)
|
new GetRandomCardInDeckCommand(req.user.id, saved.deckId, saved.id)
|
||||||
|
)
|
||||||
return card
|
|
||||||
} catch (error) {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
|
|||||||
'created',
|
'created',
|
||||||
'updated',
|
'updated',
|
||||||
'shots',
|
'shots',
|
||||||
|
'grade',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user