critical priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

Card displays the summary period label (e.g., 'Q1 2025' or 'January–March 2025') in the card header using heading typography token
Three stat chips show sessions count, total hours, and contacts count with icon, value, and label
A mini PeriodComparisonWidget is embedded in compact mode showing delta for at least one key metric
A dismiss (Ă—) icon button is visible in the top-right corner and triggers DismissPeriodicSummaryCard BLoC event
The entire card surface (excluding dismiss button) is tappable and triggers navigation to mentor profile summary
Card uses design token card background color, border radius, and elevation/shadow
Card is fully responsive: no overflow on screens 320px wide or wider
WCAG 2.2 AA contrast ratio met for all text/icon against card background
Skeleton loading placeholder renders during PeriodicSummaryCardLoading state
Error state renders a compact error message with a retry button
Dismissed state renders nothing (widget returns SizedBox.shrink())

Technical Requirements

frameworks
Flutter
BLoC
data models
PeriodicSummary
performance requirements
Card widget tree depth should not exceed 8 levels to keep layout performance optimal
Skeleton shimmer animation must not jank — use AnimationController at card level
security requirements
Card must not display mentor full name or personal identifiers in the digest view — only aggregate stats
Sensitive stat labels must have appropriate Semantics excludeSemantics if read aloud in context
ui components
PeriodicSummaryCard (this widget)
StatChip (sessions/hours/contacts)
PeriodComparisonWidget (compact mode)
SkeletonCard (loading placeholder)
AppButton or IconButton for dismiss

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Build the card as a `BlocBuilder` widget. Each state maps to a dedicated private build method (`_buildLoading`, `_buildLoaded`, `_buildError`, `_buildDismissed`) for clarity. For the tappable card surface with a separate dismiss button, wrap the card in a `Stack`: the full-card `InkWell` sits at the bottom of the stack, and the dismiss `IconButton` sits at the top-right. This avoids nested gesture conflict.

Use `ShimmerLoading` (or a simple `DecoratedBox` with animated opacity) for the skeleton — do not use a third-party shimmer package unless it is already a project dependency. All spacing and typography must come from the project's design token system.

Testing Requirements

Widget tests with flutter_test: (1) BlocProvider wrapping the card in Loaded state renders all expected child widgets (period label, 3 stat chips, comparison widget, dismiss button), (2) Loading state renders skeleton placeholder and no stat chips, (3) Error state renders error message and retry button, (4) Dismissed state renders SizedBox.shrink(), (5) Tapping dismiss button dispatches DismissPeriodicSummaryCard event to BLoC. Golden tests for each state. Accessibility audit using flutter_test's `SemanticsHandle` to confirm all interactive elements have semantic labels.

Component
Periodic Summary Digest Card
ui medium
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.