diff --git a/frontend/components/AIOnboarding.tsx b/frontend/components/AIOnboarding.tsx index 6f702300..af21fb3c 100644 --- a/frontend/components/AIOnboarding.tsx +++ b/frontend/components/AIOnboarding.tsx @@ -67,6 +67,12 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento const { index } = pendingItemData; + console.log('=== AIONBOARDING ADJUSTMENT CONFIRM ==='); + console.log('[Input] Adjustments from modal:', adjustments); + console.log('[Input] Current item index:', index); + console.log('[Input] Current extractedItems[index]:', extractedItems[index]); + console.log('[Current] extractedImageBlob before:', extractedImageBlob?.size || 'null', 'bytes'); + if (adjustments && extractedItems[index]) { const updatedItems = [...extractedItems]; updatedItems[index] = { @@ -83,17 +89,22 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento user_adjusted: true } }; + console.log('[Update] Updated item_processing:', updatedItems[index].image_processing); setExtractedItems(updatedItems); // If modal processed and returned image blob, update the hook's state // so confirmSingleItem uses the processed blob instead of original if (adjustments.imageBlob) { + console.log('[Update] Setting extractedImageBlob to processed blob:', adjustments.imageBlob.size, 'bytes'); setExtractedImageBlob(adjustments.imageBlob); } } // Always call confirm, even without adjustments + console.log('[Action] Calling hookConfirmSingleItem with index:', index); hookConfirmSingleItem(index); + console.log('=== END CONFIRM DEBUG ==='); + setShowImageAdjustment(false); setAdjustingItemIndex(null); setPendingItemData(null); diff --git a/frontend/components/ImageAdjustmentModal.tsx b/frontend/components/ImageAdjustmentModal.tsx index 4a62f77a..f7d53509 100644 --- a/frontend/components/ImageAdjustmentModal.tsx +++ b/frontend/components/ImageAdjustmentModal.tsx @@ -120,17 +120,33 @@ export function ImageAdjustmentModal({ imageUrl, onConfirm, onCancel }: ImageAdj const handleConfirm = async () => { if (!useImage || !cropBounds || !imageRef.current) { + console.log('[Modal] User clicked confirm - no image/crop/useImage flag'); onConfirm(null); return; } + console.log('=== IMAGE ADJUSTMENT MODAL DEBUG ==='); + console.log('[Original] Image dimensions:', imageDimensions); + console.log('[Original] Image URL:', imageRef.current?.src?.substring(0, 50) + '...'); + console.log('[User] Rotation:', rotation, '°'); + console.log('[User] Zoom level:', zoom); + console.log('[User] Pan X/Y:', panX, '/', panY); + console.log('[User] Crop bounds:', cropBounds); + console.log('[User] Use image flag:', useImage); + // Process image: apply rotation and crop const processCanvas = document.createElement('canvas'); const ctx = processCanvas.getContext('2d'); - if (!ctx) return; + if (!ctx) { + console.log('[ERROR] Could not get canvas context'); + return; + } const { x, y, width, height } = cropBounds; + console.log('[Processing] Canvas dimensions will be:', width, 'x', height); + console.log('[Processing] Crop region from original:', { x, y, width, height }); + // Set canvas to crop dimensions processCanvas.width = width; processCanvas.height = height; @@ -140,14 +156,22 @@ export function ImageAdjustmentModal({ imageUrl, onConfirm, onCancel }: ImageAdj ctx.translate(width / 2, height / 2); ctx.rotate((rotation * Math.PI) / 180); ctx.translate(-imageDimensions.width / 2 + x, -imageDimensions.height / 2 + y); + + console.log('[Processing] Drawing image to canvas with transforms applied'); ctx.drawImage(imageRef.current, 0, 0); ctx.restore(); + console.log('[Processing] Canvas draw complete'); + // Convert to blob processCanvas.toBlob((blob) => { if (blob) { + console.log('[Result] Processed image blob size:', blob.size, 'bytes'); + console.log('[Result] Blob type:', blob.type); + console.log('=== END DEBUG ==='); onConfirm({ rotation, cropBounds, imageBlob: blob }); } else { + console.log('[ERROR] Failed to convert canvas to blob'); onConfirm({ rotation, cropBounds }); } }, 'image/jpeg', 0.95); diff --git a/frontend/hooks/useAIExtraction.ts b/frontend/hooks/useAIExtraction.ts index 40e47176..465e3f4b 100644 --- a/frontend/hooks/useAIExtraction.ts +++ b/frontend/hooks/useAIExtraction.ts @@ -135,6 +135,13 @@ export function useAIExtraction(inventory: Item[], onComplete: (itemData: any) = const data = extractedItems[index]; const skipPhoto = data._skipPhoto === true; // User explicitly rejected the photo + console.log('=== CONFIRM SINGLE ITEM (Hook) ==='); + console.log('[Input] Item index:', index); + console.log('[Input] Item data:', data); + console.log('[Input] Skip photo flag:', skipPhoto); + console.log('[Input] extractedImageBlob size:', extractedImageBlob?.size || 'null', 'bytes'); + console.log('[Input] image_processing from data:', data.image_processing); + const newItem = { name: String(data.Item || data.name || "New AI Item"), category: String(data.Category || data.category || "Uncategorized"), @@ -158,6 +165,11 @@ export function useAIExtraction(inventory: Item[], onComplete: (itemData: any) = }) }; + console.log('[Output] newItem being sent to onComplete:', newItem); + console.log('[Output] extractedImageBlob attached:', !!newItem.extractedImageBlob); + console.log('[Output] imageProcessing attached:', !!newItem.imageProcessing); + console.log('=== END HOOK DEBUG ==='); + onComplete(newItem); if (extractedItems.length > 1) { diff --git a/frontend/public/sw.js b/frontend/public/sw.js index 03ef666c..0f506e12 100644 --- a/frontend/public/sw.js +++ b/frontend/public/sw.js @@ -1 +1 @@ -if(!self.define){let e,s={};const n=(n,t)=>(n=new URL(n+".js",t).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(t,a)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(s[c])return;let i={};const r=e=>n(e,c),o={module:{uri:c},exports:i,require:r};s[c]=Promise.all(t.map(e=>o[e]||r(e))).then(e=>(a(...e),i))}}define(["./workbox-4754cb34"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"57c6c19b5badd5160b3352954bb95118"},{url:"/_next/static/chunks/101-b50e26dce87a4010.js",revision:"b50e26dce87a4010"},{url:"/_next/static/chunks/13.ae2fd9645430ed90.js",revision:"ae2fd9645430ed90"},{url:"/_next/static/chunks/255-4f212684648fcab9.js",revision:"4f212684648fcab9"},{url:"/_next/static/chunks/374-a4ed2a0d861d9cab.js",revision:"a4ed2a0d861d9cab"},{url:"/_next/static/chunks/4bd1b696-c023c6e3521b1417.js",revision:"c023c6e3521b1417"},{url:"/_next/static/chunks/512-ce90bee899e5ddb3.js",revision:"ce90bee899e5ddb3"},{url:"/_next/static/chunks/7cb1fa1f-32fc9056ac653916.js",revision:"32fc9056ac653916"},{url:"/_next/static/chunks/802-838213ff73429b14.js",revision:"838213ff73429b14"},{url:"/_next/static/chunks/814-d4585cd22c8d1c30.js",revision:"d4585cd22c8d1c30"},{url:"/_next/static/chunks/962-96d82b34b6f28b0b.js",revision:"96d82b34b6f28b0b"},{url:"/_next/static/chunks/app/_not-found/page-e122f8f409e58055.js",revision:"e122f8f409e58055"},{url:"/_next/static/chunks/app/admin/page-62cbb02e9270bf71.js",revision:"62cbb02e9270bf71"},{url:"/_next/static/chunks/app/inventory/page-58a8e877adf2c692.js",revision:"58a8e877adf2c692"},{url:"/_next/static/chunks/app/layout-eb0f519b25043024.js",revision:"eb0f519b25043024"},{url:"/_next/static/chunks/app/login/page-11a088df67bc5554.js",revision:"11a088df67bc5554"},{url:"/_next/static/chunks/app/logs/page-08ad443e7f88bc92.js",revision:"08ad443e7f88bc92"},{url:"/_next/static/chunks/app/page-fc5650cee3044e3f.js",revision:"fc5650cee3044e3f"},{url:"/_next/static/chunks/framework-050c1f32293f7182.js",revision:"050c1f32293f7182"},{url:"/_next/static/chunks/main-aa573100fdde0547.js",revision:"aa573100fdde0547"},{url:"/_next/static/chunks/main-app-613127bff4bcda66.js",revision:"613127bff4bcda66"},{url:"/_next/static/chunks/pages/_app-7d307437aca18ad4.js",revision:"7d307437aca18ad4"},{url:"/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js",revision:"cb2a52f75f2162e2"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-7a9cf6b863b8c67d.js",revision:"7a9cf6b863b8c67d"},{url:"/_next/static/css/f83d012ed6b4181d.css",revision:"f83d012ed6b4181d"},{url:"/_next/static/qovqxo4cmPcs1sSWarnOX/_buildManifest.js",revision:"31eba5c94d685fe15b2d866310094bce"},{url:"/_next/static/qovqxo4cmPcs1sSWarnOX/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/custom-logo.png",revision:"d41d8cd98f00b204e9800998ecf8427e"},{url:"/logo.png",revision:"084f394cfe19b7d85abec9878a797795"},{url:"/logo_TFM.png",revision:"084f394cfe19b7d85abec9878a797795"},{url:"/manifest.json",revision:"7b6e42d577201b657b72b8698d44d0b2"},{url:"/network.json",revision:"b00477650779657bbd360477fa7e4fc7"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:n,state:t})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;const s=e.pathname;return!s.startsWith("/api/auth/")&&!!s.startsWith("/api/")},new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")},new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>!(self.origin===e.origin),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")}); +if(!self.define){let e,s={};const n=(n,a)=>(n=new URL(n+".js",a).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(a,t)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let c={};const r=e=>n(e,i),o={module:{uri:i},exports:c,require:r};s[i]=Promise.all(a.map(e=>o[e]||r(e))).then(e=>(t(...e),c))}}define(["./workbox-4754cb34"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"b4ffa678710fbda6110c1ced1404f457"},{url:"/_next/static/IL0a1DaKGQHbmqqliVQ_k/_buildManifest.js",revision:"31eba5c94d685fe15b2d866310094bce"},{url:"/_next/static/IL0a1DaKGQHbmqqliVQ_k/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/101-b50e26dce87a4010.js",revision:"b50e26dce87a4010"},{url:"/_next/static/chunks/13.ae2fd9645430ed90.js",revision:"ae2fd9645430ed90"},{url:"/_next/static/chunks/255-4f212684648fcab9.js",revision:"4f212684648fcab9"},{url:"/_next/static/chunks/374-a4ed2a0d861d9cab.js",revision:"a4ed2a0d861d9cab"},{url:"/_next/static/chunks/4bd1b696-c023c6e3521b1417.js",revision:"c023c6e3521b1417"},{url:"/_next/static/chunks/512-ce90bee899e5ddb3.js",revision:"ce90bee899e5ddb3"},{url:"/_next/static/chunks/7cb1fa1f-32fc9056ac653916.js",revision:"32fc9056ac653916"},{url:"/_next/static/chunks/802-838213ff73429b14.js",revision:"838213ff73429b14"},{url:"/_next/static/chunks/814-d4585cd22c8d1c30.js",revision:"d4585cd22c8d1c30"},{url:"/_next/static/chunks/962-96d82b34b6f28b0b.js",revision:"96d82b34b6f28b0b"},{url:"/_next/static/chunks/app/_not-found/page-e122f8f409e58055.js",revision:"e122f8f409e58055"},{url:"/_next/static/chunks/app/admin/page-62cbb02e9270bf71.js",revision:"62cbb02e9270bf71"},{url:"/_next/static/chunks/app/inventory/page-58a8e877adf2c692.js",revision:"58a8e877adf2c692"},{url:"/_next/static/chunks/app/layout-eb0f519b25043024.js",revision:"eb0f519b25043024"},{url:"/_next/static/chunks/app/login/page-11a088df67bc5554.js",revision:"11a088df67bc5554"},{url:"/_next/static/chunks/app/logs/page-08ad443e7f88bc92.js",revision:"08ad443e7f88bc92"},{url:"/_next/static/chunks/app/page-7a4b9830187bf8dd.js",revision:"7a4b9830187bf8dd"},{url:"/_next/static/chunks/framework-050c1f32293f7182.js",revision:"050c1f32293f7182"},{url:"/_next/static/chunks/main-aa573100fdde0547.js",revision:"aa573100fdde0547"},{url:"/_next/static/chunks/main-app-613127bff4bcda66.js",revision:"613127bff4bcda66"},{url:"/_next/static/chunks/pages/_app-7d307437aca18ad4.js",revision:"7d307437aca18ad4"},{url:"/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js",revision:"cb2a52f75f2162e2"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-7a9cf6b863b8c67d.js",revision:"7a9cf6b863b8c67d"},{url:"/_next/static/css/f83d012ed6b4181d.css",revision:"f83d012ed6b4181d"},{url:"/custom-logo.png",revision:"d41d8cd98f00b204e9800998ecf8427e"},{url:"/logo.png",revision:"084f394cfe19b7d85abec9878a797795"},{url:"/logo_TFM.png",revision:"084f394cfe19b7d85abec9878a797795"},{url:"/manifest.json",revision:"7b6e42d577201b657b72b8698d44d0b2"},{url:"/network.json",revision:"b00477650779657bbd360477fa7e4fc7"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:n,state:a})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;const s=e.pathname;return!s.startsWith("/api/auth/")&&!!s.startsWith("/api/")},new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")},new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>!(self.origin===e.origin),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")});