Start integrating the onboarding flow with backend 10
This commit is contained in:
@@ -57,6 +57,7 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
validationResults,
|
||||
suggestions
|
||||
},
|
||||
tenantCreation,
|
||||
isLoading,
|
||||
error,
|
||||
clearError
|
||||
@@ -70,22 +71,44 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
|
||||
// Get tenant ID from multiple sources with fallback
|
||||
const getTenantId = (): string | null => {
|
||||
const tenantId = currentTenant?.id || user?.tenant_id || null;
|
||||
// Also check the onboarding data for tenant creation success
|
||||
const onboardingTenantId = data.bakery?.tenant_id;
|
||||
const tenantId = currentTenant?.id || user?.tenant_id || onboardingTenantId || null;
|
||||
console.log('DataProcessingStep - getTenantId:', {
|
||||
currentTenant: currentTenant?.id,
|
||||
userTenantId: user?.tenant_id,
|
||||
onboardingTenantId: onboardingTenantId,
|
||||
finalTenantId: tenantId,
|
||||
isLoadingUserData,
|
||||
authLoading,
|
||||
tenantLoading,
|
||||
user: user ? { id: user.id, email: user.email } : null
|
||||
user: user ? { id: user.id, email: user.email } : null,
|
||||
tenantCreationSuccess: data.tenantCreation?.isSuccess
|
||||
});
|
||||
return tenantId;
|
||||
};
|
||||
|
||||
// Check if tenant data is available (not loading and has ID)
|
||||
// Check if tenant data is available (not loading and has ID, OR tenant was created successfully)
|
||||
const isTenantAvailable = (): boolean => {
|
||||
return !isLoadingUserData && getTenantId() !== null;
|
||||
const hasAuth = !authLoading && user;
|
||||
const hasTenantId = getTenantId() !== null;
|
||||
const tenantCreatedSuccessfully = tenantCreation.isSuccess;
|
||||
const tenantCreatedInOnboarding = data.bakery?.tenantCreated === true;
|
||||
|
||||
const isAvailable = hasAuth && (hasTenantId || tenantCreatedSuccessfully || tenantCreatedInOnboarding);
|
||||
console.log('DataProcessingStep - isTenantAvailable:', {
|
||||
hasAuth,
|
||||
hasTenantId,
|
||||
tenantCreatedSuccessfully,
|
||||
tenantCreatedInOnboarding,
|
||||
isAvailable,
|
||||
authLoading,
|
||||
tenantLoading,
|
||||
tenantCreationFromHook: tenantCreation,
|
||||
bakeryData: data.bakery
|
||||
});
|
||||
|
||||
return isAvailable;
|
||||
};
|
||||
// Use onboarding hook state when available, fallback to local state
|
||||
const [localStage, setLocalStage] = useState<ProcessingStage>(data.processingStage || 'upload');
|
||||
@@ -93,38 +116,67 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
const [localResults, setLocalResults] = useState<ProcessingResult | null>(data.processingResults || null);
|
||||
|
||||
// Derive current state from onboarding hooks or local state
|
||||
const stage = onboardingStage || localStage;
|
||||
// Priority: if local is 'completed' or 'error', use local; otherwise use onboarding state
|
||||
const stage = (localStage === 'completed' || localStage === 'error')
|
||||
? localStage
|
||||
: (onboardingStage || localStage);
|
||||
const progress = onboardingProgress || 0;
|
||||
const currentMessage = onboardingMessage || '';
|
||||
const results = (validationResults && suggestions) ? {
|
||||
...validationResults,
|
||||
aiSuggestions: suggestions,
|
||||
// Add calculated fields
|
||||
productsIdentified: validationResults.product_list?.length || 0,
|
||||
// Add calculated fields from backend response
|
||||
productsIdentified: validationResults.unique_products || validationResults.product_list?.length || 0,
|
||||
categoriesDetected: suggestions ? new Set(suggestions.map((s: any) => s.category)).size : 0,
|
||||
businessModel: 'production',
|
||||
confidenceScore: 85,
|
||||
recommendations: []
|
||||
recommendations: validationResults.summary?.suggestions || [],
|
||||
// Backend response details
|
||||
totalRecords: validationResults.total_records || 0,
|
||||
validRecords: validationResults.valid_records || 0,
|
||||
invalidRecords: validationResults.invalid_records || 0,
|
||||
fileFormat: validationResults.summary?.file_format || 'csv',
|
||||
fileSizeMb: validationResults.summary?.file_size_mb || 0,
|
||||
estimatedProcessingTime: validationResults.summary?.estimated_processing_time_seconds || 0,
|
||||
detectedColumns: validationResults.summary?.detected_columns || [],
|
||||
validationMessage: validationResults.message || 'Validación completada'
|
||||
} : localResults;
|
||||
|
||||
// Debug logging for state changes
|
||||
console.log('DataProcessingStep - State debug:', {
|
||||
localStage,
|
||||
onboardingStage,
|
||||
finalStage: stage,
|
||||
hasValidationResults: !!validationResults,
|
||||
hasSuggestions: !!suggestions,
|
||||
hasResults: !!results,
|
||||
localResults: !!localResults
|
||||
});
|
||||
const [dragActive, setDragActive] = useState(false);
|
||||
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const lastStateRef = useRef({ stage, progress, currentMessage, results, suggestions, uploadedFile });
|
||||
|
||||
useEffect(() => {
|
||||
// Update parent data when state changes
|
||||
onDataChange({
|
||||
...data,
|
||||
processingStage: stage,
|
||||
processingProgress: progress,
|
||||
currentMessage: currentMessage,
|
||||
processingResults: results,
|
||||
suggestions: suggestions,
|
||||
files: {
|
||||
...data.files,
|
||||
salesData: uploadedFile
|
||||
}
|
||||
});
|
||||
}, [stage, progress, currentMessage, results, suggestions, uploadedFile, onDataChange, data]);
|
||||
// Only update if state actually changed
|
||||
const currentState = { stage, progress, currentMessage, results, suggestions, uploadedFile };
|
||||
if (JSON.stringify(currentState) !== JSON.stringify(lastStateRef.current)) {
|
||||
lastStateRef.current = currentState;
|
||||
|
||||
// Update parent data when state changes
|
||||
onDataChange({
|
||||
processingStage: stage,
|
||||
processingProgress: progress,
|
||||
currentMessage: currentMessage,
|
||||
processingResults: results,
|
||||
suggestions: suggestions,
|
||||
files: {
|
||||
...data.files,
|
||||
salesData: uploadedFile
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [stage, progress, currentMessage, results, suggestions, uploadedFile, onDataChange, data.files]);
|
||||
|
||||
const handleDragOver = (e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
@@ -190,7 +242,12 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('DataProcessingStep - Starting file processing');
|
||||
console.log('DataProcessingStep - Starting file processing', {
|
||||
fileName: file.name,
|
||||
fileSize: file.size,
|
||||
fileType: file.type,
|
||||
lastModified: file.lastModified
|
||||
});
|
||||
|
||||
// Use the onboarding hook for file processing
|
||||
const success = await processSalesFile(file, (progress, stage, message) => {
|
||||
@@ -199,6 +256,21 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
|
||||
if (success) {
|
||||
setLocalStage('completed');
|
||||
|
||||
// If we have results from the onboarding hook, store them locally too
|
||||
if (validationResults && suggestions) {
|
||||
const processedResults = {
|
||||
...validationResults,
|
||||
aiSuggestions: suggestions,
|
||||
productsIdentified: validationResults.product_list?.length || 0,
|
||||
categoriesDetected: suggestions ? new Set(suggestions.map((s: any) => s.category)).size : 0,
|
||||
businessModel: 'production',
|
||||
confidenceScore: 85,
|
||||
recommendations: []
|
||||
};
|
||||
setLocalResults(processedResults);
|
||||
}
|
||||
|
||||
toast.addToast('El archivo se procesó correctamente', {
|
||||
title: 'Procesamiento completado',
|
||||
type: 'success'
|
||||
@@ -209,6 +281,15 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
|
||||
} catch (error) {
|
||||
console.error('DataProcessingStep - Processing error:', error);
|
||||
console.error('DataProcessingStep - Error details:', {
|
||||
error,
|
||||
errorMessage: error instanceof Error ? error.message : 'Unknown error',
|
||||
errorStack: error instanceof Error ? error.stack : undefined,
|
||||
uploadedFile: file?.name,
|
||||
fileSize: file?.size,
|
||||
fileType: file?.type,
|
||||
localUploadedFile: uploadedFile?.name
|
||||
});
|
||||
|
||||
setLocalStage('error');
|
||||
const errorMessage = error instanceof Error ? error.message : 'Error en el procesamiento de datos';
|
||||
@@ -471,15 +552,29 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
¡Procesamiento Completado!
|
||||
</h3>
|
||||
<p className="text-[var(--text-secondary)] max-w-2xl mx-auto">
|
||||
Tus datos han sido procesados exitosamente
|
||||
{results.validationMessage || 'Tus datos han sido procesados exitosamente'}
|
||||
</p>
|
||||
{results.fileSizeMb && (
|
||||
<div className="text-xs text-[var(--text-tertiary)] mt-2">
|
||||
Archivo {results.fileFormat?.toUpperCase()} • {results.fileSizeMb.toFixed(2)} MB
|
||||
{results.estimatedProcessingTime && ` • ${results.estimatedProcessingTime}s procesamiento`}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Simple Stats Cards */}
|
||||
{/* Enhanced Stats Cards */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div className="text-center p-4 bg-[var(--color-info)]/10 rounded-lg">
|
||||
<p className="text-2xl font-bold text-[var(--color-info)]">{results.total_records}</p>
|
||||
<p className="text-sm text-[var(--text-secondary)]">Registros</p>
|
||||
<p className="text-2xl font-bold text-[var(--color-info)]">{results.totalRecords || results.total_records}</p>
|
||||
<p className="text-sm text-[var(--text-secondary)]">Total Registros</p>
|
||||
</div>
|
||||
<div className="text-center p-4 bg-[var(--color-success)]/10 rounded-lg">
|
||||
<p className="text-2xl font-bold text-[var(--color-success)]">{results.validRecords || results.valid_records}</p>
|
||||
<p className="text-sm text-[var(--text-secondary)]">Válidos</p>
|
||||
</div>
|
||||
<div className="text-center p-4 bg-[var(--color-error)]/10 rounded-lg">
|
||||
<p className="text-2xl font-bold text-[var(--color-error)]">{results.invalidRecords || results.invalid_records || 0}</p>
|
||||
<p className="text-sm text-[var(--text-secondary)]">Inválidos</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center p-4 bg-[var(--color-primary)]/10 rounded-lg">
|
||||
@@ -500,6 +595,41 @@ export const DataProcessingStep: React.FC<OnboardingStepProps> = ({
|
||||
<p className="text-sm text-[var(--text-secondary)]">Modelo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Additional Details from Backend */}
|
||||
{(results.detectedColumns?.length > 0 || results.recommendations?.length > 0) && (
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{/* Detected Columns */}
|
||||
{results.detectedColumns?.length > 0 && (
|
||||
<Card className="p-4">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-3">Columnas Detectadas</h4>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{results.detectedColumns.map((column, index) => (
|
||||
<span key={index}
|
||||
className="px-2 py-1 bg-[var(--color-primary)]/10 text-[var(--color-primary)] text-xs rounded-full border border-[var(--color-primary)]/20">
|
||||
{column}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Backend Recommendations */}
|
||||
{results.recommendations?.length > 0 && (
|
||||
<Card className="p-4">
|
||||
<h4 className="font-semibold text-[var(--text-primary)] mb-3">Recomendaciones</h4>
|
||||
<ul className="space-y-2">
|
||||
{results.recommendations.slice(0, 3).map((rec, index) => (
|
||||
<li key={index} className="text-sm text-[var(--text-secondary)] flex items-start">
|
||||
<span className="text-[var(--color-success)] mr-2">•</span>
|
||||
{rec}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user