404 lines
13 KiB
Plaintext
404 lines
13 KiB
Plaintext
|
|
import React from 'react';
|
|||
|
|
import { Input, Select, Badge } from '../../ui';
|
|||
|
|
import type { OnboardingStepProps } from './OnboardingWizard';
|
|||
|
|
|
|||
|
|
interface CompanyInfo {
|
|||
|
|
name: string;
|
|||
|
|
type: 'artisan' | 'industrial' | 'chain' | 'mixed';
|
|||
|
|
size: 'small' | 'medium' | 'large';
|
|||
|
|
locations: number;
|
|||
|
|
specialties: string[];
|
|||
|
|
address: {
|
|||
|
|
street: string;
|
|||
|
|
city: string;
|
|||
|
|
state: string;
|
|||
|
|
postal_code: string;
|
|||
|
|
country: string;
|
|||
|
|
};
|
|||
|
|
contact: {
|
|||
|
|
phone: string;
|
|||
|
|
email: string;
|
|||
|
|
website?: string;
|
|||
|
|
};
|
|||
|
|
established_year?: number;
|
|||
|
|
tax_id?: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const BAKERY_TYPES = [
|
|||
|
|
{ value: 'artisan', label: 'Artesanal', description: 'Producción tradicional y manual' },
|
|||
|
|
{ value: 'industrial', label: 'Industrial', description: 'Producción automatizada a gran escala' },
|
|||
|
|
{ value: 'chain', label: 'Cadena', description: 'Múltiples ubicaciones con procesos estandarizados' },
|
|||
|
|
{ value: 'mixed', label: 'Mixta', description: 'Combinación de métodos artesanales e industriales' },
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const BAKERY_SIZES = [
|
|||
|
|
{ value: 'small', label: 'Pequeña', description: '1-10 empleados' },
|
|||
|
|
{ value: 'medium', label: 'Mediana', description: '11-50 empleados' },
|
|||
|
|
{ value: 'large', label: 'Grande', description: '50+ empleados' },
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const COMMON_SPECIALTIES = [
|
|||
|
|
'Pan tradicional',
|
|||
|
|
'Bollería',
|
|||
|
|
'Repostería',
|
|||
|
|
'Pan integral',
|
|||
|
|
'Pasteles',
|
|||
|
|
'Productos sin gluten',
|
|||
|
|
'Productos veganos',
|
|||
|
|
'Pan artesanal',
|
|||
|
|
'Productos de temporada',
|
|||
|
|
'Catering',
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
export const CompanyInfoStep: React.FC<OnboardingStepProps> = ({
|
|||
|
|
data,
|
|||
|
|
onDataChange,
|
|||
|
|
}) => {
|
|||
|
|
const companyData: CompanyInfo = {
|
|||
|
|
name: '',
|
|||
|
|
type: 'artisan',
|
|||
|
|
size: 'small',
|
|||
|
|
locations: 1,
|
|||
|
|
specialties: [],
|
|||
|
|
address: {
|
|||
|
|
street: '',
|
|||
|
|
city: '',
|
|||
|
|
state: '',
|
|||
|
|
postal_code: '',
|
|||
|
|
country: 'España',
|
|||
|
|
},
|
|||
|
|
contact: {
|
|||
|
|
phone: '',
|
|||
|
|
email: '',
|
|||
|
|
website: '',
|
|||
|
|
},
|
|||
|
|
...data,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleInputChange = (field: string, value: any) => {
|
|||
|
|
onDataChange({
|
|||
|
|
...companyData,
|
|||
|
|
[field]: value,
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleAddressChange = (field: string, value: string) => {
|
|||
|
|
onDataChange({
|
|||
|
|
...companyData,
|
|||
|
|
address: {
|
|||
|
|
...companyData.address,
|
|||
|
|
[field]: value,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleContactChange = (field: string, value: string) => {
|
|||
|
|
onDataChange({
|
|||
|
|
...companyData,
|
|||
|
|
contact: {
|
|||
|
|
...companyData.contact,
|
|||
|
|
[field]: value,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const handleSpecialtyToggle = (specialty: string) => {
|
|||
|
|
const currentSpecialties = companyData.specialties || [];
|
|||
|
|
const updatedSpecialties = currentSpecialties.includes(specialty)
|
|||
|
|
? currentSpecialties.filter(s => s !== specialty)
|
|||
|
|
: [...currentSpecialties, specialty];
|
|||
|
|
|
|||
|
|
handleInputChange('specialties', updatedSpecialties);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="space-y-8">
|
|||
|
|
{/* Basic Information */}
|
|||
|
|
<div className="space-y-4">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
|||
|
|
Información básica
|
|||
|
|
</h3>
|
|||
|
|
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|||
|
|
<div className="md:col-span-2">
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Nombre de la panadería *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="text"
|
|||
|
|
value={companyData.name}
|
|||
|
|
onChange={(e) => handleInputChange('name', e.target.value)}
|
|||
|
|
placeholder="Ej: Panadería San Miguel"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Tipo de panadería *
|
|||
|
|
</label>
|
|||
|
|
<Select
|
|||
|
|
value={companyData.type}
|
|||
|
|
onChange={(e) => handleInputChange('type', e.target.value)}
|
|||
|
|
className="w-full"
|
|||
|
|
>
|
|||
|
|
{BAKERY_TYPES.map((type) => (
|
|||
|
|
<option key={type.value} value={type.value}>
|
|||
|
|
{type.label} - {type.description}
|
|||
|
|
</option>
|
|||
|
|
))}
|
|||
|
|
</Select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Tamaño de la empresa *
|
|||
|
|
</label>
|
|||
|
|
<Select
|
|||
|
|
value={companyData.size}
|
|||
|
|
onChange={(e) => handleInputChange('size', e.target.value)}
|
|||
|
|
className="w-full"
|
|||
|
|
>
|
|||
|
|
{BAKERY_SIZES.map((size) => (
|
|||
|
|
<option key={size.value} value={size.value}>
|
|||
|
|
{size.label} - {size.description}
|
|||
|
|
</option>
|
|||
|
|
))}
|
|||
|
|
</Select>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Número de ubicaciones
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="number"
|
|||
|
|
min="1"
|
|||
|
|
value={companyData.locations}
|
|||
|
|
onChange={(e) => handleInputChange('locations', parseInt(e.target.value) || 1)}
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Año de fundación
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="number"
|
|||
|
|
min="1900"
|
|||
|
|
max={new Date().getFullYear()}
|
|||
|
|
value={companyData.established_year || ''}
|
|||
|
|
onChange={(e) => handleInputChange('established_year', parseInt(e.target.value) || undefined)}
|
|||
|
|
placeholder="Ej: 1995"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
NIF/CIF
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="text"
|
|||
|
|
value={companyData.tax_id || ''}
|
|||
|
|
onChange={(e) => handleInputChange('tax_id', e.target.value)}
|
|||
|
|
placeholder="Ej: B12345678"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Specialties */}
|
|||
|
|
<div className="space-y-4">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
|||
|
|
Especialidades
|
|||
|
|
</h3>
|
|||
|
|
<p className="text-sm text-gray-600">
|
|||
|
|
Selecciona los productos que produces habitualmente
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
|||
|
|
{COMMON_SPECIALTIES.map((specialty) => (
|
|||
|
|
<button
|
|||
|
|
key={specialty}
|
|||
|
|
onClick={() => handleSpecialtyToggle(specialty)}
|
|||
|
|
className={`p-3 text-left border rounded-lg transition-colors ${
|
|||
|
|
companyData.specialties?.includes(specialty)
|
|||
|
|
? 'border-blue-500 bg-blue-50 text-blue-700'
|
|||
|
|
: 'border-gray-200 hover:border-gray-300'
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
<span className="text-sm font-medium">{specialty}</span>
|
|||
|
|
</button>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{companyData.specialties && companyData.specialties.length > 0 && (
|
|||
|
|
<div>
|
|||
|
|
<p className="text-sm font-medium text-gray-700 mb-2">
|
|||
|
|
Especialidades seleccionadas:
|
|||
|
|
</p>
|
|||
|
|
<div className="flex flex-wrap gap-2">
|
|||
|
|
{companyData.specialties.map((specialty) => (
|
|||
|
|
<Badge key={specialty} className="bg-blue-100 text-blue-800">
|
|||
|
|
{specialty}
|
|||
|
|
<button
|
|||
|
|
onClick={() => handleSpecialtyToggle(specialty)}
|
|||
|
|
className="ml-1 text-blue-600 hover:text-blue-800"
|
|||
|
|
>
|
|||
|
|
×
|
|||
|
|
</button>
|
|||
|
|
</Badge>
|
|||
|
|
))}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Address */}
|
|||
|
|
<div className="space-y-4">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
|||
|
|
Dirección principal
|
|||
|
|
</h3>
|
|||
|
|
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|||
|
|
<div className="md:col-span-2">
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Dirección *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="text"
|
|||
|
|
value={companyData.address.street}
|
|||
|
|
onChange={(e) => handleAddressChange('street', e.target.value)}
|
|||
|
|
placeholder="Calle, número, piso, puerta"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Ciudad *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="text"
|
|||
|
|
value={companyData.address.city}
|
|||
|
|
onChange={(e) => handleAddressChange('city', e.target.value)}
|
|||
|
|
placeholder="Ej: Madrid"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Provincia/Estado *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="text"
|
|||
|
|
value={companyData.address.state}
|
|||
|
|
onChange={(e) => handleAddressChange('state', e.target.value)}
|
|||
|
|
placeholder="Ej: Madrid"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Código postal *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="text"
|
|||
|
|
value={companyData.address.postal_code}
|
|||
|
|
onChange={(e) => handleAddressChange('postal_code', e.target.value)}
|
|||
|
|
placeholder="Ej: 28001"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
País *
|
|||
|
|
</label>
|
|||
|
|
<Select
|
|||
|
|
value={companyData.address.country}
|
|||
|
|
onChange={(e) => handleAddressChange('country', e.target.value)}
|
|||
|
|
className="w-full"
|
|||
|
|
>
|
|||
|
|
<option value="España">España</option>
|
|||
|
|
<option value="Francia">Francia</option>
|
|||
|
|
<option value="Portugal">Portugal</option>
|
|||
|
|
<option value="Italia">Italia</option>
|
|||
|
|
<option value="México">México</option>
|
|||
|
|
<option value="Argentina">Argentina</option>
|
|||
|
|
<option value="Colombia">Colombia</option>
|
|||
|
|
<option value="Otro">Otro</option>
|
|||
|
|
</Select>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Contact Information */}
|
|||
|
|
<div className="space-y-4">
|
|||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
|||
|
|
Información de contacto
|
|||
|
|
</h3>
|
|||
|
|
|
|||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Teléfono *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="tel"
|
|||
|
|
value={companyData.contact.phone}
|
|||
|
|
onChange={(e) => handleContactChange('phone', e.target.value)}
|
|||
|
|
placeholder="Ej: +34 911 234 567"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div>
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Email de contacto *
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="email"
|
|||
|
|
value={companyData.contact.email}
|
|||
|
|
onChange={(e) => handleContactChange('email', e.target.value)}
|
|||
|
|
placeholder="contacto@panaderia.com"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div className="md:col-span-2">
|
|||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
|||
|
|
Sitio web (opcional)
|
|||
|
|
</label>
|
|||
|
|
<Input
|
|||
|
|
type="url"
|
|||
|
|
value={companyData.contact.website || ''}
|
|||
|
|
onChange={(e) => handleContactChange('website', e.target.value)}
|
|||
|
|
placeholder="https://www.panaderia.com"
|
|||
|
|
className="w-full"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{/* Summary */}
|
|||
|
|
<div className="bg-gray-50 p-4 rounded-lg">
|
|||
|
|
<h4 className="font-medium text-gray-900 mb-2">Resumen</h4>
|
|||
|
|
<div className="text-sm text-gray-600 space-y-1">
|
|||
|
|
<p><strong>Panadería:</strong> {companyData.name || 'Sin especificar'}</p>
|
|||
|
|
<p><strong>Tipo:</strong> {BAKERY_TYPES.find(t => t.value === companyData.type)?.label}</p>
|
|||
|
|
<p><strong>Tamaño:</strong> {BAKERY_SIZES.find(s => s.value === companyData.size)?.label}</p>
|
|||
|
|
<p><strong>Especialidades:</strong> {companyData.specialties?.length || 0} seleccionadas</p>
|
|||
|
|
<p><strong>Ubicaciones:</strong> {companyData.locations}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default CompanyInfoStep;
|