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 (Leave Module)

App-level navigation pattern per 00-shared/05 (global IA). Leave is a top-level workspace reachable from the home grid; org-admin surfaces nest under the same workspace. Routes are client-side names (forward-looking) until the Flutter client lands; the API surface is authoritative (leave.controller.ts:25-28, tag leave).


1. Navigation tree

Home
└── Leave workspace  (/leave)
    ├── My Requests           (/leave/requests)          — every user
    │   ├── Request Detail    (/leave/requests/:id)      — read-only for requester
    │   └── New Request       (/leave/requests/new)      — form
    ├── My Balance            (/leave/balance)           — every user
    ├── Leave Calendar        (/leave/calendar)          — every user (approved only)
    └── [Org Admin only]
        ├── Approvals Queue   (/leave/approvals)         — status=pending default
        ├── Substitutions     (/leave/substitutions)     — list + assign sheet
        └── Leave Types       (/leave/types)             — list + create sheet

2. Role gating (from source)

  • Every user (any authenticated JWT, leave.controller.ts:27): create request, list own requests, balance, types list, calendar.
  • org_admin only (inline check leave.service.ts:163): see all requests (:167), decide (leave.controller.ts:49-53), create types (:61-65), assign substitutions (:73-77).
  • Substitute teacher: GET /leave/substitutions/teacher/:id (leave.controller.ts:79-83) — client calls with the substitute's own teacher id.
  • No leave.* permissions exist (permissions.constants.ts:1-97); do not invent client-side gates stronger than the API. See gap in §5.

3. Content types

ContentSourceOwner
LeaveRequestleave_requests collection (leave-request.schema.ts:14)requester + admin
LeaveTypeleave_types (leave-type.schema.ts:7)org admin (defaults seeded)
Substitutionsubstitutions (substitution.schema.ts:13)org admin
Balancecomputed, no collection (leave.service.ts:87-88)per user

4. Screen-to-data map

ScreenDataEndpoint
My Requestsrequests (own)GET /leave/requests (leave.controller.ts:38-47)
New Requesttypes + postGET /leave/types + POST /leave/requests (:67-71, :32-36)
Approvals Queuerequests (all)GET /leave/requests?status= (:38-47)
My BalancebalanceGET /leave/balance/:userId (:55-59)
CalendarapprovedGET /leave/calendar?from&to (:85-91)
SubstitutionsassignedGET /leave/substitutions/teacher/:id (:79-83)
Leave TypestypesGET /leave/types (:67-71)

5. Known IA gaps (from source)

  • Cancel — status cancelled exists (leave-request.schema.ts:11) but no endpoint can produce it → no cancel action anywhere in IA.
  • Request detail — no GET /leave/requests/:id; the client must pass the whole object from the list (list is the only read surface).
  • RBAC — approvals UI must hide for non-admins by client role check; the API would still enforce at leave.service.ts:163-167 (non-admin userId filter) and :179-180 (self-decision).
  • Balance for other usersGET /leave/balance/:userId accepts any id; no server check restricts it (gap — expose only admin/own in client).
  • Substitutions list for absent teacher — endpoint only lists by substituteTeacherId (leave.service.ts:275-280); no "who covers me" list for the absent teacher (gap).

6. Entry points

  • Home grid tile "Leave" (per 00-shared/05).
  • Notification tap → deep link to request detail (planned) — driven by LeaveApproved/LeaveRejected events (events/leave-events.ts:10-18).
  • Calendar day tap → request detail sheet.