diff --git a/backend/src/controllers/attendance.ts b/backend/src/controllers/attendance.ts index 6069c3e..29df9d5 100644 --- a/backend/src/controllers/attendance.ts +++ b/backend/src/controllers/attendance.ts @@ -2,6 +2,8 @@ import { validationResult } from "express-validator"; import { Types } from "mongoose"; import { AttendanceModel } from "../models/attendance"; +import { Section } from "../models/sections"; +import { SessionModel } from "../models/session"; import type { RequestHandler } from "express"; @@ -54,6 +56,37 @@ export const updateAttendanceById: RequestHandler = async (req, res, next) => { } }; +const getStudentsInSection = async (sectionId: Types.ObjectId): Promise => { + const section = await Section.findById(sectionId).select("enrolledStudents"); + + // Can't be null because of validation checks prior to calling this function + return section!.enrolledStudents; +}; + +export const ensureAttendanceForSession = async (sessionId: string) => { + const existing = await AttendanceModel.find({ session: sessionId }); + if (existing.length > 0) return existing; + + const session = await SessionModel.findById(sessionId); + if (!session) throw new Error("Session not found"); + + const sessionDate = new Date(session.sessionDate); + const today = new Date(); + sessionDate.setHours(0, 0, 0, 0); + today.setHours(0, 0, 0, 0); + // Don't create attendance for future sessions + if (sessionDate > today) return []; + + const students = await getStudentsInSection(session.section); + await Promise.all( + students.map(async (studentId) => + AttendanceModel.create({ session: session._id, student: studentId, status: "PRESENT" }), + ), + ); + + return AttendanceModel.find({ session: sessionId }); +}; + export const getAttendanceBySessionId: RequestHandler = async (req, res, next) => { try { const errors = validationResult(req); diff --git a/backend/src/controllers/session.ts b/backend/src/controllers/session.ts index 9182da1..6065cf8 100644 --- a/backend/src/controllers/session.ts +++ b/backend/src/controllers/session.ts @@ -1,18 +1,11 @@ import { validationResult } from "express-validator"; import { AttendanceModel } from "../models/attendance"; -import { Section } from "../models/sections"; import { SessionModel } from "../models/session"; -import type { RequestHandler } from "express"; -import type { Types } from "mongoose"; - -const getStudentsInSection = async (sectionId: string): Promise => { - const section = await Section.findById(sectionId).select("enrolledStudents"); +import { ensureAttendanceForSession } from "./attendance"; - // Can't be null because of validation checks prior to calling this function - return section!.enrolledStudents; -}; +import type { RequestHandler } from "express"; type CreateSessionBody = { section: string; @@ -30,22 +23,6 @@ export const createSession: RequestHandler = async (req, res, next) => { sessionDate, }); - // create Attendance records for all students enrolled in Section - - // Get all student Ids in the section (enrolledStudents list) - const students = await getStudentsInSection(section); - - // Create attendance records for all students in session - await Promise.all( - students.map(async (studentId) => - AttendanceModel.create({ - session: session._id, - student: studentId, - status: "PRESENT", - }), - ), - ); - return res.status(201).json(session); } catch (error) { next(error); @@ -87,14 +64,13 @@ export const getSession: RequestHandler = async (req, res, next) => { return res.status(404).json({ error: "Session not found" }); } - // Check what we are searching for in the Attendance collection - const query = { session: id }; - // Run the query - const attendanceRecords = await AttendanceModel.find(query).populate("student"); + // This creates records if missing, checks the date, returns them + const attendanceRecords = await ensureAttendanceForSession(id); + const populated = await AttendanceModel.populate(attendanceRecords, { path: "student" }); const response = { ...session.toObject(), - attendees: attendanceRecords, + attendees: populated, }; res.status(200).json(response); diff --git a/frontend/src/app/(pages)/attendance/page.tsx b/frontend/src/app/(pages)/attendance/page.tsx index adaadab..14a8488 100644 --- a/frontend/src/app/(pages)/attendance/page.tsx +++ b/frontend/src/app/(pages)/attendance/page.tsx @@ -62,13 +62,12 @@ export default function Attendance() { void load(); }, [activeSectionId]); - // Derive available dates from the loaded sessions for this section + // Derive available dates using local time const availableDates = sessionList.map((s) => { const d = new Date(s.sessionDate); - // Use UTC values to avoid timezone shift - const year = d.getUTCFullYear(); - const month = String(d.getUTCMonth() + 1).padStart(2, "0"); - const day = String(d.getUTCDate()).padStart(2, "0"); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, "0"); + const day = String(d.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }); @@ -88,8 +87,13 @@ export default function Attendance() { if (!activeSectionId || !activeDate) return; const match = sessionList.find((s) => { - const sDate = new Date(s.sessionDate).toISOString().split("T")[0]; - return sDate === activeDate; + const d = new Date(s.sessionDate); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, "0"); + const day = String(d.getDate()).padStart(2, "0"); + const localSessionDate = `${year}-${month}-${day}`; + + return localSessionDate === activeDate; }); if (match) {