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

05 — Screen Inventory (Communication Module)

Every screen of the Communication 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. Format mirrors design-docs/auth/05_Screen_Inventory.md.


Legend

States = idle / loading / success / empty / error(offline, network) / disabled / permission. Analytics events follow {module}.{screen}.{action} (proposed; SDK open — 00-shared/10 §8). Permissions: controller is guarded by JwtAuthGuard only (announcements.controller.ts:11,18) — no communication.* RBAC perms exist yet (absent from permissions.constants.ts); role gates below are design intent (planned).


1. Announcement Feed (/announcements) — all authenticated users

FieldDetail
PurposeConsume school announcements; primary recipient surface
Entrydashboard Communication hub, app open, push tap (forward-looking)
Exitdetail sheet; compose (authors); /announcements/mine
SourceGET /announcements (+ optional ?audience=) → sort: { createdAt: -1 } (announcement.service.ts:56-60)
Tabs"For me" (client-filtered: targetUserIds contains me, or audience.type === 'all') / "All" — client-side only (forward-looking), backend does not filter by user (announcement.service.ts:56-60)
Row widgetsAppCard announcement tile: title, body excerpt, audience chip, status badge (draft/published), unread dot, date
Pull-to-refreshRefreshIndicator re-fetches list
Empty"No announcements" + CTA "Create one" (authors)
Statesloading skeleton; error offline banner + retry; permission (401 → login)
Analyticscomm.announcements.{open,refresh,tab_switch} (proposed)
a11yunread dot exposed via semantics label "Unread"; chips readable by TalkBack
Motionlist fade m-base; new item slide-in m-base (motion tokens 00-shared/08)

2. Announcement Detail (/announcements/:id — bottom sheet on mobile, page on tablet)

FieldDetail
PurposeFull body, audience line, attachments, mark-as-read action
Entryfeed row tap, search result, push deep link (forward-looking)
Exitback; attachments via external browser
SourceGap: no GET /announcements/:id route (announcements.controller.ts has only create/list/publish/read/reads). Use the list payload + receipt action (forward-looking)
ActionsPOST /announcements/:id/read — idempotent $addToSet (announcement.repository.ts:20-33); auto-fire on open for recipients (design choice, (proposed))
Audience line"To: Grade 10 · 120 recipients" from audience.type/value + targetUserIds.length
Status badgedraft / published + publishedAt local-formatted
Emptynot applicable (not-found → snackbar + pop)
a11ybody as single readable block; read-state announced via live region
Analyticscomm.announcement.detail.{open,mark_read,attachment_open} (proposed)

3. Compose Announcement (/announcements/compose) — authors

FieldDetail
PurposeCreate draft; audience targeting; publish in one flow
Entryfeed FAB, /announcements/mine FAB, empty-state CTA
Exitsave draft → success → feed/mine; publish → success → feed
SourcePOST /announcements (draft, published: false, createdBy from context — announcement.service.ts:31-37) then optional POST /announcements/:id/publish
Formtitle, body, audience picker (type + value), attachments (planned: upload), priority/expiry (planned — no fields in schema) — see 08_Form_Specifications.md
Audience warning"0 recipients will receive this" when resolution yields [] (role/grade/section typos) (planned) — backend resolves silently (announcement.service.ts:109-148)
Statesvalidation inline; draft saved snackbar; publish spinner
Analyticscomm.announcement.compose.{save_draft,publish,audience_change} (proposed)
Keyboardtitle .text, body multiline; toolbar above keyboard
a11ylabels linked; audience picker as radio group

4. My Announcements (/announcements/mine) — authors

FieldDetail
PurposeAuthor's own drafts + published list
Sourcesame GET /announcements; client filters createdBy == me — backend has no "mine" query (forward-looking)
Rowannouncement tile + status badge (draft / published) + reads count
Empty"No announcements yet" + FAB compose
Analyticscomm.announcements.mine.{open,status_filter} (proposed)

5. Read Receipts (/announcements/:id/reads — sheet) — authors

FieldDetail
PurposeWho read / who hasn't
SourceGET /announcements/:id/readsreadBy[] (announcement.service.ts:104-107); read count + targetUserIds.length from list payload
RowsAppListTile: name (user lookup), readAt; segmented "Read / Unread" (unread = targetUserIds − readBy)
Statesloading; empty (nobody read yet)
Analyticscomm.announcement.reads.{open,segmented_switch} (proposed)
Noteexport / laggard reminders (planned)

6. Threads List (/threads) — module secondary surface

FieldDetail
SourceGET /threads (threads.controller.ts)
RowAppListTile conversation: partner avatar, last message, unread badge
Empty"No conversations" + FAB new thread
Analyticscomm.threads.{open,search} (proposed)

7. Thread Detail / Chat (/threads/:id)

FieldDetail
SourceGET /threads/:id, send POST /messages, mark read PATCH /threads/:id/read (IMPLEMENTATION_PLAN.md:107-112)
RealtimeWebSocket via existing WsModule (planned)IMPLEMENTATION_PLAN.md:119
Statesoffline → outbox queue (forward-looking)
Analyticscomm.thread.{open,send,read} (proposed)

8. Messaging Compose (new thread / 1:1) — light spec

Recipient picker (user search), body field; creates via POST /threads + POST /messages. Full spec deferred — threads are secondary in this package.


Shared components used

AppCard, AppListTile, AppButton, AppTextField, AppSnackbar, AppChips, AppBadge, AppBottomSheet, AppDialog, AppMenu, AppSkeleton, AppEmptyState, AppOfflineBanner, AppFAB, AppAvatar, AppSegmentedControl. Module-specific: AnnouncementCard, AudienceChip, AnnouncementStatusBadge, ReadReceiptRow, AudiencePicker — defined in 07_Component_Library.md.

Analytics events (proposed)

comm.announcements.*, comm.announcement.{detail,compose,reads}.*, comm.threads.*, comm.thread.* — all proposed (SDK open, 00-shared/10).

Keyboard, landscape, tablet, desktop

  • Feed/detail: portrait-first; tablet → two-column list/detail; desktop hover highlights.
  • Composer: full keyboard-avoidance + resizeToAvoidBottomInset; tablet centers card ≤ 640 dp.
  • Receipts: tablet shows segmented read/unread side-by-side.