import React, { useState } from 'react'; import { Badge, Button, Card, EmptyState, Spinner, useToast, } from '@cameleer/design-system'; import { Copy } from 'lucide-react'; import { useAuth } from '../auth/useAuth'; import { useLicense } from '../api/hooks'; import styles from '../styles/platform.module.css'; import { tierColor } from '../utils/tier'; const FEATURE_LABELS: Record = { topology: 'Topology', lineage: 'Lineage', correlation: 'Correlation', debugger: 'Debugger', replay: 'Replay', }; const LIMIT_LABELS: Record = { max_agents: 'Max Agents', retention_days: 'Retention Days', max_environments: 'Max Environments', }; function daysRemaining(expiresAt: string): number { const now = Date.now(); const exp = new Date(expiresAt).getTime(); return Math.max(0, Math.ceil((exp - now) / (1000 * 60 * 60 * 24))); } export function LicensePage() { const { tenantId } = useAuth(); const { data: license, isLoading, isError } = useLicense(tenantId ?? ''); const [tokenExpanded, setTokenExpanded] = useState(false); const { toast } = useToast(); if (isLoading) { return (
); } if (!tenantId) { return ( ); } if (isError || !license) { return ( ); } const expDate = new Date(license.expiresAt).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric', }); const days = daysRemaining(license.expiresAt); const isExpiringSoon = days <= 30; const isExpired = days === 0; return (
{/* Header */}

License

{/* Expiry info */}
Issued {new Date(license.issuedAt).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric', })}
Expires {expDate}
Days remaining
{/* Feature matrix */}
{Object.entries(FEATURE_LABELS).map(([key, label]) => { const enabled = license.features[key] ?? false; return (
{label}
); })}
{/* Limits */}
{Object.entries(LIMIT_LABELS).map(([key, label]) => { const value = license.limits[key]; return (
{label} {value !== undefined ? value : '—'}
); })}
{/* License token */}

Use this token when registering Cameleer agents with your tenant.

{tokenExpanded && ( )}
{tokenExpanded && (
{license.token}
)}
); }