Tuesday, 25 November 2025

#Module 7 – Attendance UI & Bulk API

Module 7 – Attendance UI & Bulk API

Module 7 – Attendance UI & Bulk API

Build a simple web UI to mark attendance for 60-student classes and a bulk API endpoint to accept batch updates.

1. Single-page Attendance UI (HTML + JS)

Copy this file as attendance.html

<!doctype html>
<html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>Attendance</title></head><body>
<h2>Mark Attendance</h2>
<div>
  <label>SubjectId:<input id="subject" /></label>
  <label>Date:<input id="date" type="date" /></label>
  <label>Hour:<input id="hour" type="number" min="1" max="8" /></label>
  <button onclick="loadStudents()">Load Students</button>
</div>
<div id="students"></div>

<script>
async function loadStudents(){
  const subject = document.getElementById('subject').value;
  // call API to fetch students in this semester
  const res = await fetch(`/api/students?subjectId=${subject}`);
  const students = await res.json();
  const container = document.getElementById('students');
  container.innerHTML = '';
  students.forEach(s => {
    const row = document.createElement('div');
    row.innerHTML = ` ${s.name} (${s.student_code})`;
    container.appendChild(row);
  });
}

async function submitBulk(){
  const subject = document.getElementById('subject').value;
  const date = document.getElementById('date').value;
  const hour = parseInt(document.getElementById('hour').value||'1');
  const checks = Array.from(document.querySelectorAll('#students input[type=checkbox]'));
  const attendance = checks.map(c => ({ studentId: c.getAttribute('data-id'), status: c.checked? 'present' : 'absent'}));
  await fetch('/api/attendance/bulk',{ method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ subjectId: subject, date, hour, attendance }) });
  alert('Submitted');
}
</script>
<button onclick="submitBulk()">Submit Attendance</button>
</body></html>

2. Bulk API Endpoint (FastAPI)

# file: app/main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
import databases

DATABASE_URL = "postgresql://postgres:password@localhost/mcp_db"
db = databases.Database(DATABASE_URL)
app = FastAPI()

class AttRow(BaseModel):
  studentId: int
  status: str

class BulkIn(BaseModel):
  subjectId: int
  date: str
  hour: int
  attendance: List[AttRow]

@app.post('/api/attendance/bulk')
async def bulk_att(payload: BulkIn):
  # Basic validation
  if not payload.attendance:
    raise HTTPException(400,'No attendance rows')
  query = "INSERT INTO attendance(subject_id, staff_id, date, hour, student_id, status) VALUES(:subject_id, :staff_id, :date, :hour, :student_id, :status)"
  # staff_id will be set based on session - simplified here as NULL
  async with db.transaction():
    for r in payload.attendance:
      await db.execute(query, values={
        'subject_id': payload.subjectId,
        'staff_id': None,
        'date': payload.date,
        'hour': payload.hour,
        'student_id': r.studentId,
        'status': r.status
      })
  return { 'status': 'success', 'stored': len(payload.attendance) }

Notes

  • In production, attach staff_id from authenticated session and validate subject mapping.
  • Wrap the bulk insert in a transaction to ensure atomicity.
  • For 60 students, this endpoint should handle inserts promptly; consider using COPY or batch inserts for scale.

No comments:

Post a Comment

#MCP Index

MCP Tutorial – Module Index MCP Tutorial – 12 Modules Latest Edition for AU-CSE Final year Students Module 1 Introducti...