/** * Main onboarding hook - orchestrates all focused onboarding hooks * This is the primary hook that 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'; interface OnboardingActions { // Navigation nextStep: () => boolean; previousStep: () => boolean; goToStep: (stepIndex: number) => boolean; // Data Management updateStepData: (stepId: string, data: Partial) => void; validateCurrentStep: () => string | null; // Step-specific Actions createTenant: (bakeryData: BakeryRegistration) => Promise; processSalesFile: (file: File, onProgress?: ProgressCallback) => Promise; generateInventorySuggestions: (productList: string[]) => Promise; createInventoryFromSuggestions: (suggestions: ProductSuggestionResponse[]) => Promise; importSalesData: (salesData: any, inventoryMapping: { [productName: string]: string }) => Promise; startTraining: (options?: { products?: string[]; startDate?: string; endDate?: string; }) => Promise; // Completion completeOnboarding: () => Promise; // Utilities clearError: () => void; reset: () => void; } export const useOnboarding = () => { const navigate = useNavigate(); const user = useAuthUser(); const currentTenant = useCurrentTenant(); // Focused hooks const flow = useOnboardingFlow(); const data = useOnboardingData(); const tenantCreation = useTenantCreation(); const salesProcessing = useSalesProcessing(); const inventorySetup = useInventorySetup(); const trainingOrchestration = useTrainingOrchestration(); // Navigation actions const nextStep = useCallback((): boolean => { const validation = validateCurrentStep(); if (validation) { return false; } if (flow.nextStep()) { flow.markStepCompleted(flow.currentStep - 1); return true; } return false; }, [flow]); const previousStep = useCallback((): boolean => { return flow.previousStep(); }, [flow]); const goToStep = useCallback((stepIndex: number): boolean => { return flow.goToStep(stepIndex); }, [flow]); // Data management const updateStepData = useCallback((stepId: string, stepData: Partial) => { 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 => { const success = await tenantCreation.createTenant(bakeryData); if (success) { updateStepData('setup', { bakery: bakeryData }); } return success; }, [tenantCreation, updateStepData]); const processSalesFile = useCallback(async ( file: File, onProgress?: ProgressCallback ): Promise => { const result = await salesProcessing.processFile(file, onProgress); if (result.success) { updateStepData('data-processing', { files: { salesData: file }, processingStage: 'completed', processingResults: result.validationResults, suggestions: result.suggestions || [] }); } return result.success; }, [salesProcessing, updateStepData]); const generateInventorySuggestions = useCallback(async ( productList: string[] ): Promise => { return salesProcessing.generateSuggestions(productList); }, [salesProcessing]); const createInventoryFromSuggestions = useCallback(async ( suggestions: ProductSuggestionResponse[] ): Promise => { 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 => { 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 => { // 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 => { // 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; return { // State from flow management currentStep: flow.currentStep, steps: flow.steps, progress: flow.getProgress(), // State from data management data: data.data, allStepData: data.getAllStepData(), // State from individual hooks tenantCreation: { isLoading: tenantCreation.isLoading, isSuccess: tenantCreation.isSuccess, }, salesProcessing: { stage: salesProcessing.stage, progress: salesProcessing.progress, currentMessage: salesProcessing.currentMessage, validationResults: salesProcessing.validationResults, suggestions: salesProcessing.suggestions, }, inventorySetup: { createdItems: inventorySetup.createdItems, inventoryMapping: inventorySetup.inventoryMapping, salesImportResult: inventorySetup.salesImportResult, isInventoryConfigured: inventorySetup.isInventoryConfigured, }, trainingOrchestration: { status: trainingOrchestration.status, progress: trainingOrchestration.progress, currentStep: trainingOrchestration.currentStep, estimatedTimeRemaining: trainingOrchestration.estimatedTimeRemaining, job: trainingOrchestration.job, logs: trainingOrchestration.logs, metrics: trainingOrchestration.metrics, }, // Overall state isLoading, error, user, currentTenant, // Actions nextStep, previousStep, goToStep, updateStepData, validateCurrentStep, createTenant, processSalesFile, generateInventorySuggestions, createInventoryFromSuggestions, importSalesData, startTraining, completeOnboarding, clearError, reset, } satisfies ReturnType & ReturnType & { [key: string]: any } & OnboardingActions; };