Add new frontend - fix 21

This commit is contained in:
Urtzi Alfaro
2025-07-23 15:09:33 +02:00
parent f8aefa9abe
commit 96b728441a
3 changed files with 43 additions and 42 deletions

View File

@@ -82,7 +82,7 @@ export class DataService {
*/ */
async validateSalesData(file: File): Promise<DataValidation> { async validateSalesData(file: File): Promise<DataValidation> {
const response = await apiClient.upload<ApiResponse<DataValidation>>( const response = await apiClient.upload<ApiResponse<DataValidation>>(
'/api/v1/data/validate-sales', '/api/v1/sales/import/validate-sales',
file file
); );
return response.data!; return response.data!;

View File

@@ -6,14 +6,11 @@ import {
export interface TenantCreate { export interface TenantCreate {
name: string; name: string;
email: string;
phone: string;
address: string; address: string;
latitude?: number; city?: string; // Optional with default "Madrid"
longitude?: number; postal_code: string; // Required, must match pattern ^\d{5}$
business_type: 'individual_bakery' | 'central_workshop'; phone: string; // Required, validated for Spanish format
subscription_plan?: string; business_type?: string; // Optional with default "bakery", must be one of: ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant']
settings?: Record<string, any>;
} }
export interface TenantUpdate extends Partial<TenantCreate> { export interface TenantUpdate extends Partial<TenantCreate> {
@@ -66,13 +63,20 @@ export interface TenantStats {
subscription_expires: string; subscription_expires: string;
} }
export interface TenantUser { export interface TenantInfo {
id: string; id: string;
email: string; name: string;
full_name: string; subdomain?: string;
role: string; business_type: string;
address: string;
city: string;
postal_code: string;
phone?: string;
is_active: boolean; is_active: boolean;
last_login: string | null; subscription_tier: string;
model_trained: boolean;
last_training_date?: string;
owner_id: string;
created_at: string; created_at: string;
} }

View File

@@ -37,21 +37,15 @@ const OnboardingPage = () => {
password: '', password: '',
confirm_password: '', confirm_password: '',
// Bakery/Tenant fields - matching TenantCreate interface // Bakery/Tenant fields - matching ACTUAL BakeryRegistration schema
bakery_name: '', bakery_name: '',
address: '', address: '',
city: 'Madrid', city: 'Madrid', // Default as per backend
postal_code: '', postal_code: '', // Required - must match regex ^\d{5}$
phone: '', // Will use default if empty phone: '', // Will use default if empty, validated for Spanish format
business_type: 'individual_bakery' as 'individual_bakery' | 'central_workshop', business_type: 'bakery', // Must be one of: ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant']
// Optional fields // Additional form fields (not part of BakeryRegistration)
latitude: undefined as number | undefined,
longitude: undefined as number | undefined,
subscription_plan: undefined as string | undefined,
settings: undefined as Record<string, any> | undefined,
// Additional form fields
has_nearby_schools: false, has_nearby_schools: false,
has_nearby_offices: false, has_nearby_offices: false,
selected_products: ['Pan de molde', 'Croissants', 'Magdalenas'], selected_products: ['Pan de molde', 'Croissants', 'Magdalenas'],
@@ -150,17 +144,24 @@ const OnboardingPage = () => {
case 2: case 2:
if (!formData.bakery_name.trim()) newErrors.bakery_name = 'Nombre de panadería requerido'; if (!formData.bakery_name.trim()) newErrors.bakery_name = 'Nombre de panadería requerido';
if (!formData.address.trim()) newErrors.address = 'Dirección requerida'; if (!formData.address.trim()) newErrors.address = 'Dirección requerida';
if (!formData.postal_code.trim()) newErrors.postal_code = 'Código postal requerido'; if (!formData.postal_code.trim()) {
if (!formData.email.trim()) newErrors.email = 'Email requerido'; // Email is required for TenantCreate newErrors.postal_code = 'Código postal requerido';
} else if (!/^\d{5}$/.test(formData.postal_code)) {
newErrors.postal_code = 'Código postal debe tener 5 dígitos';
}
// Validate business_type is one of the allowed values // Validate business_type matches backend expectations
if (!['individual_bakery', 'central_workshop'].includes(formData.business_type)) { const validBusinessTypes = ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant'];
if (!validBusinessTypes.includes(formData.business_type)) {
newErrors.business_type = 'Tipo de negocio inválido'; newErrors.business_type = 'Tipo de negocio inválido';
} }
// Optional: Validate phone format if provided (will use default if empty) // Optional: Validate phone format if provided (Spanish format as per backend validator)
if (formData.phone && !formData.phone.match(/^(\+34|34)?[67][0-9]{8}$/)) { if (formData.phone && formData.phone.trim()) {
newErrors.phone = 'Formato de teléfono inválido'; const phoneRegex = /^(\+34|0034|34)?[6789]\d{8}$/;
if (!phoneRegex.test(formData.phone.replace(/[\s\-\(\)]/g, ''))) {
newErrors.phone = 'Formato de teléfono español inválido';
}
} }
break; break;
case 3: case 3:
@@ -192,16 +193,12 @@ const OnboardingPage = () => {
} else if (currentStep === 2) { } else if (currentStep === 2) {
// Register bakery using real tenant service with proper TenantCreate interface // Register bakery using real tenant service with proper TenantCreate interface
const bakeryData: TenantCreate = { const bakeryData: TenantCreate = {
name: formData.bakery_name, name: formData.bakery_name,
email: formData.email, // Required field from TenantCreate interface address: formData.address,
phone: formData.phone || '+34600000000', // Required field with default city: formData.city || 'Madrid', // Default value as per backend schema
address: formData.address, postal_code: formData.postal_code, // Required field
business_type: formData.business_type as 'individual_bakery' | 'central_workshop', phone: formData.phone || '+34600000000', // Required field with default
// Optional fields that could be added based on form data business_type: formData.business_type || 'bakery' // Must be one of: ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant']
latitude: formData.latitude, // if you have coordinates
longitude: formData.longitude, // if you have coordinates
subscription_plan: formData.subscription_plan, // if selected
settings: formData.settings // if any initial settings
}; };
// The response will be typed as TenantInfo // The response will be typed as TenantInfo