mirror of
https://github.com/ershisan99/flashcards-api.git
synced 2025-12-16 20:59:26 +00:00
fix: count attempts per user instead of globally
This commit is contained in:
@@ -45,6 +45,7 @@ model user {
|
|||||||
RefreshToken refreshToken[]
|
RefreshToken refreshToken[]
|
||||||
resetPassword resetPassword?
|
resetPassword resetPassword?
|
||||||
favoriteDecks favoriteDeck[]
|
favoriteDecks favoriteDeck[]
|
||||||
|
attempts cardAttempt[]
|
||||||
|
|
||||||
@@index([email])
|
@@index([email])
|
||||||
@@index([id])
|
@@index([id])
|
||||||
@@ -101,6 +102,7 @@ model card {
|
|||||||
author user @relation(fields: [userId], references: [id], onDelete: Cascade)
|
author user @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
decks deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
|
decks deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
|
||||||
grades grade[]
|
grades grade[]
|
||||||
|
attempts cardAttempt[]
|
||||||
|
|
||||||
@@index([userId])
|
@@index([userId])
|
||||||
@@index([deckId])
|
@@index([deckId])
|
||||||
@@ -175,3 +177,17 @@ model favoriteDeck {
|
|||||||
@@index([userId])
|
@@index([userId])
|
||||||
@@index([deckId])
|
@@index([deckId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model cardAttempt {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
userId String
|
||||||
|
cardId String
|
||||||
|
attemptCount Int @default(1)
|
||||||
|
lastAttempt DateTime @default(now())
|
||||||
|
user user @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
card card @relation(fields: [cardId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@unique([userId, cardId])
|
||||||
|
@@index([userId])
|
||||||
|
@@index([cardId])
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,9 +97,10 @@ export class CardsRepository {
|
|||||||
const whereClause = whereParts.join(' OR ')
|
const whereClause = whereParts.join(' OR ')
|
||||||
|
|
||||||
const sqlQuery = `
|
const sqlQuery = `
|
||||||
SELECT c.*, g.grade as "userGrade"
|
SELECT c.*, g.grade as "userGrade", COALESCE(a."attemptCount", 0) as "totalAttempts"
|
||||||
FROM flashcards.card AS c
|
FROM flashcards.card AS c
|
||||||
LEFT JOIN flashcards.grade AS g ON c.id = g."cardId" AND g."userId" = $1
|
LEFT JOIN flashcards.grade AS g ON c.id = g."cardId" AND g."userId" = $1
|
||||||
|
LEFT JOIN flashcards.cardAttempt AS a ON c.id = a."cardId" AND a."userId" = $1
|
||||||
WHERE c."deckId" = $2 AND (${whereClause})
|
WHERE c."deckId" = $2 AND (${whereClause})
|
||||||
ORDER BY g."grade" ${direction === 'asc' ? 'ASC NULLS FIRST' : 'DESC NULLS LAST'}
|
ORDER BY g."grade" ${direction === 'asc' ? 'ASC NULLS FIRST' : 'DESC NULLS LAST'}
|
||||||
LIMIT $${queryParams.length + 1} OFFSET $${queryParams.length + 2}
|
LIMIT $${queryParams.length + 1} OFFSET $${queryParams.length + 2}
|
||||||
@@ -113,13 +114,14 @@ export class CardsRepository {
|
|||||||
...queryParams
|
...queryParams
|
||||||
)) satisfies Array<any>
|
)) satisfies Array<any>
|
||||||
|
|
||||||
const cards: CardWithGrades[] = cardsRaw.map(({ userGrade, ...card }) => ({
|
const cards: CardWithGrades[] = cardsRaw.map(({ userGrade, totalAttempts, ...card }) => ({
|
||||||
...card,
|
...card,
|
||||||
grades: [
|
grades: [
|
||||||
{
|
{
|
||||||
grade: userGrade,
|
grade: userGrade,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
attempts: totalAttempts,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const totalCount = await this.prisma.card.count({ where })
|
const totalCount = await this.prisma.card.count({ where })
|
||||||
@@ -143,13 +145,33 @@ export class CardsRepository {
|
|||||||
grade: true,
|
grade: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
attempts: {
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
attemptCount: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
skip: (currentPage - 1) * itemsPerPage,
|
skip: (currentPage - 1) * itemsPerPage,
|
||||||
take: itemsPerPage,
|
take: itemsPerPage,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
return Pagination.transformPaginationData(result, { currentPage, itemsPerPage })
|
const [totalCount, cardsRaw] = result
|
||||||
|
|
||||||
|
const cards = cardsRaw.map(card => ({
|
||||||
|
...card,
|
||||||
|
shots: card.attempts.reduce((acc, attempt) => acc + attempt.attemptCount, 0),
|
||||||
|
}))
|
||||||
|
|
||||||
|
console.log(cards)
|
||||||
|
|
||||||
|
return Pagination.transformPaginationData([totalCount, cards], {
|
||||||
|
currentPage,
|
||||||
|
itemsPerPage,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(e?.message)
|
this.logger.error(e?.message)
|
||||||
@@ -159,7 +181,7 @@ export class CardsRepository {
|
|||||||
|
|
||||||
async findCardsByDeckIdWithGrade(userId: string, deckId: string) {
|
async findCardsByDeckIdWithGrade(userId: string, deckId: string) {
|
||||||
try {
|
try {
|
||||||
return this.prisma.card.findMany({
|
const cards = await this.prisma.card.findMany({
|
||||||
where: {
|
where: {
|
||||||
deckId,
|
deckId,
|
||||||
},
|
},
|
||||||
@@ -169,8 +191,18 @@ export class CardsRepository {
|
|||||||
userId,
|
userId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
attempts: {
|
||||||
|
where: {
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return cards.map(card => ({
|
||||||
|
...card,
|
||||||
|
shots: card.attempts.reduce((acc, attempt) => acc + attempt.attemptCount, 0),
|
||||||
|
}))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(e?.message)
|
this.logger.error(e?.message)
|
||||||
throw new InternalServerErrorException(e?.message)
|
throw new InternalServerErrorException(e?.message)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class GradesRepository {
|
|||||||
grade: number
|
grade: number
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
return await this.prisma.grade.upsert({
|
const gradeResult = await this.prisma.grade.upsert({
|
||||||
where: {
|
where: {
|
||||||
cardId_userId: {
|
cardId_userId: {
|
||||||
cardId,
|
cardId,
|
||||||
@@ -57,6 +57,37 @@ export class GradesRepository {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const attemptResult = await this.prisma.cardAttempt.upsert({
|
||||||
|
where: {
|
||||||
|
userId_cardId: {
|
||||||
|
userId,
|
||||||
|
cardId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
attemptCount: {
|
||||||
|
increment: 1,
|
||||||
|
},
|
||||||
|
lastAttempt: new Date(),
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
attemptCount: 1,
|
||||||
|
lastAttempt: new Date(),
|
||||||
|
user: {
|
||||||
|
connect: {
|
||||||
|
id: userId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
connect: {
|
||||||
|
id: cardId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return { gradeResult, attemptResult }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(e?.message)
|
this.logger.error(e?.message)
|
||||||
throw new InternalServerErrorException(e?.message)
|
throw new InternalServerErrorException(e?.message)
|
||||||
|
|||||||
Reference in New Issue
Block a user