Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

04 — Information Architecture (Timetable Module)

Fits the shared shell (00-shared/05_Global_Information_Architecture.md). Timetable is a scheduling workspace over the Academics/Teachers/Rooms catalogs: routes live under an Academics/Scheduling destination, keyed by the entity being scheduled (class, teacher, room).


1. Placement in the app shell

  • Primary home: Academics destination (admin/coordinator role-gated) — the class grid is the entry surface, per-class navigation following the 05_Global_Information_Architecture.md:39 shell pattern.
  • Teacher schedule: secondary entry from Teacher detail · Schedule tab (GET /timetable?teacherId=, timetable.controller.ts:26); and a teacher-self "My Schedule" surface (planned).
  • Room schedule: tertiary, from Rooms module detail — client composition today, native (planned) (see 03 §J5).
  • Cross-links: Academics (classes, subjects, academic years), Teachers, Rooms, Notifications (TimetableEntryCreated consumers (planned)).

2. Sitemap (client, this module)

Academics (Scheduling)
└── Timetable
    ├── Class Timetable                /academics/timetable?classId=:id
    │   ├── Week view (default, current week)
    │   ├── Today view (filtered)
    │   └── Entry Editor (sheet/dialog)  →  /academics/timetable/new
    ├── Teacher Timetable              /academics/timetable/teacher/:teacherId
    │   └── (same grid, read-only for teacher role)
    └── Room Timetable (planned)       /academics/timetable/room/:roomId
Teacher (self)
└── My Schedule (planned)              /my/schedule
Rooms
└── Room Detail → Schedule tab         /rooms/:id/schedule

3. Screen relationships

  • Class grid → tap empty slot → Entry Editor (bottom sheet on phone, dialog on desktop); tap filled slot → detail popover → "Edit" (planned) / "Duplicate".
  • Class grid ↔ Teacher grid: switch scope via segmented control on the same route — data source swaps between ?classId= and ?teacherId= (timetable.controller.ts:23-26).
  • Grid → Room view: open from a slot's room chip (composed view, 03 §J5).
  • Conflict banner is inline state of the editor, not a page.

4. Navigation details

AspectRule
Route paramsclassId / teacherId / roomId = Mongo ObjectIds (timetable.schema.ts:18-28)
Grid scope statecurrent scope (class | teacher | room) + week offset — kept in shell state across navigation (05 §3)
Deep linkstudylyon://timetable?classId=:id; studylyon://timetable/teacher/:teacherId
Breadcrumbsdesktop: Academics › Timetable › {Class name}
FABGrid screens: "Add slot" opens the editor prefilled with the current class
Context menuSlot long-press / right-click: Edit (planned), Duplicate, Delete (planned)
Keyboard+ / N = new slot; ←/→ = week navigation (desktop)

5. Role → surface gating (client-side; server enforces JWT only — 01 §5)

Surfaceorg_admin / coordinator (timetable.create)teacher (self)read-only staff
Class gridfullread (timetable.read, permissions.constants.ts:44)
Teacher gridfullown only (planned)read
Room view (planned)fullread
Entry editor (create)full
Edit / delete (planned)full

Server reality: no endpoint carries RBAC metadata (timetable.controller.ts:9); cross-tenant access is still structurally blocked via scopedFilter (base.repository.ts:20-30).

6. Information units (primary entities)

EntityCollectionKey fieldsClient model
TimetableEntrytimetable_entriesclassId, subjectId, teacherId, roomId?, dayOfWeek, startTime, endTime, academicYearIdTimetableEntry
Class (ref)classesname, gradeId, sectionId, academicYearId, roomId (string, distinct)Class (reference)
Subject (ref)subjectscode, name, shortNameSubject (reference)
Teacher (ref)teachersemployeeNumber, employmentStatus, userIdTeacher (reference)
Room (ref)roomsname, code, capacity, typeRoom (reference)
AcademicYear (ref)academic_yearsname, startDate, endDate, isCurrentAcademicYear (reference)

Server returns raw ObjectIds for all refs (timetable.schema.ts:18-40) — the client joins names from catalogs; missing ref id renders "—".

7. Empty-state strategy

  • Grid with zero entries → AppEmptyState "No classes scheduled" + CTA "Add slot".
  • Single empty day → dashed empty cells, no empty-state page.
  • Teacher grid empty → "No classes scheduled" (no editor CTA for teacher role).
  • Room view with no matches → "No bookings for this room".
  • Conflict submit → inline AppBanner, never an empty state.