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:
2026-04-26 14:00:47 +05:00
parent 39d84a3db2
commit 3ed7bc147b
3 changed files with 61 additions and 30 deletions
@@ -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,7 +44,39 @@ export async function submitFeedback(
},
});
if (submission) {
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(
@@ -71,10 +86,12 @@ export async function submitFeedback(
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))}