Study/prisma/schema.prisma
Elijah dad62c9914
All checks were successful
Automated Container Build / build-and-push (push) Successful in 54s
Add study activity tracking and refresh class header UI
2026-07-12 11:44:26 -07:00

164 lines
4.4 KiB
Text

datasource db {
provider = "sqlite"
}
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
model Class {
id String @id @default(uuid())
slug String @unique
name String
sortOrder Int @default(0)
createdAt DateTime @default(now())
decks Deck[]
quizSets QuizSet[]
materialGroups MaterialGroup[]
}
model Deck {
id String @id @default(uuid())
classId String
name String
description String?
sortOrder Int @default(0)
createdAt DateTime @default(now())
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
groupId String?
group MaterialGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
cards Flashcard[]
shareLink ShareLink?
progress StudyProgress[]
}
model Flashcard {
id String @id @default(uuid())
deckId String
front String
back String
sortOrder Int @default(0)
deck Deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
}
model QuizSet {
id String @id @default(uuid())
classId String
name String
description String?
sortOrder Int @default(0)
createdAt DateTime @default(now())
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
groupId String?
group MaterialGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
questions Question[]
attempts QuizAttempt[]
shareLink ShareLink?
progress StudyProgress[]
}
model Question {
id String @id @default(uuid())
quizSetId String
type String // "MULTIPLE_CHOICE" | "SATA"
prompt String
rationale String
category String
sortOrder Int @default(0)
quizSet QuizSet @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
options AnswerOption[]
}
model AnswerOption {
id String @id @default(uuid())
questionId String
text String
isCorrect Boolean @default(false)
sortOrder Int @default(0)
question Question @relation(fields: [questionId], references: [id], onDelete: Cascade)
}
model StudyProgress {
id String @id @default(uuid())
contentType String // "DECK" | "QUIZ"
deckId String?
quizSetId String?
mode String // "SEQUENTIAL" | "SHUFFLED"
currentIndex Int @default(0)
orderJson String // JSON array of card/question ids
answersJson String? // in-progress quiz answers
cardResultsJson String? // per-card grades for decks
updatedAt DateTime @updatedAt
deck Deck? @relation(fields: [deckId], references: [id], onDelete: Cascade)
quizSet QuizSet? @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
@@unique([deckId, mode])
@@unique([quizSetId, mode])
}
model QuizAttempt {
id String @id @default(uuid())
quizSetId String
score Float
maxScore Int
answersJson String
isPartialRetake Boolean @default(false)
completedAt DateTime @default(now())
quizSet QuizSet @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
}
model ShareLink {
id String @id @default(uuid())
targetType String // "DECK" | "QUIZ" | "GROUP"
deckId String? @unique
quizSetId String? @unique
groupId String? @unique
createdAt DateTime @default(now())
deck Deck? @relation(fields: [deckId], references: [id], onDelete: Cascade)
quizSet QuizSet? @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
group MaterialGroup? @relation(fields: [groupId], references: [id], onDelete: Cascade)
}
model AuthSecurity {
id Int @id @default(1)
failedAttempts Int @default(0)
lockedUntil DateTime?
lastAttemptAt DateTime?
}
model Setting {
key String @id
value String
}
model StudyActivity {
id String @id @default(uuid())
type String // "FLASHCARD" | "QUIZ_QUESTION"
occurredAt DateTime @default(now())
@@index([occurredAt])
}
model MaterialGroup {
id String @id @default(uuid())
classId String
name String
type String // "DECK" | "QUIZ"
sortOrder Int @default(0)
createdAt DateTime @default(now())
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
decks Deck[]
quizSets QuizSet[]
shareLink ShareLink?
}