diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f8cf22c1..766aa5c3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -11,8 +11,10 @@ import { ThemeProvider } from './contexts/ThemeContext'; import { AuthProvider } from './contexts/AuthContext'; import { SSEProvider } from './contexts/SSEContext'; import { SubscriptionEventsProvider } from './contexts/SubscriptionEventsContext'; +import { TourProvider } from './contexts/TourContext'; import GlobalSubscriptionHandler from './components/auth/GlobalSubscriptionHandler'; import { CookieBanner } from './components/ui/CookieConsent'; +import { Tour } from './components/ui/Tour'; import i18n from './i18n'; const queryClient = new QueryClient({ @@ -65,7 +67,10 @@ function App() { - + + + + diff --git a/frontend/src/components/domain/onboarding/UnifiedOnboardingWizard.tsx b/frontend/src/components/domain/onboarding/UnifiedOnboardingWizard.tsx index 4fcfedd8..778dc9fa 100644 --- a/frontend/src/components/domain/onboarding/UnifiedOnboardingWizard.tsx +++ b/frontend/src/components/domain/onboarding/UnifiedOnboardingWizard.tsx @@ -13,6 +13,8 @@ import { DataSourceChoiceStep, RegisterTenantStep, UploadSalesDataStep, + ProductCategorizationStep, + InitialStockEntryStep, ProductionProcessesStep, MLTrainingStep, CompletionStep @@ -89,6 +91,22 @@ const OnboardingWizardContent: React.FC = () => { isConditional: true, condition: (ctx) => ctx.state.dataSource === 'ai-assisted', }, + { + id: 'product-categorization', + title: t('onboarding:steps.categorization.title', 'Categorizar Productos'), + description: t('onboarding:steps.categorization.description', 'Clasifica ingredientes vs productos'), + component: ProductCategorizationStep, + isConditional: true, + condition: (ctx) => ctx.state.dataSource === 'ai-assisted' && ctx.state.aiAnalysisComplete, + }, + { + id: 'initial-stock-entry', + title: t('onboarding:steps.stock.title', 'Niveles de Stock'), + description: t('onboarding:steps.stock.description', 'Cantidades iniciales'), + component: InitialStockEntryStep, + isConditional: true, + condition: (ctx) => ctx.state.dataSource === 'ai-assisted' && ctx.state.categorizationCompleted, + }, // Phase 2b: Core Data Entry { id: 'suppliers-setup', @@ -322,6 +340,14 @@ const OnboardingWizardContent: React.FC = () => { wizardContext.updateAISuggestions(data.aiSuggestions); wizardContext.setAIAnalysisComplete(true); } + if (currentStep.id === 'product-categorization' && data?.categorizedProducts) { + wizardContext.updateCategorizedProducts(data.categorizedProducts); + wizardContext.markStepComplete('categorizationCompleted'); + } + if (currentStep.id === 'initial-stock-entry' && data?.productsWithStock) { + wizardContext.updateProductsWithStock(data.productsWithStock); + wizardContext.markStepComplete('stockEntryCompleted'); + } if (currentStep.id === 'inventory-setup') { wizardContext.markStepComplete('inventoryCompleted'); } @@ -381,6 +407,12 @@ const OnboardingWizardContent: React.FC = () => { if (currentStep.id === 'data-source-choice' && data?.dataSource) { wizardContext.updateDataSource(data.dataSource as DataSource); } + if (currentStep.id === 'product-categorization' && data?.categorizedProducts) { + wizardContext.updateCategorizedProducts(data.categorizedProducts); + } + if (currentStep.id === 'initial-stock-entry' && data?.productsWithStock) { + wizardContext.updateProductsWithStock(data.productsWithStock); + } }; // Show loading state diff --git a/frontend/src/components/domain/onboarding/context/WizardContext.tsx b/frontend/src/components/domain/onboarding/context/WizardContext.tsx index e9a6a36b..5d66b6d3 100644 --- a/frontend/src/components/domain/onboarding/context/WizardContext.tsx +++ b/frontend/src/components/domain/onboarding/context/WizardContext.tsx @@ -23,8 +23,12 @@ export interface WizardState { uploadedFileSize?: number; aiSuggestions: AISuggestion[]; aiAnalysisComplete: boolean; + categorizedProducts?: any[]; // Products with type classification + productsWithStock?: any[]; // Products with initial stock levels // Setup Progress + categorizationCompleted: boolean; + stockEntryCompleted: boolean; suppliersCompleted: boolean; inventoryCompleted: boolean; recipesCompleted: boolean; @@ -47,6 +51,8 @@ export interface WizardContextValue { updateDataSource: (source: DataSource) => void; updateAISuggestions: (suggestions: AISuggestion[]) => void; setAIAnalysisComplete: (complete: boolean) => void; + updateCategorizedProducts: (products: any[]) => void; + updateProductsWithStock: (products: any[]) => void; markStepComplete: (step: keyof WizardState) => void; getVisibleSteps: () => string[]; shouldShowStep: (stepId: string) => boolean; @@ -58,6 +64,10 @@ const initialState: WizardState = { dataSource: null, aiSuggestions: [], aiAnalysisComplete: false, + categorizedProducts: undefined, + productsWithStock: undefined, + categorizationCompleted: false, + stockEntryCompleted: false, suppliersCompleted: false, inventoryCompleted: false, recipesCompleted: false, @@ -121,6 +131,14 @@ export const WizardProvider: React.FC = ({ setState(prev => ({ ...prev, aiAnalysisComplete: complete })); }; + const updateCategorizedProducts = (products: any[]) => { + setState(prev => ({ ...prev, categorizedProducts: products })); + }; + + const updateProductsWithStock = (products: any[]) => { + setState(prev => ({ ...prev, productsWithStock: products })); + }; + const markStepComplete = (step: keyof WizardState) => { setState(prev => ({ ...prev, [step]: true })); }; @@ -154,6 +172,11 @@ export const WizardProvider: React.FC = ({ if (state.aiAnalysisComplete) { steps.push('review-suggestions'); + steps.push('product-categorization'); + } + + if (state.categorizationCompleted) { + steps.push('initial-stock-entry'); } } @@ -210,6 +233,8 @@ export const WizardProvider: React.FC = ({ updateDataSource, updateAISuggestions, setAIAnalysisComplete, + updateCategorizedProducts, + updateProductsWithStock, markStepComplete, getVisibleSteps, shouldShowStep, diff --git a/frontend/src/components/layout/Sidebar/Sidebar.tsx b/frontend/src/components/layout/Sidebar/Sidebar.tsx index b8373a44..f94eb770 100644 --- a/frontend/src/components/layout/Sidebar/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar/Sidebar.tsx @@ -12,6 +12,7 @@ import { Button } from '../../ui'; import { Badge } from '../../ui'; import { Tooltip } from '../../ui'; import { Avatar } from '../../ui'; +import { TourButton } from '../../ui/Tour/TourButton'; import { LayoutDashboard, Package, @@ -811,6 +812,13 @@ export const Sidebar = forwardRef(({ )} + {/* Tour Button */} + {!isCollapsed && ( +
+ +
+ )} + {/* Navigation */}