Add lesson complete button with homework-aware logic
- Show "Отметить как пройденный" button only on lessons without homework - Show static "Пройдено" badge on homework lessons completed via approval - Auto-create LessonProgress when curator/admin approves homework submission - Revalidate student lesson, course, and dashboard pages on approval Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -179,9 +179,12 @@ export default async function LessonPage({ params }: Props) {
|
||||
<div />
|
||||
)}
|
||||
|
||||
{!isAdmin && (
|
||||
{!isAdmin && !lesson.homework && (
|
||||
<LessonCompleteButton lessonId={lessonId} slug={slug} isCompleted={isCompleted} />
|
||||
)}
|
||||
{!isAdmin && lesson.homework && isCompleted && (
|
||||
<LessonCompleteButton lessonId={lessonId} slug={slug} isCompleted={true} readOnly={true} />
|
||||
)}
|
||||
|
||||
{nextLesson ? (
|
||||
<Link
|
||||
|
||||
@@ -26,27 +26,10 @@ export async function submitFeedback(
|
||||
const session = await requireCurator();
|
||||
const status = data.action === "approve" ? "APPROVED" : "REJECTED";
|
||||
|
||||
await prisma.$transaction([
|
||||
prisma.homeworkFeedback.create({
|
||||
data: {
|
||||
submissionId,
|
||||
curatorId: session.user.id,
|
||||
text: data.text,
|
||||
files: data.files ?? [],
|
||||
audioUrl: data.audioUrl ?? null,
|
||||
},
|
||||
}),
|
||||
prisma.homeworkSubmission.update({
|
||||
where: { id: submissionId },
|
||||
data: { status, statusAt: new Date() },
|
||||
}),
|
||||
]);
|
||||
|
||||
// Send email notification to student
|
||||
const submission = await prisma.homeworkSubmission.findUnique({
|
||||
where: { id: submissionId },
|
||||
include: {
|
||||
user: { select: { email: true, name: true } },
|
||||
user: { select: { id: true, email: true, name: true } },
|
||||
homework: {
|
||||
include: {
|
||||
lesson: {
|
||||
@@ -61,20 +44,54 @@ export async function submitFeedback(
|
||||
},
|
||||
});
|
||||
|
||||
if (submission) {
|
||||
const { lesson } = submission.homework;
|
||||
const lessonUrl = `${process.env.BETTER_AUTH_URL ?? "https://school.second-brain.ru"}/courses/${lesson.module.course.slug}/lessons/${lesson.id}`;
|
||||
await sendFeedbackReceivedEmail(
|
||||
submission.user.email,
|
||||
submission.user.name,
|
||||
lesson.title,
|
||||
data.text,
|
||||
lessonUrl
|
||||
);
|
||||
}
|
||||
if (!submission) throw new Error("Submission not found");
|
||||
|
||||
await prisma.$transaction(async (tx) => {
|
||||
await tx.homeworkFeedback.create({
|
||||
data: {
|
||||
submissionId,
|
||||
curatorId: session.user.id,
|
||||
text: data.text,
|
||||
files: data.files ?? [],
|
||||
audioUrl: data.audioUrl ?? null,
|
||||
},
|
||||
});
|
||||
await tx.homeworkSubmission.update({
|
||||
where: { id: submissionId },
|
||||
data: { status, statusAt: new Date() },
|
||||
});
|
||||
if (status === "APPROVED") {
|
||||
await tx.lessonProgress.upsert({
|
||||
where: {
|
||||
userId_lessonId: {
|
||||
userId: submission.user.id,
|
||||
lessonId: submission.homework.lesson.id,
|
||||
},
|
||||
},
|
||||
create: {
|
||||
userId: submission.user.id,
|
||||
lessonId: submission.homework.lesson.id,
|
||||
},
|
||||
update: {},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const { lesson } = submission.homework;
|
||||
const lessonUrl = `${process.env.BETTER_AUTH_URL ?? "https://school.second-brain.ru"}/courses/${lesson.module.course.slug}/lessons/${lesson.id}`;
|
||||
await sendFeedbackReceivedEmail(
|
||||
submission.user.email,
|
||||
submission.user.name,
|
||||
lesson.title,
|
||||
data.text,
|
||||
lessonUrl
|
||||
);
|
||||
|
||||
revalidatePath("/curator/homework");
|
||||
revalidatePath(`/curator/homework/${submissionId}`);
|
||||
revalidatePath(`/courses/${lesson.module.course.slug}/lessons/${lesson.id}`);
|
||||
revalidatePath(`/courses/${lesson.module.course.slug}`);
|
||||
revalidatePath("/dashboard");
|
||||
}
|
||||
|
||||
export async function setReviewing(submissionId: string) {
|
||||
|
||||
@@ -8,13 +8,24 @@ export function LessonCompleteButton({
|
||||
lessonId,
|
||||
slug,
|
||||
isCompleted,
|
||||
readOnly = false,
|
||||
}: {
|
||||
lessonId: string;
|
||||
slug: string;
|
||||
isCompleted: boolean;
|
||||
readOnly?: boolean;
|
||||
}) {
|
||||
const [pending, startTransition] = useTransition();
|
||||
|
||||
if (readOnly) {
|
||||
return (
|
||||
<div className="btn-aubade btn-aubade-accent flex items-center gap-2 px-5 py-2.5 text-sm cursor-default select-none">
|
||||
<Check size={15} strokeWidth={3} />
|
||||
Пройдено
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={() => startTransition(() => toggleLessonProgress(lessonId, slug))}
|
||||
|
||||
Reference in New Issue
Block a user