Enhance UI, add AI integration, improve logging and database stats

This commit is contained in:
Richard
2026-07-04 21:11:31 +02:00
parent 7a44914d9d
commit d102af2965
57 changed files with 4025 additions and 229 deletions
+41 -11
View File
@@ -149,7 +149,12 @@ async function api(endpoint) {
// ─── Format Helpers ───
const fmt = {
usd: v => { if (v === null || v === undefined) return '$0'; const n = Number(v); return n >= 1000000 ? `$${(n/1000000).toFixed(1)}M` : n >= 1000 ? `$${(n/1000).toFixed(1)}K` : `$${n.toFixed(0)}`; },
pct: v => { if (v === null || v === undefined) return '0%'; return `${Number(v).toFixed(1)}%`; },
pct: v => {
if (v === null || v === undefined) return '0%';
const n = Number(v);
const color = n > 55 ? 'var(--pnl-positive)' : n < 45 ? 'var(--pnl-negative)' : 'var(--text)';
return `<span style="color:${color};font-weight:${n>55||n<45?'600':'normal'};">${n.toFixed(1)}%</span>`;
},
num: v => { if (v === null || v === undefined) return '0'; return Number(v).toLocaleString(); },
time: v => { if (!v) return '—'; const d = new Date(v); const now = new Date(); const diff = (now - d) / 1000;
if (diff < 60) return `${Math.floor(diff)}s ago`;
@@ -207,15 +212,15 @@ async function loadDashboard() {
// Top Traders table
const tbody = document.getElementById('topTradersBody');
tbody.innerHTML = data.topTraders.map((t, i) => `
<tr onclick="viewTrader(${t.id})" style="cursor:pointer">
<td>${i + 1}</td>
<td><strong>${t.displayName}</strong></td>
<td>${t.platform}</td>
<td><strong>${Number(t.combinedScore).toFixed(1)}</strong></td>
<td>${fmt.pct(t.winRate)}</td>
<td>${fmt.pnl(t.totalPnl)}</td>
<td>${fmt.tier(t.tier)}</td>
<td>${fmt.num(t.totalTrades)}</td>
<tr>
<td onclick="viewTrader(${t.id})" style="cursor:pointer">${i + 1}</td>
<td><strong>${t.platform === 'Polymarket' ? `<a href="https://polymarket.com/profile/${t.platformUserId}" target="_blank" style="color:var(--text);text-decoration:underline;">${t.displayName}</a>` : t.displayName}</strong></td>
<td onclick="viewTrader(${t.id})" style="cursor:pointer">${t.platform}</td>
<td onclick="viewTrader(${t.id})" style="cursor:pointer"><strong>${Number(t.combinedScore).toFixed(1)}</strong></td>
<td onclick="viewTrader(${t.id})" style="cursor:pointer">${fmt.pct(t.winRate)}</td>
<td onclick="viewTrader(${t.id})" style="cursor:pointer">${fmt.pnl(t.totalPnl)}</td>
<td onclick="viewTrader(${t.id})" style="cursor:pointer">${fmt.tier(t.tier)}</td>
<td onclick="viewTrader(${t.id})" style="cursor:pointer">${fmt.num(t.totalTrades)}</td>
</tr>
`).join('');
@@ -282,7 +287,7 @@ async function loadTraders() {
tbody.innerHTML = data.map((t, i) => `
<tr>
<td>${i + 1}</td>
<td><strong>${t.displayName}</strong></td>
<td><strong>${t.platform === 'Polymarket' ? `<a href="https://polymarket.com/profile/${t.platformUserId}" target="_blank" style="color:var(--text);text-decoration:underline;">${t.displayName}</a>` : t.displayName}</strong></td>
<td>${t.platform}</td>
<td><strong>${Number(t.combinedScore).toFixed(1)}</strong></td>
<td>${fmt.pct(t.winRate)}</td>
@@ -350,10 +355,14 @@ async function viewTrader(id) {
document.getElementById('td-pnl').innerHTML = fmt.pnl(t.totalPnl);
document.getElementById('td-trades').textContent = fmt.num(t.totalTrades);
document.getElementById('td-score').textContent = Number(t.combinedScore).toFixed(1);
document.getElementById('td-ai-summary').textContent = t.aiStrategySummary || 'Not analyzed yet.';
const refreshBtn = document.getElementById('btn-refresh-trader');
refreshBtn.onclick = () => manualUpdateTrader(id);
const aiBtn = document.getElementById('btn-ai-analysis');
aiBtn.onclick = () => triggerAiAnalysis(id, true);
const tbody = document.getElementById('td-tradesBody');
tbody.innerHTML = t.recentTrades.map(tr => `
<tr>
@@ -428,3 +437,24 @@ setInterval(() => {
const activePage = document.querySelector('.page.active');
if (activePage?.id === 'page-dashboard') loadDashboard();
}, 30000);
async function triggerAiAnalysis(id, manual) {
const btn = document.getElementById('btn-ai-analysis');
const oldText = btn.textContent;
btn.textContent = 'Analyzing...';
btn.disabled = true;
try {
const res = await api(`/api/traders/${id}/ai-analysis?manual=${manual}`, { method: 'POST' });
if (res && res.summary) {
document.getElementById('td-ai-summary').textContent = res.summary;
} else {
alert('Analysis failed or returned empty.');
}
} catch (e) {
console.error(e);
alert('Analysis error: ' + e);
} finally {
btn.textContent = oldText;
btn.disabled = false;
}
}