import { useState } from 'react' import { CheckCircle2, Lock, Zap, ChevronDown, Star, ArrowUpRight, Puzzle, } from 'lucide-react' import { cn } from '../lib/utils' import { MODULES_DATA } from '../data/modulesData' import { useModules } from '../contexts/ModulesContext' import type { ModuleDef } from '../data/modulesData' import type { ModuleStatus } from '../data/modulesData' // ─── Status config ──────────────────────────────────────────────────────────── const STATUS_CFG: Record = { active: { label: 'Подключён', pill: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-400' }, trial: { label: 'Пробный', pill: 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-400' }, inactive: { label: 'Не подключён', pill: 'bg-slate-100 text-slate-500 dark:bg-slate-700/60 dark:text-slate-400' }, } // ─── Card ───────────────────────────────────────────────────────────────────── function ModuleCard({ mod, status }: { mod: ModuleDef; status: ModuleStatus }) { const [open, setOpen] = useState(false) const Icon = mod.icon const cfg = STATUS_CFG[status] return (
{/* Header */}
{mod.name} {mod.badge && ( {mod.badge} )} {mod.sidebarItem && status === 'active' && ( В меню )}

{mod.tagline}

{cfg.label}
{/* Description */}

{mod.description}

{/* Stats */} {mod.stats && status !== 'inactive' && (
{mod.stats.map(s => (

{s.value}

{s.label}

))}
)} {/* Trial banner */} {status === 'trial' && mod.trialDays !== undefined && (
Пробный период: осталось{' '} {mod.trialDays} дней
)} {/* Sidebar hint for inactive modules with sidebar */} {mod.sidebarItem && status === 'inactive' && (
После подключения появится раздел «{mod.sidebarItem.label}» в боковом меню
)}
{/* Features accordion */}
{open && (
    {mod.features.map(f => (
  • {f}
  • ))}
)}
{/* Footer */}
₽ {mod.price.toLocaleString('ru-RU')} /мес
{status === 'active' && ( )} {status === 'trial' && ( )} {status === 'inactive' && ( )}
) } // ─── Page ───────────────────────────────────────────────────────────────────── export function ModulesPage() { const { statuses } = useModules() const activeCount = MODULES_DATA.filter(m => statuses[m.id] === 'active').length const trialCount = MODULES_DATA.filter(m => statuses[m.id] === 'trial').length const totalCount = MODULES_DATA.length return (
{/* Header */}

Модули

Дополнительные возможности для вашего отеля

{/* Summary */}
{[ { value: activeCount, label: 'Активных', sub: `из ${totalCount} доступных`, color: 'text-emerald-600 dark:text-emerald-400', }, { value: trialCount, label: 'На пробном периоде', sub: 'бесплатно до окончания', color: 'text-amber-500 dark:text-amber-400', }, { value: totalCount - activeCount - trialCount, label: 'Не подключено', sub: 'доступны к активации', color: 'text-slate-400 dark:text-slate-500', }, ].map(s => (
{s.value} {s.label}

{s.sub}

))}
{/* Grid */}
{MODULES_DATA.map(mod => ( ))}
{/* CTA */}

Нужен индивидуальный модуль?

Разработаем интеграцию под ваши задачи — CRM, программа лояльности, своя кассовая система.

) }