Start integrating the onboarding flow with backend 13

This commit is contained in:
Urtzi Alfaro
2025-09-07 21:26:28 +02:00
parent b73f3b4993
commit 05898d504d
10 changed files with 24 additions and 132 deletions

View File

@@ -455,7 +455,7 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
</div>
<div>
<h3 className="text-3xl font-bold text-[var(--text-primary)] mb-4">
Sube tu historial de ventas
Sube tus datos de ventas de forma segura: eres el propietario de esos datos, nosotros solo los optimizamos.
</h3>
<p className="text-[var(--text-secondary)] text-xl leading-relaxed max-w-md mx-auto">
Arrastra y suelta tu archivo aquí, o <span className="text-[var(--color-primary)] font-semibold">haz clic para seleccionar</span>
@@ -771,7 +771,7 @@ export const SmartInventorySetupStep: React.FC<OnboardingStepProps> = ({
{/* Information */}
<Card className="p-4 bg-[var(--color-info)]/5 border-[var(--color-info)]/20">
<h4 className="font-medium text-[var(--color-info)] mb-2">
📦 Inventario Inteligente:
📦 Sube tus datos de ventas de forma segura: eres el propietario, nosotros solo los optimizamos.:
</h4>
<ul className="text-sm text-[var(--color-info)] space-y-1">
<li> <strong>Configuración automática</strong> - Los niveles de stock se calculan basándose en tus datos de ventas</li>

View File

@@ -55,7 +55,8 @@ src/hooks/business/onboarding/
├── core/
│ ├── store.ts # Zustand centralized store
│ ├── actions.ts # Business logic orchestration
── types.ts # Complete type definitions
── types.ts # Complete type definitions
│ └── useAutoResume.ts # Auto-resume wrapper
├── services/
│ ├── useTenantCreation.ts # Tenant service
│ ├── useSalesProcessing.ts # Sales processing service
@@ -65,10 +66,9 @@ src/hooks/business/onboarding/
│ └── useResumeLogic.ts # Resume service
├── utils/
│ └── createServiceHook.ts # Service factory
├── config/
│ └── steps.ts # Step definitions and validation
├── useOnboarding.ts # Main unified hook
├── useAutoResume.ts # Auto-resume wrapper
├── steps.ts # Step definitions
├── types.ts # Legacy type exports
└── index.ts # Clean exports
```

View File

@@ -2,7 +2,7 @@
* Onboarding step definitions and validation logic
*/
import type { OnboardingStep, OnboardingData } from './types';
import type { OnboardingStep, OnboardingData } from '../core/types';
export const DEFAULT_STEPS: OnboardingStep[] = [
{

View File

@@ -10,7 +10,7 @@ import { useSalesProcessing } from '../services/useSalesProcessing';
import { useInventorySetup } from '../services/useInventorySetup';
import { useTrainingOrchestration } from '../services/useTrainingOrchestration';
import { useProgressTracking } from '../services/useProgressTracking';
import { getStepById } from '../steps';
import { getStepById } from '../config/steps';
import type { ProductSuggestionResponse } from '../core/types';
import type { BakeryRegistration } from '../../../../api';

View File

@@ -6,7 +6,7 @@
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import type { OnboardingData, OnboardingStep, OnboardingProgress } from './types';
import { DEFAULT_STEPS } from '../steps';
import { DEFAULT_STEPS } from '../config/steps';
interface OnboardingStore {
// Flow state

View File

@@ -2,7 +2,7 @@
* Auto-resume hook - Simple wrapper around resume logic service
*/
import { useResumeLogic } from './services/useResumeLogic';
import { useResumeLogic } from '../services/useResumeLogic';
export const useAutoResume = () => {
const resumeLogic = useResumeLogic();

View File

@@ -7,7 +7,7 @@
export type * from './core/types';
// Steps configuration
export { DEFAULT_STEPS, getStepById, getStepIndex, canAccessStep, calculateProgress } from './steps';
export { DEFAULT_STEPS, getStepById, getStepIndex, canAccessStep, calculateProgress } from './config/steps';
// Core architecture (for advanced usage)
export { useOnboardingStore } from './core/store';
@@ -23,7 +23,7 @@ export { useResumeLogic } from './services/useResumeLogic';
// Main hooks - PRIMARY INTERFACE for components
export { useOnboarding } from './useOnboarding';
export { useAutoResume } from './useAutoResume';
export { useAutoResume } from './core/useAutoResume';
// Utility
export { createServiceHook } from './utils/createServiceHook';

View File

@@ -2,7 +2,7 @@
* Progress tracking service - Clean, standardized implementation
*/
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { onboardingService } from '../../../../api/services/onboarding';
import { createServiceHook } from '../utils/createServiceHook';
import type { ProgressTrackingState } from '../core/types';
@@ -20,6 +20,7 @@ const useProgressTrackingService = createServiceHook<ProgressTrackingState>({
export const useProgressTracking = () => {
const service = useProgressTrackingService();
const initializationAttempted = useRef(false);
// Load initial progress from backend
const loadProgress = useCallback(async (): Promise<UserProgress | null> => {
@@ -121,12 +122,13 @@ export const useProgressTracking = () => {
}
}, []);
// Auto-load progress on hook initialization
// Auto-load progress on hook initialization - PREVENT multiple attempts
useEffect(() => {
if (!service.data?.isInitialized) {
if (!service.data?.isInitialized && !initializationAttempted.current && !service.isLoading) {
initializationAttempted.current = true;
loadProgress();
}
}, [loadProgress, service.data?.isInitialized]);
}, [service.data?.isInitialized, service.isLoading]); // Remove loadProgress from deps
return {
// State

View File

@@ -2,7 +2,7 @@
* Resume logic service - Clean, standardized implementation
*/
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { useOnboardingStore } from '../core/store';
import { useProgressTracking } from './useProgressTracking';
@@ -22,6 +22,7 @@ export const useResumeLogic = () => {
const navigate = useNavigate();
const progressTracking = useProgressTracking();
const { setCurrentStep } = useOnboardingStore();
const resumeAttempted = useRef(false);
// Check if user should resume onboarding
const checkForResume = useCallback(async (): Promise<boolean> => {
@@ -114,12 +115,13 @@ export const useResumeLogic = () => {
}
}, [checkForResume, resumeFlow]);
// Auto-check for resume when the hook is first used
// Auto-check for resume when the hook is first used - PREVENT multiple attempts
useEffect(() => {
if (progressTracking.isInitialized && !service.data?.isCheckingResume) {
if (progressTracking.isInitialized && !service.data?.isCheckingResume && !resumeAttempted.current) {
resumeAttempted.current = true;
handleAutoResume();
}
}, [progressTracking.isInitialized, handleAutoResume, service.data?.isCheckingResume]);
}, [progressTracking.isInitialized, service.data?.isCheckingResume]); // Remove handleAutoResume from deps
return {
// State

View File

@@ -1,112 +0,0 @@
/**
* Shared types for onboarding hooks
*/
import type {
BakeryRegistration,
ProductSuggestionResponse,
BusinessModelAnalysisResponse,
User
} from '../../../api';
// Re-export for convenience
export type { ProductSuggestionResponse, BusinessModelAnalysisResponse };
export interface OnboardingStep {
id: string;
title: string;
description: string;
isRequired: boolean;
isCompleted: boolean;
validation?: (data: OnboardingData) => string | null;
}
export interface OnboardingData {
// Step 1: Setup
bakery?: BakeryRegistration;
// Step 2: Data Processing
files?: {
salesData?: File;
};
processingStage?: 'upload' | 'validating' | 'analyzing' | 'review' | 'completed' | 'error';
processingResults?: {
is_valid: boolean;
total_records: number;
unique_products: number;
product_list: string[];
validation_errors: string[];
validation_warnings: string[];
summary: {
date_range: string;
total_sales: number;
average_daily_sales: number;
};
};
// Step 3: Sales Validation (merged data processing + review)
suggestions?: ProductSuggestionResponse[];
detectedProducts?: any[]; // Products detected from AI analysis
approvedSuggestions?: ProductSuggestionResponse[];
approvedProducts?: ProductSuggestionResponse[];
reviewCompleted?: boolean;
// Step 4: Inventory
inventoryItems?: any[];
inventoryMapping?: { [productName: string]: string };
inventoryConfigured?: boolean;
salesImportResult?: {
success: boolean;
imported: boolean;
records_created: number;
message: string;
};
// Step 5: Suppliers
suppliers?: any[];
supplierMappings?: any[];
// Step 6: ML Training
trainingStatus?: 'idle' | 'validating' | 'training' | 'completed' | 'failed';
trainingProgress?: number;
trainingJob?: any;
trainingLogs?: any[];
trainingMetrics?: any;
autoStartTraining?: boolean;
// Step 7: Completion
completionStats?: {
totalProducts: number;
inventoryItems: number;
suppliersConfigured: number;
mlModelAccuracy: number;
estimatedTimeSaved: string;
completionScore: number;
};
// Cross-step data sharing
allStepData?: { [stepId: string]: any };
}
export interface OnboardingProgress {
currentStep: number;
totalSteps: number;
completedSteps: number;
isComplete: boolean;
progressPercentage: number;
}
export interface OnboardingError {
step?: string;
message: string;
details?: any;
}
// Processing progress callback
export type ProgressCallback = (progress: number, stage: string, message: string) => void;
// Step validation function
export type StepValidator = (data: OnboardingData) => string | null;
// Step update callback
export type StepDataUpdater = (stepId: string, data: Partial<OnboardingData>) => void;