import { useEffect, useState } from 'react' import { Blocks, AlertTriangle, PackageOpen } from 'lucide-react' import { adminApi } from '../../api/client' import { useTranslation } from '../../i18n' /** * Admin → Plugins (#plugins), M0 read-only scaffold. Lists installed plugins * from the registry table and shows whether the runtime is enabled * (TREK_PLUGINS_ENABLED). Install, activation and the registry browser arrive in * later milestones; this panel is intentionally inert. */ interface PluginRow { id: string name: string description: string | null type: string icon: string | null version: string | null status: string reviewed_at: string | null source_repo: string | null } const STATUS_CLASS: Record = { active: 'bg-emerald-500/15 text-emerald-600', inactive: 'bg-surface-tertiary text-content-muted', disabled: 'bg-amber-500/15 text-amber-600', error: 'bg-rose-500/15 text-rose-600', incompatible: 'bg-orange-500/15 text-orange-600', } export default function AdminPluginsPanel() { const { t } = useTranslation() const [enabled, setEnabled] = useState(false) const [plugins, setPlugins] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(false) useEffect(() => { let alive = true adminApi.plugins() .then((d: { enabled: boolean; plugins: PluginRow[] }) => { if (!alive) return setEnabled(!!d.enabled) setPlugins(d.plugins || []) }) .catch(() => { if (alive) setError(true) }) .finally(() => { if (alive) setLoading(false) }) return () => { alive = false } }, []) return (

{t('admin.plugins.title')}

{t('admin.plugins.subtitle')}

{!enabled && !loading && !error && (

{t('admin.plugins.disabledTitle')}

{t('admin.plugins.disabledBody')}

)}
{loading ? (
{t('common.loading')}
) : error ? (
{t('admin.plugins.loadError')}
) : plugins.length === 0 ? (

{t('admin.plugins.empty')}

) : (
{plugins.map(p => (
{p.name} {p.version && v{p.version}}
{p.description &&

{p.description}

}
{t(`admin.plugins.status.${p.status}` as never)}
))}
)}

{t('admin.plugins.scaffoldNote')}

) }