07 - Component Library (Webhooks Module)
- 1.
EventPickerChipField - 2.
SecretField - 3.
DeliveryLogTile - 4.
MetricsTile(4-stat grid) - 5.
SignatureVerifyCard(developer helper)(forward-looking) - Composition map (screen → module widgets)
Module-specific widgets on top of 00-shared/03 (authoritative component library). Shared components (
AppTextField,AppButton,AppDialog,AppSnackbar,AppCard,AppListTile,AppMenu,AppChips,AppBadge,AppFAB,AppSwitch,AppStatTile,AppSkeleton,AppEmptyState,AppErrorState,AppBottomSheet) are reused as-is; this file adds only what the module needs that shared does not define.
1. EventPickerChipField
| Attribute | Value |
|---|---|
| Purpose | Multi-select of domain event types (the webhook's events array) |
| Data | vocabulary from event-queue-map.ts:6-43 + WebhookTested (webhooks.service.ts:134); stored value string[] (webhook.schema.ts:16-17) |
| Props | selected: Set<String>, onChanged, allowCustom: bool = false, maxVisible: int = 12 |
| Behaviour | AppChips filterable grid; free-text "custom event" input chip when allowCustom (API accepts any string - create-webhook.dto.ts:20-24); grouped by source module (users/attendance/homework/results/students/teachers/staff/parents/fees/payments, event-queue-map.ts:6-43) |
| Validation | ≥ 1 selected (mirror @ArrayMinSize(1), create-webhook.dto.ts:22-23) |
| a11y | each chip semanticsLabel "Event X, selected/unselected"; group headers as Semantics headers |
2. SecretField
| Attribute | Value |
|---|---|
| Purpose | Signing-secret input with generate/reveal (create + edit + detail) |
| Props | value, onChanged, obscured: bool = true, onGenerate, canReveal |
| Behaviour | obscure toggle (eye icon); "Generate" fills a strong random secret (client-side only - no server generator); copy button on detail read-only variant |
| Security note | secret is stored plaintext and returned by API (webhooks.service.ts:31-47); field never logs; auto-clear clipboard after 30 s (proposed) |
| Validation | required on create (@IsString, create-webhook.dto.ts:27-28); blank = keep on edit |
3. DeliveryLogTile
| Attribute | Value |
|---|---|
| Purpose | One delivery attempt row (S5 list, S3 preview) |
| Data | log doc: eventType, status, responseCode?, attemptedAt, completedAt? (webhook-delivery-log.schema.ts:12-38) |
| Layout | leading status icon (pending clock / success check / failed alert), title eventType, subtitle responseCode · attemptedAt, trailing chevron |
| States | badge color per status: pending amber, success green, failed red - always with text (00-shared/09) |
| Interactions | tap → detail sheet; optional quick "Retry" on failed rows |
| Note | attemptCount exists on the schema (:31-32) but is always 0 today - tile hides it until the worker increments it (14_QA_Checklist.md G-2) |
4. MetricsTile (4-stat grid)
| Attribute | Value |
|---|---|
| Purpose | Health summary on S3 |
| Data | { total, success, failed, pending } from GET /webhooks/:id/metrics (webhooks.service.ts:142-156) |
| Layout | 2×2 AppStatTile grid; failed tile highlighted when > 0 with "Retry" affordance |
| States | per-tile load/error - one failure never blanks the grid |
5. SignatureVerifyCard (developer helper) (forward-looking)
| Attribute | Value |
|---|---|
| Purpose | Client-side verification of a captured signature against a body+secret |
| Algorithm | HMAC-SHA256 hex digest of raw request body (webhook-delivery.worker.ts:103-105) - mirrors the worker's sign() |
| Use | paste body + signature + secret → "Valid ✓ / Invalid ✗" |
| Note | documentation aid; not required by the API - receiver side is external. Signature has no timestamp/replay window today (QA G-4) |
Composition map (screen → module widgets)
| Screen (05) | Module widgets |
|---|---|
| S2/S4 | EventPickerChipField, SecretField |
| S3 | SecretField (read-only), MetricsTile |
| S5 | DeliveryLogTile |
| S6 | payload/response code blocks (monospace selectable text) |
| S3/S5/S6 | SignatureVerifyCard (dev mode) |