feat: Camera Capture Component #66

Closed
opened 2026-02-01 18:46:41 +00:00 by egullickson · 0 comments
Owner

Overview

Create a reusable React camera capture component with translucent guidance overlay, post-capture cropping, and file input fallback.

Parent Issue: #12 (OCR-powered smart capture)
Priority: P1 - VIN OCR
Dependencies: None (can be developed in parallel with OCR service)

Scope

Camera Capture Component

  • Uses getUserMedia API for camera access
  • Translucent aspect-ratio guide overlay (not rigid box)
  • Full-frame photo capture
  • Post-capture crop tool for user refinement
  • File input fallback for desktop/unsupported browsers
  • Supports HEIC, JPEG, PNG output (sent as-is to server)

Component API

interface CameraCaptureProps {
  onCapture: (file: File, croppedFile?: File) => void;
  onCancel: () => void;
  guidanceType?: 'vin' | 'receipt' | 'document' | 'none';
  allowCrop?: boolean;
  maxFileSize?: number; // bytes, default 10MB
  acceptedFormats?: string[]; // MIME types
}

User Flow

1. Component opens → request camera permission
2. Show camera viewfinder with translucent guide overlay
3. User taps capture button
4. Show captured image with crop tool overlay
5. User adjusts crop (optional) or skips
6. User confirms → onCapture called with file(s)
7. User can retake or cancel at any step

Guidance Overlays

VIN Guide:
┌─────────────────────────────────┐
│                                 │
│   ┌───────────────────────┐     │
│   │ (translucent guide)   │     │  Aspect ratio ~6:1
│   └───────────────────────┘     │
│                                 │
│          [Capture]              │
└─────────────────────────────────┘

Receipt Guide:
┌─────────────────────────────────┐
│   ┌───────────────────────┐     │
│   │                       │     │
│   │  (translucent guide)  │     │  Aspect ratio ~2:3
│   │                       │     │
│   └───────────────────────┘     │
│          [Capture]              │
└─────────────────────────────────┘

Crop Tool

  • Drag corners/edges to adjust crop area
  • Pinch-to-zoom on mobile
  • Aspect ratio lock option (for VIN)
  • Preview of cropped result
  • Confirm/Reset/Cancel actions

Directory Structure

frontend/src/shared/components/CameraCapture/
├── index.ts
├── CameraCapture.tsx        # Main component
├── CameraViewfinder.tsx     # Camera preview with overlay
├── GuidanceOverlay.tsx      # Translucent guide shapes
├── CropTool.tsx             # Post-capture crop interface
├── FileInputFallback.tsx    # Desktop/fallback file picker
├── useCameraPermission.ts   # Permission handling hook
├── useImageCrop.ts          # Crop logic hook
├── types.ts
└── CameraCapture.test.tsx

Browser Compatibility

Browser Camera File Input Notes
iOS Safari 11+ Yes Yes HTTPS required
Chrome (Android) Yes Yes
Chrome (Desktop) Yes Yes May need webcam
Firefox Yes Yes
Edge Yes Yes

Mobile Considerations

  • Touch-friendly capture button (min 44px)
  • Gesture support for crop tool
  • Handle orientation changes
  • Memory-efficient image handling
  • Support both front/rear cameras (default rear)

Acceptance Criteria

  • Camera opens with permission prompt
  • Translucent guidance overlay displays correctly
  • Photo capture works on iOS Safari
  • Photo capture works on Android Chrome
  • Post-capture crop tool functional
  • File input fallback works when camera unavailable
  • Handles HEIC files from iPhone camera
  • Handles JPEG/PNG from Android
  • Mobile-responsive design (320px - 768px)
  • Desktop-responsive design (1920px)
  • Graceful error handling (permission denied, camera busy)
  • Retake/cancel flow works correctly

Technical Notes

  • Use navigator.mediaDevices.getUserMedia() with video constraints
  • Canvas API for image capture from video stream
  • Consider using react-image-crop or similar for crop tool
  • File objects preserve original format (HEIC stays HEIC)
  • No client-side format conversion (server handles HEIC)

Out of Scope

  • OCR processing (handled by backend)
  • Feature-specific UI (VehicleForm, FuelLogForm integration)
  • Review/confirm extracted data UI
## Overview Create a reusable React camera capture component with translucent guidance overlay, post-capture cropping, and file input fallback. **Parent Issue**: #12 (OCR-powered smart capture) **Priority**: P1 - VIN OCR **Dependencies**: None (can be developed in parallel with OCR service) ## Scope ### Camera Capture Component - Uses `getUserMedia` API for camera access - Translucent aspect-ratio guide overlay (not rigid box) - Full-frame photo capture - Post-capture crop tool for user refinement - File input fallback for desktop/unsupported browsers - Supports HEIC, JPEG, PNG output (sent as-is to server) ### Component API ```typescript interface CameraCaptureProps { onCapture: (file: File, croppedFile?: File) => void; onCancel: () => void; guidanceType?: 'vin' | 'receipt' | 'document' | 'none'; allowCrop?: boolean; maxFileSize?: number; // bytes, default 10MB acceptedFormats?: string[]; // MIME types } ``` ### User Flow ``` 1. Component opens → request camera permission 2. Show camera viewfinder with translucent guide overlay 3. User taps capture button 4. Show captured image with crop tool overlay 5. User adjusts crop (optional) or skips 6. User confirms → onCapture called with file(s) 7. User can retake or cancel at any step ``` ### Guidance Overlays ``` VIN Guide: ┌─────────────────────────────────┐ │ │ │ ┌───────────────────────┐ │ │ │ (translucent guide) │ │ Aspect ratio ~6:1 │ └───────────────────────┘ │ │ │ │ [Capture] │ └─────────────────────────────────┘ Receipt Guide: ┌─────────────────────────────────┐ │ ┌───────────────────────┐ │ │ │ │ │ │ │ (translucent guide) │ │ Aspect ratio ~2:3 │ │ │ │ │ └───────────────────────┘ │ │ [Capture] │ └─────────────────────────────────┘ ``` ### Crop Tool - Drag corners/edges to adjust crop area - Pinch-to-zoom on mobile - Aspect ratio lock option (for VIN) - Preview of cropped result - Confirm/Reset/Cancel actions ## Directory Structure ``` frontend/src/shared/components/CameraCapture/ ├── index.ts ├── CameraCapture.tsx # Main component ├── CameraViewfinder.tsx # Camera preview with overlay ├── GuidanceOverlay.tsx # Translucent guide shapes ├── CropTool.tsx # Post-capture crop interface ├── FileInputFallback.tsx # Desktop/fallback file picker ├── useCameraPermission.ts # Permission handling hook ├── useImageCrop.ts # Crop logic hook ├── types.ts └── CameraCapture.test.tsx ``` ## Browser Compatibility | Browser | Camera | File Input | Notes | |---------|--------|------------|-------| | iOS Safari 11+ | Yes | Yes | HTTPS required | | Chrome (Android) | Yes | Yes | | | Chrome (Desktop) | Yes | Yes | May need webcam | | Firefox | Yes | Yes | | | Edge | Yes | Yes | | ## Mobile Considerations - Touch-friendly capture button (min 44px) - Gesture support for crop tool - Handle orientation changes - Memory-efficient image handling - Support both front/rear cameras (default rear) ## Acceptance Criteria - [ ] Camera opens with permission prompt - [ ] Translucent guidance overlay displays correctly - [ ] Photo capture works on iOS Safari - [ ] Photo capture works on Android Chrome - [ ] Post-capture crop tool functional - [ ] File input fallback works when camera unavailable - [ ] Handles HEIC files from iPhone camera - [ ] Handles JPEG/PNG from Android - [ ] Mobile-responsive design (320px - 768px) - [ ] Desktop-responsive design (1920px) - [ ] Graceful error handling (permission denied, camera busy) - [ ] Retake/cancel flow works correctly ## Technical Notes - Use `navigator.mediaDevices.getUserMedia()` with video constraints - Canvas API for image capture from video stream - Consider using `react-image-crop` or similar for crop tool - File objects preserve original format (HEIC stays HEIC) - No client-side format conversion (server handles HEIC) ## Out of Scope - OCR processing (handled by backend) - Feature-specific UI (VehicleForm, FuelLogForm integration) - Review/confirm extracted data UI
egullickson added the
status
backlog
type
feature
labels 2026-02-01 18:48:35 +00:00
egullickson added
status
in-progress
and removed
status
backlog
labels 2026-02-01 20:58:24 +00:00
egullickson added
status
review
and removed
status
in-progress
labels 2026-02-01 21:05:41 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#66