Imporve onboarding UI
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Package, Salad, AlertCircle, ArrowRight, ArrowLeft, CheckCircle } from 'lucide-react';
|
||||
import Button from '../../../ui/Button/Button';
|
||||
import Card from '../../../ui/Card/Card';
|
||||
import Input from '../../../ui/Input/Input';
|
||||
import { useCurrentTenant } from '../../../../stores/tenant.store';
|
||||
import { useAddStock } from '../../../../api/hooks/inventory';
|
||||
import { useAddStock, useStock } from '../../../../api/hooks/inventory';
|
||||
import InfoCard from '../../../ui/InfoCard';
|
||||
|
||||
export interface ProductWithStock {
|
||||
@@ -38,6 +38,7 @@ export const InitialStockEntryStep: React.FC<InitialStockEntryStepProps> = ({
|
||||
const currentTenant = useCurrentTenant();
|
||||
const tenantId = currentTenant?.id || '';
|
||||
const addStockMutation = useAddStock();
|
||||
const { data: stockData } = useStock(tenantId);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
const [products, setProducts] = useState<ProductWithStock[]>(() => {
|
||||
@@ -54,6 +55,30 @@ export const InitialStockEntryStep: React.FC<InitialStockEntryStepProps> = ({
|
||||
}));
|
||||
});
|
||||
|
||||
// Merge existing stock from backend on mount
|
||||
useEffect(() => {
|
||||
if (stockData?.items && products.length > 0) {
|
||||
console.log('🔄 Merging backend stock data into initial stock entry state...', { itemsCount: stockData.items.length });
|
||||
|
||||
let hasChanges = false;
|
||||
const updatedProducts = products.map(p => {
|
||||
const existingStock = stockData?.items?.find(s => s.ingredient_id === p.id);
|
||||
if (existingStock && p.initialStock !== existingStock.current_quantity) {
|
||||
hasChanges = true;
|
||||
return {
|
||||
...p,
|
||||
initialStock: existingStock.current_quantity
|
||||
};
|
||||
}
|
||||
return p;
|
||||
});
|
||||
|
||||
if (hasChanges) {
|
||||
setProducts(updatedProducts);
|
||||
}
|
||||
}
|
||||
}, [stockData, products]); // Run when stock data changes or products list is initialized
|
||||
|
||||
const ingredients = products.filter(p => p.type === 'ingredient');
|
||||
const finishedProducts = products.filter(p => p.type === 'finished_product');
|
||||
|
||||
@@ -87,30 +112,51 @@ export const InitialStockEntryStep: React.FC<InitialStockEntryStepProps> = ({
|
||||
const handleContinue = async () => {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
// Create stock entries for products with initial stock > 0
|
||||
const stockEntries = products.filter(p => p.initialStock && p.initialStock > 0);
|
||||
// STEP 0: Check for existing stock to avoid duplication
|
||||
const existingStockMap = new Map(
|
||||
stockData?.items?.map(s => [s.ingredient_id, s.current_quantity]) || []
|
||||
);
|
||||
|
||||
if (stockEntries.length > 0) {
|
||||
// Create stock entries in parallel
|
||||
const stockPromises = stockEntries.map(product =>
|
||||
// Create stock entries only for products where:
|
||||
// 1. initialStock is defined AND > 0
|
||||
// 2. AND (it doesn't exist OR the value is different)
|
||||
const stockEntriesToSync = products.filter(p => {
|
||||
const currentVal = p.initialStock ?? 0;
|
||||
const backendVal = existingStockMap.get(p.id);
|
||||
|
||||
// Only sync if it's new (> 0 and doesn't exist) or changed
|
||||
if (backendVal === undefined) {
|
||||
return currentVal > 0;
|
||||
}
|
||||
return currentVal !== backendVal;
|
||||
});
|
||||
|
||||
console.log(`📦 Stock processing: ${stockEntriesToSync.length} to sync, ${products.length - stockEntriesToSync.length} skipped.`);
|
||||
|
||||
if (stockEntriesToSync.length > 0) {
|
||||
// Create or update stock entries
|
||||
// Note: useAddStock currently handles creation/initial set.
|
||||
// If the backend requires a different endpoint for updates, this might need adjustment.
|
||||
// For onboarding, we assume addStock is a "set-and-forget" for initial levels.
|
||||
const stockPromises = stockEntriesToSync.map(product =>
|
||||
addStockMutation.mutateAsync({
|
||||
tenantId,
|
||||
stockData: {
|
||||
ingredient_id: product.id,
|
||||
current_quantity: product.initialStock!, // The actual stock quantity
|
||||
unit_cost: 0, // Default cost, can be updated later
|
||||
current_quantity: product.initialStock || 0,
|
||||
unit_cost: 0,
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
await Promise.all(stockPromises);
|
||||
console.log(`✅ Created ${stockEntries.length} stock entries successfully`);
|
||||
console.log(`✅ Synced ${stockEntriesToSync.length} stock entries successfully`);
|
||||
}
|
||||
|
||||
onComplete?.();
|
||||
} catch (error) {
|
||||
console.error('Error creating stock entries:', error);
|
||||
alert(t('onboarding:stock.error_creating_stock', 'Error al crear los niveles de stock. Por favor, inténtalo de nuevo.'));
|
||||
console.error('Error syncing stock entries:', error);
|
||||
alert(t('onboarding:stock.error_creating_stock', 'Error al guardar los niveles de stock. Por favor, inténtalo de nuevo.'));
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user