IMPORVE ONBOARDING STEPS
This commit is contained in:
@@ -11,7 +11,8 @@ import { WizardProvider, useWizardContext, BakeryType, DataSource } from './cont
|
||||
import {
|
||||
BakeryTypeSelectionStep,
|
||||
RegisterTenantStep,
|
||||
UploadSalesDataStep,
|
||||
FileUploadStep,
|
||||
InventoryReviewStep,
|
||||
ProductCategorizationStep,
|
||||
InitialStockEntryStep,
|
||||
ProductionProcessesStep,
|
||||
@@ -73,20 +74,20 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.state.bakeryType !== null,
|
||||
},
|
||||
// Phase 2a: AI-Assisted Path (ONLY PATH NOW)
|
||||
// Phase 2a: AI-Assisted Inventory Setup (REFACTORED - split into 3 focused steps)
|
||||
{
|
||||
id: 'smart-inventory-setup',
|
||||
title: t('onboarding:steps.smart_inventory.title', 'Subir Datos de Ventas'),
|
||||
description: t('onboarding:steps.smart_inventory.description', 'Configuración con IA'),
|
||||
component: UploadSalesDataStep,
|
||||
id: 'upload-sales-data',
|
||||
title: t('onboarding:steps.upload_sales.title', 'Subir Datos de Ventas'),
|
||||
description: t('onboarding:steps.upload_sales.description', 'Cargar archivo con historial de ventas'),
|
||||
component: FileUploadStep,
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.tenantId !== null,
|
||||
condition: (ctx) => ctx.state.bakeryType !== null, // Tenant created after bakeryType is set
|
||||
},
|
||||
{
|
||||
id: 'product-categorization',
|
||||
title: t('onboarding:steps.categorization.title', 'Categorizar Productos'),
|
||||
description: t('onboarding:steps.categorization.description', 'Clasifica ingredientes vs productos'),
|
||||
component: ProductCategorizationStep,
|
||||
id: 'inventory-review',
|
||||
title: t('onboarding:steps.inventory_review.title', 'Revisar Inventario'),
|
||||
description: t('onboarding:steps.inventory_review.description', 'Confirmar productos detectados'),
|
||||
component: InventoryReviewStep,
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.state.aiAnalysisComplete,
|
||||
},
|
||||
@@ -96,7 +97,7 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
description: t('onboarding:steps.stock.description', 'Cantidades iniciales'),
|
||||
component: InitialStockEntryStep,
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.state.categorizationCompleted,
|
||||
condition: (ctx) => ctx.state.inventoryReviewCompleted,
|
||||
},
|
||||
{
|
||||
id: 'suppliers-setup',
|
||||
@@ -130,7 +131,7 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
description: t('onboarding:steps.quality.description', 'Estándares de calidad'),
|
||||
component: QualitySetupStep,
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.tenantId !== null,
|
||||
condition: (ctx) => ctx.state.bakeryType !== null, // Tenant created after bakeryType is set
|
||||
},
|
||||
{
|
||||
id: 'team-setup',
|
||||
@@ -138,7 +139,7 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
description: t('onboarding:steps.team.description', 'Miembros del equipo'),
|
||||
component: TeamSetupStep,
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.tenantId !== null,
|
||||
condition: (ctx) => ctx.state.bakeryType !== null, // Tenant created after bakeryType is set
|
||||
},
|
||||
// Phase 4: ML & Finalization
|
||||
{
|
||||
@@ -154,7 +155,7 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
description: t('onboarding:steps.review.description', 'Confirma tu configuración'),
|
||||
component: ReviewSetupStep,
|
||||
isConditional: true,
|
||||
condition: (ctx) => ctx.tenantId !== null,
|
||||
condition: (ctx) => ctx.state.bakeryType !== null, // Tenant created after bakeryType is set
|
||||
},
|
||||
{
|
||||
id: 'completion',
|
||||
@@ -182,7 +183,7 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
});
|
||||
|
||||
return visibleSteps;
|
||||
}, [wizardContext.state, wizardContext.tenantId]);
|
||||
}, [wizardContext.state]);
|
||||
|
||||
const isNewTenant = searchParams.get('new') === 'true';
|
||||
const [currentStepIndex, setCurrentStepIndex] = useState(0);
|
||||
@@ -316,10 +317,15 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
if (currentStep.id === 'data-source-choice' && data?.dataSource) {
|
||||
wizardContext.updateDataSource(data.dataSource as DataSource);
|
||||
}
|
||||
if (currentStep.id === 'smart-inventory-setup' && data?.aiSuggestions) {
|
||||
// REFACTORED: Handle new split steps for AI-assisted inventory
|
||||
if (currentStep.id === 'upload-sales-data' && data?.aiSuggestions) {
|
||||
wizardContext.updateAISuggestions(data.aiSuggestions);
|
||||
wizardContext.updateUploadedFile(data.uploadedFile, data.validationResult);
|
||||
wizardContext.setAIAnalysisComplete(true);
|
||||
}
|
||||
if (currentStep.id === 'inventory-review') {
|
||||
wizardContext.markStepComplete('inventoryReviewCompleted');
|
||||
}
|
||||
if (currentStep.id === 'product-categorization' && data?.categorizedProducts) {
|
||||
wizardContext.updateCategorizedProducts(data.categorizedProducts);
|
||||
wizardContext.markStepComplete('categorizationCompleted');
|
||||
@@ -345,8 +351,8 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
|
||||
console.log(`✅ Successfully completed step: "${currentStep.id}"`);
|
||||
|
||||
// Special handling for smart-inventory-setup
|
||||
if (currentStep.id === 'smart-inventory-setup' && data?.shouldAutoCompleteSuppliers) {
|
||||
// Special handling for inventory-review - auto-complete suppliers if requested
|
||||
if (currentStep.id === 'inventory-review' && data?.shouldAutoCompleteSuppliers) {
|
||||
try {
|
||||
console.log('🔄 Auto-completing suppliers-setup step...');
|
||||
await markStepCompleted.mutateAsync({
|
||||
@@ -452,12 +458,12 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
: userProgress?.completion_percentage || ((currentStepIndex + 1) / VISIBLE_STEPS.length) * 100;
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 space-y-4 sm:space-y-6 pb-6">
|
||||
<div className="max-w-4xl mx-auto px-2 sm:px-4 md:px-6 space-y-3 sm:space-y-4 md:space-y-6 pb-4 md:pb-6">
|
||||
{/* Progress Header */}
|
||||
<Card shadow="sm" padding="lg">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-4 space-y-2 sm:space-y-0">
|
||||
<Card shadow="sm" padding="md">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-3 sm:mb-4 space-y-2 sm:space-y-0">
|
||||
<div className="text-center sm:text-left">
|
||||
<h1 className="text-xl sm:text-2xl font-bold text-[var(--text-primary)]">
|
||||
<h1 className="text-lg sm:text-xl md:text-2xl font-bold text-[var(--text-primary)]">
|
||||
{isNewTenant ? t('onboarding:wizard.title_new', 'Nueva Panadería') : t('onboarding:wizard.title', 'Configuración Inicial')}
|
||||
</h1>
|
||||
<p className="text-[var(--text-secondary)] text-xs sm:text-sm mt-1">
|
||||
@@ -488,9 +494,9 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
|
||||
{/* Step Content */}
|
||||
<Card shadow="lg" padding="none">
|
||||
<CardHeader padding="lg" divider>
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-[var(--color-primary)]/10 rounded-full flex items-center justify-center">
|
||||
<CardHeader padding="md" divider>
|
||||
<div className="flex items-center space-x-2 sm:space-x-3">
|
||||
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-[var(--color-primary)]/10 rounded-full flex items-center justify-center flex-shrink-0">
|
||||
<div className="w-5 h-5 sm:w-6 sm:h-6 bg-[var(--color-primary)] rounded-full flex items-center justify-center text-white text-xs font-bold">
|
||||
{currentStepIndex + 1}
|
||||
</div>
|
||||
@@ -506,7 +512,7 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<CardBody padding="lg">
|
||||
<CardBody padding="md">
|
||||
<StepComponent
|
||||
onNext={() => {}}
|
||||
onPrevious={() => {}}
|
||||
@@ -515,6 +521,18 @@ const OnboardingWizardContent: React.FC = () => {
|
||||
isFirstStep={currentStepIndex === 0}
|
||||
isLastStep={currentStepIndex === VISIBLE_STEPS.length - 1}
|
||||
canContinue={canContinue}
|
||||
initialData={
|
||||
// Pass AI data and file to InventoryReviewStep
|
||||
currentStep.id === 'inventory-review'
|
||||
? {
|
||||
uploadedFile: wizardContext.state.uploadedFile,
|
||||
validationResult: wizardContext.state.uploadedFileValidation,
|
||||
aiSuggestions: wizardContext.state.aiSuggestions,
|
||||
uploadedFileName: wizardContext.state.uploadedFileName || '',
|
||||
uploadedFileSize: wizardContext.state.uploadedFileSize || 0,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user