import { useCallback, useState } from 'react' import { Loading, ErrorState } from '../../../components/PageState.jsx' import { useAsync } from '../../../lib/useAsync.js' import { ago, dateTime } from '../../../lib/format.js' import { api } from '../../../api/client.js' import { useSite } from '../../../contexts/SiteContext.jsx' export default function Dashboard() { const { refresh: refreshSite } = useSite() const [tick, setTick] = useState(0) const reload = useCallback(() => setTick((t) => t + 1), []) const { loading, error, data } = useAsync( () => Promise.all([api.admin.dashboard(), api.admin.listPosts(), api.admin.listWiki()]), [tick], ) const [busy, setBusy] = useState(false) if (loading) return if (error) return const [dash, posts, wiki] = data const mode = dash.site_mode || 'live' const isLive = mode === 'live' const modeDot = isLive ? 'var(--mode-live)' : 'var(--mode-maint)' const published = posts.filter((p) => p.published).length const stats = [ { value: published, label: 'Published posts' }, { value: posts.length - published, label: 'Drafts' }, { value: wiki.length, label: 'Wiki pages' }, { value: dash.counts?.users ?? 0, label: 'Users' }, ] async function toggle() { setBusy(true) try { await api.admin.setSiteMode(isLive ? 'maintenance' : 'live') await refreshSite() reload() } finally { setBusy(false) } } const changed = dash.last_change || {} return ( Site mode {mode} {changed.by ? `Changed by ${changed.by}` : 'No changes recorded'} {changed.at ? ` · ${dateTime(changed.at)}` : ''} {busy ? 'Saving…' : isLive ? 'Switch to Maintenance' : 'Switch to Live'} {stats.map((s) => ( {s.value} {s.label} ))} Recent activity {(dash.recent_activity || []).length === 0 && ( No activity yet. )} {(dash.recent_activity || []).map((a) => ( {a.action} {formatDetail(a)} {ago(a.created_at)} ))} ) } // Render the JSON `detail` column in a human-ish way. export function formatDetail(a) { if (!a.detail) return a.username ? `by ${a.username}` : '—' try { const obj = JSON.parse(a.detail) return Object.entries(obj) .map(([k, v]) => `${k}: ${v}`) .join(', ') } catch { return a.detail } }