- Added search button to main page header with Ctrl+K listener
- Implemented SearchModal component rendering
- Fixed SearchModal to use axiosInstance with correct backend URL (8916)
- Fixed token key from 'auth_token' to 'inventory_token'
- Verified export endpoints working correctly
- All Phase 6 UAT fixes in place
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Make Item.id required (items from DB always have id)
- Use shared Item type from db.ts in QuantityAdjustmentModal
- Show full npm build output instead of silencing errors
- Ensures all modals use consistent type definitions
- Remove duplicate Item interface from SearchModal
- Import Item from @/lib/db to ensure type consistency
- Fixes TypeScript error with missing category/min_quantity fields
- Create Toast component for success/error messages
- Fix uvicorn invocation: use backend.main:app from project root
- Ensures relative imports work correctly in backend modules
Removed the rotation/zoom adjustment modal feature. Approach was too complex and
time-consuming without delivering stable results.
New simplified flow:
1. User extracts item with AI
2. Item saved with original image (resized/compressed by backend)
3. No rotation adjustments in frontend
4. Image editing can be implemented as a future feature
This unblocks the workflow and gets users to a working state.
Backend still applies compression/resizing, just no rotation processing.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Root cause: Image was being rotated TWICE:
1. Frontend rotated it in the modal and sent processed blob
2. Backend rotated it AGAIN based on rotation_degrees
This double rotation made the image appear unrotated or distorted.
Solution: Remove frontend image processing entirely.
- Modal now sends ONLY the rotation value
- No imageBlob from modal (uses original)
- Backend receives original image + rotation value
- Backend applies rotation ONCE
Now image is rotated correctly by backend without duplication.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
When rotating images, the rotated corners extend beyond the original canvas
bounds, causing the image to be clipped and appear skewed.
Fixed by:
1. Calculate canvas size needed to fit rotated image
2. Use formula: newSize = sqrt((w*cos)^2 + (h*sin)^2)
3. Center image and rotate around center of new canvas
4. Update cropBounds to new canvas dimensions
Now when user rotates an image, the full rotated result is saved without
any clipping or skewing. The saved image dimensions will be larger than
the original to accommodate the rotation.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Cropping UI was a placeholder and never fully implemented. Users couldn't
actually select a crop region - it always used full image bounds.
Simplified modal to focus on what works:
- Rotation adjustment ✅ (fully working)
- Zoom/pan for preview ✅ (fully working)
- Removed aspect ratio controls (crop not functional)
- Changed header to "Rotate Image"
Image processing now:
1. Takes user's rotation adjustment
2. Applies rotation to full image
3. No cropping (uses full bounds)
4. Saves rotated image
This ensures saved image matches the rotation user selected in modal.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Root cause found: setState is async, so hookConfirmSingleItem was called
before extractedItems updated, causing it to use OLD image_processing values.
Fixed by:
1. Building the final newItem directly in handleImageAdjustmentConfirm
2. Using the UPDATED image_processing values (with user adjustments)
3. Calling onComplete synchronously with correct values
4. Not relying on async setState ordering
This ensures backend receives the user-adjusted crop_bounds and rotation_degrees,
not the original AI-detected values.
Backend logs will now show user adjustments, not original AI values.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Added detailed console logging across entire image adjustment pipeline:
1. ImageAdjustmentModal.handleConfirm():
- Original image dimensions
- User inputs (rotation, zoom, pan, crop)
- Canvas processing steps
- Final blob size
2. AIOnboarding.handleImageAdjustmentConfirm():
- Adjustments received from modal
- Item being updated
- extractedImageBlob status before/after
3. useAIExtraction.confirmSingleItem():
- newItem being built
- extractedImageBlob attached
- imageProcessing attached
This will help identify where values are lost or incorrect in the flow.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Critical fix: modal processes image and returns blob, but AIOnboarding
was not actually using that blob. Now properly calls setExtractedImageBlob()
so confirmSingleItem sends the processed image to backend.
Before: Backend received original image, applied original AI crop/rotation
After: Backend receives processed image (already cropped/rotated by user)
Now the saved image matches exactly what user sees after adjusting.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Critical fixes:
1. Modal now applies rotation and crop to image, returns processed blob
2. Frontend sends processed image to backend (not original)
3. Zoom slider min/max now calculated based on image size
4. Initial zoom shows entire image in canvas
5. Zoom constraints prevent over-zooming or under-zooming
User experience improved:
- Sees full item at start (auto-fit zoom)
- Can adjust rotation/crop smoothly
- Adjusted image is what gets saved (not original)
- Zoom slider works correctly for any image size
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Fixes issue where image was too small to see full item in modal canvas.
Changes:
- Calculate initial zoom to fit entire image in 800x600 canvas
- Don't zoom in (only zoom out to fit), preserving image clarity
- Reset button also resets to fit zoom instead of always 1.0
This ensures users can see the full item from the start and understand
what they're adjusting.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Fixed two critical issues:
1. Adjustments now properly override image_processing values
2. State updates explicitly ensure extractedItems are modified before confirm
Changes:
- handleImageAdjustmentConfirm now updates extractedItems state
- Adjustments properly stored in image_processing (rotation_degrees, crop_bounds)
- user_adjusted flag added to mark user-modified values
- Backend will use adjusted values instead of AI detection
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Added user-controlled image adjustment modal that displays after item
confirmation, allowing users to adjust rotation/crop before final save.
Changes:
- AIOnboarding: wrapper confirmSingleItem to show modal post-selection
- State: showImageAdjustment, adjustingItemIndex, pendingItemData
- Handlers: confirm/cancel for applying or discarding adjustments
- Flow: item save → modal display → adjustments applied → DB commit
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Shows original image after item save
- Rotation slider + gesture rotation
- Zoom control (scroll/pinch)
- Pan support (drag on desktop/mobile)
- Preset aspect ratios for crop
- Touch support for mobile (pinch zoom, drag pan)
- Checkbox to confirm/reject image use (default ON)
- Compresses image if adjusted before saving
- Shows which edge is Top, Bottom, Left, Right on crop rectangle
- Removes ambiguity about crop box orientation
- Green labels on all four edges for clear visual reference
- Add drag-to-move functionality for entire crop box
- Add resize handles at corners (drag to resize)
- Show adjusted bounds separately from AI bounds in log
- Add Reset button to revert to original crop bounds
- Allows visual verification of AI crop detection accuracy
- Add TOP/BTM labels to rotated box showing which edge is which after rotation
- Allows user to visually see rotation direction without calculating degrees
- Fix allowedDevOrigins to include common private IP ranges (192.168.*, 10.*, 172.16.*)
- Resolves CORS warning when accessing from local network IPs
- Display UP/DOWN/LEFT/RIGHT labels at canvas edges
- Shows which direction is which in the original image
- Helps verify rotation correctness visually
- Removed black overlay that was hiding the image
- Draw crop box directly on full-brightness image with drop shadow
- Item under crop area now fully visible
- Improved visibility of both crop bounds (green) and rotation (orange)
- Clear logs between rotation updates (no more expanding text)
- Increase canvas size from 600x450 to 900x600 for better visibility
- Reorganize layout: left controls, right canvas + single-line log
- Make crop box much larger and easier to see
- Save original image before crop/rotation with '_debug_original' variant
- Store original_photo_path in labels_data.image_processing for debug access
- Update DebugRotationPanel to display original image instead of processed
- Update ItemDetailModal to pass original image path to debug panel
- Enables accurate crop/rotation visualization with true original image
Layout changes:
- Reduced padding and margins throughout
- Changed from 3-column to 2-column layout
- Canvas + logs on right side (side-by-side)
- Smaller fonts and spacing
- Sticky header that stays in view
- Max-height with scrolling for modal
- Removed footer text to save space
- More efficient use of screen real estate
Now fits on most screen sizes even with large rotation angles.
Much better UX for identifying correct rotation:
- Shows ORIGINAL image scaled to fit the modal
- Draws GREEN bounding box showing the crop area
- Draws ORANGE rotated rectangle showing rotation effect
- Darkens everything outside the crop area (visual focus)
- Rotation slider updates the overlay in real-time
- Quick preset buttons for common angles
- Detailed debug logs showing all calculations
- Better styling: dark theme for readability
User can now visually see what will be extracted with the current
rotation angle. Report the angle that makes the label readable.
New DebugRotationPanel component allows testing different rotation angles
with live preview and detailed debug logs showing:
- Current rotation angle (slider + quick presets)
- Crop bounds and calculations
- Image dimensions at each step
- Final processed image preview
- Confidence score
Integrated into ItemDetailModal via wrench icon in header (only visible
when item has a photo). Helps identify correct rotation values for images
at any angle.
Debug panel shows:
- Original image info
- Crop bounds and resulting size
- Rotation angle and final canvas size
- Step-by-step processing logs
- Live canvas preview of result
- Update photo save checkbox to match app design (border-slate-600, htmlFor label)
- Remove success popup overlay - modal closes immediately after save
- Simplify confirmSingleItem to remove setTimeout logic
- Toast notification used for user feedback instead
- Add savingIndex state to track saving operation
- Display success overlay with saved image for 1.5 seconds
- Show item name in confirmation message
- Prevents modal from closing immediately after save
Fixes user complaint about image disappearing too quickly without confirmation
- Add rotation_degrees parameter to ImageProcessor.process_photo()
- Pass rotation through _auto_save_photo_from_extraction() to processor
- Allow no-crop fallback when crop_bounds is None
- Add buildPhotoUrl() helper to resolve backend URLs correctly
- Update frontend components to use backend URL for image sources
- Replace Use/Skip Photo buttons with checkbox in AI extraction UI
- Add images/ to .gitignore to prevent accidental commits
Addresses: rotation never applied, image 404s (relative to Next.js not backend), preview blank in edit form
Users now see the extracted photo during item editing and can choose to:
- 'Use Photo': Auto-save the image with the item
- 'Skip Photo': Create item without saving the photo
Changes:
1. frontend/components/AIOnboarding.tsx: Added image preview panel in edit form
- Shows extracted image to user
- Buttons to accept/reject photo
- Visual feedback when photo is skipped
2. frontend/hooks/useAIExtraction.ts: Updated confirmSingleItem and confirmAllItems
- Respect user's photo decision (_skipPhoto flag)
- Only pass extractedImageBlob if user approved it
- Prevents unwanted auto-photo-save
This gives users full control over which extracted photos are auto-saved.
The backend returns photo_path, photo_thumbnail_path, and photo_upload_date
from the AI auto-save feature, but the frontend Item interface was missing
these fields, causing images not to display in ItemDetailModal and InventoryTable.
Updated:
- frontend/lib/db.ts: Added missing photo fields to Item interface
- frontend/components/ItemDetailModal.tsx: Use photo_path first, fallback to image_url
- frontend/components/InventoryTable.tsx: Use photo_path first, fallback to image_url
This ensures the UI can now display photos saved by the auto-photo-save feature.
- Add ItemDetailModal component for viewing item details and replacing photos
- Add photo replacement/deletion endpoints to API layer (PUT/DELETE /items/{id}/photo)
- Update InventoryTable to open detail modal on item click
- Show current photo thumbnail with Replace/Delete buttons
- Support uploading new photo with ItemPhotoUpload component
- Delete old photo on backend when replacing (no orphaned files)
- Full test coverage: 18 tests for ItemDetailModal component
- All 393 tests passing, zero TypeScript errors
- Build verified successfully
Fixed 3 critical code quality issues:
1. Act() warnings in tests (9 tests):
- Wrapped all async state updates in act() blocks in usePhotoUpload.test.ts
- Tests using waitFor() now properly await state updates within act()
- All 21 tests pass with zero act() warnings
2. Missing toast cleanup on unmount:
- Added toastIdRef to track pending toast IDs
- Added cleanup useEffect that dismisses toasts on component unmount
- Prevents memory leaks and orphaned toast notifications
3. Dual error reporting channels (lines 23-28):
- Removed useEffect that synced hook error to local state AND called onError callback
- Now syncs hook error to local state only (for display)
- Parent components rely on hook error state, reducing dual-path confusion
- Toast error calls are explicit in catch block
Test Results:
- Frontend: 312/312 tests passing (includes 21 photo upload tests)
- Act() warnings: Eliminated
- No regressions introduced