import { useEffect, useState } from 'react'; import { Wallet, CreditCard, Building2, Check, Smartphone, Users, UserPlus, Trash2 } from 'lucide-react'; import { PageHeader } from '@/components/PageHeader'; import { Card, CardHeader, Badge } from '@/components/ui/primitives'; import { KpiCard } from '@/components/ui/KpiCard'; import { cn, fmt } from '@/lib/utils'; import { apiGet, apiPost, apiDelete } from '@/api/client'; import { useAuth } from '@/core/store'; interface Billing { clientId: string; balance: number; currency: string; plan: string; devices: number; } const AMOUNTS = [300, 500, 1000, 3000]; export function CabinetModule() { const user = useAuth((s) => s.user); const [b, setB] = useState(null); const [amount, setAmount] = useState(500); const [busy, setBusy] = useState(false); const [links, setLinks] = useState([]); const [newEmail, setNewEmail] = useState(''); useEffect(() => { apiGet('/billing').then(setB).catch(() => {}); apiGet('/cabinet/links').then(setLinks).catch(() => {}); }, []); const addLink = async () => { const e = newEmail.trim(); if (!e) return; const r = await apiPost('/cabinet/links', { email: e }); setLinks(r || []); setNewEmail(''); }; const removeLink = async (email: string) => { const r = await apiDelete(`/cabinet/links/${encodeURIComponent(email)}`); setLinks(r || []); }; const topup = async (method: 'yoomoney' | 'sberbank') => { setBusy(true); try { const r = await apiPost<{ payUrl: string }>('/billing/topup', { amount, method }); if (r?.payUrl) window.open(r.payUrl, '_blank', 'noopener'); } finally { setBusy(false); } }; return (
кабинет: {user.clientId}} />
{AMOUNTS.map((a) => ( ))} setAmount(Math.max(0, Number(e.target.value)))} className="tnum w-28 rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-fg outline-none focus:border-accent" />

⚠️ Демо-заглушка: реальное списание не происходит, открывается тестовая форма оплаты. Боевая интеграция ЮMoney/Сбербанк — по плану.

{['GPS-мониторинг своего автопарка', 'Привязка трекеров по IMEI', 'Треки, поездки, геозоны', 'Отчёты CSV/PDF', 'Уведомления и «Рация»'].map((f) => (
{f}
))}
Тариф {b?.plan ?? '—'}. Расширенные модули (Энерго / Смарт / Сеть) подключает администратор.
{/* Связанные аккаунты — общий кабинет для нескольких Яндекс-входов */} Связанные аккаунты} desc="добавьте e-mail коллеги — при входе через Яндекс он попадёт в этот же кабинет (общие объекты и устройства)" right={{links.length}} />
setNewEmail(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && addLink()} type="email" placeholder="e-mail Яндекс-аккаунта" className="flex-1 rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-fg outline-none placeholder:text-fg-muted focus:border-accent" />
{links.length === 0 ? (

Связанных аккаунтов нет. Кабинет доступен только вам ({user.name}).

) : (
{links.map((e) => (
{e.slice(0, 2).toUpperCase()} {e} кабинет: {user.clientId}
))}
)}

Связанный аккаунт видит те же объекты, устройства и данные, но не является администратором. Отвязка — кнопкой корзины.

); }