"use server"; import { revalidatePath } from "next/cache"; import { requireUser } from "@/lib/auth/requireUser"; import { mockPracticeModules } from "@/lib/data/mockPractice"; import { db } from "@/lib/prisma"; import { refreshStudyRecommendations } from "@/lib/recommendations"; type SubmitAttemptInput = { slug: string; selectedAnswers: number[]; }; type PracticePrismaClient = { miniGame: { upsert: (args: object) => Promise<{ id: string }>; }; miniGameAttempt: { create: (args: object) => Promise; findMany: (args: object) => Promise< { id: string; scorePercent: number; correctCount: number; totalQuestions: number; completedAt: Date }[] >; }; }; function toDifficulty(level?: string): "BEGINNER" | "INTERMEDIATE" | "ADVANCED" { if (level === "Beginner") return "BEGINNER"; if (level === "Advanced") return "ADVANCED"; return "INTERMEDIATE"; } export async function submitPracticeAttempt({ slug, selectedAnswers }: SubmitAttemptInput) { const user = await requireUser(); if (!user?.id) return { success: false as const, error: "Unauthorized" }; const practiceModule = mockPracticeModules.find((item) => item.slug === slug && item.isInteractive && item.questions?.length); if (!practiceModule || !practiceModule.questions) return { success: false as const, error: "Practice module not found" }; const correctCount = practiceModule.questions.reduce((acc, question, index) => { return acc + (selectedAnswers[index] === question.answerIndex ? 1 : 0); }, 0); const total = practiceModule.questions.length; const scorePercent = Math.round((correctCount / total) * 100); const prismaMini = db as unknown as PracticePrismaClient; try { const miniGame = await prismaMini.miniGame.upsert({ where: { slug: practiceModule.slug }, update: { title: practiceModule.title, description: practiceModule.description, isActive: true, difficulty: toDifficulty(practiceModule.difficulty), }, create: { slug: practiceModule.slug, title: practiceModule.title, description: practiceModule.description, isActive: true, difficulty: toDifficulty(practiceModule.difficulty), }, select: { id: true }, }); await prismaMini.miniGameAttempt.create({ data: { userId: user.id, miniGameId: miniGame.id, scorePercent, correctCount, totalQuestions: total, }, }); await refreshStudyRecommendations(user.id); } catch { return { success: false as const, error: "Mini-game tables are not migrated yet" }; } revalidatePath("/profile"); return { success: true as const, scorePercent, correctCount, total }; } export async function getPracticeAttempts(slug: string) { const user = await requireUser(); if (!user?.id) return []; try { const attempts = await (db as unknown as PracticePrismaClient).miniGameAttempt.findMany({ where: { userId: user.id, miniGame: { slug, }, }, orderBy: { completedAt: "desc", }, take: 5, select: { id: true, scorePercent: true, correctCount: true, totalQuestions: true, completedAt: true, }, }); return attempts; } catch { return []; } }