Add new frontend - fix 16

This commit is contained in:
Urtzi Alfaro
2025-07-23 07:26:04 +02:00
parent e6b0be0c95
commit 1d35912459
14 changed files with 588 additions and 169 deletions

View File

@@ -18,6 +18,13 @@ import { dataApi, TrainingRequest, TrainingTask } from '../api/services/api';
import { NotificationToast } from '../components/common/NotificationToast';
import { Product, defaultProducts } from '../components/common/ProductSelector';
import {
TenantCreate
} from '@/api/services';
import api from '@/api/services';
// Define the shape of the form data
interface OnboardingFormData {
// Step 1: User Registration
@@ -161,39 +168,66 @@ const OnboardingPage: React.FC = () => {
setErrors({}); // Clear previous errors
let newErrors: Partial<OnboardingFormData> = {};
// Validate current step before proceeding
if (currentStep === 1) {
if (!formData.full_name) newErrors.full_name = 'Nombre completo es requerido.';
if (!formData.email || !/\S+@\S+\.\S+/.test(formData.email)) newErrors.email = 'Email inválido.';
if (!formData.password || formData.password.length < 6) newErrors.password = 'La contraseña debe tener al menos 6 caracteres.';
if (formData.password !== formData.confirm_password) newErrors.confirm_password = 'Las contraseñas no coinciden.';
// Validate current step before proceeding
// In your handleNext function, for step 1 registration:
if (currentStep === 1) {
if (!formData.full_name) newErrors.full_name = 'Nombre completo es requerido.';
if (!formData.email || !/\S+@\S+\.\S+/.test(formData.email)) newErrors.email = 'Email inválido.';
if (!formData.password || formData.password.length < 6) newErrors.password = 'La contraseña debe tener al menos 6 caracteres.';
if (formData.password !== formData.confirm_password) newErrors.confirm_password = 'Las contraseñas no coinciden.';
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
setLoading(true);
setLoading(true);
try {
const registerData: RegisterData = {
full_name: formData.full_name,
email: formData.email,
password: formData.password,
};
console.log('📤 Sending registration request:', registerData);
// ✅ FIX: Better error handling for registration
try {
const registerData: RegisterData = {
full_name: formData.full_name,
email: formData.email,
password: formData.password,
};
// FIXED: Registration now handles tokens automatically - no auto-login needed!
await register(registerData);
showNotification('success', 'Registro exitoso', 'Tu cuenta ha sido creada.');
setCompletedSteps([...completedSteps, 1]);
} catch (err: any) {
newErrors.email = err.message || 'Error al registrar usuario.';
showNotification('error', 'Error de registro', newErrors.email);
setErrors(newErrors);
return;
} finally {
setLoading(false);
} catch (registrationError: any) {
console.error('❌ Registration failed:', registrationError);
// ✅ FIX: Handle specific error cases
if (registrationError.message?.includes('already exists')) {
// If user already exists, show a more helpful message
showNotification('info', 'Usuario existente', 'Ya tienes una cuenta. Has sido conectado automáticamente.');
setCompletedSteps([...completedSteps, 1]);
} else if (registrationError.message?.includes('Network error')) {
newErrors.email = 'Error de conexión. Verifica tu internet.';
showNotification('error', 'Error de conexión', newErrors.email);
setErrors(newErrors);
return;
} else {
// Other registration errors
newErrors.email = registrationError.message || 'Error al registrar usuario.';
showNotification('error', 'Error de registro', newErrors.email);
setErrors(newErrors);
return;
}
}
} else if (currentStep === 2) {
} catch (err: any) {
// This catch block should rarely be reached now
console.error('❌ Unexpected error:', err);
newErrors.email = 'Error inesperado. Inténtalo de nuevo.';
showNotification('error', 'Error inesperado', newErrors.email);
setErrors(newErrors);
return;
} finally {
setLoading(false);
}
} else if (currentStep === 2) {
if (!formData.bakery_name) newErrors.bakery_name = 'Nombre de la panadería es requerido.';
if (!formData.address) newErrors.address = 'Dirección es requerida.';
if (!formData.city) newErrors.city = 'Ciudad es requerida.';
@@ -205,7 +239,39 @@ const OnboardingPage: React.FC = () => {
return;
}
setCompletedSteps([...completedSteps, 2]);
setLoading(true);
try {
// Prepare data for tenant (bakery) registration
const tenantData: TenantCreate = {
name: formData.bakery_name,
email: formData.email, // Assuming tenant email is same as user email
phone: '', // Placeholder, add a field in UI if needed
address: `${formData.address}, ${formData.city}, ${formData.postal_code}`,
latitude: 0, // Placeholder, integrate with Nominatim if needed
longitude: 0, // Placeholder, integrate with Nominatim if needed
business_type: 'individual_bakery', // Default to individual_bakery
settings: {
has_nearby_schools: formData.has_nearby_schools,
has_nearby_offices: formData.has_nearby_offices,
city: formData.city,
selected_products: formData.selected_products.map(p => p.name),
}
};
console.log('📤 Sending tenant registration request:', tenantData);
// Call the tenant registration API
await api.tenant.registerBakery(tenantData);
showNotification('success', 'Panadería registrada', 'La información de tu panadería ha sido guardada.');
setCompletedSteps([...completedSteps, 2]);
} catch (err: any) {
console.error('❌ Tenant registration failed:', err);
showNotification('error', 'Error al registrar panadería', err.message || 'No se pudo registrar la información de la panadería.');
setLoading(false); // Stop loading on error
return; // Prevent moving to next step if registration fails
} finally {
setLoading(false); // Stop loading after attempt
}
} else if (currentStep === 3) {
if (!formData.salesFile) {
showNotification('warning', 'Archivo requerido', 'Debes subir un archivo de historial de ventas.');