import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import { Check, Star, ArrowRight, Package, TrendingUp, Settings, Loader, Users, MapPin, CheckCircle, Zap } from 'lucide-react'; import { Button, Card, Badge } from '../ui'; import { subscriptionService, type PlanMetadata, type SubscriptionTier, SUBSCRIPTION_TIERS } from '../../api'; import { getRegisterUrl } from '../../utils/navigation'; type BillingCycle = 'monthly' | 'yearly'; type DisplayMode = 'landing' | 'selection'; interface SubscriptionPricingCardsProps { mode?: DisplayMode; selectedPlan?: string; onPlanSelect?: (planKey: string) => void; showPilotBanner?: boolean; pilotCouponCode?: string; pilotTrialMonths?: number; className?: string; } export const SubscriptionPricingCards: React.FC = ({ mode = 'landing', selectedPlan, onPlanSelect, showPilotBanner = false, pilotCouponCode, pilotTrialMonths = 3, className = '' }) => { const { t } = useTranslation(); const [plans, setPlans] = useState | null>(null); const [billingCycle, setBillingCycle] = useState('monthly'); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { loadPlans(); }, []); const loadPlans = async () => { try { setLoading(true); setError(null); const availablePlans = await subscriptionService.fetchAvailablePlans(); setPlans(availablePlans.plans); } catch (err) { console.error('Failed to load plans:', err); setError('No se pudieron cargar los planes. Por favor, intenta nuevamente.'); } finally { setLoading(false); } }; const getPrice = (plan: PlanMetadata) => { return billingCycle === 'monthly' ? plan.monthly_price : plan.yearly_price; }; const getSavings = (plan: PlanMetadata) => { if (billingCycle === 'yearly') { return subscriptionService.calculateYearlySavings( plan.monthly_price, plan.yearly_price ); } return null; }; const getPlanIcon = (tier: SubscriptionTier) => { switch (tier) { case SUBSCRIPTION_TIERS.STARTER: return ; case SUBSCRIPTION_TIERS.PROFESSIONAL: return ; case SUBSCRIPTION_TIERS.ENTERPRISE: return ; default: return ; } }; const formatFeatureName = (feature: string): string => { const featureNames: Record = { 'inventory_management': 'Gestión de inventario', 'sales_tracking': 'Seguimiento de ventas', 'basic_recipes': 'Recetas básicas', 'production_planning': 'Planificación de producción', 'basic_reporting': 'Informes básicos', 'mobile_app_access': 'Acceso desde app móvil', 'email_support': 'Soporte por email', 'easy_step_by_step_onboarding': 'Onboarding guiado paso a paso', 'basic_forecasting': 'Pronósticos básicos', 'demand_prediction': 'Predicción de demanda IA', 'waste_tracking': 'Seguimiento de desperdicios', 'order_management': 'Gestión de pedidos', 'customer_management': 'Gestión de clientes', 'supplier_management': 'Gestión de proveedores', 'batch_tracking': 'Trazabilidad de lotes', 'expiry_alerts': 'Alertas de caducidad', 'advanced_analytics': 'Analíticas avanzadas', 'custom_reports': 'Informes personalizados', 'sales_analytics': 'Análisis de ventas', 'supplier_performance': 'Rendimiento de proveedores', 'waste_analysis': 'Análisis de desperdicios', 'profitability_analysis': 'Análisis de rentabilidad', 'weather_data_integration': 'Integración datos meteorológicos', 'traffic_data_integration': 'Integración datos de tráfico', 'multi_location_support': 'Soporte multi-ubicación', 'location_comparison': 'Comparación entre ubicaciones', 'inventory_transfer': 'Transferencias de inventario', 'batch_scaling': 'Escalado de lotes', 'recipe_feasibility_check': 'Verificación de factibilidad', 'seasonal_patterns': 'Patrones estacionales', 'longer_forecast_horizon': 'Horizonte de pronóstico extendido', 'pos_integration': 'Integración POS', 'accounting_export': 'Exportación contable', 'basic_api_access': 'Acceso API básico', 'priority_email_support': 'Soporte prioritario por email', 'phone_support': 'Soporte telefónico', 'scenario_modeling': 'Modelado de escenarios', 'what_if_analysis': 'Análisis what-if', 'risk_assessment': 'Evaluación de riesgos', 'full_api_access': 'Acceso completo API', 'unlimited_webhooks': 'Webhooks ilimitados', 'erp_integration': 'Integración ERP', 'custom_integrations': 'Integraciones personalizadas', 'sso_saml': 'SSO/SAML', 'advanced_permissions': 'Permisos avanzados', 'audit_logs_export': 'Exportación de logs de auditoría', 'compliance_reports': 'Informes de cumplimiento', 'dedicated_account_manager': 'Gestor de cuenta dedicado', 'priority_support': 'Soporte prioritario', 'support_24_7': 'Soporte 24/7', 'custom_training': 'Formación personalizada' }; return featureNames[feature] || feature.replace(/_/g, ' '); }; const handlePlanAction = (tier: string, plan: PlanMetadata) => { if (mode === 'selection' && onPlanSelect) { onPlanSelect(tier); } }; if (loading) { return (
Cargando planes...
); } if (error || !plans) { return (

{error}

); } return (
{/* Pilot Program Banner */} {showPilotBanner && pilotCouponCode && mode === 'selection' && (

Programa Piloto Activo

Como participante del programa piloto, obtienes {pilotTrialMonths} meses completamente gratis en el plan que elijas, más un 20% de descuento de por vida si decides continuar.

)} {/* Billing Cycle Toggle */}
{/* Plans Grid */}
{Object.entries(plans).map(([tier, plan]) => { const price = getPrice(plan); const savings = getSavings(plan); const isPopular = plan.popular; const tierKey = tier as SubscriptionTier; const isSelected = mode === 'selection' && selectedPlan === tier; const CardWrapper = mode === 'landing' ? Link : 'div'; const cardProps = mode === 'landing' ? { to: plan.contact_sales ? '/contact' : getRegisterUrl(tier) } : { onClick: () => handlePlanAction(tier, plan) }; return ( {/* Popular Badge */} {isPopular && (
Más Popular
)} {/* Icon */}
{getPlanIcon(tierKey)}
{/* Header */}

{plan.name}

{plan.tagline}

{/* Pricing */}
{subscriptionService.formatPrice(price)} /{billingCycle === 'monthly' ? 'mes' : 'año'}
{/* Savings Badge */} {savings && (
Ahorra {subscriptionService.formatPrice(savings.savingsAmount)}/año
)} {/* Trial Badge */} {!savings && (
3 meses gratis
)}
{/* Key Limits */}
Usuarios: {plan.limits.users || 'Ilimitado'}
Ubicaciones: {plan.limits.locations || 'Ilimitado'}
Productos: {plan.limits.products || 'Ilimitado'}
Pronósticos/día: {plan.limits.forecasts_per_day || 'Ilimitado'}
{/* Features List */}
{plan.features.slice(0, 8).map((feature) => (
{formatFeatureName(feature)}
))} {plan.features.length > 8 && (

Y {plan.features.length - 8} características más...

)}
{/* Support */}
{plan.support}
{/* CTA Button */} {mode === 'landing' ? ( ) : ( )}

3 meses gratis • Tarjeta requerida para validación

); })}
); };