05 — Screen Inventory (Rooms Module)
- Legend
- 1. Room List Screen (
/rooms) - 2. Room Detail Screen (
/rooms/:id) - 3. Room Editor — Create (
/rooms/new) and Edit (/rooms/:id/edit) - 4. Delete Room — confirm dialog
- Shared components used
- Analytics events (proposed)
- Keyboard, landscape, tablet, desktop
Every screen of the Rooms module, its intent, route, composition, states, permissions, platform behavior and events. Authoritative components in 00-shared/03; this file enumerates which ones each screen uses with module specifics.
Legend
States = idle / loading / success / empty / error(offline, rate, invalid) / disabled / permission.
Analytics events follow {module}.{screen}.{action} (proposed; SDK open — 00-shared/10 §8).
1. Room List Screen (/rooms)
| Field | Detail |
|---|---|
| Purpose | Browse, filter, and enter the tenant's room catalog |
| Entry | admin workspace nav, deep link /rooms |
| Exit | tap row → /rooms/:id; FAB → /rooms/new; filter sheet toggle |
| Source | GET /api/v1/rooms?page&limit (rooms.controller.ts:30-34) — pagination only; no sort/filter/q (OQ-3, rooms.controller.ts:32) |
| Widgets | AppAppBar "Rooms" + count badge; AppSearchBar (proposed) (client-side filter until API lands); AppChips type/building filters (proposed); RoomCard list (ListView.builder); AppEmptyState; AppSkeleton; AppOfflineBanner; AppFAB "New room" (gated rooms.create); AppErrorState retry |
| States | loading (skeleton rows), success (cards), empty ("No rooms yet" + create CTA), error (retry), offline (banner + last-good cache), permission (rooms.read false → no nav entry) |
| Pagination | page/limit + meta {hasNext} (pagination-query.dto.ts:32-39); infinite scroll; pull-to-refresh (RefreshIndicator) |
| Permissions | read: rooms.read; create CTA: rooms.create (permissions.constants.ts:50-51) — client-gated (OQ-2) |
| Analytics | rooms.list.open, rooms.list.filter.{type,building}, rooms.list.search, rooms.list.load_more, rooms.list.refresh (proposed) |
| Adaptive | phone: single column + FAB; tablet/desktop ≥840 dp: master-detail split (list + detail pane, 00-shared/05 §3) |
2. Room Detail Screen (/rooms/:id)
| Field | Detail |
|---|---|
| Purpose | Full room profile: meta, facilities, actions |
| Entry | Room List row, deep link studylyon://rooms/:id (forward-looking) |
| Exit | back → List; Edit → /rooms/:id/edit; Delete → confirm dialog → List |
| Source | GET /api/v1/rooms/:id (rooms.controller.ts:36-40); 404 → "Room not found" |
| Widgets | AppCard header (name, type icon, code chip); meta grid (type, capacity, building); AppChips facilities; AppListTile section rows; AppButton Edit / Delete (gated); AppSnackbar on mutations |
| States | loading, success, error(404/offline/network), deleted (row gone → snackbar) |
| Permissions | read rooms.read; Edit rooms.update; Delete rooms.delete (client-gated, OQ-2) |
| Actions | Edit → editor; Delete → typed-confirm dialog (DELETE /api/v1/rooms/:id — rooms.controller.ts:48-52); (planned) Book CTA when bookings module lands |
| Future | QR code card (forward-looking): render room.code as QR for signage; check-in analytics (proposed) |
| Analytics | rooms.detail.open, rooms.detail.edit, rooms.detail.delete.{start,confirm,cancel} (proposed) |
| Adaptive | tablet/desktop: two-column (info + availability (planned)); sheet editor on narrow |
3. Room Editor — Create (/rooms/new) and Edit (/rooms/:id/edit)
| Field | Detail |
|---|---|
| Purpose | Create or update a room document |
| Entry | List FAB (create, gated rooms.create); Detail "Edit" (gated rooms.update) |
| Exit | save → pop (Detail or List) + snackbar; cancel → discard confirm if dirty |
| Source | create: POST /api/v1/rooms (rooms.controller.ts:24-28); edit: PATCH /api/v1/rooms/:id (rooms.controller.ts:42-46) — reuses CreateRoomDto, so name+code required even on PATCH (OQ-6, rooms.controller.ts:44) |
| Form | AppTextField name*, code* (with uniqueness hint), capacity (number, (proposed) min 1 — OQ-7), AppDropdown type (RoomType enum, default classroom), AppTextField building, AppChips facilities input |
| States | idle, validating (async code check (proposed)), submitting (button), success (pop), error: 400 field errors, 409 duplicate code inline (create only today; update (planned) OQ-1), offline block |
| Permissions | rooms.create / rooms.update |
| Analytics | rooms.editor.{create,edit}.{open,submit,success,failure,duplicate} (proposed) |
| Adaptive | phone: single-column scroll + keyboard avoidance; tablet/desktop: centered card ≤ 640 dp |
4. Delete Room — confirm dialog
| Field | Detail |
|---|---|
| Purpose | Confirm soft delete with explicit room name |
| Source | DELETE /api/v1/rooms/:id (rooms.controller.ts:48-52); void response (rooms.service.ts:48) |
| Behaviour | typed-name confirm (matches room.name); loading state on confirm; success → pop to List + snackbar; 404 → "already deleted" snackbar |
| Gap | no in-use guard (OQ-4) — warn copy "room may be referenced by timetables" (planned) server truth |
| Analytics | rooms.delete.confirm, rooms.delete.cancel (proposed) |
Shared components used
AppAppBar, AppSearchBar, AppChips, AppCard, AppListTile, AppTextField,
AppDropdown, AppButton, AppFAB, AppSkeleton, AppEmptyState, AppErrorState,
AppOfflineBanner, AppSnackbar, AppDialog, AppMenu, RefreshIndicator,
AppAvatar/AppIconBadge. Module-specific: RoomCard, RoomTypeIcon, CapacityBadge,
FacilityChips — defined in 07_Component_Library.md.
Analytics events (proposed)
rooms.list.{open,filter,search,load_more,refresh}, rooms.detail.{open,edit,delete},
rooms.editor.{open,submit,success,failure,duplicate}, rooms.delete.{confirm,cancel}.
Future: rooms.booking.{book,cancel} (planned), rooms.checkin.scan (forward-looking),
rooms.analytics.utilization (proposed).
Keyboard, landscape, tablet, desktop
- Editor: portrait-first; landscape scrolls; tablet/desktop constrain width (≤ 640 dp card).
- List: master-detail at ≥ 840 dp; desktop hover highlights rows; filter chips wrap.
- All fields keyboard-avoidance +
ScrollViewresizeToAvoidBottomInset.