Compare commits
2 Commits
f72b976c33
...
c95e4c40b8
| Author | SHA1 | Date | |
|---|---|---|---|
| c95e4c40b8 | |||
| cbfd7232ca |
@@ -94,7 +94,8 @@
|
||||
"Bash(grep -E \"\\\\.\\(py|txt\\)$\")",
|
||||
"Bash(npx vitest *)",
|
||||
"Bash(sed -i 's/jest\\\\.fn\\(\\)/vi.fn\\(\\)/g' tests/hooks/useAIExtraction.test.ts)",
|
||||
"Bash(sed -i 's/as jest\\\\.Mock/as any/g' tests/hooks/useAIExtraction.test.ts)"
|
||||
"Bash(sed -i 's/as jest\\\\.Mock/as any/g' tests/hooks/useAIExtraction.test.ts)",
|
||||
"Bash(grep -E \"\\\\.tsx?$\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.14.1",
|
||||
"version": "1.14.2",
|
||||
"lastUpdated": "2026-04-21",
|
||||
"phase": "Phase 3 Complete - Image Display Fix"
|
||||
"phase": "Phase 3 Complete - Blob Serialization Fix"
|
||||
}
|
||||
|
||||
@@ -1,46 +1,61 @@
|
||||
# CURRENT AI WORKING SESSION — HANDOVER
|
||||
|
||||
**Active AI:** Claude Haiku 4.5
|
||||
**Last Updated:** 2026-04-21 (Session 29 - Image Display Bugfix)
|
||||
**Current Version:** v1.14.1 (Image display fix: photo_path fields now surfaced to frontend)
|
||||
**Branch:** dev (Phase 3 complete + bugfix applied, production-ready)
|
||||
**Last Updated:** 2026-04-21 (Session 29 - Image Serialization Bugfix)
|
||||
**Current Version:** v1.14.2 (Blob serialization + photo display fixes complete)
|
||||
**Branch:** dev (Phase 3 complete + critical fixes applied, production-ready)
|
||||
|
||||
---
|
||||
|
||||
## SESSION 29 SUMMARY — Image Display Bugfix
|
||||
## SESSION 29 SUMMARY — Complete Image Pipeline Bugfix
|
||||
|
||||
### Issue Identified
|
||||
Images saved by Phase 3's auto-photo-save feature were not being displayed in the UI, even though the backend was correctly saving and returning the photo data.
|
||||
### Two-Part Issue Identified
|
||||
1. **Photo Display Issue**: Images saved by Phase 3's auto-photo-save weren't being displayed in the UI
|
||||
2. **Photo Save Issue**: "Flash" of image indicated photo wasn't being persisted; extracted image blob wasn't reaching the backend
|
||||
|
||||
### Root Cause
|
||||
**Type system mismatch**: The backend's Item response schema includes `photo_path`, `photo_thumbnail_path`, and `photo_upload_date` fields, but the frontend's Item interface (in `frontend/lib/db.ts`) was missing these fields. This prevented TypeScript from accessing the photo data in UI components.
|
||||
### Root Causes
|
||||
|
||||
### Changes Made (v1.14.1)
|
||||
1. **frontend/lib/db.ts**: Added missing photo fields to Item interface
|
||||
- `photo_path?: string`
|
||||
- `photo_thumbnail_path?: string`
|
||||
- `photo_upload_date?: string`
|
||||
**Part 1 - Display Issue (v1.14.1)**
|
||||
Type system mismatch: Backend returns `photo_path`, `photo_thumbnail_path`, `photo_upload_date`, but frontend Item interface was missing these fields.
|
||||
|
||||
2. **frontend/components/ItemDetailModal.tsx**: Updated to use photo fields
|
||||
- Changed initialization to check `photo_path` first, then fallback to `image_url`
|
||||
**Part 2 - Serialization Issue (v1.14.2)**
|
||||
The extracted image Blob object cannot be JSON serialized. When `handleOnboardingComplete` sent `itemData` to the backend with `extractedImageBlob: Blob`, the Blob was lost during JSON encoding.
|
||||
|
||||
3. **frontend/components/InventoryTable.tsx**: Updated to use photo fields
|
||||
- Changed thumbnail check to use `photo_path` with fallback to `image_url`
|
||||
- Updated PhotoModal trigger to use new fields
|
||||
### Changes Made
|
||||
|
||||
4. **frontend/hooks/useItemCreate.ts**: Fixed TypeScript error
|
||||
- Replaced `toast.warning()` (doesn't exist) with `toast.success()`
|
||||
**v1.14.1 (Display Fix)**
|
||||
1. **frontend/lib/db.ts**: Added photo fields to Item interface
|
||||
2. **frontend/components/ItemDetailModal.tsx**: Use photo_path with fallback
|
||||
3. **frontend/components/InventoryTable.tsx**: Use photo_path with fallback
|
||||
4. **frontend/hooks/useItemCreate.ts**: Fixed toast.warning → toast.success
|
||||
|
||||
**v1.14.2 (Serialization Fix)**
|
||||
1. **frontend/app/page.tsx - handleOnboardingComplete()**:
|
||||
- Convert Blob to base64 before sending to API
|
||||
- Rename `extractedImageBlob` → `extracted_image_bytes` (base64 string)
|
||||
- Rename `imageProcessing` → `image_processing`
|
||||
- Keep Blob in local DB version (for IndexedDB), remove from backend payload
|
||||
|
||||
2. **frontend/app/page.tsx - handleComparisonUpdate()**:
|
||||
- Applied same Blob-to-base64 conversion for duplicate item updates
|
||||
|
||||
### Why This Works
|
||||
- Blobs cannot be JSON serialized, so they disappear during HTTP POST
|
||||
- Base64 strings are JSON-safe and match the backend's `ItemCreate` schema
|
||||
- Frontend keeps original data structure for local DB; backend gets clean API-compatible data
|
||||
|
||||
### Testing
|
||||
- Frontend build: ✅ Compiles successfully
|
||||
- Frontend build: ✅ Compiles successfully (v1.14.2)
|
||||
- No regressions: TypeScript strict mode passes
|
||||
- User Flow: Image now persists through save and displays correctly
|
||||
|
||||
### Commits
|
||||
- `b5fb2a8c` - fix: add photo_path fields to frontend Item interface
|
||||
- `eaa2d2d2` - fix: replace toast.warning with toast.success
|
||||
- `a62e4e0b` - build: version bump to v1.14.1
|
||||
- `cbfd7232` - fix: convert extracted image blob to base64 before sending to API
|
||||
|
||||
**Status:** ✅ **FIXED** — Images now display correctly in both ItemDetailModal and InventoryTable
|
||||
**Status:** ✅ **FIXED** — Full image pipeline working: extract → serialize → save → display
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -167,13 +167,35 @@ export default function Home() {
|
||||
if (itemData.part_number) {
|
||||
itemData.part_number = itemData.part_number.toLowerCase();
|
||||
}
|
||||
// 1. Add to local DB cache
|
||||
|
||||
// Prepare data for backend: convert Blob to base64 and rename fields
|
||||
const backendData = { ...itemData };
|
||||
delete backendData.extractedImageBlob; // Remove Blob from local DB version
|
||||
|
||||
// If extracted image blob is present, convert to base64 for backend
|
||||
if (itemData.extractedImageBlob) {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(itemData.extractedImageBlob);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
reader.onload = () => {
|
||||
const base64 = (reader.result as string).split(',')[1]; // Remove data URL prefix
|
||||
backendData.extracted_image_bytes = base64;
|
||||
backendData.image_processing = itemData.imageProcessing; // Use correct field name for API
|
||||
delete backendData.imageProcessing; // Remove old field name
|
||||
resolve(null);
|
||||
};
|
||||
reader.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
// 1. Add to local DB cache (without Blob)
|
||||
await db.items.add(itemData);
|
||||
|
||||
// 2. If online, try to push to backend immediately
|
||||
if (isOnline && currentUser) {
|
||||
try {
|
||||
await inventoryApi.createItem(currentUser.id, itemData);
|
||||
await inventoryApi.createItem(currentUser.id, backendData);
|
||||
toast.success("Item saved to cloud catalog!");
|
||||
setShowOnboarding(false);
|
||||
await loadInventory();
|
||||
@@ -186,7 +208,7 @@ export default function Home() {
|
||||
const detail = responseData.detail;
|
||||
setComparisonModal({
|
||||
show: true,
|
||||
newItem: itemData,
|
||||
newItem: backendData,
|
||||
existingItem: detail.existing_item,
|
||||
existingId: detail.existing_id
|
||||
});
|
||||
@@ -215,8 +237,28 @@ export default function Home() {
|
||||
if (!comparisonModal.existingId) return;
|
||||
setComparisonLoading(true);
|
||||
try {
|
||||
// Prepare data: convert Blob to base64 if present
|
||||
const updateData = { ...comparisonModal.newItem };
|
||||
|
||||
if (updateData.extractedImageBlob) {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(updateData.extractedImageBlob);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
reader.onload = () => {
|
||||
const base64 = (reader.result as string).split(',')[1];
|
||||
updateData.extracted_image_bytes = base64;
|
||||
updateData.image_processing = updateData.imageProcessing;
|
||||
delete updateData.extractedImageBlob;
|
||||
delete updateData.imageProcessing;
|
||||
resolve(null);
|
||||
};
|
||||
reader.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
// Update existing item
|
||||
await inventoryApi.updateItem(comparisonModal.existingId, comparisonModal.newItem);
|
||||
await inventoryApi.updateItem(comparisonModal.existingId, updateData);
|
||||
toast.success("Item updated successfully!");
|
||||
setComparisonModal({ show: false, newItem: null, existingItem: null, existingId: null });
|
||||
setShowOnboarding(false);
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user