high priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

PeriodComparisonWidget accepts two nullable PeriodicSummary objects (current and previous) as constructor parameters
Widget renders in both side-by-side (Row) and stacked (Column) layout modes controlled by a `layout` enum parameter
Each metric tile displays: label, current value, previous value, and a directional delta indicator (up/down/neutral arrow + percentage)
Widget renders correctly with only one PeriodicSummary (previous period absent), showing dashes or 'N/A' for delta
Widget renders correctly from fully cached/offline data without requiring active network
All metric tiles use design token colors for text, backgrounds, and borders — no hardcoded hex values
Widget is fully accessible: semantic labels on all tiles, screen reader announces metric name, current value, and delta direction
Widget passes flutter_test golden tests for both layout modes with sample data
Hot-reload preserves widget state without errors

Technical Requirements

frameworks
Flutter
BLoC
data models
PeriodicSummary
performance requirements
Widget build time under 16ms to maintain 60fps
No unnecessary rebuilds — widget should use const constructors wherever possible
Offline rendering must not trigger network calls
security requirements
No PII rendered in widget labels — only aggregated metrics
Cached data must be read from secure local storage (no plain SharedPreferences for sensitive counts)
ui components
MetricTile (internal sub-widget)
DeltaIndicator (arrow icon + percentage text)
PeriodComparisonWidget (top-level exportable widget)

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Define a `PeriodicSummary` model class (or confirm it exists) with typed fields for sessions, hours, and contacts counts before building the widget. Use a `PeriodComparisonLayout` enum (`sideBySide`, `stacked`) to control layout. Internal `MetricTile` widget should be a private stateless widget within the same file to keep the API surface minimal. Use `Flexible` / `Expanded` inside Row/Column layouts to handle varying screen widths.

For offline support, the widget is purely presentational — it does not fetch data; the parent BLoC/provider supplies the data objects. Prefer `const` constructors everywhere to minimize rebuild cost. Apply design tokens via the project's token system (e.g., `AppColors.textPrimary`, `AppSpacing.md`) — never inline hex.

Testing Requirements

Unit tests with flutter_test covering: (1) widget renders with two valid PeriodicSummary objects, (2) widget renders with only current period (no previous), (3) both layout modes (side-by-side, stacked) produce correct widget trees. Golden tests for visual regression. Accessibility test asserting Semantics nodes exist for each metric tile. No integration tests required at this stage.

Component
Period Comparison Widget
ui low
Epic Risks (3)
medium impact medium prob technical

If the cached summary is from a prior period (e.g., previous quarter's card is still cached), the digest card could appear on the home screen with outdated numbers after a new period begins, confusing users who have already seen that data.

Mitigation & Contingency

Mitigation: In the SummaryCacheRepository, store the period_start and period_end alongside cached data. In the PeriodicSummaryCard BLoC, compare the cached record's period against the current date using PeriodCalculatorService. Only render the card if the cached summary belongs to the active period.

Contingency: If stale cards appear in production, push a hotfix that adds the period validity check to the BLoC and clears all cached summaries older than the current period boundary via a forced cache flush on next app launch.

medium impact medium prob technical

Using colour alone to distinguish underactive from overloaded mentors in the coordinator view would fail WCAG 1.4.1 (use of colour). This is especially critical for organisations serving users with colour vision deficiency.

Mitigation & Contingency

Mitigation: Always pair colour indicators with a text label or icon (e.g., a downward arrow + 'Underactive' text alongside the amber colour). Use the contrast-safe-color-palette design tokens throughout. Run the contrast-ratio-validator on all new colour combinations in CI.

Contingency: If an accessibility audit flags colour-only indicators post-launch, introduce icon-based indicators as a patch release and update the design token definitions to enforce the paired-indicator pattern going forward.

low impact medium prob integration

Inserting a new card into the role-based home screen requires changes to shared home screen widget composition, which may conflict with parallel feature branches also modifying the home screen layout, causing merge conflicts and integration delays.

Mitigation & Contingency

Mitigation: Implement the PeriodicSummaryCard as a fully self-contained widget that the home screen conditionally renders based on a BLoC state flag. Minimise changes to the home screen itself to a single conditional insertion point, reducing the surface area for merge conflicts.

Contingency: If integration conflicts block the PR, isolate the card behind the organisation-scoped feature flag so it can be toggled independently and merged without affecting other home screen changes.