Add optional audio response for students in homework submissions
- Course: add allowAudio toggle (per-course setting, off by default) - HomeworkSubmission: add audioUrl field - Student: AudioRecorder in homework form when allowAudio is enabled - Student: show audio player in submission view and curator feedback view - Curator: show student audio on submission detail page - AudioRecorder: accept uploadUrl prop (reused for student/curator) - API: /api/student/audio-upload route for S3 upload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,8 @@ export async function submitHomework(
|
||||
slug: string,
|
||||
lessonId: string,
|
||||
text: string,
|
||||
files: HomeworkFile[]
|
||||
files: HomeworkFile[],
|
||||
audioUrl?: string | null
|
||||
) {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
if (!session) throw new Error("Unauthorized");
|
||||
@@ -36,12 +37,12 @@ export async function submitHomework(
|
||||
if (existing) {
|
||||
const updated = await prisma.homeworkSubmission.update({
|
||||
where: { id: existing.id },
|
||||
data: { text, files: files as object[], submittedAt: new Date() },
|
||||
data: { text, files: files as object[], audioUrl: audioUrl ?? null, submittedAt: new Date() },
|
||||
});
|
||||
submissionId = updated.id;
|
||||
} else {
|
||||
const created = await prisma.homeworkSubmission.create({
|
||||
data: { homeworkId, userId: session.user.id, text, files: files as object[] },
|
||||
data: { homeworkId, userId: session.user.id, text, files: files as object[], audioUrl: audioUrl ?? null },
|
||||
});
|
||||
submissionId = created.id;
|
||||
|
||||
|
||||
@@ -61,7 +61,12 @@ export default async function LessonPage({ params }: Props) {
|
||||
const homeworkSubmission = lesson?.homework && session && !isAdmin
|
||||
? await prisma.homeworkSubmission.findFirst({
|
||||
where: { homeworkId: lesson.homework.id, userId: session.user.id },
|
||||
include: { feedbacks: { include: { curator: { select: { name: true } } }, orderBy: { createdAt: "desc" } } },
|
||||
include: {
|
||||
feedbacks: {
|
||||
include: { curator: { select: { name: true } } },
|
||||
orderBy: { createdAt: "asc" },
|
||||
},
|
||||
},
|
||||
})
|
||||
: null;
|
||||
|
||||
@@ -145,9 +150,16 @@ export default async function LessonPage({ params }: Props) {
|
||||
submission={homeworkSubmission ? {
|
||||
...homeworkSubmission,
|
||||
files: (homeworkSubmission.files as { name: string; url: string; size: number }[]) ?? [],
|
||||
audioUrl: homeworkSubmission.audioUrl ?? null,
|
||||
feedbacks: homeworkSubmission.feedbacks.map((fb) => ({
|
||||
...fb,
|
||||
files: (fb.files as { name: string; url: string; size: number }[]) ?? [],
|
||||
audioUrl: fb.audioUrl ?? null,
|
||||
})),
|
||||
} : null}
|
||||
slug={slug}
|
||||
lessonId={lessonId}
|
||||
allowAudio={lesson.module.course.allowAudio}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user