Skip to content

Commit

Permalink
fix: count attempts per user instead of globally
Browse files Browse the repository at this point in the history
  • Loading branch information
ershisan99 committed Jun 2, 2024
1 parent 5a1d375 commit 958f9ba
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 34 deletions.
62 changes: 39 additions & 23 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ model user {
RefreshToken refreshToken[]
resetPassword resetPassword?
favoriteDecks favoriteDeck[]
attempts cardAttempt[]
@@index([email])
@@index([id])
Expand Down Expand Up @@ -83,40 +84,41 @@ model resetPassword {
}

model card {
id String @id @default(cuid())
id String @id @default(cuid())
deckId String
userId String
question String @db.Text
answer String @db.Text
shots Int @default(0)
questionImg String? @db.VarChar(500)
answerImg String? @db.VarChar(500)
answerVideo String? @db.VarChar(500)
questionVideo String? @db.VarChar(500)
question String @db.Text
answer String @db.Text
shots Int @default(0)
questionImg String? @db.VarChar(500)
answerImg String? @db.VarChar(500)
answerVideo String? @db.VarChar(500)
questionVideo String? @db.VarChar(500)
comments String?
type String?
moreId String?
created DateTime @default(now())
updated DateTime @updatedAt
author user @relation(fields: [userId], references: [id], onDelete: Cascade)
decks deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
created DateTime @default(now())
updated DateTime @updatedAt
author user @relation(fields: [userId], references: [id], onDelete: Cascade)
decks deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
grades grade[]
attempts cardAttempt[]
@@index([userId])
@@index([deckId])
}

model deck {
id String @id @default(cuid())
userId String
name String
isPrivate Boolean @default(false)
cover String? @db.VarChar(500)
created DateTime @default(now())
updated DateTime @updatedAt
author user @relation(fields: [userId], references: [id], onDelete: Cascade)
card card[]
grades grade[]
id String @id @default(cuid())
userId String
name String
isPrivate Boolean @default(false)
cover String? @db.VarChar(500)
created DateTime @default(now())
updated DateTime @updatedAt
author user @relation(fields: [userId], references: [id], onDelete: Cascade)
card card[]
grades grade[]
favoritedBy favoriteDeck[]
@@index([userId])
Expand Down Expand Up @@ -174,4 +176,18 @@ model favoriteDeck {
@@unique([userId, deckId])
@@index([userId])
@@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])
}
52 changes: 42 additions & 10 deletions src/modules/cards/infrastructure/cards.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,14 @@ export class CardsRepository {
const whereClause = whereParts.join(' OR ')

const sqlQuery = `
SELECT c.*, g.grade as "userGrade"
FROM flashcards.card AS c
LEFT JOIN flashcards.grade AS g ON c.id = g."cardId" AND g."userId" = $1
WHERE c."deckId" = $2 AND (${whereClause})
ORDER BY g."grade" ${direction === 'asc' ? 'ASC NULLS FIRST' : 'DESC NULLS LAST'}
LIMIT $${queryParams.length + 1} OFFSET $${queryParams.length + 2}
`
SELECT c.*, g.grade as "userGrade", COALESCE(a."attemptCount", 0) as "totalAttempts"
FROM flashcards.card AS c
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})
ORDER BY g."grade" ${direction === 'asc' ? 'ASC NULLS FIRST' : 'DESC NULLS LAST'}
LIMIT $${queryParams.length + 1} OFFSET $${queryParams.length + 2}
`

// Add itemsPerPage and start to the queryParams
queryParams.push(itemsPerPage, start)
Expand All @@ -113,13 +114,14 @@ export class CardsRepository {
...queryParams
)) satisfies Array<any>

const cards: CardWithGrades[] = cardsRaw.map(({ userGrade, ...card }) => ({
const cards: CardWithGrades[] = cardsRaw.map(({ userGrade, totalAttempts, ...card }) => ({
...card,
grades: [
{
grade: userGrade,
},
],
attempts: totalAttempts,
}))

const totalCount = await this.prisma.card.count({ where })
Expand All @@ -143,13 +145,33 @@ export class CardsRepository {
grade: true,
},
},
attempts: {
where: {
userId,
},
select: {
attemptCount: true,
},
},
},
skip: (currentPage - 1) * 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) {
this.logger.error(e?.message)
Expand All @@ -159,7 +181,7 @@ export class CardsRepository {

async findCardsByDeckIdWithGrade(userId: string, deckId: string) {
try {
return this.prisma.card.findMany({
const cards = await this.prisma.card.findMany({
where: {
deckId,
},
Expand All @@ -169,8 +191,18 @@ export class CardsRepository {
userId,
},
},
attempts: {
where: {
userId,
},
},
},
})

return cards.map(card => ({
...card,
shots: card.attempts.reduce((acc, attempt) => acc + attempt.attemptCount, 0),
}))
} catch (e) {
this.logger.error(e?.message)
throw new InternalServerErrorException(e?.message)
Expand Down
33 changes: 32 additions & 1 deletion src/modules/decks/infrastructure/grades.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class GradesRepository {
grade: number
}) {
try {
return await this.prisma.grade.upsert({
const gradeResult = await this.prisma.grade.upsert({
where: {
cardId_userId: {
cardId,
Expand Down Expand Up @@ -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) {
this.logger.error(e?.message)
throw new InternalServerErrorException(e?.message)
Expand Down

0 comments on commit 958f9ba

Please sign in to comment.