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

07 — Component Library (Communication Module)

Module-specific components. Reuse 00-shared/03 (App*) for everything generic; only announcement-specific composites live here. All components are stateless widgets driven by Cubit state (see 13_State_Management.md).


1. AnnouncementCard

PropertyTypeNotes
announcementAnnouncement modelfrom GET /announcements payload (announcement.schema.ts:31-53)
isUnreadboolderived: myUserId ∉ readBy[].userId
onTapVoidCallback→ detail
trailingwidget?optional AppMenu (authors: view receipts)

Render: AppCard + AppListTile: unread dot (leading, 8 dp amber dot — semantics "Unread"), title titleMedium, body excerpt bodySmall maxLines 2, row of AudienceChip + AnnouncementStatusBadge, createdAt relative time. Draft rows show AnnouncementStatusBadge(draft) and no unread dot (recipients never see drafts — draft filter is published: false, announcement.schema.ts:45-46).

States: idle / loading (AppSkeleton variant) / error.

2. AudienceChip

PropertyTypeNotes
audienceAnnouncementAudience{ type, value } (announcement.schema.ts:15-21)

Label mapping (verbatim enum, announcement.schema.ts:7-13):

typelabel
all"Everyone"
rolevalue (e.g. "Teacher")
gradevalue (e.g. "Grade 10")
sectionvalue (e.g. "10-A")
custom"Selected people" (+count if known)

AppChip with module palette (see 11_Design_System_Mapping.md).

3. AnnouncementStatusBadge

PropertyTypeNotes
publishedboolannouncement.schema.ts:45-46
  • true → "Published" + publishedAt on detail
  • false → "Draft" (publishedAt absent — :48-49)

AppBadge; published = success color, draft = neutral.

4. ReadReceiptBar

PropertyTypeNotes
readCountintreadBy.length (announcement.service.ts:104-107)
targetCountinttargetUserIds.length; 0 ⇒ render "Everyone", hide ratio (announcement.service.ts:144-146)

Render: progress bar (readCount/targetCount) + "72 of 120 read". Used on "AnnouncementCard(authors)" and receipts sheet.

5. ReadReceiptRow

PropertyTypeNotes
userIdstringreceipt.userId (announcement.schema.ts:24-25)
readAtDateTime:27-28
displayNamestringuser lookup (forward-looking) — API returns ids only

AppListTile: avatar, name, "Read 3 Aug 9:04". Unread variant shows "Not read yet".

6. AudiencePicker (composer)

PropertyTypeNotes
valueAnnouncementAudience{ type, value? }
onChangedcallback
optionsenum listall|role|grade|section|custom (announcement.schema.ts:7-13)

Render: 5 AppChoiceChips + conditional value input:

  • role → dropdown of org roles (RBAC constants (planned) — no perms exist today)
  • grade / section → picker fed by academics module data (values are names, announcement.service.ts:121,128)
  • custom → user search + chips
  • all → none; label "Everyone in your school"

7. ComposerField (reused trio)

AppTextField variants bound to DTO: title (single-line), body (multiline), attachments chip list (create-announcement.dto.ts:29-49). Validation mirrors class-validator rules (see 08_Form_Specifications.md §5).

8. ThreadTile / MessageBubble (secondary surface)

AppListTile (thread row) + outgoing/incoming bubble with sentAt, delivery tick (WebSocket (planned)IMPLEMENTATION_PLAN.md:119). Deferred detail to messaging package.


Composability map (screen → component)

Screen (05)Components
FeedAnnouncementCard, AudienceChip, AnnouncementStatusBadge, App*
DetailAnnouncementStatusBadge, AudienceChip, AppSheet/Page
ComposeAudiencePicker, ComposerField, App*
MineAnnouncementCard, AnnouncementStatusBadge
ReceiptsReadReceiptBar, ReadReceiptRow
ThreadsThreadTile, MessageBubble