Add i18 support
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { Button } from '../../ui/Button';
|
||||
import { Card, CardHeader, CardBody } from '../../ui/Card';
|
||||
import { useAuth } from '../../../contexts/AuthContext';
|
||||
import { useUserProgress, useMarkStepCompleted } from '../../../api/hooks/onboarding';
|
||||
import { useTenantActions } from '../../../stores/tenant.store';
|
||||
import { useTenantInitializer } from '../../../stores/useTenantInitializer';
|
||||
import {
|
||||
import {
|
||||
RegisterTenantStep,
|
||||
UploadSalesDataStep,
|
||||
MLTrainingStep,
|
||||
CompletionStep
|
||||
} from './steps';
|
||||
import { Building2 } from 'lucide-react';
|
||||
|
||||
interface StepConfig {
|
||||
id: string;
|
||||
@@ -58,11 +59,26 @@ const STEPS: StepConfig[] = [
|
||||
];
|
||||
|
||||
export const OnboardingWizard: React.FC = () => {
|
||||
const [currentStepIndex, setCurrentStepIndex] = useState(0);
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
|
||||
|
||||
// Check if this is a fresh onboarding (new tenant creation)
|
||||
const isNewTenant = searchParams.get('new') === 'true';
|
||||
|
||||
// Initialize state based on whether this is a new tenant or not
|
||||
const [currentStepIndex, setCurrentStepIndex] = useState(0);
|
||||
const [isInitialized, setIsInitialized] = useState(isNewTenant); // If new tenant, consider initialized immediately
|
||||
|
||||
// Debug log for new tenant creation
|
||||
useEffect(() => {
|
||||
if (isNewTenant) {
|
||||
console.log('🆕 New tenant creation detected - UI will reset to step 0');
|
||||
console.log('📊 Current step index:', currentStepIndex);
|
||||
console.log('🎯 Is initialized:', isInitialized);
|
||||
}
|
||||
}, [isNewTenant, currentStepIndex, isInitialized]);
|
||||
|
||||
// Initialize tenant data for authenticated users
|
||||
useTenantInitializer();
|
||||
|
||||
@@ -106,64 +122,77 @@ export const OnboardingWizard: React.FC = () => {
|
||||
|
||||
// Initialize step index based on backend progress with validation
|
||||
useEffect(() => {
|
||||
// Skip backend progress loading for new tenant creation
|
||||
if (isNewTenant) {
|
||||
return; // Already initialized to step 0
|
||||
}
|
||||
|
||||
if (userProgress && !isInitialized) {
|
||||
console.log('🔄 Initializing onboarding progress:', userProgress);
|
||||
|
||||
|
||||
// Check if user_registered step is completed
|
||||
const userRegisteredStep = userProgress.steps.find(s => s.step_name === 'user_registered');
|
||||
if (!userRegisteredStep?.completed) {
|
||||
console.log('⏳ Waiting for user_registered step to be auto-completed...');
|
||||
return; // Wait for auto-completion to finish
|
||||
}
|
||||
|
||||
// Find the current step index based on backend progress
|
||||
const currentStepFromBackend = userProgress.current_step;
|
||||
let stepIndex = STEPS.findIndex(step => step.id === currentStepFromBackend);
|
||||
|
||||
console.log(`🎯 Backend current step: "${currentStepFromBackend}", found at index: ${stepIndex}`);
|
||||
|
||||
// If current step is not found (e.g., suppliers step), find the next incomplete step
|
||||
if (stepIndex === -1) {
|
||||
console.log('🔍 Current step not found in UI steps, finding first incomplete step...');
|
||||
|
||||
// Find the first incomplete step that user can access
|
||||
for (let i = 0; i < STEPS.length; i++) {
|
||||
const step = STEPS[i];
|
||||
const stepProgress = userProgress.steps.find(s => s.step_name === step.id);
|
||||
|
||||
if (!stepProgress?.completed) {
|
||||
stepIndex = i;
|
||||
console.log(`📍 Found first incomplete step: "${step.id}" at index ${i}`);
|
||||
break;
|
||||
|
||||
let stepIndex = 0; // Default to first step
|
||||
|
||||
// If this is a new tenant creation, always start from the beginning
|
||||
if (isNewTenant) {
|
||||
console.log('🆕 New tenant creation - starting from first step');
|
||||
stepIndex = 0;
|
||||
} else {
|
||||
// Find the current step index based on backend progress
|
||||
const currentStepFromBackend = userProgress.current_step;
|
||||
stepIndex = STEPS.findIndex(step => step.id === currentStepFromBackend);
|
||||
|
||||
console.log(`🎯 Backend current step: "${currentStepFromBackend}", found at index: ${stepIndex}`);
|
||||
|
||||
// If current step is not found (e.g., suppliers step), find the next incomplete step
|
||||
if (stepIndex === -1) {
|
||||
console.log('🔍 Current step not found in UI steps, finding first incomplete step...');
|
||||
|
||||
// Find the first incomplete step that user can access
|
||||
for (let i = 0; i < STEPS.length; i++) {
|
||||
const step = STEPS[i];
|
||||
const stepProgress = userProgress.steps.find(s => s.step_name === step.id);
|
||||
|
||||
if (!stepProgress?.completed) {
|
||||
stepIndex = i;
|
||||
console.log(`📍 Found first incomplete step: "${step.id}" at index ${i}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all visible steps are completed, go to last step
|
||||
if (stepIndex === -1) {
|
||||
stepIndex = STEPS.length - 1;
|
||||
console.log('✅ All steps completed, going to last step');
|
||||
}
|
||||
}
|
||||
|
||||
// If all visible steps are completed, go to last step
|
||||
if (stepIndex === -1) {
|
||||
stepIndex = STEPS.length - 1;
|
||||
console.log('✅ All steps completed, going to last step');
|
||||
|
||||
// Ensure user can't skip ahead - find the first incomplete step
|
||||
const firstIncompleteStepIndex = STEPS.findIndex(step => {
|
||||
const stepProgress = userProgress.steps.find(s => s.step_name === step.id);
|
||||
return !stepProgress?.completed;
|
||||
});
|
||||
|
||||
if (firstIncompleteStepIndex !== -1 && stepIndex > firstIncompleteStepIndex) {
|
||||
console.log(`🚫 User trying to skip ahead. Redirecting to first incomplete step at index ${firstIncompleteStepIndex}`);
|
||||
stepIndex = firstIncompleteStepIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure user can't skip ahead - find the first incomplete step
|
||||
const firstIncompleteStepIndex = STEPS.findIndex(step => {
|
||||
const stepProgress = userProgress.steps.find(s => s.step_name === step.id);
|
||||
return !stepProgress?.completed;
|
||||
});
|
||||
|
||||
if (firstIncompleteStepIndex !== -1 && stepIndex > firstIncompleteStepIndex) {
|
||||
console.log(`🚫 User trying to skip ahead. Redirecting to first incomplete step at index ${firstIncompleteStepIndex}`);
|
||||
stepIndex = firstIncompleteStepIndex;
|
||||
}
|
||||
|
||||
|
||||
console.log(`🎯 Final step index: ${stepIndex} ("${STEPS[stepIndex]?.id}")`);
|
||||
|
||||
|
||||
if (stepIndex !== currentStepIndex) {
|
||||
setCurrentStepIndex(stepIndex);
|
||||
}
|
||||
setIsInitialized(true);
|
||||
}
|
||||
}, [userProgress, isInitialized, currentStepIndex]);
|
||||
}, [userProgress, isInitialized, currentStepIndex, isNewTenant]);
|
||||
|
||||
const currentStep = STEPS[currentStepIndex];
|
||||
|
||||
@@ -214,7 +243,13 @@ export const OnboardingWizard: React.FC = () => {
|
||||
}
|
||||
|
||||
if (currentStep.id === 'completion') {
|
||||
navigate('/app');
|
||||
// Navigate to dashboard after completion
|
||||
if (isNewTenant) {
|
||||
// For new tenant creation, navigate to dashboard and remove the new param
|
||||
navigate('/app/dashboard');
|
||||
} else {
|
||||
navigate('/app');
|
||||
}
|
||||
} else {
|
||||
// Auto-advance to next step after successful completion
|
||||
if (currentStepIndex < STEPS.length - 1) {
|
||||
@@ -246,8 +281,8 @@ export const OnboardingWizard: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Show loading state while initializing progress
|
||||
if (isLoadingProgress || !isInitialized) {
|
||||
// Show loading state while initializing progress (skip for new tenant)
|
||||
if (!isNewTenant && (isLoadingProgress || !isInitialized)) {
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<Card padding="lg" shadow="lg">
|
||||
@@ -262,8 +297,8 @@ export const OnboardingWizard: React.FC = () => {
|
||||
);
|
||||
}
|
||||
|
||||
// Show error state if progress fails to load
|
||||
if (progressError) {
|
||||
// Show error state if progress fails to load (skip for new tenant)
|
||||
if (!isNewTenant && progressError) {
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<Card padding="lg" shadow="lg">
|
||||
@@ -297,19 +332,47 @@ export const OnboardingWizard: React.FC = () => {
|
||||
}
|
||||
|
||||
const StepComponent = currentStep.component;
|
||||
const progressPercentage = userProgress?.completion_percentage || ((currentStepIndex + 1) / STEPS.length) * 100;
|
||||
|
||||
// Calculate progress percentage - reset for new tenant creation
|
||||
const progressPercentage = isNewTenant
|
||||
? ((currentStepIndex + 1) / STEPS.length) * 100 // For new tenant, base progress only on current step
|
||||
: userProgress?.completion_percentage || ((currentStepIndex + 1) / 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">
|
||||
{/* New Tenant Info Banner */}
|
||||
{isNewTenant && (
|
||||
<Card className="bg-gradient-to-r from-[var(--color-primary)]/5 to-[var(--color-primary)]/10 border-[var(--color-primary)]/20">
|
||||
<CardBody className="py-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-8 h-8 bg-[var(--color-primary)]/10 rounded-full flex items-center justify-center">
|
||||
<Building2 className="w-4 h-4 text-[var(--color-primary)]" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-[var(--text-primary)]">
|
||||
Creando Nueva Organización
|
||||
</p>
|
||||
<p className="text-xs text-[var(--text-secondary)]">
|
||||
Configurarás una nueva panadería desde cero. Este proceso es independiente de tus organizaciones existentes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Enhanced 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">
|
||||
<div className="text-center sm:text-left">
|
||||
<h1 className="text-xl sm:text-2xl font-bold text-[var(--text-primary)]">
|
||||
Bienvenido a Bakery IA
|
||||
{isNewTenant ? 'Crear Nueva Organización' : 'Bienvenido a Bakery IA'}
|
||||
</h1>
|
||||
<p className="text-[var(--text-secondary)] text-xs sm:text-sm mt-1">
|
||||
Configura tu sistema de gestión inteligente paso a paso
|
||||
{isNewTenant
|
||||
? 'Configura tu nueva panadería desde cero'
|
||||
: 'Configura tu sistema de gestión inteligente paso a paso'
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center sm:text-right">
|
||||
@@ -318,6 +381,7 @@ export const OnboardingWizard: React.FC = () => {
|
||||
</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">
|
||||
{Math.round(progressPercentage)}% completado
|
||||
{isNewTenant && <span className="text-[var(--color-primary)] ml-1">(nuevo)</span>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -334,7 +398,10 @@ export const OnboardingWizard: React.FC = () => {
|
||||
<div className="sm:hidden">
|
||||
<div className="flex space-x-4 overflow-x-auto pb-2 px-1">
|
||||
{STEPS.map((step, index) => {
|
||||
const isCompleted = userProgress?.steps.find(s => s.step_name === step.id)?.completed || index < currentStepIndex;
|
||||
// For new tenant creation, only show completed if index is less than current step
|
||||
const isCompleted = isNewTenant
|
||||
? index < currentStepIndex
|
||||
: userProgress?.steps.find(s => s.step_name === step.id)?.completed || index < currentStepIndex;
|
||||
const isCurrent = index === currentStepIndex;
|
||||
|
||||
return (
|
||||
@@ -377,7 +444,10 @@ export const OnboardingWizard: React.FC = () => {
|
||||
{/* Desktop Step Indicators */}
|
||||
<div className="hidden sm:flex sm:justify-between">
|
||||
{STEPS.map((step, index) => {
|
||||
const isCompleted = userProgress?.steps.find(s => s.step_name === step.id)?.completed || index < currentStepIndex;
|
||||
// For new tenant creation, only show completed if index is less than current step
|
||||
const isCompleted = isNewTenant
|
||||
? index < currentStepIndex
|
||||
: userProgress?.steps.find(s => s.step_name === step.id)?.completed || index < currentStepIndex;
|
||||
const isCurrent = index === currentStepIndex;
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user