feat: integrate ImageAdjustmentModal into AIOnboarding flow

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>
This commit is contained in:
2026-04-22 12:45:44 +03:00
parent da8b2ed07b
commit b73f012332
4 changed files with 109 additions and 7 deletions

View File

@@ -1,9 +1,10 @@
'use client';
import React from 'react';
import React, { useState } from 'react';
import { toast } from 'react-hot-toast';
import { Camera, Check, RefreshCw, X, Image as ImageIcon, Sparkles, Hash, Layout, Layers, Package, ChevronDown } from 'lucide-react';
import { useAIExtraction } from '@/hooks/useAIExtraction';
import { ImageAdjustmentModal } from './ImageAdjustmentModal';
interface AIOnboardingProps {
onCancel: () => void;
@@ -13,6 +14,10 @@ interface AIOnboardingProps {
}
export default function AIOnboarding({ onCancel, onComplete, categories, inventory }: AIOnboardingProps) {
const [showImageAdjustment, setShowImageAdjustment] = useState(false);
const [adjustingItemIndex, setAdjustingItemIndex] = useState<number | null>(null);
const [pendingItemData, setPendingItemData] = useState<any>(null);
const {
image,
setImage,
@@ -33,12 +38,49 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
stopLiveCamera,
captureSnapshot,
processImage,
confirmSingleItem,
confirmSingleItem: hookConfirmSingleItem,
confirmAllItems: hookConfirmAllItems,
updateEditingItem,
handleFileChange
} = useAIExtraction(inventory, onComplete);
const confirmSingleItem = (index: number) => {
if (!extractedItems[index]) return;
const data = extractedItems[index];
const skipPhoto = data._skipPhoto === true;
if (skipPhoto || !image) {
hookConfirmSingleItem(index);
return;
}
setPendingItemData({ index, data, skipPhoto });
setAdjustingItemIndex(index);
setShowImageAdjustment(true);
};
const handleImageAdjustmentConfirm = async (adjustments: { rotation: number; cropBounds: { x: number; y: number; width: number; height: number } } | null) => {
if (!pendingItemData) return;
const { index, data } = pendingItemData;
if (adjustments) {
data.image_adjustments = adjustments;
}
hookConfirmSingleItem(index);
setShowImageAdjustment(false);
setAdjustingItemIndex(null);
setPendingItemData(null);
};
const handleImageAdjustmentCancel = () => {
setShowImageAdjustment(false);
setAdjustingItemIndex(null);
setPendingItemData(null);
};
const confirmAllItems = async () => {
await hookConfirmAllItems();
onCancel(); // Close modal after bulk completion
@@ -487,6 +529,13 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
</div>
)}
{showImageAdjustment && image && (
<ImageAdjustmentModal
imageUrl={image}
onConfirm={handleImageAdjustmentConfirm}
onCancel={handleImageAdjustmentCancel}
/>
)}
</div>
);
}