556 lines
19 KiB
Plaintext
556 lines
19 KiB
Plaintext
|
|
import React from 'react';
|
||
|
|
import { Card, Button, Input, Select, Badge } from '../../ui';
|
||
|
|
import type { OnboardingStepProps } from './OnboardingWizard';
|
||
|
|
|
||
|
|
interface SystemConfig {
|
||
|
|
timezone: string;
|
||
|
|
currency: string;
|
||
|
|
language: string;
|
||
|
|
date_format: string;
|
||
|
|
number_format: string;
|
||
|
|
working_hours: {
|
||
|
|
start: string;
|
||
|
|
end: string;
|
||
|
|
days: number[];
|
||
|
|
};
|
||
|
|
notifications: {
|
||
|
|
email_enabled: boolean;
|
||
|
|
sms_enabled: boolean;
|
||
|
|
push_enabled: boolean;
|
||
|
|
alert_preferences: string[];
|
||
|
|
};
|
||
|
|
integrations: {
|
||
|
|
pos_system?: string;
|
||
|
|
accounting_software?: string;
|
||
|
|
payment_provider?: string;
|
||
|
|
};
|
||
|
|
features: {
|
||
|
|
inventory_management: boolean;
|
||
|
|
production_planning: boolean;
|
||
|
|
sales_analytics: boolean;
|
||
|
|
customer_management: boolean;
|
||
|
|
financial_reporting: boolean;
|
||
|
|
quality_control: boolean;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const TIMEZONES = [
|
||
|
|
{ value: 'Europe/Madrid', label: 'Madrid (GMT+1)' },
|
||
|
|
{ value: 'Europe/London', label: 'London (GMT+0)' },
|
||
|
|
{ value: 'Europe/Paris', label: 'Paris (GMT+1)' },
|
||
|
|
{ value: 'America/New_York', label: 'New York (GMT-5)' },
|
||
|
|
{ value: 'America/Los_Angeles', label: 'Los Angeles (GMT-8)' },
|
||
|
|
{ value: 'America/Mexico_City', label: 'Mexico City (GMT-6)' },
|
||
|
|
{ value: 'America/Buenos_Aires', label: 'Buenos Aires (GMT-3)' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const CURRENCIES = [
|
||
|
|
{ value: 'EUR', label: 'Euro (€)', symbol: '€' },
|
||
|
|
{ value: 'USD', label: 'US Dollar ($)', symbol: '$' },
|
||
|
|
{ value: 'GBP', label: 'British Pound (£)', symbol: '£' },
|
||
|
|
{ value: 'MXN', label: 'Mexican Peso ($)', symbol: '$' },
|
||
|
|
{ value: 'ARS', label: 'Argentine Peso ($)', symbol: '$' },
|
||
|
|
{ value: 'COP', label: 'Colombian Peso ($)', symbol: '$' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const LANGUAGES = [
|
||
|
|
{ value: 'es', label: 'Español' },
|
||
|
|
{ value: 'en', label: 'English' },
|
||
|
|
{ value: 'fr', label: 'Français' },
|
||
|
|
{ value: 'pt', label: 'Português' },
|
||
|
|
{ value: 'it', label: 'Italiano' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const DAYS_OF_WEEK = [
|
||
|
|
{ value: 1, label: 'Lunes', short: 'L' },
|
||
|
|
{ value: 2, label: 'Martes', short: 'M' },
|
||
|
|
{ value: 3, label: 'Miércoles', short: 'X' },
|
||
|
|
{ value: 4, label: 'Jueves', short: 'J' },
|
||
|
|
{ value: 5, label: 'Viernes', short: 'V' },
|
||
|
|
{ value: 6, label: 'Sábado', short: 'S' },
|
||
|
|
{ value: 0, label: 'Domingo', short: 'D' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const ALERT_TYPES = [
|
||
|
|
{ value: 'low_stock', label: 'Stock bajo', description: 'Cuando los ingredientes están por debajo del mínimo' },
|
||
|
|
{ value: 'production_delays', label: 'Retrasos de producción', description: 'Cuando los lotes se retrasan' },
|
||
|
|
{ value: 'quality_issues', label: 'Problemas de calidad', description: 'Cuando se detectan problemas de calidad' },
|
||
|
|
{ value: 'financial_targets', label: 'Objetivos financieros', description: 'Cuando se alcanzan o no se cumplen objetivos' },
|
||
|
|
{ value: 'equipment_maintenance', label: 'Mantenimiento de equipos', description: 'Recordatorios de mantenimiento' },
|
||
|
|
{ value: 'food_safety', label: 'Seguridad alimentaria', description: 'Alertas relacionadas con seguridad alimentaria' },
|
||
|
|
];
|
||
|
|
|
||
|
|
const FEATURES = [
|
||
|
|
{
|
||
|
|
key: 'inventory_management',
|
||
|
|
title: 'Gestión de inventario',
|
||
|
|
description: 'Control de stock, ingredientes y materias primas',
|
||
|
|
recommended: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'production_planning',
|
||
|
|
title: 'Planificación de producción',
|
||
|
|
description: 'Programación de lotes y gestión de recetas',
|
||
|
|
recommended: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'sales_analytics',
|
||
|
|
title: 'Analytics de ventas',
|
||
|
|
description: 'Reportes y análisis de ventas y tendencias',
|
||
|
|
recommended: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'customer_management',
|
||
|
|
title: 'Gestión de clientes',
|
||
|
|
description: 'Base de datos de clientes y programa de fidelización',
|
||
|
|
recommended: false,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'financial_reporting',
|
||
|
|
title: 'Reportes financieros',
|
||
|
|
description: 'Análisis de costos, márgenes y rentabilidad',
|
||
|
|
recommended: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'quality_control',
|
||
|
|
title: 'Control de calidad',
|
||
|
|
description: 'Seguimiento de calidad y estándares',
|
||
|
|
recommended: true,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
export const SystemSetupStep: React.FC<OnboardingStepProps> = ({
|
||
|
|
data,
|
||
|
|
onDataChange,
|
||
|
|
}) => {
|
||
|
|
const systemData: SystemConfig = {
|
||
|
|
timezone: 'Europe/Madrid',
|
||
|
|
currency: 'EUR',
|
||
|
|
language: 'es',
|
||
|
|
date_format: 'DD/MM/YYYY',
|
||
|
|
number_format: 'European',
|
||
|
|
working_hours: {
|
||
|
|
start: '06:00',
|
||
|
|
end: '20:00',
|
||
|
|
days: [1, 2, 3, 4, 5, 6], // Monday to Saturday
|
||
|
|
},
|
||
|
|
notifications: {
|
||
|
|
email_enabled: true,
|
||
|
|
sms_enabled: false,
|
||
|
|
push_enabled: true,
|
||
|
|
alert_preferences: ['low_stock', 'production_delays', 'quality_issues'],
|
||
|
|
},
|
||
|
|
integrations: {},
|
||
|
|
features: {
|
||
|
|
inventory_management: true,
|
||
|
|
production_planning: true,
|
||
|
|
sales_analytics: true,
|
||
|
|
customer_management: false,
|
||
|
|
financial_reporting: true,
|
||
|
|
quality_control: true,
|
||
|
|
},
|
||
|
|
...data,
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleInputChange = (field: string, value: any) => {
|
||
|
|
onDataChange({
|
||
|
|
...systemData,
|
||
|
|
[field]: value,
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleWorkingHoursChange = (field: string, value: any) => {
|
||
|
|
onDataChange({
|
||
|
|
...systemData,
|
||
|
|
working_hours: {
|
||
|
|
...systemData.working_hours,
|
||
|
|
[field]: value,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleNotificationChange = (field: string, value: any) => {
|
||
|
|
onDataChange({
|
||
|
|
...systemData,
|
||
|
|
notifications: {
|
||
|
|
...systemData.notifications,
|
||
|
|
[field]: value,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleIntegrationChange = (field: string, value: string) => {
|
||
|
|
onDataChange({
|
||
|
|
...systemData,
|
||
|
|
integrations: {
|
||
|
|
...systemData.integrations,
|
||
|
|
[field]: value,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleFeatureToggle = (feature: string) => {
|
||
|
|
onDataChange({
|
||
|
|
...systemData,
|
||
|
|
features: {
|
||
|
|
...systemData.features,
|
||
|
|
[feature]: !systemData.features[feature as keyof typeof systemData.features],
|
||
|
|
},
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
const toggleWorkingDay = (day: number) => {
|
||
|
|
const currentDays = systemData.working_hours.days;
|
||
|
|
const updatedDays = currentDays.includes(day)
|
||
|
|
? currentDays.filter(d => d !== day)
|
||
|
|
: [...currentDays, day].sort();
|
||
|
|
|
||
|
|
handleWorkingHoursChange('days', updatedDays);
|
||
|
|
};
|
||
|
|
|
||
|
|
const toggleAlertPreference = (alert: string) => {
|
||
|
|
const current = systemData.notifications.alert_preferences;
|
||
|
|
const updated = current.includes(alert)
|
||
|
|
? current.filter(a => a !== alert)
|
||
|
|
: [...current, alert];
|
||
|
|
|
||
|
|
handleNotificationChange('alert_preferences', updated);
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="space-y-8">
|
||
|
|
{/* Regional Settings */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
||
|
|
Configuración regional
|
||
|
|
</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">
|
||
|
|
Zona horaria *
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.timezone}
|
||
|
|
onChange={(e) => handleInputChange('timezone', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
{TIMEZONES.map((tz) => (
|
||
|
|
<option key={tz.value} value={tz.value}>
|
||
|
|
{tz.label}
|
||
|
|
</option>
|
||
|
|
))}
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
|
|
Moneda *
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.currency}
|
||
|
|
onChange={(e) => handleInputChange('currency', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
{CURRENCIES.map((currency) => (
|
||
|
|
<option key={currency.value} value={currency.value}>
|
||
|
|
{currency.label}
|
||
|
|
</option>
|
||
|
|
))}
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
|
|
Idioma *
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.language}
|
||
|
|
onChange={(e) => handleInputChange('language', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
{LANGUAGES.map((lang) => (
|
||
|
|
<option key={lang.value} value={lang.value}>
|
||
|
|
{lang.label}
|
||
|
|
</option>
|
||
|
|
))}
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
|
|
Formato de fecha *
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.date_format}
|
||
|
|
onChange={(e) => handleInputChange('date_format', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
<option value="DD/MM/YYYY">DD/MM/YYYY</option>
|
||
|
|
<option value="MM/DD/YYYY">MM/DD/YYYY</option>
|
||
|
|
<option value="YYYY-MM-DD">YYYY-MM-DD</option>
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Working Hours */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
||
|
|
Horario de trabajo
|
||
|
|
</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">
|
||
|
|
Hora de apertura *
|
||
|
|
</label>
|
||
|
|
<Input
|
||
|
|
type="time"
|
||
|
|
value={systemData.working_hours.start}
|
||
|
|
onChange={(e) => handleWorkingHoursChange('start', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
|
|
Hora de cierre *
|
||
|
|
</label>
|
||
|
|
<Input
|
||
|
|
type="time"
|
||
|
|
value={systemData.working_hours.end}
|
||
|
|
onChange={(e) => handleWorkingHoursChange('end', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Días de operación *
|
||
|
|
</label>
|
||
|
|
<div className="flex flex-wrap gap-2">
|
||
|
|
{DAYS_OF_WEEK.map((day) => (
|
||
|
|
<button
|
||
|
|
key={day.value}
|
||
|
|
onClick={() => toggleWorkingDay(day.value)}
|
||
|
|
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||
|
|
systemData.working_hours.days.includes(day.value)
|
||
|
|
? 'bg-blue-500 text-white'
|
||
|
|
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
{day.short} - {day.label}
|
||
|
|
</button>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Features */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
||
|
|
Módulos y características
|
||
|
|
</h3>
|
||
|
|
<p className="text-sm text-gray-600">
|
||
|
|
Selecciona las características que quieres activar. Podrás cambiar esto más tarde.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
|
|
{FEATURES.map((feature) => (
|
||
|
|
<Card
|
||
|
|
key={feature.key}
|
||
|
|
className={`p-4 cursor-pointer transition-colors ${
|
||
|
|
systemData.features[feature.key as keyof typeof systemData.features]
|
||
|
|
? 'border-blue-500 bg-blue-50'
|
||
|
|
: 'border-gray-200 hover:border-gray-300'
|
||
|
|
}`}
|
||
|
|
onClick={() => handleFeatureToggle(feature.key)}
|
||
|
|
>
|
||
|
|
<div className="flex items-start justify-between">
|
||
|
|
<div className="flex-1">
|
||
|
|
<div className="flex items-center gap-2 mb-1">
|
||
|
|
<h4 className="font-medium text-gray-900">{feature.title}</h4>
|
||
|
|
{feature.recommended && (
|
||
|
|
<Badge className="bg-green-100 text-green-800 text-xs">
|
||
|
|
Recomendado
|
||
|
|
</Badge>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<p className="text-sm text-gray-600">{feature.description}</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className={`w-5 h-5 rounded border-2 flex items-center justify-center ${
|
||
|
|
systemData.features[feature.key as keyof typeof systemData.features]
|
||
|
|
? 'border-blue-500 bg-blue-500'
|
||
|
|
: 'border-gray-300'
|
||
|
|
}`}>
|
||
|
|
{systemData.features[feature.key as keyof typeof systemData.features] && (
|
||
|
|
<span className="text-white text-xs">✓</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</Card>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Notifications */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
||
|
|
Notificaciones
|
||
|
|
</h3>
|
||
|
|
|
||
|
|
<div className="space-y-4">
|
||
|
|
<div className="flex flex-wrap gap-4">
|
||
|
|
<label className="flex items-center">
|
||
|
|
<input
|
||
|
|
type="checkbox"
|
||
|
|
checked={systemData.notifications.email_enabled}
|
||
|
|
onChange={(e) => handleNotificationChange('email_enabled', e.target.checked)}
|
||
|
|
className="mr-2 rounded"
|
||
|
|
/>
|
||
|
|
Notificaciones por email
|
||
|
|
</label>
|
||
|
|
|
||
|
|
<label className="flex items-center">
|
||
|
|
<input
|
||
|
|
type="checkbox"
|
||
|
|
checked={systemData.notifications.push_enabled}
|
||
|
|
onChange={(e) => handleNotificationChange('push_enabled', e.target.checked)}
|
||
|
|
className="mr-2 rounded"
|
||
|
|
/>
|
||
|
|
Notificaciones push
|
||
|
|
</label>
|
||
|
|
|
||
|
|
<label className="flex items-center">
|
||
|
|
<input
|
||
|
|
type="checkbox"
|
||
|
|
checked={systemData.notifications.sms_enabled}
|
||
|
|
onChange={(e) => handleNotificationChange('sms_enabled', e.target.checked)}
|
||
|
|
className="mr-2 rounded"
|
||
|
|
/>
|
||
|
|
Notificaciones por SMS
|
||
|
|
</label>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||
|
|
Tipos de alertas que deseas recibir
|
||
|
|
</label>
|
||
|
|
<div className="space-y-2">
|
||
|
|
{ALERT_TYPES.map((alert) => (
|
||
|
|
<div
|
||
|
|
key={alert.value}
|
||
|
|
className={`p-3 border rounded-lg cursor-pointer transition-colors ${
|
||
|
|
systemData.notifications.alert_preferences.includes(alert.value)
|
||
|
|
? 'border-blue-500 bg-blue-50'
|
||
|
|
: 'border-gray-200 hover:border-gray-300'
|
||
|
|
}`}
|
||
|
|
onClick={() => toggleAlertPreference(alert.value)}
|
||
|
|
>
|
||
|
|
<div className="flex items-start justify-between">
|
||
|
|
<div>
|
||
|
|
<h5 className="font-medium text-gray-900">{alert.label}</h5>
|
||
|
|
<p className="text-sm text-gray-600">{alert.description}</p>
|
||
|
|
</div>
|
||
|
|
<div className={`w-5 h-5 rounded border-2 flex items-center justify-center ${
|
||
|
|
systemData.notifications.alert_preferences.includes(alert.value)
|
||
|
|
? 'border-blue-500 bg-blue-500'
|
||
|
|
: 'border-gray-300'
|
||
|
|
}`}>
|
||
|
|
{systemData.notifications.alert_preferences.includes(alert.value) && (
|
||
|
|
<span className="text-white text-xs">✓</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Integrations */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="text-lg font-semibold text-gray-900 border-b pb-2">
|
||
|
|
Integraciones (opcional)
|
||
|
|
</h3>
|
||
|
|
<p className="text-sm text-gray-600">
|
||
|
|
Estas integraciones se pueden configurar más tarde desde el panel de administración.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<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">
|
||
|
|
Sistema POS
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.integrations.pos_system || ''}
|
||
|
|
onChange={(e) => handleIntegrationChange('pos_system', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
<option value="">Seleccionar...</option>
|
||
|
|
<option value="square">Square</option>
|
||
|
|
<option value="shopify">Shopify POS</option>
|
||
|
|
<option value="toast">Toast</option>
|
||
|
|
<option value="lightspeed">Lightspeed</option>
|
||
|
|
<option value="other">Otro</option>
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
|
|
Software de contabilidad
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.integrations.accounting_software || ''}
|
||
|
|
onChange={(e) => handleIntegrationChange('accounting_software', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
<option value="">Seleccionar...</option>
|
||
|
|
<option value="sage">Sage</option>
|
||
|
|
<option value="contaplus">ContaPlus</option>
|
||
|
|
<option value="a3">A3 Software</option>
|
||
|
|
<option value="quickbooks">QuickBooks</option>
|
||
|
|
<option value="other">Otro</option>
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
|
|
Proveedor de pagos
|
||
|
|
</label>
|
||
|
|
<Select
|
||
|
|
value={systemData.integrations.payment_provider || ''}
|
||
|
|
onChange={(e) => handleIntegrationChange('payment_provider', e.target.value)}
|
||
|
|
className="w-full"
|
||
|
|
>
|
||
|
|
<option value="">Seleccionar...</option>
|
||
|
|
<option value="stripe">Stripe</option>
|
||
|
|
<option value="paypal">PayPal</option>
|
||
|
|
<option value="redsys">Redsys</option>
|
||
|
|
<option value="bizum">Bizum</option>
|
||
|
|
<option value="other">Otro</option>
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Summary */}
|
||
|
|
<div className="bg-gray-50 p-4 rounded-lg">
|
||
|
|
<h4 className="font-medium text-gray-900 mb-2">Configuración seleccionada</h4>
|
||
|
|
<div className="text-sm text-gray-600 space-y-1">
|
||
|
|
<p><strong>Zona horaria:</strong> {TIMEZONES.find(tz => tz.value === systemData.timezone)?.label}</p>
|
||
|
|
<p><strong>Moneda:</strong> {CURRENCIES.find(c => c.value === systemData.currency)?.label}</p>
|
||
|
|
<p><strong>Horario:</strong> {systemData.working_hours.start} - {systemData.working_hours.end}</p>
|
||
|
|
<p><strong>Días operativos:</strong> {systemData.working_hours.days.length} días por semana</p>
|
||
|
|
<p><strong>Módulos activados:</strong> {Object.values(systemData.features).filter(Boolean).length} de {Object.keys(systemData.features).length}</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default SystemSetupStep;
|