Files
bakery-ia/ARCHITECTURE_ANALYSIS.md
2025-11-09 09:22:08 +01:00

32 KiB

Comprehensive Architecture Analysis: UnifiedOnboardingWizard

Executive Summary

The UnifiedOnboardingWizard is a 14-step onboarding flow that has evolved to integrate multiple concerns (file upload, inventory management, product categorization, stock entry, ML training) into a single, monolithic UploadSalesDataStep component. While the overall wizard architecture is sound, there is significant technical debt in the step implementations, particularly in UploadSalesDataStep which mixes file upload, inventory management, and state management responsibilities.


1. CURRENT ARCHITECTURE OVERVIEW

1.1 Wizard Structure

Location: /frontend/src/components/domain/onboarding/

The wizard consists of:

  • UnifiedOnboardingWizard.tsx - Main wizard orchestrator (533 lines)
  • WizardContext.tsx - State management (277 lines)
  • OnboardingWizard.tsx - Deprecated (567 lines - SHOULD BE DELETED)
  • 14 individual step components (ranging from 736 to 74,627 lines)

1.2 Visible Steps Flow

The wizard displays 14 steps in this order:

Phase 1: Discovery
├─ 1. bakery-type-selection (BakeryTypeSelectionStep)
└─ 2. setup (RegisterTenantStep)

Phase 2a: AI-Assisted Inventory Path
├─ 3. smart-inventory-setup (UploadSalesDataStep) ⚠️ MEGA-COMPONENT
├─ 4. product-categorization (ProductCategorizationStep)
├─ 5. initial-stock-entry (InitialStockEntryStep)
└─ (Auto-completes: suppliers-setup)

Phase 2b: Setup Operations
├─ 6. suppliers-setup (SuppliersSetupStep)
├─ 7. recipes-setup (RecipesSetupStep - conditional)
├─ 8. production-processes (ProductionProcessesStep - conditional)

Phase 3: Advanced Features
├─ 9. quality-setup (QualitySetupStep)
└─ 10. team-setup (TeamSetupStep)

Phase 4: ML & Finalization
├─ 11. ml-training (MLTrainingStep)
├─ 12. setup-review (ReviewSetupStep)
└─ 13. completion (CompletionStep)

Note: Step numbering is complex because:

  • Steps 1-13 are in UnifiedOnboardingWizard
  • SetupWizard (deprecated) has separate steps (setup-welcome, suppliers-setup, etc.)
  • Conditional visibility based on bakeryType
  • Auto-completion logic for suppliers-setup

2. DETAILED ARCHITECTURAL ISSUES

2.1 ISSUE #1: UploadSalesDataStep is a Mega-Component (74,627 lines)

Severity: CRITICAL

Current Responsibilities:

  1. File upload & validation (lines 1-169)
  2. Automatic file analysis with AI (lines 141-169)
  3. AI-based product classification (lines 171-247)
  4. Inventory item form management (lines 249-433)
  5. Stock lot management (lines 335-435)
  6. Batch operations (lines 437-589)
  7. Sales data import (lines 548-569)
  8. UI rendering for two distinct phases:
    • File upload phase (lines 1408-1575)
    • Inventory list/editing phase (lines 612-1405)
  9. Modal integration (BatchAddIngredientsModal)

Problems:

  • Violates Single Responsibility Principle
  • Hard to test (>1500 lines in single component)
  • Multiple state variables (23 useState calls)
  • Tightly couples file upload with inventory management
  • Complex conditional rendering logic
  • Difficult to reuse any sub-functionality

Code Indicators:

// Line 22-114: THREE separate form interfaces and states
interface ProgressState { ... }
interface InventoryItemForm { ... }
// Plus: [selectedFile, isValidating, validationResult, inventoryItems, ...]
// TOTAL: 23+ state variables
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [isValidating, setIsValidating] = useState(false);
const [validationResult, setValidationResult] = useState<ImportValidationResponse | null>(null);
// ... 20 more state declarations

2.2 ISSUE #2: Separated File Upload & Inventory Concerns

Severity: HIGH

The UploadSalesDataStep handles TWO distinct user journeys:

Journey 1: File Upload & Auto-Classification

User uploads CSV
  ↓
Validate file (validateFileMutation)
  ↓
Classify products (classifyBatchMutation)
  ↓
Generate AI suggestions
  ↓
Show inventory list for review

Journey 2: Manual Inventory Entry

After AI suggestions generated
  ↓
Edit/add inventory items manually
  ↓
Add stock lots per item
  ↓
Create all ingredients via API (createIngredient)
  ↓
Create all stock lots (addStockMutation)
  ↓
Import sales data

Problem: Both journeys are in ONE component with complex conditional rendering:

// Line 613: Conditional branch for entire second phase
if (showInventoryStep) {
  // 800+ lines of inventory management UI
  return (<div className="space-y-6"> ... </div>);
}

// Line 1408: Final 167 lines for file upload UI
return (<div className="space-y-6"> ... </div>);

2.3 ISSUE #3: State Management Fragmentation

Severity: MEDIUM

Local Component State (UploadSalesDataStep):

  • File selection: selectedFile, isValidating, validationResult
  • Inventory: inventoryItems, showInventoryStep, error, progressState
  • Form data: formData, editingId, isAdding, formErrors
  • Stock lots: addingStockForId, stockFormData, stockErrors, ingredientStocks

Wizard Context State (WizardContext.tsx):

  • bakeryType, dataSource, uploadedFileName, uploadedFileSize
  • aiSuggestions, aiAnalysisComplete, categorizedProducts, productsWithStock
  • Various completion flags: categorizationCompleted, stockEntryCompleted, etc.

Backend Progress State (API):

  • useUserProgress() fetches current step, completed steps, completion percentage
  • useMarkStepCompleted() updates backend after step completion

Problem: No clear separation of concerns

  • Wizard context is "source of truth" but individual steps also have local state
  • UI state (isAdding, editingId) mixed with data state (inventoryItems)
  • No clear data flow: Step data → Wizard context → Backend
  • Difficult to understand which data persists across sessions

2.4 ISSUE #4: Circular State Dependencies

Severity: MEDIUM

UploadSalesDataStep → Wizard Context:

// Line 320: Updates wizard context on completion
wizardContext.updateAISuggestions(data.aiSuggestions);
wizardContext.setAIAnalysisComplete(true);
// Line 325:
wizardContext.updateCategorizedProducts(data.categorizedProducts);

ProductCategorizationStep → Wizard Context:

// Receives products from wizard context
// Updates categorizedProducts in wizard context
onUpdate?.({ categorizedProducts: updatedProducts });

InitialStockEntryStep → Wizard Context:

// Receives products from categorization
// Updates productsWithStock in wizard context
onUpdate?.({ productsWithStock: updatedProducts });

Problem: Steps update wizard context via onUpdate() AND onComplete()

  • Data flows both ways (child → parent AND parent → child)
  • Difficult to trace data transformations
  • No clear contract between parent and child

2.5 ISSUE #5: Tight Coupling Between Wizard & Setup Components

Severity: HIGH

UnifiedOnboardingWizard mixes:

  • 8 onboarding-specific steps from /onboarding/steps/
  • 5 setup-specific steps from /setup-wizard/steps/

Import at line 22-28:

import {
  SuppliersSetupStep,
  RecipesSetupStep,
  QualitySetupStep,
  TeamSetupStep,
  ReviewSetupStep,
} from '../setup-wizard/steps';

Problem:

  • UnifiedOnboardingWizard shouldn't need setup-wizard imports
  • Creates dependency between onboarding and setup domains
  • Changes in setup steps affect onboarding flow
  • Makes it harder to modify setup flow independently
  • Violates layering/module boundaries

2.6 ISSUE #6: Auto-Completion Logic Scattered

Severity: MEDIUM

Auto-completion of suppliers-setup (line 349-365):

// In UnifiedOnboardingWizard.handleStepComplete()
if (currentStep.id === 'smart-inventory-setup' && data?.shouldAutoCompleteSuppliers) {
  try {
    await markStepCompleted.mutateAsync({
      userId: user.id,
      stepName: 'suppliers-setup',
      data: { auto_completed: true, ... }
    });
  } catch (supplierError) {
    console.warn('Could not auto-complete suppliers-setup step');
  }
}

Auto-completion of user_registered (line 204-232):

// In OnboardingWizardContent.useEffect()
useEffect(() => {
  if (userProgress && user?.id && !autoCompletionAttempted && !markStepCompleted.isPending) {
    const userRegisteredStep = userProgress.steps.find(s => s.step_name === 'user_registered');
    if (!userRegisteredStep?.completed) {
      // Auto-complete...
    }
  }
}, [...]);

Problem:

  • Auto-completion logic is buried in step completion handler
  • No clear policy for which steps can be auto-completed
  • Difficult to add new auto-completion rules
  • Inconsistent with manual step completion flow

2.7 ISSUE #7: Condition Functions Are Scattered & Duplicated

Severity: LOW-MEDIUM

Step visibility conditions (line 59-165):

const ALL_STEPS: StepConfig[] = [
  {
    id: 'smart-inventory-setup',
    condition: (ctx) => ctx.tenantId !== null,
  },
  {
    id: 'product-categorization',
    condition: (ctx) => ctx.state.aiAnalysisComplete,
  },
  {
    id: 'initial-stock-entry',
    condition: (ctx) => ctx.state.categorizationCompleted,
  },
  {
    id: 'suppliers-setup',
    // Always show - no conditional
  },
  {
    id: 'recipes-setup',
    condition: (ctx) =>
      ctx.state.bakeryType === 'production' || ctx.state.bakeryType === 'mixed',
  },
  // ... more conditions
];

Identical conditions in WizardContext (line 183-189):

getVisibleSteps = (): string[] => {
  // ... same conditions repeated
  if (state.bakeryType === 'production' || state.bakeryType === 'mixed') {
    steps.push('recipes-setup');
  }
  if (state.bakeryType === 'retail' || state.bakeryType === 'mixed') {
    steps.push('production-processes');
  }
};

Problem:

  • Same logic defined in TWO places
  • Changes require updates in multiple files
  • No single source of truth for visibility rules
  • Conditions are business logic, should be defined separately

2.8 ISSUE #8: Complex Data Transformations Without Clear Contracts

Severity: MEDIUM**

UploadSalesDataStep → ProductCategorizationStep:

// Line 203-235: UploadSalesDataStep generates InventoryItemForm[]
const items: InventoryItemForm[] = classificationResponse.suggestions.map((suggestion) => ({
  id: `ai-${index}-${Date.now()}`,
  name: suggestion.suggested_name,
  // ... 15 more properties
}));

// Then completes with:
onComplete({
  createdIngredients,
  totalItems: createdIngredients.length,
  validationResult,
  // ... more data
});

// But ProductCategorizationStep expects Product[] (different interface!)
interface Product {
  id: string;
  name: string;
  category?: string;
  confidence?: number;
  type?: 'ingredient' | 'finished_product' | null;
  suggestedType?: 'ingredient' | 'finished_product';
}

Problem:

  • No clear transformation between step outputs and next step inputs
  • Multiple data formats for similar data
  • Type mismatches not caught until runtime
  • No schema/contract for inter-step communication

3. STEP DEPENDENCIES & DATA FLOW

3.1 Dependency Diagram

BakeryTypeSelectionStep
  └─> wizardContext.updateBakeryType()
      └─> affects visibility of: recipes-setup, production-processes

RegisterTenantStep
  └─> wizardContext.tenantId (implicit - via tenant store)
      └─> enables: smart-inventory-setup

UploadSalesDataStep [MEGA-COMPONENT]
  ├─> Validates file (validateFileMutation)
  ├─> Classifies products (classifyBatchMutation)
  ├─> Creates inventory (createIngredient) ← INVENTORY CONCERN
  ├─> Creates stock lots (addStockMutation) ← INVENTORY CONCERN
  ├─> Imports sales data (importMutation)
  ├─> wizardContext.updateAISuggestions()
  ├─> wizardContext.setAIAnalysisComplete()
  ├─> markStepCompleted() [auto-completes suppliers-setup] ← ORCHESTRATION
  └─> onComplete() with shouldAutoCompleteSuppliers flag

ProductCategorizationStep
  ├─> Input: wizard context aiSuggestions or initialData.categorizedProducts
  ├─> onUpdate() → wizardContext.updateCategorizedProducts()
  └─> onComplete()
      └─> wizardContext.markStepComplete('categorizationCompleted')

InitialStockEntryStep
  ├─> Input: categorizedProducts (which type: ingredient or finished_product?)
  ├─> onUpdate() → wizardContext.updateProductsWithStock()
  └─> onComplete()
      └─> wizardContext.markStepComplete('stockEntryCompleted')

SuppliersSetupStep (from setup-wizard)
  ├─> May be auto-completed by UploadSalesDataStep
  └─> Creates suppliers

RecipesSetupStep (conditional: production or mixed)
  └─> Depends on suppliers existing

ProductionProcessesStep (conditional: retail or mixed)
  └─> May depend on recipes?

MLTrainingStep
  └─> Input: inventory data from previous steps
      └─> No explicit dependency check

ReviewSetupStep
  └─> Shows summary of configuration

CompletionStep
  └─> Final step, navigates away

3.2 Data Flow Diagram

┌─────────────────────────────────────────────────────────────────┐
│                       UnifiedOnboardingWizard                   │
│                     (Step Orchestrator)                         │
└─────────────────────────────────────────────────────────────────┘
         ↑                                                    ↑
         │ state (VISIBLE_STEPS, currentStepIndex)          │ markStepCompleted()
         │                                                    │
    ┌────┴───────────────────────────────────────────────────┴──┐
    │                     WizardContext                          │
    │  (State: bakeryType, aiSuggestions, categorizedProducts)   │
    │  (State: productsWithStock, various completion flags)      │
    └────┬───────────────────────────────────────────────────┬───┘
         │ onUpdate() / onComplete()                         │
         │ (data flows FROM steps TO context)               │
         │                                                    │
    ┌────┴────────────────────────────────────────────────┬──┘
    │                   Individual Steps                   │
    │                                                      │
    │  BakeryTypeSelectionStep                           │
    │  RegisterTenantStep                                │
    │  UploadSalesDataStep ⚠️ [73KB, 23 state vars]      │
    │    ├─ File validation                              │
    │    ├─ AI classification                            │
    │    ├─ Inventory creation                           │
    │    └─ Stock lot management                         │
    │  ProductCategorizationStep                         │
    │  InitialStockEntryStep                             │
    │  SuppliersSetupStep (from setup-wizard)            │
    │  ...                                                │
    └──────────────────────────────────────────────────────┘
              │                                  │
              │                                  │
         API mutations                  Backend progress
    (validateFile, classifyBatch,      (useUserProgress,
     createIngredient, addStock,        useMarkStepCompleted)
     importSalesData)

3.3 Data Transformation Pipeline

CSV/JSON File
    ↓
[UploadSalesDataStep] validateFileMutation
    ↓ (ImportValidationResponse)
    ├─ total_records, valid_records, invalid_records
    ├─ product_list: string[]
    └─ ...
    ↓
[UploadSalesDataStep] classifyBatchMutation
    ↓ (ProductSuggestionResponse[])
    ├─ id, suggested_name, product_type
    ├─ category, unit_of_measure
    ├─ confidence_score
    ├─ estimated_shelf_life_days
    ├─ requires_refrigeration, requires_freezing, is_seasonal
    ├─ low_stock_threshold, reorder_point
    └─ sales_data: { total_quantity, average_daily_sales }
    ↓
[UploadSalesDataStep] Transform to InventoryItemForm[]
    ├─ id: string (temporary UI ID)
    ├─ name, product_type, category
    ├─ unit_of_measure
    ├─ stock_quantity (calculated from sales data)
    ├─ cost_per_unit (estimated)
    ├─ estimated_shelf_life_days
    ├─ requires_refrigeration, requires_freezing, is_seasonal
    ├─ low_stock_threshold, reorder_point
    ├─ isSuggested: boolean
    ├─ confidence_score
    └─ sales_data: { total_quantity, average_daily_sales }
    ↓
[UploadSalesDataStep] User review & manual edits
    ├─ Add/edit/delete inventory items
    ├─ Add stock lots (optional)
    └─ ...
    ↓
[UploadSalesDataStep] createIngredient mutations (parallel)
    ↓ (Ingredient[])
    ├─ id (from backend)
    ├─ name, product_type, category
    ├─ unit_of_measure, shelf_life_days
    ├─ requires_refrigeration, requires_freezing, is_seasonal
    ├─ low_stock_threshold, max_stock_level, reorder_point
    └─ average_cost
    ↓
[UploadSalesDataStep] addStockMutation (parallel)
    ↓ (StockResponse[])
    ├─ id (from backend)
    ├─ ingredient_id
    ├─ current_quantity
    ├─ expiration_date
    ├─ supplier_id
    ├─ batch_number
    ├─ production_stage
    └─ quality_status
    ↓
[UploadSalesDataStep] importMutation (sales data)
    ↓
[ProductCategorizationStep] ← BUT RECEIVES: wizard context aiSuggestions
    ↓ (Product[] with type: 'ingredient' | 'finished_product')
    ↓
[InitialStockEntryStep] ← Receives: categorizedProducts
    ↓ (ProductWithStock[] with initialStock)
    ↓
[Backend] Final inventory saved

Problem: Data transformations are implicit and scattered across files. No clear schema/types for inter-step data passing.


4. LEGACY & DEPRECATED COMPONENTS

4.1 OnboardingWizard.tsx - DEPRECATED

Location: /frontend/src/components/domain/onboarding/OnboardingWizard.tsx

Status: DEPRECATED but still exported in index.ts

Usage:

// frontend/src/components/domain/onboarding/index.ts
export { OnboardingWizard } from './OnboardingWizard';   EXPORTED BUT NOT USED
export { UnifiedOnboardingWizard } from './UnifiedOnboardingWizard';   THIS IS USED

Confirmation of non-usage:

  • OnboardingPage.tsx uses only UnifiedOnboardingWizard
  • No other imports of OnboardingWizard found in codebase
  • Old wizard has simplified step flow (4 steps vs 14)

Recommendation: DELETE OnboardingWizard.tsx and remove from index.ts exports

4.2 SetupWizard.tsx - STILL IN USE

Location: /frontend/src/components/domain/setup-wizard/SetupWizard.tsx

Status: ACTIVE but DEPRECATED by design

Usage:

// frontend/src/pages/setup/SetupPage.tsx
const SetupPage: React.FC = () => {
  return <SetupWizard />;
};

Problem:

  • UnifiedOnboardingWizard imports setup-wizard steps directly
  • Creates tight coupling between onboarding and setup domains
  • SetupWizard is now redundant - setup steps are integrated into UnifiedOnboardingWizard
  • Separate SetupPage route still exists (/app/setup)

Recommendation:

  1. Remove setup-wizard imports from UnifiedOnboardingWizard
  2. Keep SetupWizard.tsx for backwards compatibility OR
  3. Transition to new onboarding flow only and deprecate SetupPage

4.3 Route Duplication

Current Routes:

  • /app/onboarding → OnboardingPage → UnifiedOnboardingWizard ✓ CORRECT
  • /app/setup → SetupPage → SetupWizard ✓ LEGACY (now integrated into onboarding)

Recommendation:

  • Remove /app/setup route OR
  • Make it redirect to /app/onboarding for backwards compatibility

5. FILES TO DELETE

File Status Reason
/frontend/src/components/domain/onboarding/OnboardingWizard.tsx DELETE Fully deprecated, non-functional
/frontend/src/pages/setup/SetupPage.tsx DELETE or REDIRECT Setup flow now integrated into onboarding
Setup wizard route entry in routes.config.ts REMOVE Duplicate with onboarding

6. ARCHITECTURAL PROBLEMS SUMMARY

Problem #1: MEGA-COMPONENT (UploadSalesDataStep)

  • Type: Single Responsibility Principle Violation
  • Severity: CRITICAL
  • Impact: Hard to test, maintain, and extend
  • Solution: Split into:
    • FileUploadPhase (controlled by parent)
    • InventoryManagementPhase (separate component or reusable)
    • AI classification logic (service)

Problem #2: State Management Fragmentation

  • Type: State Distribution Anti-Pattern
  • Severity: HIGH
  • Impact: Difficult to trace data flow, understand state transitions
  • Solution:
    • Clear separation: UI state (local) vs Data state (context)
    • Define explicit data contracts between steps
    • Consider step output → context mapping layer

Problem #3: Mixed Concerns in One Component

  • Type: Separation of Concerns Violation
  • Severity: HIGH
  • Impact: Tight coupling, difficult to test individual features
  • Solution:
    • File upload logic → FileUploadService
    • Inventory form logic → InventoryFormComponent
    • Stock lot logic → StockLotComponent
    • Composition pattern to combine them

Problem #4: Duplicate Visibility Logic

  • Type: DRY Principle Violation
  • Severity: MEDIUM
  • Impact: Maintenance burden, potential inconsistencies
  • Solution:
    • Extract visibility rules into dedicated config/service
    • Single source of truth for step conditions

Problem #5: Circular Data Dependencies

  • Type: Bidirectional Data Flow Anti-Pattern
  • Severity: MEDIUM
  • Impact: Hard to understand data flow direction
  • Solution:
    • Strict unidirectional data flow (parent → child via props, child → parent via callbacks)
    • Clear input/output contracts for each step

Problem #6: Tight Coupling: Onboarding ↔ Setup Wizard

  • Type: Module Boundary Violation
  • Severity: HIGH
  • Impact: Difficult to modify either wizard independently
  • Solution:
    • Remove setup-wizard imports from UnifiedOnboardingWizard
    • Define step interface contract
    • Load steps dynamically by configuration

Problem #7: Complex Auto-Completion Logic

  • Type: Business Logic Distribution
  • Severity: MEDIUM
  • Impact: Difficult to understand which steps auto-complete
  • Solution:
    • Centralized auto-completion policy
    • Explicit configuration for which steps can auto-complete
    • Clear rules for completion dependencies

Problem #8: No Clear Inter-Step Communication Contract

  • Type: Interface Definition Anti-Pattern
  • Severity: MEDIUM
  • Impact: Type mismatches between steps (InventoryItemForm vs Product vs ProductWithStock)
  • Solution:
    • Define Step Interface Contract
    • Create transformation layer between step outputs
    • Use consistent naming/typing across all steps

7. STEP RESPONSIBILITIES MATRIX

Step Primary Responsibility State Type Dependencies Outputs
BakeryTypeSelectionStep Select bakery model UI None bakeryType
RegisterTenantStep Register bakery details API call bakeryType tenantId, tenant object
UploadSalesDataStep File upload + Inventory mgmt + Stock lots API calls + Local forms tenantId Ingredients[] + Stock[] + Sales import result
ProductCategorizationStep Classify products Drag-drop state aiSuggestions categorizedProducts
InitialStockEntryStep Set initial stock levels Form state categorizedProducts productsWithStock
SuppliersSetupStep Add suppliers API + Form tenantId suppliers (or auto-completed)
RecipesSetupStep Create recipes API + Complex forms ingredients + suppliers recipes
ProductionProcessesStep Define processes API + Complex forms bakeryType processes
QualitySetupStep Set quality standards API + Forms tenantId quality templates
TeamSetupStep Add team members API + Forms tenantId team members
MLTrainingStep Train ML models API poll + long-running inventory data trained models
ReviewSetupStep Show configuration summary Read-only All previous data (none, informational)
CompletionStep Celebrate + redirect Navigation None Navigate to dashboard

8. RECOMMENDATIONS FOR REFACTORING

Immediate Actions (Quick Wins)

  1. Delete OnboardingWizard.tsx

    • Remove from exports in index.ts
    • Impact: LOW (not used)
    • Time: 5 minutes
  2. Remove setup-wizard imports from UnifiedOnboardingWizard

    • Load setup steps dynamically
    • Create step registry/configuration
    • Impact: MEDIUM (refactoring pattern needed)
    • Time: 2-3 hours
  3. Extract visibility rules to dedicated config

    • Move bakeryType conditions to one place
    • Impact: LOW (pure refactoring)
    • Time: 1 hour

Medium-term Refactoring (1-2 Sprint)

  1. Split UploadSalesDataStep

    • Extract FileUploadPhase (lines 1408-1575)
    • Extract InventoryManagementPhase (lines 612-1405)
    • Create composition layer
    • Move AI classification to service
    • Impact: HIGH (major refactoring)
    • Time: 6-8 hours
  2. Define Inter-Step Data Contracts

    • Create interfaces for step input/output
    • Add transformation layer between steps
    • Impact: HIGH (enforces consistency)
    • Time: 4-6 hours
  3. Separate UI State from Data State in WizardContext

    • Move isAdding, editingId to component state
    • Keep only data state in context
    • Impact: MEDIUM (refactoring)
    • Time: 3-4 hours

Long-term Architecture (2-3 Months)

  1. Implement Step Interface Contract

    • Define standard step props/callback signatures
    • Enforce typing at wizard level
    • Impact: HIGH (system-wide improvement)
    • Time: 1-2 sprints
  2. Extract Auto-Completion Policy Engine

    • Centralized configuration for auto-completion
    • Clear rules for step dependencies
    • Impact: MEDIUM (optional feature)
    • Time: 1 sprint
  3. Consolidate Setup & Onboarding Routes

    • Make /app/setup redirect to /app/onboarding
    • OR keep SetupPage for post-onboarding scenarios
    • Impact: LOW-MEDIUM (routing refactoring)
    • Time: 2-3 hours

9. CURRENT STEP-BY-STEP FLOW DIAGRAM

┌───────────────────────────────────────────────────────────┐
│ USER FLOW: UnifiedOnboardingWizard (14 Steps)             │
└───────────────────────────────────────────────────────────┘

START: User completes registration
       ↓ Auto-completes user_registered step
       
STEP 1: Bakery Type Selection
       └─> SELECT: production | retail | mixed
           └─> STORES: bakeryType in context
       
STEP 2: Register Tenant
       └─> ENTER: Bakery name, address, phone, city
           └─> API: registerBakery()
           └─> STORES: tenantId, tenant object
       
STEP 3: Upload Sales Data (⚠️ MEGA-COMPONENT)
       ├─> UPLOAD: CSV/JSON file with sales history
       │   └─> API: validateFile()
       │   └─> API: classifyBatch() [AI classification]
       │   └─> DISPLAY: Suggested inventory items
       │
       └─> REVIEW & EDIT: Inventory items
           ├─ ALLOW: Add, edit, delete items
           ├─ ALLOW: Add stock lots per item
           │   └─> FIELDS: Quantity, expiration date, supplier, batch number
           │
           └─> API: createIngredient() [parallel for all items]
               └─> API: addStock() [parallel for all stock lots]
               └─> API: importSalesData() [background import]
               └─> Auto-complete: suppliers-setup step
       
STEP 4: Product Categorization
       ├─> DISPLAY: Suggested AI classifications
       ├─> ALLOW: Drag-drop to categorize as ingredient or finished_product
       └─> STORES: categorizedProducts in context
       
STEP 5: Initial Stock Entry
       ├─> DISPLAY: All products from categorization
       ├─> ALLOW: Enter initial stock quantities
       └─> STORES: productsWithStock in context
       
STEP 6: Suppliers Setup ⭐ (May be auto-completed)
       ├─> IF auto-completed: Display "✓ Auto-setup"
       └─> ELSE: ALLOW: Add suppliers (company, contact, details)
           └─> API: createSupplier()
       
STEP 7: Recipes Setup (CONDITIONAL: production or mixed bakeries)
       ├─> ALLOW: Create recipes with ingredients
       ├─> INPUT: Select ingredients from inventory
       ├─> INPUT: Set quantities, proportions
       └─> API: createRecipe()
       
STEP 8: Production Processes (CONDITIONAL: retail or mixed bakeries)
       ├─> ALLOW: Define production workflows
       └─> API: createProcess()
       
STEP 9: Quality Setup
       ├─> ALLOW: Define quality templates/standards
       └─> API: createQualityTemplate()
       
STEP 10: Team Setup
       ├─> ALLOW: Add team members, assign roles
       └─> API: inviteUser()
       
STEP 11: ML Training
       ├─> INFO: "Training personalized AI model..."
       ├─> DISPLAY: Progress indicator
       ├─> WAIT: For training job completion (API poll)
       └─> DISPLAY: Model accuracy metrics
       
STEP 12: Setup Review
       ├─> DISPLAY: Summary of all configuration
       └─> ALLOW: Review before finalizing
       
STEP 13: Completion
       └─> DISPLAY: "✓ Setup complete!"
           └─> REDIRECT: /app/dashboard

END: User is now in the main application

10. SUMMARY TABLE

Aspect Status Priority Notes
Overall Architecture FUNCTIONAL - Works but has technical debt
UnifiedOnboardingWizard Main GOOD LOW Well-structured orchestrator
WizardContext ACCEPTABLE MEDIUM State management needs clarification
UploadSalesDataStep POOR CRITICAL 74KB mega-component needs refactoring
OnboardingWizard (old) DEPRECATED HIGH Should be deleted
SetupWizard Integration PROBLEMATIC HIGH Tight coupling needs fixing
Visibility Rules DUPLICATE MEDIUM DRY principle violation
Inter-Step Contracts UNDEFINED MEDIUM No formal interface definition
Auto-Completion AD-HOC MEDIUM Needs centralized policy
State Management FRAGMENTED MEDIUM Mixing UI and data state

APPENDIX: FILE STATISTICS

File Size LOC Complexity Status
UnifiedOnboardingWizard.tsx 20.5 KB 533 MEDIUM GOOD
WizardContext.tsx 9.5 KB 277 MEDIUM ACCEPTABLE
OnboardingWizard.tsx 19.5 KB 567 MEDIUM DEPRECATED
UploadSalesDataStep.tsx 74.6 KB 1577 HIGH POOR
ProductCategorizationStep.tsx 14.3 KB 365 MEDIUM ACCEPTABLE
InitialStockEntryStep.tsx 11.2 KB 286 LOW GOOD
BakeryTypeSelectionStep.tsx 11 KB 277 MEDIUM GOOD
RegisterTenantStep.tsx 7.8 KB ~200 LOW GOOD
SetupWizard.tsx ~30 KB ~800 MEDIUM ACTIVE
TOTAL ONBOARDING ~169 KB ~3665 - -