189 lines
5.9 KiB
Markdown
189 lines
5.9 KiB
Markdown
|
|
# AI Inventory Step Redesign - Key Differences
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
Completely redesigned UploadSalesDataStep to follow the suppliers/recipes pattern with list-based management and deferred creation.
|
|||
|
|
|
|||
|
|
## Major Changes
|
|||
|
|
|
|||
|
|
### 1. **Data Model**
|
|||
|
|
**BEFORE**:
|
|||
|
|
```typescript
|
|||
|
|
interface InventoryItem {
|
|||
|
|
suggestion_id: string;
|
|||
|
|
selected: boolean; // Checkbox selection
|
|||
|
|
stock_quantity: number;
|
|||
|
|
cost_per_unit: number;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**AFTER**:
|
|||
|
|
```typescript
|
|||
|
|
interface InventoryItemForm {
|
|||
|
|
id: string; // UI tracking
|
|||
|
|
name: string;
|
|||
|
|
// ... all inventory fields
|
|||
|
|
isSuggested: boolean; // Track if from AI or manual
|
|||
|
|
// NO "selected" field - all items in list will be created
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. **Creation Timing**
|
|||
|
|
**BEFORE**:
|
|||
|
|
- Checkbox selection UI
|
|||
|
|
- "Create Inventory" button → Creates immediately → Proceeds to next step
|
|||
|
|
|
|||
|
|
**AFTER**:
|
|||
|
|
- List-based UI (like suppliers/recipes)
|
|||
|
|
- Items added to list (NOT created yet)
|
|||
|
|
- "Next" button → Creates ALL items → Proceeds to next step
|
|||
|
|
|
|||
|
|
### 3. **UI Pattern**
|
|||
|
|
|
|||
|
|
**BEFORE** (Old Pattern):
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ ☑️ Product 1 [Edit fields inline] │
|
|||
|
|
│ ☐ Product 2 [Edit fields inline] │
|
|||
|
|
│ ☑️ Product 3 [Edit fields inline] │
|
|||
|
|
│ │
|
|||
|
|
│ [Create 2 Selected Items] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**AFTER** (New Pattern - Like Suppliers/Recipes):
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ Product 1 (AI 95%) [Edit][Delete]│
|
|||
|
|
│ Stock: 50kg Cost: €5.00 │
|
|||
|
|
│ │
|
|||
|
|
│ Product 2 (Manual) [Edit][Delete]│
|
|||
|
|
│ Stock: 30kg Cost: €3.00 │
|
|||
|
|
│ │
|
|||
|
|
│ [➕ Add Ingredient Manually] │
|
|||
|
|
│ │
|
|||
|
|
│ ────────────────────────────────── │
|
|||
|
|
│ 3 ingredients - Ready! [Next →] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. **Manual Addition**
|
|||
|
|
**BEFORE**: No way to add manual ingredients
|
|||
|
|
|
|||
|
|
**AFTER**:
|
|||
|
|
- "Add Ingredient Manually" button
|
|||
|
|
- Full form with all fields
|
|||
|
|
- Adds to the same list as AI suggestions
|
|||
|
|
- Can edit/delete both AI and manual items
|
|||
|
|
|
|||
|
|
### 5. **Edit/Delete**
|
|||
|
|
**BEFORE**:
|
|||
|
|
- Inline editing only
|
|||
|
|
- No delete (just deselect)
|
|||
|
|
|
|||
|
|
**AFTER**:
|
|||
|
|
- Click "Edit" → Opens form with all fields
|
|||
|
|
- Click "Delete" → Removes from list
|
|||
|
|
- Works for both AI suggestions and manual entries
|
|||
|
|
|
|||
|
|
### 6. **Code Structure**
|
|||
|
|
|
|||
|
|
**BEFORE** (Old):
|
|||
|
|
```typescript
|
|||
|
|
// State
|
|||
|
|
const [inventoryItems, setInventoryItems] = useState<InventoryItem[]>([]);
|
|||
|
|
|
|||
|
|
// Selection toggle
|
|||
|
|
const handleToggleSelection = (id: string) => {
|
|||
|
|
setInventoryItems(items =>
|
|||
|
|
items.map(item =>
|
|||
|
|
item.suggestion_id === id ? { ...item, selected: !item.selected } : item
|
|||
|
|
)
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// Create button - immediate creation
|
|||
|
|
const handleCreateInventory = async () => {
|
|||
|
|
const selectedItems = inventoryItems.filter(item => item.selected);
|
|||
|
|
// Create immediately...
|
|||
|
|
await Promise.all(creationPromises);
|
|||
|
|
onComplete(); // Then proceed
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**AFTER** (New):
|
|||
|
|
```typescript
|
|||
|
|
// State
|
|||
|
|
const [inventoryItems, setInventoryItems] = useState<InventoryItemForm[]>([]);
|
|||
|
|
const [isAdding, setIsAdding] = useState(false);
|
|||
|
|
const [editingId, setEditingId] = useState<string | null>(null);
|
|||
|
|
const [formData, setFormData] = useState<InventoryItemForm>({ ... });
|
|||
|
|
|
|||
|
|
// Add/Edit item in list (NOT in database)
|
|||
|
|
const handleSubmitForm = (e: React.FormEvent) => {
|
|||
|
|
if (editingId) {
|
|||
|
|
// Update in list
|
|||
|
|
setInventoryItems(items => items.map(item =>
|
|||
|
|
item.id === editingId ? { ...formData, id: editingId } : item
|
|||
|
|
));
|
|||
|
|
} else {
|
|||
|
|
// Add to list
|
|||
|
|
setInventoryItems(items => [...items, newItem]);
|
|||
|
|
}
|
|||
|
|
resetForm();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// Delete from list
|
|||
|
|
const handleDelete = (itemId: string) => {
|
|||
|
|
setInventoryItems(items => items.filter(item => item.id !== itemId));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// Next button - create ALL at once
|
|||
|
|
const handleNext = async () => {
|
|||
|
|
// Create ALL items in the list
|
|||
|
|
const creationPromises = inventoryItems.map(item => createIngredient.mutateAsync(...));
|
|||
|
|
await Promise.allSettled(creationPromises);
|
|||
|
|
onComplete(); // Then proceed
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7. **Component Sections**
|
|||
|
|
|
|||
|
|
**BEFORE**: 2 main sections
|
|||
|
|
1. File upload view
|
|||
|
|
2. Checkbox selection + edit view
|
|||
|
|
|
|||
|
|
**AFTER**: 2 main sections
|
|||
|
|
1. File upload view (same)
|
|||
|
|
2. **List management view**:
|
|||
|
|
- "Why This Matters" info box
|
|||
|
|
- Ingredient list (cards with edit/delete)
|
|||
|
|
- Add/Edit form (appears on click)
|
|||
|
|
- Navigation with "Next" button
|
|||
|
|
|
|||
|
|
## Key Benefits
|
|||
|
|
|
|||
|
|
✅ **Consistent UI**: Matches suppliers/recipes pattern exactly
|
|||
|
|
✅ **Flexibility**: Users can review, edit, delete, and add items before creating
|
|||
|
|
✅ **Deferred Creation**: All items created at once when clicking "Next"
|
|||
|
|
✅ **Manual Addition**: Users can add ingredients beyond AI suggestions
|
|||
|
|
✅ **Better UX**: Clear "Edit" and "Delete" actions per item
|
|||
|
|
✅ **Unified Pattern**: Same workflow for AI and manual items
|
|||
|
|
|
|||
|
|
## Files Changed
|
|||
|
|
|
|||
|
|
- `/home/user/bakery_ia/frontend/src/components/domain/onboarding/steps/UploadSalesDataStep.tsx` - **Completely rewritten** (963 lines)
|
|||
|
|
- `/home/user/bakery_ia/frontend/src/components/domain/setup-wizard/steps/RecipesSetupStep.tsx` - Added Next button (2 lines)
|
|||
|
|
|
|||
|
|
## Testing Checklist
|
|||
|
|
|
|||
|
|
- [ ] Upload sales data file → AI suggestions load correctly
|
|||
|
|
- [ ] Edit AI suggestion → Changes saved to list
|
|||
|
|
- [ ] Delete AI suggestion → Removed from list
|
|||
|
|
- [ ] Add manual ingredient → Added to list
|
|||
|
|
- [ ] Edit manual ingredient → Changes saved
|
|||
|
|
- [ ] Delete manual ingredient → Removed from list
|
|||
|
|
- [ ] Click "Next" with 0 items → Error shown
|
|||
|
|
- [ ] Click "Next" with items → All created and proceeds to next step
|
|||
|
|
- [ ] Form validation works (required fields, min values)
|
|||
|
|
- [ ] UI matches suppliers/recipes styling
|