Story CP-027: Notification UI (Bell, Unread Count, Offline Queuing)¶
Module: control-plane Slice: Slice 10b from architecture (split from CP-010) Brand context: [BOTH] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priority: 10.1 Depends on: CP-010 Estimated complexity: S
Objective¶
Build the notification UI components: bell icon with unread count badge, notification dropdown, mark-as-read interactions, and offline notification queuing. These components integrate into the host shell header and consume the notification backend from CP-010.
Backend Scope¶
No new backend work. This story consumes the API endpoints defined in CP-010:
| Method | Path | Response | Auth |
|---|---|---|---|
| GET | /api/v1/notifications | Page |
Any authenticated |
| GET | /api/v1/notifications/unread-count | {count} |
Any authenticated |
| PATCH | /api/v1/notifications/{id}/read | 204 | Any authenticated |
| PATCH | /api/v1/notifications/read-all | 204 | Any authenticated |
WebSocket subscription: /user/queue/notifications (STOMP over SockJS, configured in CP-010).
Frontend Scope¶
Pages & Routes¶
No dedicated notification page. Notifications appear in header bell icon — part of host shell.
Components¶
NotificationBell.tsx— Bell icon with unread count badge (integrates into host shell header). Connects to WebSocket for real-time updates.NotificationDropdown.tsx— Dropdown panel showing recent notifications (most recent first). "Tout marquer comme lu" link at top.NotificationItem.tsx— Single notification with read/unread styling. Tap → mark as read + navigate to relevant page.
UI States (ALL REQUIRED)¶
| State | Behavior | French Copy |
|---|---|---|
| No unread | Bell icon without badge | — |
| Unread | Bell icon with red badge showing count | — |
| Loading | Spinner in dropdown | — |
| Empty | Message in dropdown | "Aucune notification" |
| New notification | Bell bounces briefly, badge count increments | — |
| Offline | Queued notifications delivered on reconnect | — |
Responsive Behavior¶
- 360px (mobile): Bell in header. Dropdown takes full width. Notifications stacked vertically.
- 1024px+ (desktop): Bell in header. Dropdown as floating panel, max-width 400px.
Interactions¶
- Tap bell → dropdown with notification list (most recent first)
- Tap notification → mark as read + navigate to relevant page
- "Tout marquer comme lu" link at top of dropdown
- WebSocket: new notifications appear in real-time without page refresh
- Offline: notifications queued server-side, delivered on next WebSocket connect
Offline Queuing Behavior¶
When a user is offline when a notification is sent: 1. Server queues the notification (NotificationBroadcaster in CP-010) 2. On reconnect, WebSocket delivers all queued notifications 3. Bell badge updates to reflect total unread count 4. No notifications are lost
French micro-copy:
| Key | French Text |
|---|---|
notifications.empty |
"Aucune notification" |
notifications.mark_all_read |
"Tout marquer comme lu" |
Acceptance Criteria¶
AC-109: Unread count
Given user has 3 unread notifications
When the bell icon renders
Then it shows a badge with "3"
AC-110: Mark as read
Given a notification is unread
When user clicks on it
Then it is marked as read and the unread count decreases
AC-111: Offline notification queuing
Given user "Aminata" is offline when a notification is sent
When Aminata comes back online
Then she receives the queued notification
OHADA & Regulatory Rules¶
No direct regulatory requirements for notification UI.
Standards & Conventions¶
docs/standards/react-typescript-guidelines.md— §WebSocket integration, §Header componentsdocs/standards/offline-sync-guidelines.md— §Offline queuing patterns
Testing Requirements¶
Unit Tests¶
- NotificationBell: renders correct badge count (0, 1, 9, 99+)
- NotificationDropdown: renders notification list sorted by date
- NotificationItem: read vs unread styling
Integration Tests¶
- Mark as read: click notification → PATCH called → badge decrements
- Mark all as read: click "Tout marquer comme lu" → all marked → badge disappears
- Offline queuing: disconnect → send notification → reconnect → notification appears
What QA Will Validate¶
- Bell icon shows correct unread count
- Notifications appear in real-time when online
- Dropdown displays notifications correctly
- "Tout marquer comme lu" works
- Offline queuing: notifications received after reconnect
Out of Scope¶
- Notification backend, templates, email delivery — CP-010
- Notification preferences (opt out of specific types) — V2
- Push notifications (mobile) — V2
- Dedicated notification history page — V2
Definition of Done¶
- [ ] All frontend components render correctly at 360px, 768px, 1024px
- [ ] All 6 UI states implemented (no unread, unread, loading, empty, new notification, offline)
- [ ] French micro-copy matches design spec exactly
- [ ] All acceptance criteria pass manually
- [ ] Unit tests written and passing
- [ ] Integration tests written and passing
- [ ] WebSocket real-time delivery verified
- [ ] Offline queuing verified
- [ ] No TypeScript
any— all types explicit