From ca090125f7d61bf74b5002fe78f0872d49a19082 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 12 Nov 2025 15:03:33 +0000 Subject: [PATCH] feat: Enhance onboarding wizard UX with improved feedback and completion This commit adds significant UX improvements to multiple onboarding steps: **1. Recipes Setup Step:** - Fixed double next button issue (removed duplicate navigation button) - Filtered finished products dropdown to show only 'finished_product' type ingredients - Users can now only select appropriate finished products for recipes **2. File Upload Step:** - Added comprehensive validation success state with detailed feedback - Shows file name, rows found, and unique products count after validation - Enhanced error display with helpful troubleshooting tips - Clear visual distinction between file selected, validation success, and processing states - Improved user confidence by clearly communicating validation results **3. Completion Step:** - Complete redesign with animated success icon and gradient text - Added 4 quick access cards for Analytics, Inventory, Procurement, and Production - Interactive hover effects on quick access cards (scale and shadow) - New "Tips for Success" section with actionable advice - Enhanced primary CTA button with better sizing and prominence - More engaging and valuable final step that guides users to next actions All changes use global CSS variables for proper dark mode support and maintain consistent design language throughout the application. --- .../onboarding/steps/CompletionStep.tsx | 134 +++++++++++++----- .../onboarding/steps/FileUploadStep.tsx | 77 ++++++++-- .../setup-wizard/steps/RecipesSetupStep.tsx | 25 +--- 3 files changed, 172 insertions(+), 64 deletions(-) diff --git a/frontend/src/components/domain/onboarding/steps/CompletionStep.tsx b/frontend/src/components/domain/onboarding/steps/CompletionStep.tsx index bd013ee0..c847482f 100644 --- a/frontend/src/components/domain/onboarding/steps/CompletionStep.tsx +++ b/frontend/src/components/domain/onboarding/steps/CompletionStep.tsx @@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Button } from '../../../ui/Button'; import { useCurrentTenant } from '../../../../stores/tenant.store'; +import { ChartBar, ShoppingCart, Users, TrendingUp, Zap, CheckCircle2 } from 'lucide-react'; interface CompletionStepProps { onNext: () => void; @@ -30,20 +31,21 @@ export const CompletionStep: React.FC = ({ }; return ( -
- {/* Success Icon */} -
- - - +
+ {/* Animated Success Icon */} +
+
+
+ +
{/* Success Message */}
-

+

{t('onboarding:completion.congratulations', '¡Felicidades! Tu Sistema Está Listo')}

-

+

{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 })}

@@ -140,49 +142,109 @@ export const CompletionStep: React.FC = ({
- {/* Next Steps */} -
+ {/* Quick Access Cards */} +
+ + + + + + + +
+ + {/* Tips for Success */} +
-
- 🚀 +
+
-
-

{t('onboarding:completion.ready_to_start', '¡Listo para Empezar!')}

-

- {t('onboarding:completion.explore_message', 'Ahora puedes explorar el panel de control y comenzar a gestionar tu panadería con inteligencia artificial.')} -

-
-
- - - - {t('onboarding:completion.view_analytics', 'Ve análisis y predicciones de demanda')} +
+

+ {t('onboarding:completion.tips_title', 'Consejos para Maximizar tu Éxito')} +

+
+
+ + + {t('onboarding:completion.tip1', 'Revisa el dashboard diariamente para insights')} +
-
- - - - {t('onboarding:completion.manage_operations', 'Gestiona producción y operaciones diarias')} +
+ + + {t('onboarding:completion.tip2', 'Actualiza el inventario regularmente')} +
-
- - - - {t('onboarding:completion.optimize_costs', 'Optimiza costos y reduce desperdicios')} +
+ + + {t('onboarding:completion.tip3', 'Usa las predicciones de IA para planificar')} + +
+
+ + + {t('onboarding:completion.tip4', 'Invita a tu equipo para colaborar')} +
- {/* Action Buttons */} + {/* Primary Action Button */}
diff --git a/frontend/src/components/domain/onboarding/steps/FileUploadStep.tsx b/frontend/src/components/domain/onboarding/steps/FileUploadStep.tsx index 09ab06f0..ddb60fe8 100644 --- a/frontend/src/components/domain/onboarding/steps/FileUploadStep.tsx +++ b/frontend/src/components/domain/onboarding/steps/FileUploadStep.tsx @@ -39,6 +39,8 @@ export const FileUploadStep: React.FC = ({ const [error, setError] = useState(''); const [progressState, setProgressState] = useState(null); const [showGuide, setShowGuide] = useState(false); + const [validationSuccess, setValidationSuccess] = useState(false); + const [validationDetails, setValidationDetails] = useState<{rows: number, products: number} | null>(null); const fileInputRef = useRef(null); const currentTenant = useCurrentTenant(); @@ -101,6 +103,13 @@ export const FileUploadStep: React.FC = ({ throw new Error(errorMsg); } + // Show validation success feedback + setValidationSuccess(true); + setValidationDetails({ + rows: validationResult.total_rows || 0, + products: validationResult.product_list?.length || 0 + }); + // Step 2: Extract product list setProgressState({ stage: 'analyzing', @@ -158,6 +167,8 @@ export const FileUploadStep: React.FC = ({ setSelectedFile(null); setError(''); setProgressState(null); + setValidationSuccess(false); + setValidationDetails(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } @@ -215,14 +226,14 @@ export const FileUploadStep: React.FC = ({ )} {/* Selected File Preview */} - {selectedFile && !isProcessing && ( -
+ {selectedFile && !isProcessing && !validationSuccess && ( +
- +

{selectedFile.name}

-

+

{(selectedFile.size / 1024).toFixed(2)} KB

@@ -237,6 +248,40 @@ export const FileUploadStep: React.FC = ({
)} + {/* Validation Success State */} + {selectedFile && validationSuccess && !isProcessing && validationDetails && ( +
+
+ +
+

+ {t('onboarding:file_upload.validation_success', '¡Archivo validado correctamente!')} +

+
+
+ {t('onboarding:file_upload.file_name', 'Archivo:')} + {selectedFile.name} +
+
+ {t('onboarding:file_upload.rows_found', 'Registros encontrados:')} + {validationDetails.rows} +
+
+ {t('onboarding:file_upload.products_found', 'Productos únicos:')} + {validationDetails.products} +
+
+ +
+
+
+ )} + {/* Progress Indicator */} {isProcessing && progressState && (
@@ -260,12 +305,24 @@ export const FileUploadStep: React.FC = ({ {/* Error Display */} {error && ( -
-
- -
-

Error

-

{error}

+
+
+ +
+

+ {t('onboarding:file_upload.validation_failed', 'Error al validar el archivo')} +

+

{error}

+
+

+ {t('onboarding:file_upload.error_tips', 'Consejos para solucionar el problema:')} +

+
    +
  • {t('onboarding:file_upload.tip_1', 'Verifica que el archivo tenga las columnas: Fecha, Producto, Cantidad')}
  • +
  • {t('onboarding:file_upload.tip_2', 'Asegúrate de que las fechas estén en formato YYYY-MM-DD')}
  • +
  • {t('onboarding:file_upload.tip_3', 'Comprueba que no haya filas vacías o datos incorrectos')}
  • +
+
diff --git a/frontend/src/components/domain/setup-wizard/steps/RecipesSetupStep.tsx b/frontend/src/components/domain/setup-wizard/steps/RecipesSetupStep.tsx index 562a39ee..58780c08 100644 --- a/frontend/src/components/domain/setup-wizard/steps/RecipesSetupStep.tsx +++ b/frontend/src/components/domain/setup-wizard/steps/RecipesSetupStep.tsx @@ -565,11 +565,13 @@ export const RecipesSetupStep: React.FC = ({ onUpdate, onComplet className={`w-full px-3 py-2 bg-[var(--bg-primary)] border ${errors.finished_product_id ? 'border-[var(--color-error)]' : 'border-[var(--border-secondary)]'} rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] text-[var(--text-primary)]`} > - {ingredients.map((ing) => ( - - ))} + {ingredients + .filter((ing) => ing.product_type === 'finished_product') + .map((ing) => ( + + ))} @@ -793,19 +795,6 @@ export const RecipesSetupStep: React.FC = ({ onUpdate, onComplet tenantId={tenantId} context="recipe" /> - - {/* Continue button - only shown when used in onboarding context */} - {onComplete && ( -
- -
- )}
); };