Start integrating the onboarding flow with backend 17
This commit is contained in:
@@ -85,6 +85,7 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
// Use onboarding hooks
|
||||
const {
|
||||
processSalesFile,
|
||||
generateProductSuggestions, // New separated function
|
||||
createInventoryFromSuggestions,
|
||||
importSalesData,
|
||||
salesProcessing: {
|
||||
@@ -120,8 +121,11 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
const tenantCreatedSuccessfully = tenantCreation.isSuccess;
|
||||
const tenantCreatedInOnboarding = data.bakery?.tenantCreated === true;
|
||||
|
||||
const result = Boolean(hasAuth && (hasTenantId || tenantCreatedSuccessfully || tenantCreatedInOnboarding));
|
||||
// If user has already uploaded a file or has processing data, assume tenant is available
|
||||
// This prevents blocking the UI due to temporary state inconsistencies after successful progress
|
||||
const hasProgressData = !!(data.files?.salesData || data.processingResults || data.processingStage);
|
||||
|
||||
const result = Boolean(hasAuth && (hasTenantId || tenantCreatedSuccessfully || tenantCreatedInOnboarding || isAlreadyInStep));
|
||||
|
||||
return result;
|
||||
};
|
||||
@@ -152,20 +156,55 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
productsLength: products.length,
|
||||
suggestionsIsArray: Array.isArray(suggestions),
|
||||
suggestionsType: typeof suggestions,
|
||||
shouldConvert: suggestions && suggestions.length > 0 && products.length === 0
|
||||
});
|
||||
|
||||
if (suggestions && suggestions.length > 0 && products.length === 0) {
|
||||
if (suggestions && Array.isArray(suggestions) && suggestions.length > 0 && products.length === 0) {
|
||||
console.log('✅ Converting suggestions to products and setting stage to review');
|
||||
const newProducts = convertSuggestionsToCards(suggestions);
|
||||
setProducts(newProducts);
|
||||
setLocalStage('review');
|
||||
try {
|
||||
const newProducts = convertSuggestionsToCards(suggestions);
|
||||
console.log('📦 Converted products:', newProducts.length);
|
||||
setProducts(newProducts);
|
||||
setLocalStage('review');
|
||||
|
||||
// Force update parent data immediately
|
||||
const updatedData = {
|
||||
...data,
|
||||
detectedProducts: newProducts,
|
||||
processingStage: 'review'
|
||||
};
|
||||
onDataChange(updatedData);
|
||||
} catch (error) {
|
||||
console.error('❌ Error converting suggestions to products:', error);
|
||||
}
|
||||
}
|
||||
}, [suggestions, products.length]);
|
||||
}, [suggestions, products.length, data, onDataChange]);
|
||||
|
||||
// Derive current stage
|
||||
const stage = (localStage === 'completed' || localStage === 'error')
|
||||
? localStage
|
||||
: (onboardingStage === 'completed' ? 'review' : onboardingStage || localStage);
|
||||
const stage = (() => {
|
||||
// If local stage is explicitly set to completed or error, use it
|
||||
if (localStage === 'completed' || localStage === 'error') {
|
||||
return localStage;
|
||||
}
|
||||
|
||||
// If we have products to review, always show review stage
|
||||
if (products.length > 0) {
|
||||
return 'review';
|
||||
}
|
||||
|
||||
// If onboarding processing completed but no products yet, wait for conversion
|
||||
if (onboardingStage === 'completed' && suggestions && suggestions.length > 0) {
|
||||
return 'review';
|
||||
}
|
||||
|
||||
// If file is validated but no suggestions generated yet, show confirmation stage
|
||||
if (onboardingStage === 'validated' || localStage === 'validated') {
|
||||
return 'validated';
|
||||
}
|
||||
|
||||
// Otherwise use the onboarding stage or local stage
|
||||
return onboardingStage || localStage;
|
||||
})();
|
||||
const progress = onboardingProgress || 0;
|
||||
const currentMessage = onboardingMessage || '';
|
||||
|
||||
@@ -176,7 +215,10 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
onboardingStage,
|
||||
finalStage: stage,
|
||||
productsLength: products.length,
|
||||
suggestionsLength: suggestions?.length || 0
|
||||
suggestionsLength: suggestions?.length || 0,
|
||||
hasSuggestions: !!suggestions,
|
||||
suggestionsArray: Array.isArray(suggestions),
|
||||
willShowReview: stage === 'review' && products.length > 0
|
||||
});
|
||||
}, [localStage, onboardingStage, stage, products.length, suggestions?.length]);
|
||||
|
||||
@@ -275,22 +317,14 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
console.log('🔄 SmartInventorySetup - Processing result:', { success });
|
||||
|
||||
if (success) {
|
||||
console.log('✅ File processed successfully, setting stage to review');
|
||||
setLocalStage('review');
|
||||
console.log('✅ File validation completed successfully');
|
||||
// Don't set to review stage anymore - let the 'validated' stage show first
|
||||
setLocalStage('validated');
|
||||
|
||||
// Check if there was a suggestion error (AI service timeout)
|
||||
const stepData = data.allStepData?.['smart-inventory-setup'];
|
||||
if (stepData?.suggestionError) {
|
||||
toast.addToast(`Archivo procesado. ${stepData.suggestionError} Se crearon sugerencias básicas que puedes editar.`, {
|
||||
title: 'Procesamiento completado con advertencias',
|
||||
type: 'warning'
|
||||
});
|
||||
} else {
|
||||
toast.addToast('El archivo se procesó correctamente. Revisa los productos detectados.', {
|
||||
title: 'Procesamiento completado',
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
toast.addToast(`Archivo validado correctamente. Se encontraron ${validationResults?.product_list?.length || 0} productos.`, {
|
||||
title: 'Validación completada',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
console.error('❌ File processing failed - processSalesFile returned false');
|
||||
throw new Error('Error procesando el archivo');
|
||||
@@ -364,6 +398,40 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
setEditingProduct(null);
|
||||
};
|
||||
|
||||
// Handle generating suggestions after file validation
|
||||
const handleGenerateSuggestions = async () => {
|
||||
if (!validationResults?.product_list?.length) {
|
||||
toast.addToast('No se encontraron productos para analizar', {
|
||||
title: 'Error',
|
||||
type: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLocalStage('analyzing');
|
||||
const success = await generateProductSuggestions(validationResults.product_list);
|
||||
|
||||
if (success) {
|
||||
toast.addToast('Sugerencias generadas correctamente', {
|
||||
title: 'Análisis completado',
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
toast.addToast('Error generando sugerencias de productos', {
|
||||
title: 'Error en análisis',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error generating suggestions:', error);
|
||||
toast.addToast('Error generando sugerencias de productos', {
|
||||
title: 'Error en análisis',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Update parent data
|
||||
useEffect(() => {
|
||||
const updatedData = {
|
||||
@@ -529,6 +597,57 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* File Validated - User Confirmation Required */}
|
||||
{stage === 'validated' && validationResults && (
|
||||
<Card className="p-8">
|
||||
<div className="text-center">
|
||||
<div className="w-20 h-20 bg-[var(--color-success)]/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="w-10 h-10 text-[var(--color-success)]" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold text-[var(--color-success)] mb-4">
|
||||
¡Archivo Validado Correctamente!
|
||||
</h3>
|
||||
<p className="text-[var(--text-secondary)] text-lg mb-6 max-w-2xl mx-auto">
|
||||
Hemos encontrado <strong>{validationResults.product_list?.length || 0} productos únicos</strong> en tu archivo de ventas.
|
||||
</p>
|
||||
|
||||
<div className="bg-[var(--bg-secondary)] rounded-lg p-6 mb-8 max-w-2xl mx-auto">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-3">Lo que haremos a continuación:</h4>
|
||||
<ul className="text-[var(--text-secondary)] text-left space-y-2">
|
||||
<li>🤖 <strong>Análisis con IA:</strong> Clasificaremos automáticamente tus productos</li>
|
||||
<li>📦 <strong>Configuración inteligente:</strong> Calcularemos niveles de stock óptimos</li>
|
||||
<li>✅ <strong>Tu aprobación:</strong> Podrás revisar y aprobar cada sugerencia</li>
|
||||
<li>🎯 <strong>Inventario personalizado:</strong> Crearemos tu inventario final</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<Button
|
||||
onClick={handleGenerateSuggestions}
|
||||
className="bg-[var(--color-primary)] hover:bg-[var(--color-primary)]/90 text-white shadow-lg px-8 py-3 text-lg"
|
||||
>
|
||||
<Brain className="w-5 h-5 mr-2" />
|
||||
Generar Sugerencias con IA
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setLocalStage('upload');
|
||||
setUploadedFile(null);
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = '';
|
||||
}
|
||||
}}
|
||||
className="text-[var(--text-secondary)] border-[var(--border-secondary)] hover:bg-[var(--bg-tertiary)] px-6 py-3"
|
||||
>
|
||||
Subir otro archivo
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Processing Stages */}
|
||||
{(stage === 'validating' || stage === 'analyzing') && (
|
||||
<Card className="p-8">
|
||||
@@ -589,6 +708,23 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Waiting for Suggestions to Load */}
|
||||
{(stage === 'review' || (onboardingStage === 'completed' && suggestions)) && products.length === 0 && suggestions && suggestions.length > 0 && (
|
||||
<Card className="p-8">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-[var(--color-info)]/10 rounded-full flex items-center justify-center mx-auto mb-6 animate-pulse">
|
||||
<Brain className="w-8 h-8 text-[var(--color-info)]" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-semibold text-[var(--text-primary)] mb-2">
|
||||
Preparando sugerencias...
|
||||
</h3>
|
||||
<p className="text-[var(--text-secondary)]">
|
||||
Convirtiendo {suggestions.length} productos en sugerencias personalizadas
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Review & Configure Stage */}
|
||||
{(stage === 'review') && products.length > 0 && (
|
||||
<div className="space-y-8">
|
||||
|
||||
Reference in New Issue
Block a user