Skip to content

Pull Request: Finance Education Module Enhancements #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 149 additions & 23 deletions backend-node/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,36 @@ datasource db {
}

model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
id String @id @default(auto()) @map("_id") @db.ObjectId
username String
email String @unique
password String?
emailVerified DateTime?
image String?
accounts Account[]

email String @unique
password String?
emailVerified DateTime?
image String?
level Int @default(1)
xp Int @default(5)
currentRank String @default("Novice")
accounts Account[]
educationProgress EducationProgress[]
achievements Achievement[]
skillTrees UserSkillTree[]
dailyStreak Int @default(0)
lastActiveDate DateTime?

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model UserSkillTree {
id String @id @default(uuid()) @map("_id")
user User @relation(fields: [userId], references: [id])
userId String @db.ObjectId
skillTreeId String
progress Json // Stores completed nodes, etc.

@@unique([userId, skillTreeId])
}

model Account {
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String @db.ObjectId
Expand All @@ -32,29 +50,137 @@ model Account {
scope String?
id_token String? @db.String
session_state String?

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@unique([provider, providerAccountId])
}


model EmailVerificationToken {
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String @unique @db.ObjectId
token String @unique
expireAt DateTime
createdAt DateTime @default(now())
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String @unique @db.ObjectId
token String @unique
expireAt DateTime
createdAt DateTime @default(now())
}

model PasswordResetToken {
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String @unique @db.ObjectId
token String @unique
expireAt DateTime
isUsed Boolean @default(false)
createdAt DateTime @default(now())
}
id String @id @default(auto()) @map("_id") @db.ObjectId
userId String @unique @db.ObjectId
token String @unique
expireAt DateTime
isUsed Boolean @default(false)
createdAt DateTime @default(now())
}

model EducationProgress {
id String @id @default(uuid()) @map("_id")
user User @relation(fields: [userId], references: [id])
userId String @db.ObjectId
lessonId String
completed Boolean @default(false)
xpEarned Int @default(0)
completedAt DateTime?

@@unique([userId, lessonId])
}

model Lesson {
id String @id @default(uuid()) @map("_id")
title String
description String
duration Int // in minutes
xpReward Int
category String
icon String?
learningPath LearningPath? @relation(fields: [learningPathId], references: [id])
learningPathId String? @db.ObjectId
quizzes Quiz[]
flashcardDecks FlashcardDeck[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model Quiz {
id String @id @default(uuid()) @map("_id")
lesson Lesson? @relation(fields: [lessonId], references: [id])
lessonId String? @db.ObjectId
title String
description String
xpReward Int
questions QuizQuestion[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model QuizQuestion {
id String @id @default(uuid()) @map("_id")
quiz Quiz @relation(fields: [quizId], references: [id])
quizId String @db.ObjectId
question String
options String[]
correctAnswer Int
explanation String
}

model FlashcardDeck {
id String @id @default(uuid()) @map("_id")
lesson Lesson? @relation(fields: [lessonId], references: [id])
lessonId String? @db.ObjectId
title String
description String
flashcards Flashcard[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model Flashcard {
id String @id @default(uuid()) @map("_id")
deck FlashcardDeck @relation(fields: [deckId], references: [id])
deckId String @db.ObjectId
front String
back String
}

model LearningPath {
id String @id @default(uuid()) @map("_id")
title String
color String
icon String?
lessons Lesson[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model SkillChallenge {
id String @id @default(uuid()) @map("_id")
title String
description String
difficulty String
xpReward Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

model Reward {
id String @id @default(uuid()) @map("_id")
title String
description String
icon String?
unlockAtXp Int
}

model Achievement {
id String @id @default(uuid()) @map("_id")
user User @relation(fields: [userId], references: [id])
userId String @db.ObjectId
type String
title String
description String
color String?
requirement String?
earnedAt DateTime @default(now())
}
82 changes: 82 additions & 0 deletions backend-node/src/FinanceEducation/flashcardController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { prisma } from '../../prisma/client';
import { Request, Response } from 'express';

// Get all flashcard decks
export async function getFlashcardDecks(req: Request, res: Response) {
try {
const decks = await prisma.flashcardDeck.findMany({
include: { flashcards: true },
});
res.status(200).json({ decks });
} catch (error) {
console.error('Error fetching flashcard decks:', error);
res.status(500).json({ error: 'Failed to fetch flashcard decks' });
}
}

// Get flashcard deck by ID
export async function getFlashcardDeckById(req: Request, res: Response) {
try {
const { id } = req.params;
const deck = await prisma.flashcardDeck.findUnique({
where: { id },
include: { flashcards: true },
});
if (!deck)
return res.status(404).json({ error: 'Flashcard deck not found' });
res.status(200).json({ deck });
} catch (error) {
console.error('Error fetching flashcard deck:', error);
res.status(500).json({ error: 'Failed to fetch flashcard deck' });
}
}

// Create flashcard deck
export async function createFlashcardDeck(req: Request, res: Response) {
try {
const { lessonId, title, description, flashcards } = req.body;
const deck = await prisma.flashcardDeck.create({
data: {
lessonId,
title,
description,
flashcards: {
create: flashcards,
},
},
include: { flashcards: true },
});
res.status(201).json({ deck });
} catch (error) {
console.error('Error creating flashcard deck:', error);
res.status(500).json({ error: 'Failed to create flashcard deck' });
}
}

// Update flashcard deck
export async function updateFlashcardDeck(req: Request, res: Response) {
try {
const { id } = req.params;
const deck = await prisma.flashcardDeck.update({
where: { id },
data: req.body,
include: { flashcards: true },
});
res.status(200).json({ deck });
} catch (error) {
console.error('Error updating flashcard deck:', error);
res.status(500).json({ error: 'Failed to update flashcard deck' });
}
}

// Delete flashcard deck
export async function deleteFlashcardDeck(req: Request, res: Response) {
try {
const { id } = req.params;
await prisma.flashcardDeck.delete({ where: { id } });
res.status(204).end();
} catch (error) {
console.error('Error deleting flashcard deck:', error);
res.status(500).json({ error: 'Failed to delete flashcard deck' });
}
}
17 changes: 17 additions & 0 deletions backend-node/src/FinanceEducation/flashcardRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { RequestHandler, Router } from 'express';
import { getFlashcardDeckById,
getFlashcardDecks,
createFlashcardDeck,
updateFlashcardDeck,
deleteFlashcardDeck
} from './flashcardController';

const router = Router();

router.get('/', getFlashcardDecks);
router.get('/:id', getFlashcardDeckById as RequestHandler);
router.post('/', createFlashcardDeck);
router.patch('/:id', updateFlashcardDeck);
router.delete('/:id', deleteFlashcardDeck);

export default router;
Loading