feat: Form integration, tier gating, and receipt display (#16) #153

Closed
opened 2026-02-13 02:54:44 +00:00 by egullickson · 1 comment
Owner

Relates to #16

Summary

Integrate maintenance receipt OCR into MaintenanceRecordForm with tier gating, auto-populate form fields from accepted OCR results, and display linked receipt on existing maintenance record components.

Scope

  • Add "Scan Receipt" button to MaintenanceRecordForm (tier-gated)
  • Tier gating: useTierAccess('maintenance.receiptScan') with lock icon + upgrade dialog for non-Pro
  • Wire accepted OCR results to form via setValue() (React Hook Form)
  • Store receipt as document and pass receiptDocumentId when creating maintenance record
  • Display linked receipt thumbnail + view action on MaintenanceRecordEditDialog
  • Show receipt indicator icon on MaintenanceRecordsList rows

Files

  • frontend/src/features/maintenance/components/MaintenanceRecordForm.tsx (MODIFY - add scan button, wire OCR)
  • frontend/src/features/maintenance/components/MaintenanceRecordEditDialog.tsx (MODIFY - show linked receipt thumbnail + view button)
  • frontend/src/features/maintenance/components/MaintenanceRecordsList.tsx (MODIFY - show receipt indicator on list rows)
  • frontend/src/features/maintenance/api/maintenance.api.ts (MODIFY - add receiptDocumentId to create payload)
  • frontend/src/core/config/feature-tiers.ts (MODIFY - add maintenance.receiptScan feature key)

Technical Notes

  • Follow fuel log "Scan Receipt" button pattern (position, styling, tier gate)
  • Camera capture on mobile via shared CameraCapture component
  • File upload fallback for desktop (PDF, PNG, JPG, HEIC)
  • Form auto-populate: use mappedFields from the hook's acceptResult() callback via setValue() calls
  • Document upload: use existing documents API to store receipt, get back document ID
  • Receipt display on MaintenanceRecordEditDialog: thumbnail + "View Receipt" button when receiptDocument exists
    • Mobile (< 768px): 64x64 thumbnail, full-width "View Receipt" button below, stack layout
    • Desktop (>= 768px): 80x80 thumbnail, inline "View Receipt" button, row layout
  • Receipt indicator on MaintenanceRecordsList: small icon on rows with linked receipts
  • Mobile-first: responsive layout, scan button prominent on mobile, 44px touch targets

Acceptance Criteria

  • "Scan Receipt" button appears on maintenance record form (Pro tier only)
  • Non-Pro users see lock icon + upgrade dialog
  • Camera capture works on mobile; file upload works on desktop
  • Accepted OCR results auto-populate form fields
  • Receipt stored as document and linked via receiptDocumentId
  • Linked receipt viewable from maintenance record edit dialog
  • Receipt indicator shown on records list
  • Mobile and desktop responsive
Relates to #16 ## Summary Integrate maintenance receipt OCR into `MaintenanceRecordForm` with tier gating, auto-populate form fields from accepted OCR results, and display linked receipt on existing maintenance record components. ## Scope - Add "Scan Receipt" button to `MaintenanceRecordForm` (tier-gated) - Tier gating: `useTierAccess('maintenance.receiptScan')` with lock icon + upgrade dialog for non-Pro - Wire accepted OCR results to form via `setValue()` (React Hook Form) - Store receipt as document and pass `receiptDocumentId` when creating maintenance record - Display linked receipt thumbnail + view action on `MaintenanceRecordEditDialog` - Show receipt indicator icon on `MaintenanceRecordsList` rows ## Files - `frontend/src/features/maintenance/components/MaintenanceRecordForm.tsx` (MODIFY - add scan button, wire OCR) - `frontend/src/features/maintenance/components/MaintenanceRecordEditDialog.tsx` (MODIFY - show linked receipt thumbnail + view button) - `frontend/src/features/maintenance/components/MaintenanceRecordsList.tsx` (MODIFY - show receipt indicator on list rows) - `frontend/src/features/maintenance/api/maintenance.api.ts` (MODIFY - add receiptDocumentId to create payload) - `frontend/src/core/config/feature-tiers.ts` (MODIFY - add maintenance.receiptScan feature key) ## Technical Notes - Follow fuel log "Scan Receipt" button pattern (position, styling, tier gate) - Camera capture on mobile via shared `CameraCapture` component - File upload fallback for desktop (PDF, PNG, JPG, HEIC) - Form auto-populate: use `mappedFields` from the hook's `acceptResult()` callback via `setValue()` calls - Document upload: use existing documents API to store receipt, get back document ID - Receipt display on `MaintenanceRecordEditDialog`: thumbnail + "View Receipt" button when `receiptDocument` exists - Mobile (< 768px): 64x64 thumbnail, full-width "View Receipt" button below, stack layout - Desktop (>= 768px): 80x80 thumbnail, inline "View Receipt" button, row layout - Receipt indicator on `MaintenanceRecordsList`: small icon on rows with linked receipts - Mobile-first: responsive layout, scan button prominent on mobile, 44px touch targets ## Acceptance Criteria - [ ] "Scan Receipt" button appears on maintenance record form (Pro tier only) - [ ] Non-Pro users see lock icon + upgrade dialog - [ ] Camera capture works on mobile; file upload works on desktop - [ ] Accepted OCR results auto-populate form fields - [ ] Receipt stored as document and linked via receiptDocumentId - [ ] Linked receipt viewable from maintenance record edit dialog - [ ] Receipt indicator shown on records list - [ ] Mobile and desktop responsive
egullickson added the
status
backlog
type
feature
labels 2026-02-13 02:55:02 +00:00
egullickson added this to the Sprint 2026-02-02 milestone 2026-02-13 02:55:04 +00:00
egullickson added
status
in-progress
and removed
status
backlog
labels 2026-02-13 03:32:58 +00:00
Author
Owner

Milestone: Form Integration, Tier Gating, Receipt Display (#153)

Phase: Execution | Agent: Frontend Agent | Status: PASS


Changes Made

File Action Description
frontend/src/features/maintenance/types/maintenance.types.ts MODIFY Added receiptDocumentId to MaintenanceRecord and CreateMaintenanceRecordRequest, added ReceiptDocumentMeta interface, added receiptDocument to MaintenanceRecordResponse
frontend/src/features/maintenance/components/MaintenanceRecordForm.tsx MODIFY Added tier-gated "Scan Receipt" button, wired useMaintenanceReceiptOcr hook + CameraCapture + MaintenanceReceiptReviewModal, auto-populate via setValue(), upload receipt as document on submit
frontend/src/features/maintenance/components/MaintenanceRecordEditDialog.tsx MODIFY Added linked receipt display section with async thumbnail loading + "View Receipt" button, responsive (64x64 mobile / 80x80 desktop)
frontend/src/features/maintenance/components/MaintenanceRecordsList.tsx MODIFY Added receipt indicator chip with Receipt icon on rows with linked receipts

Implementation Notes

  • Tier gating: Uses useTierAccess('maintenance.receiptScan') with ReceiptCameraButton locked state + UpgradeRequiredDialog (mirrors fuel log pattern)
  • OCR flow: CameraCapture -> processImage -> MaintenanceReceiptReviewModal -> acceptResult -> setValue for category, subtypes, date, cost, shopName, odometerReading, notes
  • Document upload: On form submit, captured receipt file is uploaded via documents API (create + upload), document ID linked to maintenance record
  • Receipt display: Edit dialog loads receipt thumbnail async via documentsApi.download(), shows responsive layout with "View Receipt" button
  • Backend feature-tiers.ts: maintenance.receiptScan already present from M2

Verification

  • TypeScript: 0 errors (npx tsc --noEmit)
  • ESLint: 0 errors (12 pre-existing any type warnings)
  • Commit: 06ff810 on branch issue-16-maintenance-receipt-upload-ocr

Verdict: PASS | Next: QR post-implementation review

## Milestone: Form Integration, Tier Gating, Receipt Display (#153) **Phase**: Execution | **Agent**: Frontend Agent | **Status**: PASS --- ### Changes Made | File | Action | Description | |------|--------|-------------| | `frontend/src/features/maintenance/types/maintenance.types.ts` | MODIFY | Added `receiptDocumentId` to `MaintenanceRecord` and `CreateMaintenanceRecordRequest`, added `ReceiptDocumentMeta` interface, added `receiptDocument` to `MaintenanceRecordResponse` | | `frontend/src/features/maintenance/components/MaintenanceRecordForm.tsx` | MODIFY | Added tier-gated "Scan Receipt" button, wired `useMaintenanceReceiptOcr` hook + `CameraCapture` + `MaintenanceReceiptReviewModal`, auto-populate via `setValue()`, upload receipt as document on submit | | `frontend/src/features/maintenance/components/MaintenanceRecordEditDialog.tsx` | MODIFY | Added linked receipt display section with async thumbnail loading + "View Receipt" button, responsive (64x64 mobile / 80x80 desktop) | | `frontend/src/features/maintenance/components/MaintenanceRecordsList.tsx` | MODIFY | Added receipt indicator chip with `Receipt` icon on rows with linked receipts | ### Implementation Notes - **Tier gating**: Uses `useTierAccess('maintenance.receiptScan')` with `ReceiptCameraButton` locked state + `UpgradeRequiredDialog` (mirrors fuel log pattern) - **OCR flow**: CameraCapture -> processImage -> MaintenanceReceiptReviewModal -> acceptResult -> setValue for category, subtypes, date, cost, shopName, odometerReading, notes - **Document upload**: On form submit, captured receipt file is uploaded via documents API (create + upload), document ID linked to maintenance record - **Receipt display**: Edit dialog loads receipt thumbnail async via `documentsApi.download()`, shows responsive layout with "View Receipt" button - **Backend feature-tiers.ts**: `maintenance.receiptScan` already present from M2 ### Verification - TypeScript: 0 errors (`npx tsc --noEmit`) - ESLint: 0 errors (12 pre-existing `any` type warnings) - Commit: `06ff810` on branch `issue-16-maintenance-receipt-upload-ocr` --- *Verdict*: PASS | *Next*: QR post-implementation review
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#153