Display last-updated timestamp in admin preview
epic-dynamic-terminology-and-labels-ui-and-accessibility-task-011 — Retrieve and display the last-updated timestamp of the active organization's terminology map from the TerminologyRepository in the TerminologyAdminPreviewScreen. Show it in the app bar subtitle or a dedicated info card. Format the timestamp in Norwegian locale (dd.MM.yyyy HH:mm). If no timestamp is available, display a 'Never synced' indicator.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Use the intl package (already likely a transitive dependency via Flutter) with DateFormat('dd.MM.yyyy HH:mm', 'nb_NO') for formatting. Ensure 'nb' locale is initialized via initializeDateFormatting() at app startup — if not already done, add it to the app's locale initialization block, not inside this widget. The lastUpdatedAt field should already exist on OrganizationLabelMap if the data model is complete; if not, coordinate with the backend team to add it to the Supabase response. Prefer placing the timestamp in the app bar subtitle (via AppBar(title: ..., bottom: PreferredSize(...))) rather than a separate card to keep the screen uncluttered.
Use a ternary on the nullable DateTime: timestamp != null ? DateFormat(...).format(timestamp) : 'Never synced'.
Testing Requirements
Write flutter_test widget tests for: (1) populated DateTime renders formatted as 'dd.MM.yyyy HH:mm', (2) null timestamp renders 'Never synced' string, (3) Semantics node contains correct label text for both cases. Unit-test the timestamp formatting function in isolation with known DateTime inputs including edge cases (midnight, year boundary). Verify Norwegian locale formatting by asserting the exact formatted string for a known DateTime value.
WcagSemanticsLabelResolver's Semantics wrappers may conflict with Semantics nodes already defined by existing accessible widgets (e.g., accessible-bottom-navigation, activity-wizard-semantics), causing duplicate or contradictory screen reader announcements that fail WCAG 2.2 AA criteria.
Mitigation & Contingency
Mitigation: Audit all existing Semantics-annotated widgets in the accessibility feature before implementing WcagSemanticsLabelResolver. Define a clear hierarchy rule: WcagSemanticsLabelResolver always merges with, never replaces, existing Semantics nodes. Use Flutter's debugSemantics output in CI to detect conflicts automatically.
Contingency: If conflicts are discovered in testing, introduce a resolverMode parameter to WcagSemanticsLabelResolver allowing it to operate in 'override' or 'merge' mode per call site; coordinate with the Screen Reader Support feature team to align Semantics strategies.
If TerminologyAwareTextWidget subscribes to the full terminology map provider rather than the per-key labelProvider family, a single label update will trigger a full widget-tree rebuild across all screens simultaneously, causing jank on devices used by older peer mentors.
Mitigation & Contingency
Mitigation: Implement TerminologyAwareTextWidget using ref.watch(labelProvider(key)) on the per-key family provider from TerminologyRiverpodProviders so that only widgets bound to the changed key rebuild. Verify with Flutter DevTools 'rebuild tracking' in widget tests.
Contingency: If full-map subscriptions slip through code review, add a Riverpod lint rule that flags direct organizationLabelsNotifierProvider subscriptions inside widget build methods and enforces the per-key family pattern.
The TerminologyAdminPreviewScreen requires coordinator-level access, but if role checks rely solely on client-side guard logic without matching Supabase RLS policies, a peer mentor could potentially access the admin preview by manipulating navigation state.
Mitigation & Contingency
Mitigation: Protect the admin preview route with a server-validated role guard that re-fetches the user's role from Supabase on screen initialization, not just from local state. Add a Supabase RLS policy that restricts label map read access for the admin preview endpoint to coordinator and admin roles only.
Contingency: If unauthorized access is discovered in testing, immediately add a middleware role assertion that redirects non-coordinators to the no-access screen and logs the unauthorized navigation attempt for audit.