Add quiz feature: student UI, admin editor, lesson page integration
- QuizSection component: shows questions as text inputs, read-only after submission - QuizEditor component: admin CRUD for quiz questions with type selector - saveQuiz/deleteQuiz server actions for admin - submitQuizAttempt server action: idempotent, auto-marks lesson complete - Student lesson page: renders QuizSection, updates complete button logic - Admin lesson page: renders QuizEditor below homework section Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
"use server";
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { headers } from "next/headers";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
async function requireAdmin() {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
if (!session || session.user.role !== "admin") throw new Error("Forbidden");
|
||||
}
|
||||
|
||||
export async function saveQuiz(
|
||||
lessonId: string,
|
||||
questions: { text: string; type: "TEXT" | "SINGLE" | "MULTIPLE"; order: number }[]
|
||||
) {
|
||||
await requireAdmin();
|
||||
|
||||
const existing = await prisma.quiz.findUnique({ where: { lessonId } });
|
||||
|
||||
if (existing) {
|
||||
await prisma.quizQuestion.deleteMany({ where: { quizId: existing.id } });
|
||||
await prisma.quizQuestion.createMany({
|
||||
data: questions.map((q) => ({
|
||||
quizId: existing.id,
|
||||
text: q.text,
|
||||
type: q.type,
|
||||
order: q.order,
|
||||
})),
|
||||
});
|
||||
} else {
|
||||
await prisma.quiz.create({
|
||||
data: {
|
||||
lessonId,
|
||||
questions: {
|
||||
create: questions.map((q) => ({
|
||||
text: q.text,
|
||||
type: q.type,
|
||||
order: q.order,
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
revalidatePath(`/admin`);
|
||||
}
|
||||
|
||||
export async function deleteQuiz(lessonId: string) {
|
||||
await requireAdmin();
|
||||
await prisma.quiz.delete({ where: { lessonId } });
|
||||
revalidatePath(`/admin`);
|
||||
}
|
||||
Reference in New Issue
Block a user