feat: add API endpoint and service logic for reordering quiz questions.
This commit is contained in:
parent
44c61c8fb2
commit
84e4d478c7
3 changed files with 125 additions and 0 deletions
|
|
@ -37,6 +37,8 @@ import {
|
|||
DeleteQuestionInput,
|
||||
DeleteQuestionResponse,
|
||||
QuizQuestionData,
|
||||
ReorderQuestionInput,
|
||||
ReorderQuestionResponse,
|
||||
} from "../types/ChaptersLesson.typs";
|
||||
import { CoursesInstructorService } from './CoursesInstructor.service';
|
||||
|
||||
|
|
@ -832,6 +834,87 @@ export class ChaptersLessonService {
|
|||
}
|
||||
}
|
||||
|
||||
async reorderQuestion(request: ReorderQuestionInput): Promise<ReorderQuestionResponse> {
|
||||
try {
|
||||
const { token, course_id, lesson_id, question_id, sort_order } = request;
|
||||
const decodedToken = jwt.verify(token, config.jwt.secret) as { id: number };
|
||||
await CoursesInstructorService.validateCourseStatus(course_id);
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { id: decodedToken.id } });
|
||||
if (!user) throw new UnauthorizedError('Invalid token');
|
||||
|
||||
const courseInstructor = await CoursesInstructorService.validateCourseInstructor(token, course_id);
|
||||
if (!courseInstructor) throw new ForbiddenError('You are not permitted to modify this lesson');
|
||||
|
||||
// Verify lesson exists and is QUIZ type
|
||||
const lesson = await prisma.lesson.findUnique({
|
||||
where: { id: lesson_id },
|
||||
include: { quiz: true }
|
||||
});
|
||||
if (!lesson) throw new NotFoundError('Lesson not found');
|
||||
if (lesson.type !== 'QUIZ') throw new ValidationError('Cannot reorder question in non-QUIZ type lesson');
|
||||
if (!lesson.quiz) throw new NotFoundError('Quiz not found for this lesson');
|
||||
|
||||
// Verify question exists and belongs to this quiz
|
||||
const existingQuestion = await prisma.question.findUnique({ where: { id: question_id } });
|
||||
if (!existingQuestion || existingQuestion.quiz_id !== lesson.quiz.id) {
|
||||
throw new NotFoundError('Question not found in this quiz');
|
||||
}
|
||||
|
||||
const oldSortOrder = existingQuestion.sort_order;
|
||||
const quizId = lesson.quiz.id;
|
||||
|
||||
// If same position, no need to reorder
|
||||
if (oldSortOrder === sort_order) {
|
||||
const questions = await prisma.question.findMany({
|
||||
where: { quiz_id: quizId },
|
||||
orderBy: { sort_order: 'asc' },
|
||||
include: { choices: { orderBy: { sort_order: 'asc' } } }
|
||||
});
|
||||
return { code: 200, message: 'Question reordered successfully', data: questions as QuizQuestionData[] };
|
||||
}
|
||||
|
||||
// Shift other questions to make room for the insert
|
||||
if (oldSortOrder > sort_order) {
|
||||
// Moving up: shift questions between newSortOrder and oldSortOrder-1 down by 1
|
||||
await prisma.question.updateMany({
|
||||
where: {
|
||||
quiz_id: quizId,
|
||||
sort_order: { gte: sort_order, lt: oldSortOrder }
|
||||
},
|
||||
data: { sort_order: { increment: 1 } }
|
||||
});
|
||||
} else {
|
||||
// Moving down: shift questions between oldSortOrder+1 and newSortOrder up by 1
|
||||
await prisma.question.updateMany({
|
||||
where: {
|
||||
quiz_id: quizId,
|
||||
sort_order: { gt: oldSortOrder, lte: sort_order }
|
||||
},
|
||||
data: { sort_order: { decrement: 1 } }
|
||||
});
|
||||
}
|
||||
|
||||
// Update the question's sort order
|
||||
await prisma.question.update({
|
||||
where: { id: question_id },
|
||||
data: { sort_order }
|
||||
});
|
||||
|
||||
// Fetch all questions with updated order
|
||||
const questions = await prisma.question.findMany({
|
||||
where: { quiz_id: quizId },
|
||||
orderBy: { sort_order: 'asc' },
|
||||
include: { choices: { orderBy: { sort_order: 'asc' } } }
|
||||
});
|
||||
|
||||
return { code: 200, message: 'Question reordered successfully', data: questions as QuizQuestionData[] };
|
||||
} catch (error) {
|
||||
logger.error(`Error reordering question: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ลบคำถาม
|
||||
* Delete a question and all its choices
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue