import { useEffect, useState } from 'react' import { apiFetch } from '@core/lib/api' interface HealthRecord { id: string title: string data: { temperature?: 'green' | 'yellow' | 'red'; churn_risk_score?: number; adoption_score?: number; nps_score?: number; notes?: string } created_at: string } const TEMP_STYLE: Record = { green: { bg: 'bg-green-50', text: 'text-green-700', dot: 'bg-green-500', label: 'Healthy' }, yellow: { bg: 'bg-yellow-50', text: 'text-yellow-700', dot: 'bg-yellow-500', label: 'At Risk' }, red: { bg: 'bg-red-50', text: 'text-red-700', dot: 'bg-red-500', label: 'Critical' }, } function ScoreBar({ label, value }: { label: string; value?: number }) { if (value == null) return null const pct = Math.min(100, Math.max(0, value)) const color = pct >= 70 ? 'bg-green-500' : pct >= 40 ? 'bg-yellow-500' : 'bg-red-500' return (
{label}
{value}
) } export default function HealthPage() { const [records, setRecords] = useState([]) const [loading, setLoading] = useState(true) const [filter, setFilter] = useState<'all' | 'green' | 'yellow' | 'red'>('all') useEffect(() => { apiFetch('/api/admin-data?action=list&entity=items&type_slug=csm_health&limit=200') .then(r => r.json()) .then(json => setRecords(Array.isArray(json?.data) ? json.data : json || [])) .catch(() => setRecords([])) .finally(() => setLoading(false)) }, []) const filtered = filter === 'all' ? records : records.filter(r => r.data?.temperature === filter) const counts = { green: records.filter(r => r.data?.temperature === 'green').length, yellow: records.filter(r => r.data?.temperature === 'yellow').length, red: records.filter(r => r.data?.temperature === 'red').length } return (

Customer Health

CSM health records across accounts

{(['green', 'yellow', 'red'] as const).map(temp => { const s = TEMP_STYLE[temp] return ( ) })}
{loading ? (
Loading health records…
) : filtered.length === 0 ? (
No health records {filter !== 'all' ? `with ${filter} status` : 'yet'}.
) : filtered.map(record => { const temp = record.data?.temperature || 'green' const s = TEMP_STYLE[temp] return (
{record.title}
{s.label}
{record.data?.nps_score != null && (
NPS: {record.data.nps_score}
)} {record.data?.notes && (
{record.data.notes}
)}
) })}
) }