Make suppliers and ML training steps unconditional + rewrite completion

CHANGES:

1. **Make suppliers-setup unconditional:**
   - Removed isConditional: true and condition
   - Suppliers step now ALWAYS appears in onboarding flow
   - No longer depends on stockEntryCompleted flag

2. **Make ml-training unconditional:**
   - Removed isConditional: true and condition
   - ML training step now ALWAYS appears in onboarding flow
   - No longer depends on aiAnalysisComplete flag

3. **Completely rewrote CompletionStep content:**
   - Changed title: "¡Felicidades! Tu Sistema Está Listo"
   - Shows what user HAS ACCOMPLISHED during onboarding:
     ✓ Información de Panadería
     ✓ Inventario con IA
     ✓ Proveedores Agregados
     ✓ Recetas Configuradas
     ✓ Calidad Establecida
     ✓ Equipo Invitado
     ✓ Modelo IA Entrenado
   - REMOVED misleading "One More Thing" section that asked users
     to configure things they JUST configured
   - Changed next steps to celebrate accomplishments and guide to dashboard
   - Updated buttons: "Ir al Panel de Control →" (single clear CTA)

FIXES:
- User frustration: suppliers and ML training steps were hidden
- User confusion: completion message didn't make sense - asking to
  configure suppliers, inventory, recipes after they just did it

ONBOARDING FLOW NOW:
1. bakery-type-selection
2. setup
3. smart-inventory-setup
4. product-categorization
5. initial-stock-entry
6. suppliers-setup ✓ ALWAYS SHOWS
7. recipes-setup (conditional on bakery type)
8. production-processes (conditional on bakery type)
9. quality-setup
10. team-setup
11. ml-training ✓ ALWAYS SHOWS
12. setup-review
13. completion (celebrates accomplishments!)

Files Modified:
- frontend/src/components/domain/onboarding/UnifiedOnboardingWizard.tsx
- frontend/src/components/domain/onboarding/steps/CompletionStep.tsx
This commit is contained in:
Claude
2025-11-07 10:00:33 +00:00
parent 3a17a423eb
commit 75916adfee
2 changed files with 128 additions and 124 deletions

View File

@@ -103,8 +103,7 @@ const OnboardingWizardContent: React.FC = () => {
title: t('onboarding:steps.suppliers.title', 'Proveedores'), title: t('onboarding:steps.suppliers.title', 'Proveedores'),
description: t('onboarding:steps.suppliers.description', 'Configura tus proveedores'), description: t('onboarding:steps.suppliers.description', 'Configura tus proveedores'),
component: SuppliersSetupStep, component: SuppliersSetupStep,
isConditional: true, // Always show - no conditional
condition: (ctx) => ctx.state.stockEntryCompleted,
}, },
{ {
id: 'recipes-setup', id: 'recipes-setup',
@@ -147,8 +146,7 @@ const OnboardingWizardContent: React.FC = () => {
title: t('onboarding:steps.ml_training.title', 'Entrenamiento IA'), title: t('onboarding:steps.ml_training.title', 'Entrenamiento IA'),
description: t('onboarding:steps.ml_training.description', 'Modelo personalizado'), description: t('onboarding:steps.ml_training.description', 'Modelo personalizado'),
component: MLTrainingStep, component: MLTrainingStep,
isConditional: true, // Always show - no conditional
condition: (ctx) => ctx.state.aiAnalysisComplete,
}, },
{ {
id: 'setup-review', id: 'setup-review',

View File

@@ -19,14 +19,14 @@ export const CompletionStep: React.FC<CompletionStepProps> = ({
const navigate = useNavigate(); const navigate = useNavigate();
const currentTenant = useCurrentTenant(); const currentTenant = useCurrentTenant();
const handleGetStarted = () => { const handleStartUsingSystem = () => {
onComplete({ redirectTo: '/app' }); onComplete({ redirectTo: '/app/dashboard' });
navigate('/app'); navigate('/app/dashboard');
}; };
const handleContinueSetup = () => { const handleExploreDashboard = () => {
onComplete({ redirectTo: '/app/setup' }); onComplete({ redirectTo: '/app/dashboard' });
navigate('/app/setup'); navigate('/app/dashboard');
}; };
return ( return (
@@ -41,142 +41,148 @@ export const CompletionStep: React.FC<CompletionStepProps> = ({
{/* Success Message */} {/* Success Message */}
<div className="space-y-4"> <div className="space-y-4">
<h1 className="text-3xl font-bold text-[var(--text-primary)]"> <h1 className="text-3xl font-bold text-[var(--text-primary)]">
{t('onboarding:completion.welcome', '¡Bienvenido a Bakery IA!')} {t('onboarding:completion.congratulations', '¡Felicidades! Tu Sistema Está Listo')}
</h1> </h1>
<p className="text-lg text-[var(--text-secondary)] max-w-2xl mx-auto"> <p className="text-lg text-[var(--text-secondary)] max-w-2xl mx-auto">
{t('onboarding:completion.ready_message', 'Tu panadería {{name}} está lista para usar nuestro sistema de gestión inteligente.', { name: currentTenant?.name })} {t('onboarding:completion.all_configured', 'Has configurado exitosamente {{name}} con nuestro sistema de gestión inteligente. Todo está listo para empezar a optimizar tu panadería.', { name: currentTenant?.name })}
</p> </p>
</div> </div>
{/* Summary Cards */} {/* What You Configured */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto"> <div className="bg-[var(--bg-secondary)] rounded-lg p-6 max-w-3xl mx-auto text-left">
<div className="bg-[var(--bg-secondary)] rounded-lg p-6 text-center"> <h3 className="font-semibold text-lg mb-4 text-center text-[var(--text-primary)]">
<div className="w-12 h-12 bg-[var(--color-primary)]/10 rounded-lg mx-auto mb-4 flex items-center justify-center"> {t('onboarding:completion.what_configured', 'Lo Que Has Configurado')}
<svg className="w-6 h-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24"> </h3>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" /> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div className="flex items-start gap-3">
<div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg> </svg>
</div> </div>
<h3 className="font-semibold mb-2">{t('onboarding:completion.bakery_registered', 'Panadería Registrada')}</h3>
<p className="text-sm text-[var(--text-secondary)]">
{t('onboarding:completion.bakery_info_ready', 'Tu información empresarial está configurada y lista')}
</p>
</div>
<div className="bg-[var(--bg-secondary)] rounded-lg p-6 text-center">
<div className="w-12 h-12 bg-[var(--color-primary)]/10 rounded-lg mx-auto mb-4 flex items-center justify-center">
<svg className="w-6 h-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
</svg>
</div>
<h3 className="font-semibold mb-2">{t('onboarding:completion.inventory_created', 'Inventario Creado')}</h3>
<p className="text-sm text-[var(--text-secondary)]">
{t('onboarding:completion.products_configured', 'Tus productos base están configurados con datos iniciales')}
</p>
</div>
<div className="bg-[var(--bg-secondary)] rounded-lg p-6 text-center">
<div className="w-12 h-12 bg-[var(--color-primary)]/10 rounded-lg mx-auto mb-4 flex items-center justify-center">
<svg className="w-6 h-6 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
</div>
<h3 className="font-semibold mb-2">{t('onboarding:completion.ai_trained', 'IA Entrenada')}</h3>
<p className="text-sm text-[var(--text-secondary)]">
{t('onboarding:completion.ai_ready', 'Tu modelo de inteligencia artificial está listo para predecir demanda')}
</p>
</div>
</div>
{/* One More Thing - Setup Wizard CTA */}
<div className="bg-gradient-to-r from-[var(--color-primary)]/10 to-[var(--color-primary)]/5 border border-[var(--color-primary)]/20 rounded-lg p-6 max-w-2xl mx-auto text-left">
<div className="flex items-start gap-4">
<div className="w-12 h-12 bg-[var(--color-primary)] text-white rounded-full flex items-center justify-center text-xl font-bold flex-shrink-0">
</div>
<div> <div>
<h3 className="font-semibold text-lg mb-2 text-[var(--text-primary)]">{t('onboarding:completion.one_more_thing', '¡Una cosa más!')}</h3> <p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.bakery_info', 'Información de Panadería')}</p>
<p className="text-sm text-[var(--text-secondary)] mb-4"> <p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.bakery_info_desc', 'Datos básicos registrados')}</p>
{t('onboarding:completion.maximize_message', 'Para aprovechar al máximo el sistema, configura tus operaciones diarias: proveedores, inventario, recetas y estándares de calidad.')} </div>
</p> </div>
<div className="flex items-center gap-2 text-sm text-[var(--text-secondary)]">
<svg className="w-4 h-4 text-[var(--color-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <div className="flex items-start gap-3">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /> <div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg> </svg>
<span>{t('onboarding:completion.time_estimate', 'Toma solo 15-20 minutos')}</span> </div>
<div>
<p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.inventory_ai', 'Inventario con IA')}</p>
<p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.inventory_ai_desc', 'Productos analizados y categorizados')}</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.suppliers_added', 'Proveedores Agregados')}</p>
<p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.suppliers_added_desc', 'Red de suministro configurada')}</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.recipes_configured', 'Recetas Configuradas')}</p>
<p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.recipes_configured_desc', 'Producción lista para usar')}</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.quality_set', 'Calidad Establecida')}</p>
<p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.quality_set_desc', 'Estándares definidos')}</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.team_invited', 'Equipo Invitado')}</p>
<p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.team_invited_desc', 'Colaboradores configurados')}</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 bg-[var(--color-success)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
<svg className="w-4 h-4 text-[var(--color-success)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<div>
<p className="font-medium text-sm text-[var(--text-primary)]">{t('onboarding:completion.ml_model_trained', 'Modelo IA Entrenado')}</p>
<p className="text-xs text-[var(--text-secondary)]">{t('onboarding:completion.ml_model_trained_desc', 'Predicciones personalizadas activas')}</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{/* Next Steps */} {/* Next Steps */}
<div className="bg-[var(--bg-secondary)] rounded-lg p-6 max-w-2xl mx-auto text-left"> <div className="bg-gradient-to-r from-[var(--color-primary)]/10 to-[var(--color-primary)]/5 border border-[var(--color-primary)]/20 rounded-lg p-6 max-w-2xl mx-auto text-left">
<h3 className="font-semibold mb-4 text-center">{t('onboarding:completion.what_to_configure', 'Lo Que Configurarás')}</h3> <div className="flex items-start gap-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> <div className="w-12 h-12 bg-[var(--color-primary)] text-white rounded-full flex items-center justify-center text-xl font-bold flex-shrink-0">
<div className="flex items-start gap-2"> 🚀
<div className="w-5 h-5 bg-[var(--color-primary)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
📦
</div> </div>
<div> <div>
<p className="font-medium text-sm">{t('onboarding:completion.suppliers_inventory', 'Proveedores e Inventario')}</p> <h3 className="font-semibold text-lg mb-2 text-[var(--text-primary)]">{t('onboarding:completion.ready_to_start', '¡Listo para Empezar!')}</h3>
<p className="text-xs text-[var(--text-secondary)]"> <p className="text-sm text-[var(--text-secondary)] mb-3">
{t('onboarding:completion.stock_tracking', 'Tracking automático de stock')} {t('onboarding:completion.explore_message', 'Ahora puedes explorar el panel de control y comenzar a gestionar tu panadería con inteligencia artificial.')}
</p> </p>
<div className="space-y-2">
<div className="flex items-start gap-2 text-sm">
<svg className="w-4 h-4 text-[var(--color-primary)] mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
<span className="text-[var(--text-secondary)]">{t('onboarding:completion.view_analytics', 'Ve análisis y predicciones de demanda')}</span>
</div> </div>
<div className="flex items-start gap-2 text-sm">
<svg className="w-4 h-4 text-[var(--color-primary)] mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span className="text-[var(--text-secondary)]">{t('onboarding:completion.manage_operations', 'Gestiona producción y operaciones diarias')}</span>
</div> </div>
<div className="flex items-start gap-2 text-sm">
<div className="flex items-start gap-2"> <svg className="w-4 h-4 text-[var(--color-primary)] mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div className="w-5 h-5 bg-[var(--color-primary)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5"> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" />
👨🍳 </svg>
<span className="text-[var(--text-secondary)]">{t('onboarding:completion.optimize_costs', 'Optimiza costos y reduce desperdicios')}</span>
</div> </div>
<div>
<p className="font-medium text-sm">{t('onboarding:completion.recipes', 'Recetas')}</p>
<p className="text-xs text-[var(--text-secondary)]">
{t('onboarding:completion.auto_costs', 'Costos automáticos por producto')}
</p>
</div>
</div>
<div className="flex items-start gap-2">
<div className="w-5 h-5 bg-[var(--color-primary)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
</div>
<div>
<p className="font-medium text-sm">{t('onboarding:completion.quality_standards', 'Estándares de Calidad')}</p>
<p className="text-xs text-[var(--text-secondary)]">
{t('onboarding:completion.production_monitoring', 'Monitoreo de producción')}
</p>
</div>
</div>
<div className="flex items-start gap-2">
<div className="w-5 h-5 bg-[var(--color-primary)]/10 rounded flex items-center justify-center flex-shrink-0 mt-0.5">
👥
</div>
<div>
<p className="font-medium text-sm">{t('onboarding:completion.team', 'Equipo')}</p>
<p className="text-xs text-[var(--text-secondary)]">
{t('onboarding:completion.coordination', 'Coordinación y tareas')}
</p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{/* Action Buttons */} {/* Action Buttons */}
<div className="flex flex-col sm:flex-row gap-3 justify-center items-center pt-4"> <div className="flex justify-center items-center pt-4">
<Button <Button
variant="ghost" onClick={handleExploreDashboard}
onClick={handleGetStarted}
className="sm:order-2"
>
{t('onboarding:completion.do_later', 'Lo haré después')}
</Button>
<Button
onClick={handleContinueSetup}
size="lg" size="lg"
className="px-8 sm:order-1" className="px-8"
> >
{t('onboarding:completion.configure_now', 'Configurar Ahora (15 min) →')} {t('onboarding:completion.go_to_dashboard', 'Ir al Panel de Control →')}
</Button> </Button>
</div> </div>