User Story #607
openFeature #533: Authentication Hum Rahi
EPIC #597: Epic: E2.3 — Citizen Report Status Tracking
US-027.2 · Status Timeline — Frontend Implementation on Report Detail Screen
0%
Description
US-027.2 · Status Timeline — Frontend Implementation on Report Detail Screen¶
Epic: E2.3 — Citizen Report Status Tracking Owner: Rahul | Type: FRONTEND | Priority: Should Have Story Points: 3 | Sprint Target: Sprint 4
📖 Story¶
As Rahul (a citizen), I want the status timeline on my report's detail screen to accurately reflect every status change with its timestamp and any operator notes, so that I can follow the full history of my report without ambiguity.
🎯 Goal & Context¶
This story implements the timeline component designed in US-027.1. By the time this story begins, the design spec is signed off and the backend API delivering timeline data is confirmed. The frontend engineer's responsibility is to consume that data, render the timeline faithfully against the spec, and handle all edge cases gracefully — including varying numbers of entries, missing operator notes, and failed data fetches.
✅ In-Scope¶
- Implementation of the timeline component on the Report Detail screen, below the report summary block
- Fetching timeline/status history data from the API for the given
report_id - Rendering all status nodes with correct timestamps, labels, and optional operator notes
- Visual differentiation between current (most recent) and past (completed) nodes
- Skeleton loading state while timeline data is fetching
- Error state if timeline data fails to load
- Single-node state (report only has "Submitted" entry)
- Scroll behaviour when timeline entries overflow the screen
❌ Out-of-Scope¶
- Triggering or writing status changes (backend/admin story)
- Push notification from timeline events (US-026)
- Operator note authoring from the citizen side
- Any animation or transition effects beyond what is specified in the US-027.1 design handoff
- Web portal version (Phase 2)
📡 Data Requirements¶
The timeline endpoint must return, per status entry:
| Field | Description |
|---|---|
status |
Machine-readable status key (e.g., ASSIGNED, RESOLVED) |
status_label |
Human-readable label (e.g., "Assigned", "Resolved") |
changed_at |
ISO 8601 timestamp of when the status changed |
operator_note |
Optional string — null if no note was added |
The list must be returned in ascending chronological order (oldest first) so the timeline renders correctly top-to-bottom without client-side sorting.
Confirm with Backend: Is
operator_notealways returned (null when absent) or omitted from the response entirely when not present? The frontend must handle both cases.
🗂️ Rendering Rules¶
Node Rendering Logic¶
- Render one node per entry in the timeline data array
- The last entry in the array (most recent) must receive the "current" visual treatment as defined in the US-027.1 design spec
- All preceding entries receive the "completed" visual treatment
- If
operator_noteis null or an empty string, do not render the note line — the node collapses to label + timestamp
Timestamp Display Rules¶
- Format:
DD MMM YYYY, HH:MMper the design spec - If
changed_atdate is today's date, display as:Today, HH:MM - Use the device's local timezone for display — do not display UTC directly
Operator Note Truncation¶
- Display up to 120 characters
- If
operator_noteexceeds 120 characters, truncate with an ellipsis and show a "Read more" inline tap target - Tapping "Read more" expands the full note inline — no modal or new screen
🔄 Screen States¶
| State | Trigger | Behaviour |
|---|---|---|
| Loading | API call in flight | Show skeleton placeholders for 3 timeline nodes |
| Success — multiple entries | API returns 2+ entries | Render full timeline |
| Success — single entry | API returns only the Submitted entry | Render single-node timeline; no empty state message |
| Error | API call fails | Show inline error message: "Unable to load status history. Pull down to retry." |
| Empty | API returns an empty array | This should not occur — treat as an error state; log for investigation |
🗺️ Placement & Layout¶
- The timeline section is placed below the report summary block on the Report Detail screen
- Section heading: "Status History" — styled per the design spec
- If the combined height of the report summary + timeline exceeds the screen height, the entire Report Detail screen scrolls as one unit — the timeline does not have its own independent scroll container
- The timeline must be visible without horizontal scroll at 375px minimum screen width
♿ Accessibility Requirements¶
- Each timeline node must be individually readable by screen readers
- Screen reader announcement per node:
"[Status Label], [Timestamp]"— e.g., "Assigned, 24 October 2024, 2:30 PM" - If an operator note is present:
"[Status Label], [Timestamp]. Note: [operator_note]" - "Read more" tap target must have a descriptive
aria-label:"Read full note for [Status Label] update" - Minimum tap target for "Read more": 44×44px
- Colour is not the sole differentiator between current and completed nodes — shape, weight, or size must also differ (WCAG 1.4.1)
❗ Error Handling¶
| Scenario | Behaviour |
|---|---|
| Timeline API returns 500 | Show inline error with pull-to-retry prompt; do not crash the Report Detail screen |
changed_at timestamp is malformed or missing |
Skip rendering that node; log the anomaly; do not break the rest of the timeline |
operator_note contains special characters or HTML |
Render as plain text — strip any HTML tags before display |
report_id returns no matching timeline data |
Treat as error state — empty array should not be a valid production response |
📏 Acceptance Criteria¶
| # | Criteria | Test Method |
|---|---|---|
| AC-1 | Timeline renders all status entries for a report in chronological order, oldest at top | Manual + data test |
| AC-2 | The most recent status node is visually distinct from past nodes, per the design spec | Design QA |
| AC-3 | Timestamps display in correct local timezone and in the DD MMM YYYY, HH:MM format |
Manual |
| AC-4 | "Today" shorthand is used when the status change occurred on the current date | Manual |
| AC-5 | Operator notes display correctly when present; node collapses correctly when absent | Manual — both scenarios |
| AC-6 | Operator notes longer than 120 chars are truncated with a functional "Read more" toggle | Manual — edge case |
| AC-7 | Skeleton loading state is shown while data is fetching | Manual |
| AC-8 | Inline error state is shown and pull-to-retry functions correctly on API failure | Manual — simulated failure |
| AC-9 | Single-node timeline (Submitted only) renders without visual breakage | Manual |
| AC-10 | Timeline is accessible — each node is announced correctly by screen reader | Screen reader test (TalkBack / VoiceOver) |
🔗 Dependencies & Open Questions¶
| # | Question | Owner | Status |
|---|---|---|---|
| 1 | Is the timeline endpoint a separate API call (GET /reports/:id/timeline) or embedded in the Report Detail API response? |
Backend | Open — blocks start |
| 2 | Is operator_note always returned as null when absent, or omitted from the response entirely? |
Backend | Open |
| 3 | Is the timeline data returned already sorted ascending by changed_at, or must the frontend sort it? |
Backend | Open |
| 4 | What is the confirmed maximum number of timeline entries? This affects skeleton placeholder count | Backend | Open |
| 5 | Is "Read more" for operator notes in scope for this sprint, or should long notes simply be truncated with no expansion? | PM (Rahul) | Open — scope decision |
✅ Definition of Done¶
- All 10 ACs pass QA sign-off
- Renders correctly against the US-027.1 design spec — no deviations without PM approval
- Unit tests for timestamp formatting logic (today shorthand, timezone handling)
- Unit tests for operator note truncation and "Read more" toggle
- Skeleton, error, and single-node states all implemented and reviewed
- HTML-stripping confirmed on operator note field — no XSS risk
- Accessibility tested on TalkBack (Android) and VoiceOver (iOS)
- No independent horizontal or vertical scroll container introduced for the timeline — screen scrolls as one unit
Predecessor: US-027.1 (Design spec sign-off), US-025 (Report Detail screen exists) Successor: None in current sprint — feeds into overall Report Detail screen completeness
No data to display