Imporve onboarding UI

This commit is contained in:
Urtzi Alfaro
2025-12-19 13:10:24 +01:00
parent 71ee2976a2
commit bfa5ff0637
39 changed files with 1016 additions and 483 deletions

View File

@@ -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);
}