feat: Add category performance, update WebUI and OpenRouter integration, fix bugs
This commit is contained in:
@@ -213,12 +213,12 @@ async function loadDashboard() {
|
||||
const tbody = document.getElementById('topTradersBody');
|
||||
tbody.innerHTML = data.topTraders.map((t, i) => `
|
||||
<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">${i + 1}</td>
|
||||
<td><strong><a href="#" onclick="viewTrader(${t.id}); return false;" style="color:var(--primary);text-decoration:none;">${t.displayName}</a></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>
|
||||
@@ -231,7 +231,7 @@ async function loadDashboard() {
|
||||
<td>${fmt.time(t.executedAt)}</td>
|
||||
<td onclick="viewTrader(${t.traderId})" style="cursor:pointer; color:var(--primary)">${t.traderName}</td>
|
||||
<td onclick="${t.dbMarketId ? `viewMarket(${t.dbMarketId})` : `''`}" style="cursor:${t.dbMarketId ? 'pointer' : 'default'}" title="Market ID: ${t.marketId}">
|
||||
${t.dbMarketId ? `<span style="color:var(--primary)">Market #${t.dbMarketId}</span>` : (t.marketId ? t.marketId.substring(0, 12) + '...' : '—')}
|
||||
${t.marketName || (t.marketId.length > 20 ? t.marketId.substring(0,20)+'...' : t.marketId)}
|
||||
</td>
|
||||
<td>${fmt.side(t.side)}</td>
|
||||
<td>${Number(t.price).toFixed(2)}</td>
|
||||
@@ -287,7 +287,7 @@ async function loadTraders() {
|
||||
tbody.innerHTML = data.map((t, i) => `
|
||||
<tr>
|
||||
<td>${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><strong><a href="#" onclick="viewTrader(${t.id}); return false;" style="color:var(--primary);text-decoration:none;">${t.displayName}</a></strong></td>
|
||||
<td>${t.platform}</td>
|
||||
<td><strong>${Number(t.combinedScore).toFixed(1)}</strong></td>
|
||||
<td>${fmt.pct(t.winRate)}</td>
|
||||
@@ -351,7 +351,7 @@ async function viewTrader(id) {
|
||||
document.getElementById('td-platformId').textContent = t.platformUserId;
|
||||
document.getElementById('td-tier').innerHTML = fmt.tier(t.tier);
|
||||
document.getElementById('td-strategy').textContent = t.strategy;
|
||||
document.getElementById('td-winrate').textContent = fmt.pct(t.winRate);
|
||||
document.getElementById('td-winrate').innerHTML = fmt.pct(t.winRate);
|
||||
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);
|
||||
@@ -363,13 +363,45 @@ async function viewTrader(id) {
|
||||
const aiBtn = document.getElementById('btn-ai-analysis');
|
||||
aiBtn.onclick = () => triggerAiAnalysis(id, true);
|
||||
|
||||
const wlBtn = document.getElementById('btn-toggle-watchlist');
|
||||
wlBtn.textContent = t.isOnWatchlist ? '★ Watchlist (Remove)' : '☆ Watchlist (Add)';
|
||||
wlBtn.onclick = async () => {
|
||||
const method = t.isOnWatchlist ? 'DELETE' : 'POST';
|
||||
await api(`/api/traders/${id}/watchlist`, { method });
|
||||
viewTrader(id); // Reload to update UI
|
||||
};
|
||||
|
||||
const openBtn = document.getElementById('btn-open-platform');
|
||||
if (t.platform === 'Polymarket') {
|
||||
openBtn.style.display = 'inline-block';
|
||||
openBtn.textContent = 'Open on Polymarket';
|
||||
openBtn.onclick = () => window.open(`https://polymarket.com/profile/${t.platformUserId}`, '_blank');
|
||||
} else {
|
||||
openBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
const catBody = document.getElementById('td-categoryBody');
|
||||
if (t.categoryPerformances && t.categoryPerformances.length > 0) {
|
||||
catBody.innerHTML = t.categoryPerformances.map(c => `
|
||||
<tr>
|
||||
<td>${c.category}</td>
|
||||
<td>${fmt.pct(c.winRate)}</td>
|
||||
<td>${fmt.pnl(c.totalPnL)}</td>
|
||||
<td>${fmt.usd(c.totalVolume)}</td>
|
||||
<td>${fmt.num(c.totalTrades)}</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
} else {
|
||||
catBody.innerHTML = '<tr><td colspan="5" style="text-align:center; padding:16px; color:var(--text-muted)">No category data available</td></tr>';
|
||||
}
|
||||
|
||||
const tbody = document.getElementById('td-tradesBody');
|
||||
tbody.innerHTML = t.recentTrades.map(tr => `
|
||||
<tr>
|
||||
<td>${fmt.time(tr.executedAt)}</td>
|
||||
<td onclick="${tr.dbMarketId ? `viewMarket(${tr.dbMarketId})` : `''`}" style="cursor:${tr.dbMarketId ? 'pointer' : 'default'}; color:${tr.dbMarketId ? 'var(--primary)' : 'inherit'}" title="Market ID: ${tr.marketId}">
|
||||
${tr.dbMarketId ? `Market #${tr.dbMarketId}` : (tr.marketId ? tr.marketId.substring(0, 16) + '...' : '—')}
|
||||
</td>
|
||||
<td onclick="${tr.dbMarketId ? `viewMarket(${tr.dbMarketId})` : `''`}" style="cursor:${tr.dbMarketId ? 'pointer' : 'default'}; color:${tr.dbMarketId ? 'var(--primary)' : 'inherit'}" title="Market ID: ${tr.marketId}">
|
||||
${tr.marketName || (tr.marketId.length > 20 ? tr.marketId.substring(0,20)+'...' : tr.marketId)}
|
||||
</td>
|
||||
<td>${fmt.side(tr.side)}</td>
|
||||
<td>${Number(tr.price).toFixed(2)}</td>
|
||||
<td>${fmt.num(tr.size)}</td>
|
||||
|
||||
Reference in New Issue
Block a user