···316316 formData.append("audio", this.selectedFile);
317317 formData.append("class_id", this.classId);
318318319319- // Use user's section by default, or allow override
320320- const sectionToUse = this.selectedSectionId || this.userSection;
321321- if (sectionToUse) {
322322- formData.append("section_id", sectionToUse);
319319+ // Send recording date (from date picker or file timestamp)
320320+ if (this.selectedDate) {
321321+ // Convert YYYY-MM-DD to timestamp (noon local time)
322322+ const date = new Date(`${this.selectedDate}T12:00:00`);
323323+ formData.append("recording_date", Math.floor(date.getTime() / 1000).toString());
324324+ } else if (this.selectedFile.lastModified) {
325325+ // Use file's lastModified as recording date
326326+ formData.append("recording_date", Math.floor(this.selectedFile.lastModified / 1000).toString());
323327 }
328328+329329+ // Don't send section_id yet - will be set via PATCH when user confirms
324330325331 const xhr = new XMLHttpRequest();
326332···434440 this.error = null;
435441436442 try {
443443+ // Get section to use (selected override or user's section)
444444+ const sectionToUse = this.selectedSectionId || this.userSection;
445445+437446 const response = await fetch(
438447 `/api/transcriptions/${this.uploadedTranscriptionId}/meeting-time`,
439448 {
···441450 headers: { "Content-Type": "application/json" },
442451 body: JSON.stringify({
443452 meeting_time_id: this.selectedMeetingTimeId,
453453+ section_id: sectionToUse,
444454 }),
445455 },
446456 );
+15
src/db/schema.ts
···278278 CREATE INDEX IF NOT EXISTS idx_recording_votes_user_id ON recording_votes(user_id);
279279 `,
280280 },
281281+ {
282282+ version: 4,
283283+ name: "Add recording_date to transcriptions for chronological ordering",
284284+ sql: `
285285+ -- Add recording_date (timestamp when the recording was made, not uploaded)
286286+ -- Defaults to created_at for existing records
287287+ ALTER TABLE transcriptions ADD COLUMN recording_date INTEGER;
288288+289289+ -- Set recording_date to created_at for existing records
290290+ UPDATE transcriptions SET recording_date = created_at WHERE recording_date IS NULL;
291291+292292+ -- Create index for ordering by recording date
293293+ CREATE INDEX IF NOT EXISTS idx_transcriptions_recording_date ON transcriptions(recording_date);
294294+ `,
295295+ },
281296];
282297283298function getCurrentVersion(): number {
+34-11
src/index.ts
···2189218921902190 const body = await req.json();
21912191 const meetingTimeId = body.meeting_time_id;
21922192+ const sectionId = body.section_id;
2192219321932194 if (!meetingTimeId) {
21942195 return Response.json(
···22352236 }
22362237 }
2237223822382238- // Update meeting time
22392239- db.run(
22402240- "UPDATE transcriptions SET meeting_time_id = ? WHERE id = ?",
22412241- [meetingTimeId, transcriptionId],
22422242- );
22392239+ // Update meeting time and optionally section_id
22402240+ if (sectionId !== undefined) {
22412241+ db.run(
22422242+ "UPDATE transcriptions SET meeting_time_id = ?, section_id = ? WHERE id = ?",
22432243+ [meetingTimeId, sectionId, transcriptionId],
22442244+ );
22452245+ } else {
22462246+ db.run(
22472247+ "UPDATE transcriptions SET meeting_time_id = ? WHERE id = ?",
22482248+ [meetingTimeId, transcriptionId],
22492249+ );
22502250+ }
2243225122442252 return Response.json({
22452253 success: true,
···22662274 );
22672275 }
2268227622692269- // Get user's section for filtering (admins see all)
22702270- const userSection =
22712271- user.role === "admin" ? null : getUserSection(user.id, classId);
22772277+ // Get section filter from query params or use user's section
22782278+ const url = new URL(req.url);
22792279+ const sectionParam = url.searchParams.get("section_id");
22802280+ const sectionFilter =
22812281+ sectionParam !== null
22822282+ ? sectionParam || null // empty string becomes null
22832283+ : user.role === "admin"
22842284+ ? null
22852285+ : getUserSection(user.id, classId);
2272228622732287 const recordings = getPendingRecordings(
22742288 classId,
22752289 meetingTimeId,
22762276- userSection,
22902290+ sectionFilter,
22772291 );
22782292 const totalUsers = getEnrolledUserCount(classId);
22792293 const userVote = getUserVoteForMeeting(
···22862300 const winningId = checkAutoSubmit(
22872301 classId,
22882302 meetingTimeId,
22892289- userSection,
23032303+ sectionFilter,
22902304 );
2291230522922306 return Response.json({
···25572571 const file = formData.get("audio") as File;
25582572 const classId = formData.get("class_id") as string | null;
25592573 const sectionId = formData.get("section_id") as string | null;
25742574+ const recordingDateStr = formData.get("recording_date") as
25752575+ | string
25762576+ | null;
2560257725612578 if (!file) throw ValidationErrors.missingField("audio");
25622579···26232640 const uploadDir = "./uploads";
26242641 await Bun.write(`${uploadDir}/${filename}`, file);
2625264226432643+ // Parse recording date (default to current time if not provided)
26442644+ const recordingDate = recordingDateStr
26452645+ ? Number.parseInt(recordingDateStr, 10)
26462646+ : Math.floor(Date.now() / 1000);
26472647+26262648 // Create database record (without meeting_time_id - will be set later via PATCH)
26272649 db.run(
26282628- "INSERT INTO transcriptions (id, user_id, class_id, meeting_time_id, section_id, filename, original_filename, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
26502650+ "INSERT INTO transcriptions (id, user_id, class_id, meeting_time_id, section_id, filename, original_filename, status, recording_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
26292651 [
26302652 transcriptionId,
26312653 user.id,
···26352657 filename,
26362658 file.name,
26372659 "pending",
26602660+ recordingDate,
26382661 ],
26392662 );
26402663
+1-1
src/lib/classes.ts
···406406 `SELECT id, user_id, meeting_time_id, section_id, filename, original_filename, status, progress, error_message, created_at, updated_at
407407 FROM transcriptions
408408 WHERE class_id = ?
409409- ORDER BY created_at DESC`,
409409+ ORDER BY recording_date DESC, created_at DESC`,
410410 )
411411 .all(classId);
412412}