CryptoFox-Mukan-Edition/src/web/positions.html
Mukan Erkin 64806dd32e feat(mse): minijinja template engine, shared header partial
- tmpl.rs: OnceLock ile build-time compile edilmiş minijinja env
- _header.html: ortak header partial — logo, nav (active_page değişkeni), mode-toggle, çıkış
- index.html, bots.html, positions.html: hardcoded header → {% include "_header.html" %}
- bots.html: + Yeni Bot butonu header'dan page-toolbar'a taşındı

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 20:26:15 +03:00

128 lines
6.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pozisyonlar — CryptoFox Mukan Edition</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #0f0f13; --surface: #1a1a22; --border: #2a2a38;
--text: #e0e0f0; --muted: #666; --accent: #6c63ff;
--green: #2ecc71; --red: #e74c3c; --yellow: #f39c12;
}
body { background: var(--bg); color: var(--text); font-family: 'Segoe UI', system-ui, sans-serif; font-size: 14px; min-height: 100vh; }
header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 0 24px; height: 52px; display: flex; align-items: center; gap: 16px; }
.logo { font-size: 16px; font-weight: 700; }
.logo-crypto { color: #d0d0d0; } .logo-fox { color: #00d4ff; }
.h-sep { width: 1px; height: 20px; background: var(--border); }
nav { display: flex; gap: 4px; }
.nav-link { padding: 5px 12px; border-radius: 5px; font-size: 13px; color: var(--muted); text-decoration: none; transition: all .15s; }
.nav-link:hover { color: var(--text); background: rgba(255,255,255,.05); }
.nav-link.active { color: var(--text); background: rgba(108,99,255,.15); }
.spacer { flex: 1; }
.btn { padding: 5px 12px; border-radius: 5px; border: 1px solid var(--border); background: transparent; color: var(--text); font-size: 12px; cursor: pointer; transition: all .15s; }
.btn-logout { border-color: var(--red); color: var(--red); font-size: 12px; }
.btn-logout:hover { background: rgba(231,76,60,.1); }
.mode-toggle { display: flex; align-items: center; gap: 4px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 3px; }
.mode-btn { padding: 3px 12px; border-radius: 4px; border: none; background: transparent; color: var(--muted); font-size: 11px; font-weight: 600; cursor: pointer; transition: all .15s; }
.mode-btn.active-live { background: rgba(46,204,113,.15); color: var(--green); }
.mode-btn.active-testnet { background: rgba(243,156,18,.15); color: var(--yellow); }
main { padding: 24px; max-width: 1400px; margin: 0 auto; display: flex; flex-direction: column; gap: 24px; }
section { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.section-header { padding: 14px 18px; border-bottom: 1px solid var(--border); font-weight: 600; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px 18px; text-align: left; border-bottom: 1px solid var(--border); }
th { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 500; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: rgba(255,255,255,.02); }
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.badge-filled { background: rgba(46,204,113,.15); color: var(--green); }
.badge-new { background: rgba(108,99,255,.15); color: var(--accent); }
.badge-canceled { background: rgba(136,136,136,.1); color: var(--muted); }
.empty { padding: 24px 18px; color: var(--muted); font-size: 13px; text-align: center; }
</style>
</head>
<body>
{% include "_header.html" %}
<main>
<section>
<div class="section-header">ık Pozisyonlar</div>
<table>
<thead><tr><th>Bot</th><th>Sembol</th><th>Alış</th><th>Hedef</th><th>Miktar</th><th>Zaman</th></tr></thead>
<tbody id="open-body"><tr><td colspan="6" class="empty">Yükleniyor...</td></tr></tbody>
</table>
</section>
<section>
<div class="section-header">Kapalı İşlemler</div>
<table>
<thead><tr><th>Bot</th><th>Sembol</th><th>Alış</th><th>Hedef</th><th>Miktar</th><th>Durum</th><th>Kapanış</th></tr></thead>
<tbody id="closed-body"><tr><td colspan="7" class="empty">Yükleniyor...</td></tr></tbody>
</table>
</section>
</main>
<script>
async function api(method, path) {
const res = await fetch('/api' + path, { method, credentials: 'include' });
if (res.status === 401) { window.location.href = '/'; throw new Error('Unauthorized'); }
return res;
}
function fmt(n, d=2) { return parseFloat(n).toLocaleString('tr-TR', { minimumFractionDigits: d, maximumFractionDigits: d }); }
function ts(ms) { return new Date(ms).toLocaleString('tr-TR'); }
async function loadMode() {
const res = await api('GET', '/mode');
if (!res.ok) return;
const { mode } = await res.json();
document.getElementById('btn-live').className = 'mode-btn' + (mode === 'live' ? ' active-live' : '');
document.getElementById('btn-testnet').className = 'mode-btn' + (mode === 'testnet' ? ' active-testnet' : '');
}
async function loadOpen() {
const res = await api('GET', '/positions');
const tbody = document.getElementById('open-body');
if (!res.ok) { tbody.innerHTML = '<tr><td colspan="6" class="empty">Yüklenemedi</td></tr>'; return; }
const data = await res.json();
if (!data.length) { tbody.innerHTML = '<tr><td colspan="6" class="empty">Açık pozisyon yok</td></tr>'; return; }
tbody.innerHTML = data.map(p => `<tr>
<td>${p.bot_name}</td>
<td>${p.symbol}</td>
<td>${fmt(p.buy_price, 4)}</td>
<td>${fmt(p.sell_target, 4)}</td>
<td>${fmt(p.quantity, 4)}</td>
<td>${ts(p.opened_at)}</td>
</tr>`).join('');
}
async function loadClosed() {
const res = await api('GET', '/positions/closed');
const tbody = document.getElementById('closed-body');
if (!res.ok) { tbody.innerHTML = '<tr><td colspan="7" class="empty">Yüklenemedi</td></tr>'; return; }
const data = await res.json();
if (!data.length) { tbody.innerHTML = '<tr><td colspan="7" class="empty">Henüz işlem yok</td></tr>'; return; }
tbody.innerHTML = data.map(p => `<tr>
<td>${p.bot_name}</td>
<td>${p.symbol}</td>
<td>${fmt(p.buy_price, 4)}</td>
<td>${fmt(p.sell_target, 4)}</td>
<td>${fmt(p.quantity, 4)}</td>
<td><span class="badge badge-${p.status.toLowerCase()}">${p.status}</span></td>
<td>${ts(p.closed_at)}</td>
</tr>`).join('');
}
async function logout() {
await fetch('/api/auth/logout', { method: 'POST', credentials: 'include' });
window.location.href = '/';
}
loadMode();
loadOpen();
loadClosed();
</script>
</body>
</html>