Receipt upload with preview, cropping, compression, and manual entry fallback. Built for the StellarSplit receipt flow.
- Drag-and-drop and file browser upload (via
react-dropzone) - Image preview with thumbnails and PDF placeholder
- Crop/rotate tools (touch-friendly) via
ImageCropper - Compression before upload with
browser-image-compressionand progress - Manual entry fallback when user has no receipt image
- Multiple files support (configurable max)
- Accepted types: JPG, PNG, PDF · Max size: 10MB per file
import { ReceiptUpload } from '@/components/ReceiptUpload';
<ReceiptUpload
onFilesChange={(files) => {
// files: File[] (images compressed, PDFs as-is)
}}
onManualEntry={(data) => {
// data: { amount, date, merchant, notes }
}}
onError={(err) => console.error(err)}
maxFileSize={10 * 1024 * 1024} // 10MB
maxFiles={10}
/>| Component | Role |
|---|---|
ReceiptUpload |
Main container: dropzone, preview list, crop modal, manual entry toggle |
ImagePreview |
Grid of uploaded items (image thumbnails, PDF placeholder, crop/remove) |
ImageCropper |
Modal crop/rotate (touch-friendly), outputs cropped File |
ManualEntryFallback |
Form: amount, date, merchant, notes |
On Split Detail page, click “Upload or replace receipt” to open the receipt upload block. Use it to test drag-and-drop, file picker, crop/rotate, and “Enter details manually”.
npm run test -- --run src/components/ReceiptUpload- Upload working (drag-and-drop + file browser)
- Preview displaying (images + PDF placeholder)
- Crop/rotate functional (ImageCropper with Apply/Cancel)
- Compression working (browser-image-compression + progress)
- Fallback available (Enter details manually)
- Mobile responsive (touch-friendly controls, min tap 44px)
- Component tests (ReceiptUpload, ImagePreview, ImageCropper, ManualEntryFallback)