Frontend UI for resolving pending vehicle associations when multi-vehicle users submit receipts via email.
API Endpoints (Backend)
GET /api/email-ingestion/pending: List pending vehicle associations for authenticated user
POST /api/email-ingestion/pending/:id/resolve: Resolve by selecting a vehicle (body: { vehicleId })
DELETE /api/email-ingestion/pending/:id: Dismiss/discard a pending association
Frontend Components
PendingAssociationBanner: Shown on dashboard when user has pending associations. Shows count + link to resolve.
PendingAssociationList: List view of pending items showing extracted receipt data (merchant, date, amount, type)
ResolveAssociationDialog: Modal/drawer to select vehicle from dropdown and confirm. On confirm, creates the fuel log or maintenance record with the selected vehicle.
Mobile + Desktop
Mobile: Bottom sheet for resolution dialog, full-width cards for list
Desktop: Dialog modal for resolution, table/card layout for list
Dashboard shows banner when pending associations exist
User can view list of pending items with receipt details
User can select vehicle and resolve association (creates record)
User can dismiss/discard pending items
Mobile and desktop responsive
44px touch targets on mobile
Relates to #149
## Scope
Frontend UI for resolving pending vehicle associations when multi-vehicle users submit receipts via email.
### API Endpoints (Backend)
- `GET /api/email-ingestion/pending`: List pending vehicle associations for authenticated user
- `POST /api/email-ingestion/pending/:id/resolve`: Resolve by selecting a vehicle (body: { vehicleId })
- `DELETE /api/email-ingestion/pending/:id`: Dismiss/discard a pending association
### Frontend Components
- **PendingAssociationBanner**: Shown on dashboard when user has pending associations. Shows count + link to resolve.
- **PendingAssociationList**: List view of pending items showing extracted receipt data (merchant, date, amount, type)
- **ResolveAssociationDialog**: Modal/drawer to select vehicle from dropdown and confirm. On confirm, creates the fuel log or maintenance record with the selected vehicle.
### Mobile + Desktop
- Mobile: Bottom sheet for resolution dialog, full-width cards for list
- Desktop: Dialog modal for resolution, table/card layout for list
### Files
- `backend/src/features/email-ingestion/api/email-ingestion.routes.ts` (add user-facing routes)
- `backend/src/features/email-ingestion/api/email-ingestion.controller.ts` (add handlers)
- `frontend/src/features/email-ingestion/` (new feature directory)
- `frontend/src/features/email-ingestion/components/PendingAssociationBanner.tsx`
- `frontend/src/features/email-ingestion/components/PendingAssociationList.tsx`
- `frontend/src/features/email-ingestion/components/ResolveAssociationDialog.tsx`
- `frontend/src/features/email-ingestion/hooks/usePendingAssociations.ts`
## Acceptance Criteria
- [ ] Dashboard shows banner when pending associations exist
- [ ] User can view list of pending items with receipt details
- [ ] User can select vehicle and resolve association (creates record)
- [ ] User can dismiss/discard pending items
- [ ] Mobile and desktop responsive
- [ ] 44px touch targets on mobile
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Relates to #149
Scope
Frontend UI for resolving pending vehicle associations when multi-vehicle users submit receipts via email.
API Endpoints (Backend)
GET /api/email-ingestion/pending: List pending vehicle associations for authenticated userPOST /api/email-ingestion/pending/:id/resolve: Resolve by selecting a vehicle (body: { vehicleId })DELETE /api/email-ingestion/pending/:id: Dismiss/discard a pending associationFrontend Components
Mobile + Desktop
Files
backend/src/features/email-ingestion/api/email-ingestion.routes.ts(add user-facing routes)backend/src/features/email-ingestion/api/email-ingestion.controller.ts(add handlers)frontend/src/features/email-ingestion/(new feature directory)frontend/src/features/email-ingestion/components/PendingAssociationBanner.tsxfrontend/src/features/email-ingestion/components/PendingAssociationList.tsxfrontend/src/features/email-ingestion/components/ResolveAssociationDialog.tsxfrontend/src/features/email-ingestion/hooks/usePendingAssociations.tsAcceptance Criteria
Milestone: Implementation Complete
Phase: Execution | Agent: Developer | Status: PASS
Backend Changes
getPendingAssociationById()andgetPendingAssociationCount()toemail-ingestion.repository.tsresolveAssociation()(creates record + marks resolved) anddismissAssociation()methods toemail-ingestion.service.tsgetPendingAssociations,getPendingAssociationCount,resolveAssociation,dismissAssociationemailIngestionRoutesplugin with JWT-authenticated endpoints:GET /api/email-ingestion/pending- List pending associationsGET /api/email-ingestion/pending/count- Count for bannerPOST /api/email-ingestion/pending/:id/resolve- Resolve with vehicle selectionDELETE /api/email-ingestion/pending/:id- Dismiss/discardapp.tsFrontend Changes
frontend/src/features/email-ingestion/with types, API, hooks, componentsPendingVehicleAssociation,ExtractedReceiptData,ResolveAssociationResultemailIngestionApiwithgetPending,getPendingCount,resolve,dismissusePendingAssociationCount(polled),usePendingAssociations,useResolveAssociation,useDismissAssociationDashboardScreen.tsxQuality Checks
anywarnings only)Verdict: PASS | Next: Quality Agent review