← back to Ken
src/app/dashboard/settings/page.js
131 lines
'use client';
import { useState, useEffect } from 'react';
export default function SettingsPage() {
const [health, setHealth] = useState(null);
const [testResult, setTestResult] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/health').then(r => r.json()).then(d => { setHealth(d); setLoading(false); }).catch(() => setLoading(false));
}, []);
async function testSlack() {
try {
const res = await fetch('/api/alerts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'test' }) });
const data = await res.json();
setTestResult(data);
} catch (err) { setTestResult({ error: err.message }); }
}
async function testNWS() {
try {
const res = await fetch('/api/weather', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'test_nws' }) });
const data = await res.json();
alert(data.success ? 'NWS API connected successfully!' : 'NWS API error: ' + (data.error || 'Unknown'));
} catch (err) { alert('Error: ' + err.message); }
}
async function testPolymarket() {
try {
const res = await fetch('/api/markets', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'test_api' }) });
const data = await res.json();
alert(data.success ? `Polymarket API connected! Found ${data.market_count} markets.` : 'API error: ' + (data.error || 'Unknown'));
} catch (err) { alert('Error: ' + err.message); }
}
async function runWorker(worker) {
try {
const res = await fetch('/api/workers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'run', worker }) });
const data = await res.json();
alert(data.message || JSON.stringify(data));
} catch (err) { alert('Error: ' + err.message); }
}
if (loading) return <div className="flex items-center justify-center h-64"><div className="animate-spin w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full" /></div>;
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold">Settings</h1>
<p className="text-gray-500 text-sm">System configuration and connectivity tests</p>
</div>
{/* System Status */}
<div className="card">
<h2 className="font-semibold mb-3">System Status</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
{[
{ label: 'Database', status: health?.db_connected, detail: 'PostgreSQL' },
{ label: 'NWS API', status: 'unknown', detail: 'api.weather.gov' },
{ label: 'Polymarket', status: 'unknown', detail: 'gamma-api.polymarket.com' },
{ label: 'Slack', status: health?.slack_configured ? 'ok' : 'no_token', detail: 'U03TV3UC2V7' },
].map(s => (
<div key={s.label} className="bg-gray-800/30 rounded-lg p-3">
<div className="flex items-center gap-2 mb-1">
<span className={`w-2 h-2 rounded-full ${s.status === true || s.status === 'ok' ? 'bg-green-500' : s.status === 'unknown' ? 'bg-yellow-500' : 'bg-red-500'}`} />
<span className="text-sm font-medium">{s.label}</span>
</div>
<p className="text-xs text-gray-500">{s.detail}</p>
</div>
))}
</div>
</div>
{/* Connectivity Tests */}
<div className="card">
<h2 className="font-semibold mb-3">Connectivity Tests</h2>
<div className="flex gap-3">
<button onClick={testNWS} className="btn btn-primary">Test NWS API</button>
<button onClick={testPolymarket} className="btn btn-primary">Test Polymarket</button>
<button onClick={testSlack} className="btn btn-primary">Test Slack Alert</button>
</div>
{testResult && (
<pre className="mt-3 bg-gray-900 rounded-lg p-3 text-xs text-gray-300 overflow-auto max-h-48">
{JSON.stringify(testResult, null, 2)}
</pre>
)}
</div>
{/* Manual Worker Triggers */}
<div className="card">
<h2 className="font-semibold mb-3">Manual Worker Triggers</h2>
<div className="flex flex-wrap gap-3">
<button onClick={() => runWorker('market_ingest')} className="btn btn-primary">Ingest Markets</button>
<button onClick={() => runWorker('weather_fetch')} className="btn btn-primary">Fetch Weather</button>
<button onClick={() => runWorker('run_predictions')} className="btn btn-primary">Run Predictions</button>
<button onClick={() => runWorker('risk_scan')} className="btn btn-primary">Risk Scan</button>
<button onClick={() => runWorker('paper_trade')} className="btn btn-primary">Paper Trade Cycle</button>
</div>
</div>
{/* Architecture Info */}
<div className="card">
<h2 className="font-semibold mb-3">Architecture</h2>
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<p className="text-gray-500 text-xs uppercase mb-2">Data Sources</p>
<ul className="space-y-1">
<li className="flex items-center gap-2"><span className="badge badge-blue">NWS</span> Live US forecasts (api.weather.gov)</li>
<li className="flex items-center gap-2"><span className="badge badge-purple">GEFS</span> Ensemble forecasts (AWS)</li>
<li className="flex items-center gap-2"><span className="badge badge-green">Gamma</span> Polymarket markets</li>
<li className="flex items-center gap-2"><span className="badge badge-yellow">CLOB</span> Orderbook data</li>
</ul>
</div>
<div>
<p className="text-gray-500 text-xs uppercase mb-2">Model Pipeline</p>
<ul className="space-y-1">
<li>1. Market parsing + event extraction</li>
<li>2. Ensemble exceedance probability</li>
<li>3. Climatological prior</li>
<li>4. Bayesian combination + calibration</li>
<li>5. Edge gate + risk sizing</li>
<li>6. Paper/live execution</li>
</ul>
</div>
</div>
</div>
</div>
);
}