# Wizard Improvements - Implementation Guide ## Executive Summary This document provides comprehensive guidance for completing the wizard improvements project based on backend/frontend research and UX best practices. ### **COMPLETED** ✅ 1. **RecipeWizard** - Fully rewritten with all 46 backend fields 2. **CustomerWizard** - Fully rewritten with all 31 backend fields 3. **SupplierWizard** - Fully rewritten with all 48 backend fields 4. **AdvancedOptionsSection** - Reusable component created 5. **Research Documentation** - Complete backend/frontend analysis ### **REMAINING** ⏳ 1. **InventoryWizard** - 44 backend fields to add 2. **QualityTemplateWizard** - 25 backend fields to add 3. **CustomerOrderWizard** - 72 backend fields to add 4. **Type Inconsistency Fixes** - PaymentTerms enum, field naming --- ## Part 1: What Was Fixed ### Critical Issues Resolved #### 1. **RecipeWizard.tsx:505 Error** **Problem**: `TypeError: a.map is not a function` **Root Cause**: ```typescript // Line 387 - BEFORE const result = await qualityTemplateService.getTemplates(...); setTemplates(result); // ❌ result = {templates: [], total: 0, ...} // Line 505 {templates.map((template) => ( // ❌ templates is object, not array ``` **Solution**: ```typescript // Line 387 - AFTER const result = await qualityTemplateService.getTemplates(...); setTemplates(result.templates || []); // ✅ Extract array ``` #### 2. **Duplicate Next Buttons** **Problem**: Two "Next" buttons causing UX confusion - WizardModal footer button (no validation) - Step component button (with validation) **Solution**: - Removed all internal step buttons - Used WizardModal's `validate` prop: ```typescript { id: 'recipe-details', validate: () => !!(data.name && data.finishedProductId && data.yieldQuantity), component: (props) => } ``` #### 3. **Missing Required Backend Fields** **Problem**: Wizards missing fields that backend requires **Examples Fixed**: - Recipe: `version`, `difficulty_level`, `status` (with proper defaults) - Customer: `customer_code` (with auto-generation) - Supplier: `supplier_type`, `status`, `payment_terms`, `currency`, `standard_lead_time` #### 4. **No Advanced Options** **Problem**: All fields shown at once = overwhelming forms **Solution**: Progressive disclosure with `AdvancedOptionsSection` ```typescript {/* 20-30 optional fields here */} ``` --- ## Part 2: Implementation Pattern All three completed wizards follow this exact pattern: ### File Structure ```typescript import { AdvancedOptionsSection } from '../../../ui/AdvancedOptionsSection'; import Tooltip from '../../../ui/Tooltip/Tooltip'; interface WizardDataProps extends WizardStepProps { data: Record; onDataChange: (data: Record) => void; } const DetailsStep: React.FC = ({ data, onDataChange, onComplete }) => { const [wizardData, setWizardData] = useState({ // Required fields with defaults name: data.name || '', requiredField: data.requiredField || 'default', // Basic optional fields email: data.email || '', // Advanced optional fields (20-40 fields) advancedField1: data.advancedField1 || '', advancedField2: data.advancedField2 || '', // ... more fields }); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Auto-generation logic (if applicable) useEffect(() => { if (!wizardData.code && wizardData.name) { const code = `PREFIX-${wizardData.name.substring(0, 3).toUpperCase()}-${Date.now().toString().slice(-4)}`; setWizardData(prev => ({ ...prev, code })); } }, [wizardData.name]); // Real-time data sync useEffect(() => { onDataChange({ ...data, ...wizardData }); }, [wizardData]); const handleCreate = async () => { if (!currentTenant?.id) { setError('Could not obtain tenant information'); return; } setLoading(true); setError(null); try { const payload = { // Map camelCase to snake_case required_field: wizardData.requiredField, optional_field: wizardData.optionalField || undefined, // ... }; await service.create(currentTenant.id, payload); showToast.success('Created successfully'); onComplete(); } catch (err: any) { const errorMessage = err.response?.data?.detail || 'Error creating'; setError(errorMessage); showToast.error(errorMessage); } finally { setLoading(false); } }; return (
{/* Header */} {/* Error display */} {/* Required Fields */}
{/* Form fields */}
{/* Advanced Options */} {/* Optional fields */} {/* Submit Button */}
); }; export const WizardSteps = (data, setData): WizardStep[] => [ { id: 'details', title: 'Details', description: 'Essential information', component: (props) => , validate: () => !!(data.requiredField1 && data.requiredField2), }, ]; ``` --- ## Part 3: Step-by-Step Implementation Guide ### For InventoryWizard **Required Backend Fields:** - `name` (String) - `unit_of_measure` (Enum: kg, g, l, ml, units, pcs, pkg, bags, boxes) - `product_type` (Enum: INGREDIENT, FINISHED_PRODUCT - default: INGREDIENT) **Optional Fields to Add in Advanced Section:** - Basic: `sku`, `barcode`, `ingredient_category`, `product_category`, `description`, `brand` - Pricing: `average_cost`, `last_purchase_price`, `standard_cost` - Inventory Mgmt: `low_stock_threshold`, `reorder_point`, `reorder_quantity`, `max_stock_level` - Product Info: `package_size`, `shelf_life_days`, `display_life_hours`, `best_before_hours` - Storage: `storage_instructions`, `is_perishable` - Central Bakery: `central_baker_product_code`, `delivery_days`, `minimum_order_quantity`, `pack_size` - Flags: `is_active`, `produced_locally` - References: `recipe_id` (for finished products) - Allergens: `allergen_info` (JSONB array) - Nutrition: `nutritional_info` (JSONB for finished products) **Auto-generation:** ```typescript useEffect(() => { if (!wizardData.sku && wizardData.name) { const sku = `INV-${wizardData.name.substring(0, 3).toUpperCase()}-${Date.now().toString().slice(-4)}`; setWizardData(prev => ({ ...prev, sku })); } }, [wizardData.name]); ``` ### For QualityTemplateWizard **Required Backend Fields:** - `name` (String) - `check_type` (String: visual, measurement, temperature, weight, boolean, timing, checklist) - `weight` (Float 0.0-10.0, default: 1.0) - `created_by` (UUID - use currentTenant.id) **Optional Fields to Add in Advanced Section:** - Identification: `template_code` - Details: `description`, `category`, `instructions` - Configuration: `parameters`, `thresholds`, `scoring_criteria` (all JSONB) - Values: `min_value`, `max_value`, `target_value`, `unit`, `tolerance_percentage` - Flags: `is_active`, `is_required`, `is_critical` - Stages: `applicable_stages` (JSONB array of ProcessStage values) **Note**: `parameters`, `thresholds`, `scoring_criteria` are JSONB - consider textarea with JSON validation or structured form builder. ### For CustomerOrderWizard **Required Backend Fields:** - `customer_id` (UUID - select from customers) - `requested_delivery_date` (DateTime) - `order_number` (String - auto-generate) - `status` (Enum: pending, confirmed, in_production, ready, out_for_delivery, delivered, cancelled, failed) - `order_type` (Enum: standard, rush, recurring, special - default: standard) - `priority` (Enum: high, normal, low - default: normal) - `delivery_method` (Enum: delivery, pickup - default: delivery) **Optional Fields - MANY (72 total backend fields):** **Step 1: Customer & Delivery** - `delivery_address` (JSONB) - `delivery_instructions`, `delivery_window_start`, `delivery_window_end` - `confirmed_delivery_date`, `actual_delivery_date` **Step 2: Order Items** (separate array management) - OrderItem[] with: `product_id`, `quantity`, `unit_price`, `product_name` - Item fields: `customization_details`, `special_instructions`, `product_specifications` **Step 3: Pricing & Payment** (Advanced) - `subtotal`, `discount_amount`, `discount_percentage`, `tax_amount`, `delivery_fee`, `total_amount` - `payment_status`, `payment_method`, `payment_terms`, `payment_due_date` **Step 4: Additional Info** (Advanced) - `special_instructions`, `custom_requirements`, `allergen_warnings` - `business_model`, `order_source`, `sales_channel`, `order_origin` - Production: `production_batch_id`, `fulfillment_location`, `estimated_preparation_time` - Notifications: `customer_notified_confirmed`, `customer_notified_ready`, `customer_notified_delivered` - Quality: `quality_score`, `customer_rating`, `customer_feedback` **Auto-generation:** ```typescript useEffect(() => { if (!wizardData.orderNumber) { const orderNum = `ORD-${new Date().getFullYear()}${(new Date().getMonth() + 1).toString().padStart(2, '0')}${new Date().getDate().toString().padStart(2, '0')}-${Date.now().toString().slice(-6)}`; setWizardData(prev => ({ ...prev, orderNumber: orderNum })); } }, []); ``` --- ## Part 4: Type Inconsistencies to Fix ### Issue 1: PaymentTerms Enum Conflict **Problem**: Two different enums with same name **Suppliers** (`frontend/src/api/types/suppliers.ts`): ```typescript export enum PaymentTerms { COD = 'cod', NET_15 = 'net_15', NET_30 = 'net_30', NET_45 = 'net_45', NET_60 = 'net_60', PREPAID = 'prepaid', CREDIT_TERMS = 'credit_terms', } ``` **Orders** (`frontend/src/api/types/orders.ts`): ```typescript export enum PaymentTerms { IMMEDIATE = 'immediate', NET_30 = 'net_30', NET_60 = 'net_60', } ``` **Solution Options**: 1. Rename one: `SupplierPaymentTerms` and `CustomerPaymentTerms` 2. Merge into one comprehensive enum (if backend supports) 3. Use string literals instead of enum **Recommended Fix**: ```typescript // frontend/src/api/types/common.ts export enum SupplierPaymentTerms { COD = 'cod', NET_15 = 'net_15', NET_30 = 'net_30', NET_45 = 'net_45', NET_60 = 'net_60', PREPAID = 'prepaid', CREDIT_TERMS = 'credit_terms', } export enum CustomerPaymentTerms { IMMEDIATE = 'immediate', NET_30 = 'net_30', NET_60 = 'net_60', } ``` Then update imports: ```typescript // In suppliers wizard import { SupplierPaymentTerms } from '../../../api/types/common'; // In customers/orders wizard import { CustomerPaymentTerms } from '../../../api/types/common'; ``` ### Issue 2: unit_cost vs unit_price **Problem**: Inconsistent field naming **Stock Type** defines: ```typescript unit_cost: number; ``` **Hook** uses: ```typescript unit_price: number; ``` **Solution**: Search and replace all `unit_price` → `unit_cost` in inventory hooks/services, OR update backend to accept both. **Files to check**: ```bash grep -r "unit_price" frontend/src/api/services/inventory.ts grep -r "unit_price" frontend/src/api/hooks/useInventory.ts ``` --- ## Part 5: Testing Checklist For each wizard, verify: ### Functional Testing - [ ] All required fields prevent submission when empty - [ ] Validation messages display correctly - [ ] Optional fields don't prevent submission - [ ] Advanced options section expands/collapses - [ ] Auto-generation works (codes, etc.) - [ ] Form submits successfully - [ ] Success toast appears - [ ] Modal closes after success - [ ] Error messages display on failure - [ ] Loading state shows during submission ### Field Validation - [ ] Email fields validate format - [ ] Phone fields validate format (if applicable) - [ ] Number fields enforce min/max - [ ] Date fields use proper format - [ ] Enum fields use correct values - [ ] JSONB fields parse correctly ### Backend Alignment - [ ] All required backend fields present - [ ] Field names match backend (snake_case) - [ ] Enums match backend values - [ ] Data types match (string, number, boolean) - [ ] Defaults match backend defaults ### UX Testing - [ ] Form is not overwhelming (required fields visible, optional hidden) - [ ] Clear visual hierarchy - [ ] Helpful tooltips on complex fields - [ ] Responsive design works on mobile - [ ] Tab order is logical - [ ] Keyboard navigation works --- ## Part 6: Quick Reference ### Completed Wizard Examples **Recipe**: `/frontend/src/components/domain/unified-wizard/wizards/RecipeWizard.tsx` - Best example of complex advanced options - Shows ingredient list management - Quality template selection - Seasonal conditional fields **Customer**: `/frontend/src/components/domain/unified-wizard/wizards/CustomerWizard.tsx` - Clean single-step wizard - Auto-code generation - Address fields in advanced section **Supplier**: `/frontend/src/components/domain/unified-wizard/wizards/SupplierWizard.tsx` - All payment terms properly aligned - Certification/specialization handling - Checkbox fields for preferences ### Key Components **AdvancedOptionsSection**: `/frontend/src/components/ui/AdvancedOptionsSection/AdvancedOptionsSection.tsx` **Tooltip**: `/frontend/src/components/ui/Tooltip/Tooltip.tsx` **WizardModal**: `/frontend/src/components/ui/WizardModal/WizardModal.tsx` ### Research Documents **Backend Models**: `/home/user/bakery_ia/FRONTEND_API_TYPES_ANALYSIS.md` **API Summary**: `/home/user/bakery_ia/FRONTEND_API_ANALYSIS_SUMMARY.md` --- ## Part 7: Git Workflow ### Commits Created 1. `020acc4` - Research documentation 2. `3b66bb8` - RecipeWizard rewrite 3. `478d423` - CustomerWizard rewrite 4. `b596359` - SupplierWizard rewrite ### Branch `claude/bakery-jtbd-wizard-design-011CUwzatRMmw9L2wVGdXYgm` --- ## Part 8: Estimated Effort **Remaining Wizards:** - InventoryWizard: ~2-3 hours (moderate complexity, 44 fields) - QualityTemplateWizard: ~1-2 hours (simpler, 25 fields, but JSONB handling) - CustomerOrderWizard: ~4-6 hours (complex, 72 fields, multi-step with items) **Type Fixes:** - PaymentTerms enum: ~30 minutes - unit_cost vs unit_price: ~15 minutes **Total Remaining**: ~8-12 hours --- ## Part 9: Success Criteria ✅ **All wizards should:** 1. Have NO duplicate Next buttons 2. Include ALL backend required fields 3. Include ALL backend optional fields (in advanced section) 4. Use validate prop for field validation 5. Auto-generate codes where applicable 6. Have English labels 7. Use AdvancedOptionsSection component 8. Include tooltips for complex fields 9. Handle errors gracefully 10. Show loading states ✅ **All type inconsistencies fixed** ✅ **All wizards tested end-to-end** --- ## Part 10: Future Enhancements (Not in Scope) - Multi-step wizards for complex entities (e.g., Order with items as separate step) - Real-time field validation as user types - Field dependencies (show field X only if field Y has value Z) - Draft saving (persist wizard state) - Form analytics (track where users drop off) - Accessibility improvements (ARIA labels, keyboard shortcuts) - i18n support (Spanish translations) --- ## Conclusion This guide provides everything needed to complete the wizard improvements. The pattern is established, components are built, and research is documented. Simply follow the pattern from the completed wizards for each remaining wizard. **Key Principle**: Progressive disclosure + complete backend alignment + clean UX = excellent wizard experience. --- ## Appendix: Field Mapping Reference ### Recipe → Backend Mapping ```typescript // Frontend (camelCase) → Backend (snake_case) name → name finishedProductId → finished_product_id yieldQuantity → yield_quantity yieldUnit → yield_unit recipeCode → recipe_code difficultyLevel → difficulty_level prepTime → prep_time_minutes cookTime → cook_time_minutes restTime → rest_time_minutes optimalProductionTemp → optimal_production_temperature optimalHumidity → optimal_humidity isSeasonal → is_seasonal isSignatureItem → is_signature_item seasonStartMonth → season_start_month seasonEndMonth → season_end_month targetMargin → target_margin_percentage ``` ### Customer → Backend Mapping ```typescript name → name customerCode → customer_code customerType → customer_type businessName → business_name addressLine1 → address_line1 addressLine2 → address_line2 postalCode → postal_code taxId → tax_id businessLicense → business_license paymentTerms → payment_terms creditLimit → credit_limit discountPercentage → discount_percentage customerSegment → customer_segment priorityLevel → priority_level preferredDeliveryMethod → preferred_delivery_method specialInstructions → special_instructions ``` ### Supplier → Backend Mapping ```typescript name → name supplierCode → supplier_code supplierType → supplier_type taxId → tax_id registrationNumber → registration_number contactPerson → contact_person addressLine1 → address_line1 addressLine2 → address_line2 stateProvince → state_province postalCode → postal_code paymentTerms → payment_terms standardLeadTime → standard_lead_time creditLimit → credit_limit minimumOrderAmount → minimum_order_amount deliveryArea → delivery_area isPreferredSupplier → is_preferred_supplier autoApproveEnabled → auto_approve_enabled ``` --- **Document Version**: 1.0 **Last Updated**: 2025-11-10 **Author**: Claude (AI Assistant) **Status**: Reference Implementation Guide