project-standalo-todo-super/app/api/quizzes/[taskId]/submit/route.ts

156 lines
3.7 KiB
TypeScript

/**
* POST /api/quizzes/[taskId]/submit - Submit quiz answers
*/
import { NextRequest, NextResponse } from 'next/server';
import { requireAuth } from '@/app/lib/auth';
import { findTask, findQuizByTaskId, hasUserCompletedTask, createUserTask } from '@/app/lib/db/store';
import { addPoints } from '@/app/lib/points';
import { checkAndAwardBadges } from '@/app/lib/badges';
import { TaskType, ApiResponse } from '@/app/lib/types';
interface SubmitQuizRequest {
answer: number;
}
interface QuizResult {
correct: boolean;
correctAnswer: number;
pointsEarned: number;
userTask?: {
id: string;
userId: string;
taskId: string;
completedAt: Date;
pointsEarned: number;
};
}
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ taskId: string }> }
) {
try {
// Authenticate user
const user = requireAuth(request);
const { taskId } = await params;
// Parse request body
const body: SubmitQuizRequest = await request.json();
const { answer } = body;
if (answer === undefined || answer === null) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Answer is required'
},
{ status: 400 }
);
}
// Find the task
const task = findTask(taskId);
if (!task) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Task not found'
},
{ status: 404 }
);
}
// Verify it's a quiz task
if (task.type !== TaskType.QUIZ) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'This is not a quiz task'
},
{ status: 400 }
);
}
// Check if user has already completed this quiz
if (hasUserCompletedTask(user.id, taskId)) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'You have already completed this quiz'
},
{ status: 409 }
);
}
// Find the quiz
const quiz = findQuizByTaskId(taskId);
if (!quiz) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Quiz not found for this task'
},
{ status: 404 }
);
}
// Check the answer
const isCorrect = answer === quiz.correctAnswer;
const pointsEarned = isCorrect ? task.pointsReward : 0;
let userTask = undefined;
let newBadges = [];
if (isCorrect) {
// Complete the task
userTask = createUserTask(user.id, taskId, pointsEarned);
// Award points
addPoints(user.id, pointsEarned, `task:${taskId}`);
// Check and award badges
newBadges = checkAndAwardBadges(user.id);
}
const result: QuizResult = {
correct: isCorrect,
correctAnswer: quiz.correctAnswer,
pointsEarned,
userTask
};
return NextResponse.json<ApiResponse<QuizResult>>(
{
success: true,
data: result,
message: isCorrect
? `Correct! You earned ${pointsEarned} points${
newBadges.length > 0 ? ` and ${newBadges.length} new badge(s)!` : ''
}`
: `Incorrect. The correct answer was option ${quiz.correctAnswer}.`
},
{ status: isCorrect ? 201 : 200 }
);
} catch (error) {
if (error instanceof Error && error.message === 'Unauthorized') {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Unauthorized'
},
{ status: 401 }
);
}
console.error('Submit quiz error:', error);
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Internal server error'
},
{ status: 500 }
);
}
}