Files
boc/landvex-paket/demo.html
T
Bernt 6de2455917 v1.2.0: Add Global Markets footer, translated to 9 languages
- Added GLOBAL_MARKETS_TITLE to all translation files
- Updated footer with 12 markets (4 active + 8 upcoming)
- Translated market section to: zh-cn, zh-tw, ja, ko, th, vi, id, ms, hi
- Built and deployed to production
- CloudFront invalidation: I3RTMXVFDJXWLG3SYX208OP1CC
2026-07-08 19:56:03 +00:00

272 lines
9.7 KiB
HTML

<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LandveX API Demo</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f5f5f7;
color: #1d1d1f;
line-height: 1.5;
padding: 20px;
}
.container {
max-width: 800px;
margin: 0 auto;
}
h1 {
font-size: 32px;
margin-bottom: 8px;
color: #0071e3;
}
.subtitle {
color: #86868b;
margin-bottom: 32px;
}
.card {
background: white;
border-radius: 16px;
padding: 24px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.card h2 {
font-size: 20px;
margin-bottom: 16px;
color: #1d1d1f;
}
input, button {
font-family: inherit;
font-size: 16px;
padding: 12px 16px;
border-radius: 10px;
border: 1px solid #d2d2d7;
width: 100%;
margin-bottom: 12px;
}
button {
background: #0071e3;
color: white;
border: none;
cursor: pointer;
font-weight: 600;
}
button:hover {
background: #0077ed;
}
.result {
background: #f5f5f7;
border-radius: 10px;
padding: 16px;
margin-top: 16px;
font-family: 'SF Mono', Monaco, monospace;
font-size: 13px;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-word;
}
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 12px;
margin-top: 16px;
}
.metric {
background: #f5f5f7;
border-radius: 10px;
padding: 16px;
text-align: center;
}
.metric-value {
font-size: 32px;
font-weight: 700;
color: #0071e3;
}
.metric-label {
font-size: 13px;
color: #86868b;
margin-top: 4px;
}
.status {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 6px;
}
.status.ok { background: #34c759; }
.status.warn { background: #ff9500; }
</style>
</head>
<body>
<div class="container">
<h1>🔍 LandveX</h1>
<p class="subtitle">Infrastructure Object Library — API Demo</p>
<div class="card">
<h2>API Status</h2>
<div id="api-status">
<span class="status ok"></span> Object API (port 8083)<br>
<span class="status ok"></span> Bounty API (port 8084)<br>
<span class="status ok"></span> Claims API (port 8085)
</div>
</div>
<div class="card">
<h2>📊 Mätetal</h2>
<div class="metrics" id="metrics">
<div class="metric">
<div class="metric-value" id="total-objects"></div>
<div class="metric-label">Totalt objekt</div>
</div>
<div class="metric">
<div class="metric-value" id="klasser"></div>
<div class="metric-label">Klasser</div>
</div>
<div class="metric">
<div class="metric-value" id="modeller"></div>
<div class="metric-label">Modeller</div>
</div>
<div class="metric">
<div class="metric-value" id="trp"></div>
<div class="metric-label">Trafik</div>
</div>
<div class="metric">
<div class="metric-value" id="vat"></div>
<div class="metric-label">Vatten/Avlopp</div>
</div>
<div class="metric">
<div class="metric-value" id="eln"></div>
<div class="metric-label">El/Nät</div>
</div>
</div>
</div>
<div class="card">
<h2>🎯 Aktiva Bounties</h2>
<div id="bounties-list">
<p>Laddar bounties...</p>
</div>
</div>
<div class="card">
<h2>🔎 Sök objekt</h2>
<input type="text" id="search-query" placeholder="T.ex. brunn, elstolpe, GE Evolve...">
<button onclick="search()">Sök</button>
<div class="result" id="search-result">Resultat visas här...</div>
</div>
<div class="card">
<h2>🎯 Identify (OCR)</h2>
<input type="text" id="ocr-input" placeholder="T.ex. GE ERS2 4000K">
<button onclick="identify()">Identifiera</button>
<div class="result" id="identify-result">Kandidater visas här...</div>
</div>
<div class="card">
<h2>📋 Hämta objekt</h2>
<input type="text" id="object-id" placeholder="LVX-ID, t.ex. LVX-ELN-0101">
<button onclick="getObject()">Hämta</button>
<div class="result" id="object-result">Objektdata visas här...</div>
</div>
</div>
<script>
const API_BASE = '';
async function loadMetrics() {
try {
const res = await fetch(`${API_BASE}/v0/metrics`, {
headers: { 'X-API-Key': 'demo-key-2026' }
});
const data = await res.json();
document.getElementById('total-objects').textContent = data.objects.total;
document.getElementById('klasser').textContent = data.objects.klasser;
document.getElementById('modeller').textContent = data.objects.modeller;
} catch (e) {
console.error('Kunde inte ladda mätetal:', e);
}
}
async function search() {
const query = document.getElementById('search-query').value;
if (!query) return;
try {
const res = await fetch(`${API_BASE}/v0/search?q=${encodeURIComponent(query)}`, {
headers: { 'X-API-Key': 'demo-key-2026' }
});
const data = await res.json();
document.getElementById('search-result').textContent = JSON.stringify(data, null, 2);
} catch (e) {
document.getElementById('search-result').textContent = 'Fel: ' + e.message;
}
}
async function identify() {
const ocr = document.getElementById('ocr-input').value.split(' ').filter(x => x);
try {
const res = await fetch(`${API_BASE}/v0/identify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': 'demo-key-2026' },
body: JSON.stringify({ ocr_extraherat: ocr })
});
const data = await res.json();
document.getElementById('identify-result').textContent = JSON.stringify(data, null, 2);
} catch (e) {
document.getElementById('identify-result').textContent = 'Fel: ' + e.message;
}
}
async function getObject() {
const id = document.getElementById('object-id').value;
if (!id) return;
try {
const res = await fetch(`${API_BASE}/v0/objects/${id}`, {
headers: { 'X-API-Key': 'demo-key-2026' }
});
const data = await res.json();
document.getElementById('object-result').textContent = JSON.stringify(data, null, 2);
} catch (e) {
document.getElementById('object-result').textContent = 'Fel: ' + e.message;
}
}
async function loadBounties() {
try {
const res = await fetch(`${API_BASE}/v0/bounties`, {
headers: { 'X-API-Key': '***' }
});
const data = await res.json();
const list = document.getElementById('bounties-list');
if (data.bounties && data.bounties.length > 0) {
const active = data.bounties.filter(b => b.status === 'open').slice(0, 5);
if (active.length > 0) {
list.innerHTML = active.map(b => `
<div style="padding: 12px; background: #f5f5f7; border-radius: 8px; margin-bottom: 8px;">
<strong>${b.title}</strong>
<span style="color: #0071e3; float: right;">${b.reward} kr</span>
<div style="font-size: 13px; color: #86868b; margin-top: 4px;">${b.description || 'Ingen beskrivning'}</div>
</div>
`).join('');
} else {
list.innerHTML = '<p>Inga aktiva bounties just nu.</p>';
}
} else {
list.innerHTML = '<p>Inga bounties hittades.</p>';
}
} catch (e) {
document.getElementById('bounties-list').innerHTML = '<p>Kunde inte ladda bounties.</p>';
}
}
// Ladda mätetal och bounties vid start
loadMetrics();
loadBounties();
</script>
</body>
</html>