Start integrating the onboarding flow with backend 12
This commit is contained in:
@@ -1,282 +1,87 @@
|
||||
/**
|
||||
* Main onboarding hook - orchestrates all focused onboarding hooks
|
||||
* This is the primary hook that components should use
|
||||
* Main onboarding hook - Clean, unified interface for components
|
||||
* This is the primary hook that all components should use
|
||||
*/
|
||||
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuthUser } from '../../../stores/auth.store';
|
||||
import { useCurrentTenant } from '../../../stores';
|
||||
import { useOnboardingFlow } from './useOnboardingFlow';
|
||||
import { useOnboardingData } from './useOnboardingData';
|
||||
import { useTenantCreation } from './useTenantCreation';
|
||||
import { useSalesProcessing } from './useSalesProcessing';
|
||||
import { useInventorySetup } from './useInventorySetup';
|
||||
import { useTrainingOrchestration } from './useTrainingOrchestration';
|
||||
import type {
|
||||
OnboardingData,
|
||||
ProgressCallback,
|
||||
ProductSuggestionResponse
|
||||
} from './types';
|
||||
import type { BakeryRegistration } from '../../../api';
|
||||
|
||||
import { useOnboardingStore } from './core/store';
|
||||
import { useOnboardingActions } from './core/actions';
|
||||
import { useTenantCreation } from './services/useTenantCreation';
|
||||
import { useSalesProcessing } from './services/useSalesProcessing';
|
||||
import { useInventorySetup } from './services/useInventorySetup';
|
||||
import { useTrainingOrchestration } from './services/useTrainingOrchestration';
|
||||
import { useProgressTracking } from './services/useProgressTracking';
|
||||
import { useResumeLogic } from './services/useResumeLogic';
|
||||
|
||||
export const useOnboarding = () => {
|
||||
const navigate = useNavigate();
|
||||
const user = useAuthUser();
|
||||
const currentTenant = useCurrentTenant();
|
||||
|
||||
// Focused hooks
|
||||
const flow = useOnboardingFlow();
|
||||
const data = useOnboardingData();
|
||||
// Core store and actions
|
||||
const store = useOnboardingStore();
|
||||
const actions = useOnboardingActions();
|
||||
|
||||
// Service hooks for detailed state access
|
||||
const tenantCreation = useTenantCreation();
|
||||
const salesProcessing = useSalesProcessing();
|
||||
const inventorySetup = useInventorySetup();
|
||||
const trainingOrchestration = useTrainingOrchestration();
|
||||
|
||||
// Data management
|
||||
const updateStepData = useCallback((stepId: string, stepData: Partial<OnboardingData>) => {
|
||||
data.updateStepData(stepId, stepData);
|
||||
}, [data]);
|
||||
|
||||
const validateCurrentStep = useCallback((): string | null => {
|
||||
const currentStep = flow.getCurrentStep();
|
||||
const validationResult = data.validateStep(currentStep.id);
|
||||
|
||||
// Also check for specific step validations
|
||||
if (validationResult) return validationResult;
|
||||
|
||||
return null;
|
||||
}, [flow, data]);
|
||||
|
||||
// Step-specific actions
|
||||
const createTenant = useCallback(async (bakeryData: BakeryRegistration): Promise<boolean> => {
|
||||
const success = await tenantCreation.createTenant(bakeryData);
|
||||
if (success) {
|
||||
// Store the bakery data with tenant creation success flag and tenant ID
|
||||
updateStepData('setup', {
|
||||
bakery: {
|
||||
...bakeryData,
|
||||
tenantCreated: true,
|
||||
tenant_id: currentTenant?.id || 'created'
|
||||
} as any // Type assertion to allow the additional properties
|
||||
});
|
||||
console.log('useOnboarding - Tenant created successfully, updated step data with tenant ID:', currentTenant?.id);
|
||||
}
|
||||
return success;
|
||||
}, [tenantCreation, updateStepData, currentTenant]);
|
||||
|
||||
// Navigation actions
|
||||
const nextStep = useCallback(async (): Promise<boolean> => {
|
||||
try {
|
||||
const currentStep = flow.getCurrentStep();
|
||||
console.log('useOnboarding - nextStep called from step:', currentStep.id);
|
||||
|
||||
const validation = validateCurrentStep();
|
||||
if (validation) {
|
||||
console.log('useOnboarding - Validation failed:', validation);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle step-specific actions before moving to next step
|
||||
if (currentStep.id === 'setup') {
|
||||
console.log('useOnboarding - Creating tenant before leaving setup step');
|
||||
const allStepData = data.getAllStepData();
|
||||
const bakeryData = allStepData?.setup?.bakery;
|
||||
|
||||
if (bakeryData && !tenantCreation.isSuccess) {
|
||||
console.log('useOnboarding - Tenant data found, creating tenant:', bakeryData);
|
||||
const tenantSuccess = await createTenant(bakeryData);
|
||||
console.log('useOnboarding - Tenant creation result:', tenantSuccess);
|
||||
|
||||
if (!tenantSuccess) {
|
||||
console.log('useOnboarding - Tenant creation failed, stopping navigation');
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
console.log('useOnboarding - No tenant data found or tenant already created');
|
||||
}
|
||||
}
|
||||
|
||||
if (flow.nextStep()) {
|
||||
flow.markStepCompleted(flow.currentStep - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('useOnboarding - Error in nextStep:', error);
|
||||
return false;
|
||||
}
|
||||
}, [flow, validateCurrentStep, data, createTenant, tenantCreation]);
|
||||
|
||||
const previousStep = useCallback((): boolean => {
|
||||
return flow.previousStep();
|
||||
}, [flow]);
|
||||
|
||||
const goToStep = useCallback((stepIndex: number): boolean => {
|
||||
return flow.goToStep(stepIndex);
|
||||
}, [flow]);
|
||||
|
||||
const processSalesFile = useCallback(async (
|
||||
file: File,
|
||||
onProgress?: ProgressCallback
|
||||
): Promise<boolean> => {
|
||||
const result = await salesProcessing.processFile(file, onProgress);
|
||||
if (result.success) {
|
||||
updateStepData('sales-validation', {
|
||||
files: { salesData: file },
|
||||
processingStage: 'completed',
|
||||
processingResults: result.validationResults,
|
||||
suggestions: result.suggestions || []
|
||||
});
|
||||
}
|
||||
return result.success;
|
||||
}, [salesProcessing, updateStepData]);
|
||||
|
||||
const generateInventorySuggestions = useCallback(async (
|
||||
productList: string[]
|
||||
): Promise<ProductSuggestionResponse[] | null> => {
|
||||
return salesProcessing.generateSuggestions(productList);
|
||||
}, [salesProcessing]);
|
||||
|
||||
const createInventoryFromSuggestions = useCallback(async (
|
||||
suggestions: ProductSuggestionResponse[]
|
||||
): Promise<boolean> => {
|
||||
const result = await inventorySetup.createInventoryFromSuggestions(suggestions);
|
||||
if (result.success) {
|
||||
updateStepData('inventory', {
|
||||
inventoryItems: result.createdItems,
|
||||
inventoryMapping: result.inventoryMapping,
|
||||
inventoryConfigured: true,
|
||||
});
|
||||
}
|
||||
return result.success;
|
||||
}, [inventorySetup, updateStepData]);
|
||||
|
||||
const importSalesData = useCallback(async (
|
||||
salesData: any,
|
||||
inventoryMapping: { [productName: string]: string }
|
||||
): Promise<boolean> => {
|
||||
const result = await inventorySetup.importSalesData(salesData, inventoryMapping);
|
||||
if (result.success) {
|
||||
updateStepData('inventory', {
|
||||
salesImportResult: {
|
||||
success: result.success,
|
||||
imported: true,
|
||||
records_created: result.recordsCreated,
|
||||
message: result.message,
|
||||
},
|
||||
});
|
||||
}
|
||||
return result.success;
|
||||
}, [inventorySetup, updateStepData]);
|
||||
|
||||
const startTraining = useCallback(async (options?: {
|
||||
products?: string[];
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}): Promise<boolean> => {
|
||||
// First validate training data requirements
|
||||
const allStepData = data.getAllStepData();
|
||||
const validation = await trainingOrchestration.validateTrainingData(allStepData);
|
||||
|
||||
if (!validation.isValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const success = await trainingOrchestration.startTraining(options);
|
||||
if (success) {
|
||||
updateStepData('ml-training', {
|
||||
trainingStatus: 'training',
|
||||
trainingJob: trainingOrchestration.job,
|
||||
trainingLogs: trainingOrchestration.logs,
|
||||
});
|
||||
}
|
||||
return success;
|
||||
}, [trainingOrchestration, data, updateStepData]);
|
||||
|
||||
const completeOnboarding = useCallback(async (): Promise<boolean> => {
|
||||
// Mark final completion
|
||||
updateStepData('completion', {
|
||||
completionStats: {
|
||||
totalProducts: data.data.processingResults?.unique_products || 0,
|
||||
inventoryItems: data.data.inventoryItems?.length || 0,
|
||||
suppliersConfigured: data.data.suppliers?.length || 0,
|
||||
mlModelAccuracy: data.data.trainingMetrics?.accuracy || 0,
|
||||
estimatedTimeSaved: '2-3 horas por día',
|
||||
completionScore: 95,
|
||||
},
|
||||
});
|
||||
|
||||
flow.markStepCompleted(flow.steps.length - 1);
|
||||
|
||||
// Navigate to dashboard after completion
|
||||
setTimeout(() => {
|
||||
navigate('/app/dashboard');
|
||||
}, 2000);
|
||||
|
||||
return true;
|
||||
}, [data, flow, navigate, updateStepData]);
|
||||
|
||||
// Utilities
|
||||
const clearError = useCallback(() => {
|
||||
data.clearError();
|
||||
tenantCreation.clearError();
|
||||
salesProcessing.clearError();
|
||||
inventorySetup.clearError();
|
||||
trainingOrchestration.clearError();
|
||||
}, [data, tenantCreation, salesProcessing, inventorySetup, trainingOrchestration]);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
flow.resetFlow();
|
||||
data.resetData();
|
||||
tenantCreation.reset();
|
||||
salesProcessing.reset();
|
||||
inventorySetup.reset();
|
||||
trainingOrchestration.reset();
|
||||
}, [flow, data, tenantCreation, salesProcessing, inventorySetup, trainingOrchestration]);
|
||||
|
||||
// Determine overall loading and error state
|
||||
const isLoading = tenantCreation.isLoading ||
|
||||
salesProcessing.isLoading ||
|
||||
inventorySetup.isLoading ||
|
||||
trainingOrchestration.isLoading;
|
||||
|
||||
const error = data.error?.message ||
|
||||
tenantCreation.error ||
|
||||
salesProcessing.error ||
|
||||
inventorySetup.error ||
|
||||
trainingOrchestration.error;
|
||||
const progressTracking = useProgressTracking();
|
||||
const resumeLogic = useResumeLogic();
|
||||
|
||||
return {
|
||||
// State from flow management
|
||||
currentStep: flow.currentStep,
|
||||
steps: flow.steps,
|
||||
progress: flow.getProgress(),
|
||||
// Core state from store
|
||||
currentStep: store.getCurrentStep(),
|
||||
steps: store.steps,
|
||||
data: store.data,
|
||||
progress: store.getProgress(),
|
||||
isLoading: store.isLoading,
|
||||
error: store.error,
|
||||
|
||||
// State from data management
|
||||
data: data.data,
|
||||
allStepData: data.getAllStepData(),
|
||||
// User context
|
||||
user,
|
||||
currentTenant,
|
||||
|
||||
// State from individual hooks
|
||||
// Step data helpers
|
||||
stepData: {
|
||||
setup: store.getStepData('setup'),
|
||||
'smart-inventory-setup': store.getStepData('smart-inventory-setup'),
|
||||
suppliers: store.getStepData('suppliers'),
|
||||
'ml-training': store.getStepData('ml-training'),
|
||||
completion: store.getStepData('completion'),
|
||||
},
|
||||
|
||||
// Service states (for components that need detailed service info)
|
||||
tenantCreation: {
|
||||
isLoading: tenantCreation.isLoading,
|
||||
isSuccess: tenantCreation.isSuccess,
|
||||
error: tenantCreation.error,
|
||||
tenantData: tenantCreation.tenantData,
|
||||
},
|
||||
|
||||
salesProcessing: {
|
||||
isLoading: salesProcessing.isLoading,
|
||||
error: salesProcessing.error,
|
||||
stage: salesProcessing.stage,
|
||||
progress: salesProcessing.progress,
|
||||
currentMessage: salesProcessing.currentMessage,
|
||||
validationResults: salesProcessing.validationResults,
|
||||
suggestions: salesProcessing.suggestions,
|
||||
},
|
||||
|
||||
inventorySetup: {
|
||||
isLoading: inventorySetup.isLoading,
|
||||
error: inventorySetup.error,
|
||||
createdItems: inventorySetup.createdItems,
|
||||
inventoryMapping: inventorySetup.inventoryMapping,
|
||||
salesImportResult: inventorySetup.salesImportResult,
|
||||
isInventoryConfigured: inventorySetup.isInventoryConfigured,
|
||||
},
|
||||
|
||||
trainingOrchestration: {
|
||||
isLoading: trainingOrchestration.isLoading,
|
||||
error: trainingOrchestration.error,
|
||||
status: trainingOrchestration.status,
|
||||
progress: trainingOrchestration.progress,
|
||||
currentStep: trainingOrchestration.currentStep,
|
||||
@@ -285,27 +90,55 @@ export const useOnboarding = () => {
|
||||
logs: trainingOrchestration.logs,
|
||||
metrics: trainingOrchestration.metrics,
|
||||
},
|
||||
|
||||
progressTracking: {
|
||||
isLoading: progressTracking.isLoading,
|
||||
error: progressTracking.error,
|
||||
progress: progressTracking.progress,
|
||||
isCompleted: progressTracking.isCompleted,
|
||||
completionPercentage: progressTracking.completionPercentage,
|
||||
isInitialized: progressTracking.isInitialized,
|
||||
currentBackendStep: progressTracking.currentBackendStep,
|
||||
},
|
||||
|
||||
resumeLogic: {
|
||||
isCheckingResume: resumeLogic.isCheckingResume,
|
||||
resumePoint: resumeLogic.resumePoint,
|
||||
shouldResume: resumeLogic.shouldResume,
|
||||
progress: resumeLogic.progress,
|
||||
isCompleted: resumeLogic.isCompleted,
|
||||
completionPercentage: resumeLogic.completionPercentage,
|
||||
},
|
||||
|
||||
// Overall state
|
||||
isLoading,
|
||||
error,
|
||||
user,
|
||||
currentTenant,
|
||||
|
||||
// Actions
|
||||
nextStep,
|
||||
previousStep,
|
||||
goToStep,
|
||||
updateStepData,
|
||||
validateCurrentStep,
|
||||
createTenant,
|
||||
processSalesFile,
|
||||
generateInventorySuggestions,
|
||||
createInventoryFromSuggestions,
|
||||
importSalesData,
|
||||
startTraining,
|
||||
completeOnboarding,
|
||||
clearError,
|
||||
reset,
|
||||
// Actions from the core actions hook
|
||||
nextStep: actions.nextStep,
|
||||
previousStep: actions.previousStep,
|
||||
goToStep: actions.goToStep,
|
||||
validateCurrentStep: actions.validateCurrentStep,
|
||||
|
||||
// Step data management
|
||||
updateStepData: store.setStepData,
|
||||
clearStepData: store.clearStepData,
|
||||
|
||||
// Step-specific actions
|
||||
createTenant: actions.createTenant,
|
||||
processSalesFile: actions.processSalesFile,
|
||||
createInventoryFromSuggestions: actions.createInventoryFromSuggestions,
|
||||
importSalesData: actions.importSalesData,
|
||||
startTraining: actions.startTraining,
|
||||
completeOnboarding: actions.completeOnboarding,
|
||||
|
||||
// Service-specific actions (for components that need direct service access)
|
||||
generateSuggestions: salesProcessing.generateSuggestions,
|
||||
addTrainingLog: trainingOrchestration.addLog,
|
||||
validateTrainingData: trainingOrchestration.validateTrainingData,
|
||||
|
||||
// Resume actions
|
||||
checkForSavedProgress: resumeLogic.checkForResume,
|
||||
resumeFromSavedProgress: resumeLogic.resumeFlow,
|
||||
|
||||
// Utility actions
|
||||
clearError: actions.clearError,
|
||||
reset: actions.reset,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user