Skip to content

feat(timetable): replace the hard-coded weekly schedule with a real timetable module (fixes #251) - #256

Open
MOHITKOURAV01 wants to merge 2 commits into
Sitaram8472:mainfrom
MOHITKOURAV01:feat/issue-251-timetable-management
Open

feat(timetable): replace the hard-coded weekly schedule with a real timetable module (fixes #251)#256
MOHITKOURAV01 wants to merge 2 commits into
Sitaram8472:mainfrom
MOHITKOURAV01:feat/issue-251-timetable-management

Conversation

@MOHITKOURAV01

Copy link
Copy Markdown
Contributor

What this does

Closes #251.

frontend/src/components/WeeklyClassSchedule.jsx rendered five fake periods from an array literal inside the component, so every student in every class saw the same made-up week, no teacher could change it, and a day could only ever have one period. This PR adds a real timetable module and points the widget at it.

Backend

File What it adds
backend/models/Timetable.js Per class + section + academic year, periods[] with HH:mm validation, a pre-validate hook rejecting overlaps and duplicate period numbers, plus periodsForDay(), currentPeriod() and findClash()
backend/controllers/timetableController.js CRUD, per-period add/update/remove, activate/deactivate, and the resolved /me and /today views
backend/routes/timetableRoutes.js /api/timetables, teacher and admin guarded

Endpoints

GET    /api/timetables/me                        resolved for the caller
GET    /api/timetables/today                     today's periods, current one flagged
GET    /api/timetables                           list                (teacher/admin)
POST   /api/timetables                           create              (teacher/admin)
GET    /api/timetables/:id                       one timetable
PUT    /api/timetables/:id                       edit                (teacher/admin)
DELETE /api/timetables/:id                       delete              (teacher/admin)
POST   /api/timetables/:id/periods               add a period        (teacher/admin)
PUT    /api/timetables/:id/periods/:periodId     edit a period       (teacher/admin)
DELETE /api/timetables/:id/periods/:periodId     remove a period     (teacher/admin)
PATCH  /api/timetables/:id/activate              publish             (teacher/admin)
PATCH  /api/timetables/:id/deactivate            unpublish           (teacher/admin)

Frontend

  • components/teacher/TimetablePanel.jsx — a new Timetable tab on the Teacher Dashboard: create a grid for a class, add periods day by day with type (lecture/lab/activity/break/exam) and room, and publish it. Clashes are detected client-side before the request so an obvious mistake is reported instantly.
  • pages/Timetable.jsx/timetable. Full six-day grid on desktop, a day picker on mobile, a live "happening now" highlight that re-ticks every minute, weekly statistics, and a print stylesheet.
  • components/WeeklyClassSchedule.jsx — now fetches the active timetable and renders every period per day, falling back to the original sample week (clearly labelled as a sample) only when nothing is published or the API is unreachable, so the student dashboard never breaks.

Design notes

  • Times are HH:mm strings compared as minutes since midnight. That keeps the model free of timezones and makes overlap arithmetic trivially correct.
  • A class cannot be in two places at once. The pre-validate hook groups periods by day, rejects duplicate period numbers, then sorts by start time and rejects any period starting before the previous one ends. The error names both periods so the teacher knows exactly what to move.
  • findClash() is exposed on the model so the single-period endpoint can answer without re-validating the whole document, and the panel can preview the same rule client-side. One rule, three call sites.
  • Exactly one live timetable per class. Activating deactivates its siblings for the same class + section + year, and publishing an empty timetable is refused.
  • Errors are tagged. Clash and duplicate failures carry a userFacing flag, so the controller can return 400 for those and keep 500 for genuine bugs, rather than blanket-converting every thrown error into a client error.
  • /me resolves by role: a student gets their class grid, a teacher gets the periods they personally teach across every live class.

Verification

The validation rules were exercised directly:

PASS overlap: Monday: "Physics" (09:30-10:30) overlaps "Math" (09:00-10:00)
PASS duplicate: Duplicate period number 1 on Monday
PASS reversed times rejected
PASS malformed time ("9am") rejected
PASS valid timetable accepted; same times on different days allowed
PASS findClash detects a conflict and returns null on a free day

Plus node --check on every file, routers mounting on a real Express app, a clean vite build, and no new eslint errors.

Note on Mongoose 9

The project is on mongoose@^9.4.1, which no longer passes a next callback to document middleware — a callback-style pre('validate') hook resolves without running its body, which would have made the overlap checks silently no-ops. Both hooks are async functions; the second commit fixes this after it was caught in testing. Worth knowing for any other PR adding a model to this repo.

Compatibility

The only change to existing code is WeeklyClassSchedule gaining a data source, and it still renders when signed out or offline. server.js gains two lines, App.jsx one route, TeacherDashboard.jsx one tab.

WeeklyClassSchedule rendered five fake periods from an array literal, so
every student in every class saw the same made-up week and no teacher
could change it.

- Add Timetable model with HH:mm period validation and a pre-validate
  hook that rejects overlapping periods and duplicate period numbers
- Add periodsForDay/currentPeriod/findClash helpers so the controller and
  the UI agree on what "now" and "clash" mean
- Add timetableController with CRUD, per-period add/update/remove,
  activate (which deactivates the class's previous live timetable), and
  resolved /me and /today views
- Add /api/timetables routes with teacher and admin guards
- Add TimetablePanel dashboard tab that flags clashes before saving
- Add /timetable page: weekly grid, mobile day picker, live period
  highlight and a print stylesheet
- Make WeeklyClassSchedule read the API and fall back to the sample week
  only when nothing is published

Fixes Sitaram8472#251
Mongoose 9 no longer passes a `next` callback to document middleware, so
both callback-style pre('validate') hooks resolved without running their
checks — overlapping and duplicate periods were silently accepted.

Convert both hooks to async functions that throw.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Timetable Management — replace the hard-coded weekly class schedule with a real API

1 participant