Skip to content
Draft
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d0faaff
feat: added class joining for students and removed dummy auth for now
Krishang-Zinzuwadia Oct 31, 2025
8979ac6
Merge pull request #1 from Krishang-Zinzuwadia/dev
vimal-299 Oct 31, 2025
5ee0569
feat: Added Auth
Maitri-shah29 Oct 31, 2025
8661ee4
Auth: fixed role handling and routing
Maitri-shah29 Oct 31, 2025
e626b71
Merge pull request #2 from Maitri-shah29/dev
vimal-299 Oct 31, 2025
87b78fb
feat: Attendance Working
RishikaGupta915 Nov 1, 2025
dc73cb1
feat(quiz): integrate quiz creation and fetching with backend API
devipriya006 Nov 1, 2025
758bd8d
fix: update project files
devipriya006 Nov 1, 2025
dfb68fd
fixes
RishikaGupta915 Nov 1, 2025
a5b2ac7
refactor(backend): enhance code clarity
devipriya006 Nov 1, 2025
75ddf55
Removed trivial files
devipriya006 Nov 1, 2025
979c340
Merge pull request #4 from RishikaGupta915/dev
Krishang-Zinzuwadia Nov 1, 2025
19bf69f
Merge branch 'dev' into dev
Krishang-Zinzuwadia Nov 1, 2025
d73d77c
Merge pull request #5 from devipriya006/dev
Krishang-Zinzuwadia Nov 1, 2025
535fa02
feat: made classes integrated with the db
Krishang-Zinzuwadia Nov 1, 2025
c8f07d5
feat: added frontend too
Krishang-Zinzuwadia Nov 1, 2025
3288132
feat: fixes
Krishang-Zinzuwadia Nov 1, 2025
ad15aa8
Update backend/routes/classes.js
Krishang-Zinzuwadia Nov 1, 2025
47583d9
Update backend/routes/classes.js
Krishang-Zinzuwadia Nov 1, 2025
da8f802
Update frontend/lib/api/classes.js
Krishang-Zinzuwadia Nov 1, 2025
cb8679b
Update frontend/app/student/class/[id]/page.jsx
Krishang-Zinzuwadia Nov 1, 2025
c811837
Merge pull request #6 from Krishang-Zinzuwadia/dev
vimal-299 Nov 1, 2025
b4adb4c
UI/UX improvement
vimal-299 Nov 1, 2025
834e39a
feat: made notes quizzes and announcements integrated with the db
Krishang-Zinzuwadia Nov 1, 2025
6f96397
feat: addded shit
Krishang-Zinzuwadia Nov 1, 2025
e8dd40d
Merge pull request #7 from Krishang-Zinzuwadia/dev
Krishang-Zinzuwadia Nov 1, 2025
dec05eb
feat: quiz fixes
Krishang-Zinzuwadia Nov 1, 2025
ae72471
fix : quiz shit smh
Krishang-Zinzuwadia Nov 1, 2025
7820742
Merge branch 'ACM-VIT:dev' into dev
Krishang-Zinzuwadia Nov 1, 2025
d3136a4
gotta be ragebait
Krishang-Zinzuwadia Nov 1, 2025
99d3649
Merge pull request #12 from Krishang-Zinzuwadia/dev
Krishang-Zinzuwadia Nov 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
node_modules/
# dependencies
node_modules/

# environment variables
.env
.env.local
.env.development
.env.production

# system files
.DS_Store
Thumbs.db

# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
88 changes: 88 additions & 0 deletions backend/attendance/attendanceDB.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
class AttendanceDB {
constructor() {
this.attendance = [];
this.nextId = 1;
}

async save(classId, date, entries) {
const dateStr = new Date(date).toDateString();
const existingIndex = this.attendance.findIndex(
(record) => record.classId === classId && record.date === dateStr
);

const attendanceRecord = {
id:
existingIndex >= 0 ? this.attendance[existingIndex].id : this.nextId++,
classId,
date: dateStr,
entries,
createdAt:
existingIndex >= 0
? this.attendance[existingIndex].createdAt
: new Date(),
updatedAt: new Date(),
};

if (existingIndex >= 0) {
this.attendance[existingIndex] = attendanceRecord;
return { message: 'Attendance updated', attendance: attendanceRecord };
} else {
this.attendance.push(attendanceRecord);
return { message: 'Attendance created', attendance: attendanceRecord };
}
}

// Find attendance by class and date
async findByClassAndDate(classId, date) {
const dateStr = new Date(date).toDateString();
return this.attendance.find(
(record) => record.classId === classId && record.date === dateStr
);
}

// Find all attendance for a student
async findByStudent(studentId) {
const studentRecords = [];

this.attendance.forEach((record) => {
const studentEntry = record.entries.find(
(entry) => entry.studentId === studentId
);
if (studentEntry) {
studentRecords.push({
classId: record.classId,
date: record.date,
status: studentEntry.status,
recordId: record.id,
});
}
});

return studentRecords;
}

// Get all attendance records
async findAll() {
return this.attendance;
}

// Get attendance summary for a class
async getClassSummary(classId) {
const classRecords = this.attendance.filter(
(record) => record.classId === classId
);
return classRecords.map((record) => ({
date: record.date,
totalStudents: record.entries.length,
presentCount: record.entries.filter((entry) => entry.status === 'present')
.length,
absentCount: record.entries.filter((entry) => entry.status === 'absent')
.length,
entries: record.entries,
}));
}
}

const attendanceDB = new AttendanceDB();

export default attendanceDB;
100 changes: 100 additions & 0 deletions backend/attendance/attendanceRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import express from 'express';
import Attendance from '../models/attendance.js';

const router = express.Router();

router.post('/', async (req, res) => {
try {
console.log('Received attendance data:', req.body);
const { classId, date, entries } = req.body;

if (!classId || !date || !entries) {
console.log('Missing required fields');
return res
.status(400)
.json({ error: 'Missing required fields: classId, date, entries' });
}

const existing = await Attendance.findOne({ classId, date });

if (existing) {
console.log('Updating existing attendance record');
existing.entries = entries;
await existing.save();
console.log('Attendance updated successfully');
return res.json({ message: 'Attendance updated', attendance: existing });
}

console.log('Creating new attendance record');
const newAttendance = new Attendance({ classId, date, entries });
await newAttendance.save();
console.log('Attendance saved successfully:', newAttendance);
res.status(201).json(newAttendance);
} catch (error) {
console.error('Error saving attendance:', error);
res.status(500).json({ error: error.message });
}
});

router.get('/debug/all', async (req, res) => {
try {
console.log('Fetching ALL attendance records for debugging');
const allRecords = await Attendance.find({}).limit(50);
console.log('Total records in database:', allRecords.length);

const summary = allRecords.map((r) => ({
classId: r.classId,
date: r.date,
studentIds: r.entries.map((e) => e.studentId),
entriesCount: r.entries.length,
}));

res.json({
totalRecords: allRecords.length,
records: summary,
fullRecords: allRecords,
});
} catch (error) {
console.error('Error fetching all records:', error);
res.status(500).json({ error: error.message });
}
});

router.get('/student/:studentId', async (req, res) => {
try {
const { studentId } = req.params;
console.log('Attendance for student:', studentId);

const records = await Attendance.find({ 'entries.studentId': studentId });
console.log('Found', records.length, 'attendance records');

if (records.length > 0) {
console.log('Sample record:', JSON.stringify(records[0], null, 2));
}

const formatted = records.map((r) => ({
classId: r.classId,
date: r.date,
status:
r.entries.find((e) => e.studentId === studentId)?.status || 'absent',
}));

console.log('Sending formatted records:', formatted);
res.json(formatted);
} catch (error) {
console.error('Error fetching student attendance:', error);
res.status(500).json({ error: error.message });
}
});

router.get('/:classId/:date', async (req, res) => {
try {
const { classId, date } = req.params;
const attendance = await Attendance.findOne({ classId, date });
res.json(attendance || { message: 'No record found' });
} catch (error) {
res.status(500).json({ error: error.message });
}
});

export default router;
44 changes: 39 additions & 5 deletions backend/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
const express = require('express')
const app = express()
const port = 8000
import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
import dotenv from 'dotenv';
import attendanceRoutes from './attendance/attendanceRoutes.js';
import classRoutes from './routes/classes.js';

dotenv.config();

const app = express();
const port = 8000;

app.use(cors());
app.use(express.json());

const MONGODB_URI = process.env.MONGODB_URI;

if (!process.env.MONGODB_URI) {
console.warn(
' Warning: MONGODB_URI not found in .env file, using fallback'
);

}

console.log('Attempting to connect to MongoDB...');
mongoose
.connect(MONGODB_URI)
.then(() => {
console.log('Connected to MongoDB successfully');
console.log('Database:', mongoose.connection.name);
})
.catch((err) => {
console.error('MongoDB connection error:', err.message);
});

app.use('/api/attendance', attendanceRoutes);
app.use('/api/classes', classRoutes);
Comment on lines 1 to 40

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Quiz API never exposed after server rewrite

The frontend now loads quizzes from GET ${process.env.NEXT_PUBLIC_API_URL}/api/quiz and posts new quizzes to the same path, but the Express entry point only mounts attendance and class routes. backend/index.js no longer wires up /api/quiz, and the alternative server in backend/server.js that did mount those routes uses CommonJS and cannot run with the new "type": "module" package configuration. As a result every quiz fetch or creation call will return 404 once this commit is deployed. Consider importing the quiz router into index.js (after converting it to ESM) so /api/quiz is available on the running server.

Useful? React with 👍 / 👎.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i found this fixing this

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
console.log(`Server running on port ${port}`);
});
35 changes: 35 additions & 0 deletions backend/models/Class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import mongoose from 'mongoose';

const classSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
},
code: {
type: String,
required: true,
unique: true,
uppercase: true,
length: 6,
},
professorId: {
type: String,
required: true,
},
professorName: {
type: String,
required: true,
},
students: [{
type: String,
}],
createdAt: {
type: Date,
default: Date.now,
},
});

classSchema.index({ professorId: 1 });

export default mongoose.model('Class', classSchema);
17 changes: 17 additions & 0 deletions backend/models/Quiz.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const mongoose = require("mongoose");

const questionSchema = new mongoose.Schema({
question: { type: String, required: true },
options: { type: [String], required: true },
correctAnswer: { type: Number, required: true },
});

const quizSchema = new mongoose.Schema({
classId: { type: String, required: true },
title: { type: String, required: true },
questions: [questionSchema],
professor: { type: String, default: "Mr. Sharma" },
createdAt: { type: Date, default: Date.now },
});

module.exports = mongoose.model("Quiz", quizSchema);
14 changes: 14 additions & 0 deletions backend/models/attendance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import mongoose from 'mongoose';

const attendanceEntrySchema = new mongoose.Schema({
studentId: { type: String, required: true },
status: { type: String, enum: ['present', 'absent'], required: true },
});

const attendanceSchema = new mongoose.Schema({
classId: { type: String, required: true },
date: { type: Date, required: true },
entries: [attendanceEntrySchema],
});

export default mongoose.model('Attendance', attendanceSchema);
Loading