high priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

Screen is accessible only to users with coordinator or admin role; peer mentors see an empty state or are redirected
Queue items are displayed in a scrollable list ordered by created_at ascending; each item shows peer mentor name, activity type, date, and a conflict summary badge
Each queue item expands inline to show the DuplicateComparisonPanel when tapped; only one item is expanded at a time
Individual resolve actions (Keep Both / Cancel) are available per item; resolving an item removes it from the list with a smooth AnimatedList removal
'Select All' checkbox and bulk-dismiss button are visible when the queue contains 3+ items, supporting NHF group event scenarios
Bulk dismiss shows a confirmation dialog listing the count of items to be dismissed before executing
Empty state displays a friendly illustration and the message 'No duplicate activities to review' when the queue is empty
Real-time updates from DeduplicationQueueService are reflected immediately — if another coordinator resolves an item, it disappears from the list without requiring a manual refresh
Screen displays a loading skeleton while the initial queue fetch is in progress
Bulk dismiss button shows a loading indicator and is disabled while the operation is in progress; success shows a snackbar with item count dismissed

Technical Requirements

frameworks
Flutter
BLoC
Riverpod
apis
Supabase Realtime WebSocket
data models
activity
bufdir_export_audit_log
performance requirements
Initial list render for up to 100 queue items must complete within 1.5 seconds
AnimatedList item removal must not cause visible jank (60fps maintained)
Bulk dismiss of 50 items must complete within 3 seconds with progress feedback
security requirements
Screen must enforce coordinator/admin role check on mount — do not rely solely on navigation guard
Queue items must only show activities belonging to the coordinator's organization_id
Bulk dismiss confirmation must show item count to prevent accidental mass-dismissal
ui components
DeduplicationQueueScreen
DuplicateQueueItemTile (expandable list item)
DuplicateComparisonPanel (dependency task-004)
BulkDismissConfirmationDialog
AnimatedList for smooth item removal
EmptyQueueIllustration
LoadingSkeletonList

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use a BlocBuilder consuming DeduplicationQueueBLoC state (loading, loaded, error) to drive the screen. The queue list should use AnimatedList (not ListView) so item removals animate smoothly. For real-time updates, the DeduplicationQueueService streams queue changes — have the BLoC subscribe to the stream and emit DeduplicationQueueUpdated events. The 'Select All' visibility threshold of 3+ items reflects NHF's group event use case where bulk registration creates many duplicates simultaneously — below 3, per-item resolution is less disruptive.

Use a SliverList inside a CustomScrollView for the queue to allow a sticky bulk-action bar at the bottom. The BulkDismissConfirmationDialog should be a simple AlertDialog with item count and 'Dismiss N items' / 'Cancel' buttons — no need for a custom bottom sheet. For the expanded DuplicateComparisonPanel, use a single-expansion model: store the expanded item ID in BLoC state, not local widget state, so it survives rebuilds.

Testing Requirements

Widget tests: verify empty state renders when queue is empty. Verify loading skeleton shown during initial fetch. Verify 'Select All' checkbox appears only when 3+ items present. Verify bulk dismiss confirmation dialog shows correct item count.

Verify individual item resolve removes it from AnimatedList. Verify role guard redirects peer mentor users. BLoC integration tests: verify real-time removal when another coordinator resolves an item. Verify bulk dismiss emits correct events and all items are removed on success.

Accessibility tests: verify each queue item tile has correct Semantics label including peer mentor name and conflict type. Golden test: render queue with 3 items at standard and large font sizes.

Component
Duplicate Detection BLoC
infrastructure medium
Epic Risks (2)
medium impact high prob technical

For bulk registration with many participants, running duplicate checks sequentially before surfacing the consolidated summary could introduce a multi-second delay as each peer mentor is checked individually against the RPC. This degrades the bulk submission UX significantly.

Mitigation & Contingency

Mitigation: Issue all duplicate check RPC calls concurrently using Dart's `Future.wait` or a bounded parallel executor (max 5 concurrent calls to avoid Supabase rate limits). The BLoC collects all results and emits a single BulkDuplicateSummary state with the consolidated list.

Contingency: If concurrent RPC calls hit Supabase connection limits or rate limits, implement a batched sequential approach with a progress indicator showing 'Checking participant N of M' so the coordinator understands the delay is expected and bounded.

high impact medium prob integration

In proxy registration, the peer mentor's ID must be used as the duplicate check parameter, not the coordinator's ID. If the proxy context is not correctly threaded through the BLoC and service layer, duplicate checks will silently run against the wrong person, missing actual duplicates.

Mitigation & Contingency

Mitigation: Define a `SubmissionContext` model that carries the effective `peer_mentor_id` (distinct from `submitter_id`) and pass it explicitly through the BLoC event payload. The DuplicateDetectionService always reads peer_mentor_id from SubmissionContext, never from the authenticated user session.

Contingency: If SubmissionContext threading proves difficult to retrofit into the existing proxy registration BLoC, add an assertion in DuplicateDetectionService that throws a descriptive error when peer_mentor_id is null or matches the coordinator's own ID in a proxy context, making the bug immediately visible in testing.