Spaces:
Sleeping
Sleeping
| <html lang="et"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>ATOM · Command Center</title> | |
| <style> | |
| :root { | |
| --green: #059669; | |
| --green-dark: #047857; | |
| --bg: #0b1220; | |
| --panel: #111827; | |
| --border: #1f2937; | |
| --text: #f8fafc; | |
| --muted: #94a3b8; | |
| --card: #0f172a; | |
| --ok: #34d399; | |
| --warn: #fbbf24; | |
| --err: #f87171; | |
| } | |
| * { box-sizing: border-box; } | |
| body { | |
| margin: 0; min-height: 100vh; font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; | |
| background: radial-gradient(1200px 600px at 10% -10%, #064e3b 0%, transparent 50%), | |
| radial-gradient(900px 500px at 100% 0%, #1e3a5f 0%, transparent 45%), | |
| var(--bg); | |
| color: var(--text); | |
| } | |
| header { | |
| display: flex; align-items: center; justify-content: space-between; gap: 1rem; | |
| padding: 1rem 1.5rem; border-bottom: 1px solid var(--border); | |
| background: rgba(15, 23, 42, 0.75); backdrop-filter: blur(10px); position: sticky; top: 0; z-index: 10; | |
| } | |
| .brand { display: flex; align-items: center; gap: .75rem; font-weight: 800; letter-spacing: .02em; } | |
| .mark { | |
| width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center; | |
| background: linear-gradient(135deg, var(--green), #0ea5e9); color: white; font-size: .9rem; | |
| } | |
| .brand small { display: block; font-weight: 500; color: var(--muted); font-size: .75rem; } | |
| nav { display: flex; flex-wrap: wrap; gap: .5rem; } | |
| nav a, .btn { | |
| color: var(--text); text-decoration: none; border: 1px solid var(--border); background: var(--panel); | |
| padding: .55rem .85rem; border-radius: 10px; font-size: .9rem; font-weight: 600; cursor: pointer; | |
| } | |
| nav a:hover, .btn:hover { border-color: var(--green); } | |
| .btn-primary { background: var(--green); border-color: var(--green); color: white; } | |
| main { max-width: 1100px; margin: 0 auto; padding: 1.5rem; } | |
| .hero { | |
| display: grid; gap: 1rem; grid-template-columns: 1.4fr 1fr; margin-bottom: 1.25rem; | |
| } | |
| @media (max-width: 800px) { .hero { grid-template-columns: 1fr; } } | |
| .card { | |
| background: rgba(17, 24, 39, 0.9); border: 1px solid var(--border); border-radius: 16px; padding: 1.25rem; | |
| } | |
| h1 { margin: 0 0 .5rem; font-size: clamp(1.5rem, 3vw, 2rem); } | |
| p { color: var(--muted); line-height: 1.55; } | |
| .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; } | |
| .tile h3 { margin: 0 0 .35rem; font-size: 1rem; } | |
| .tile p { margin: 0 0 .85rem; font-size: .9rem; } | |
| .status { display: flex; flex-wrap: wrap; gap: .5rem; margin: 1rem 0; } | |
| .badge { | |
| display: inline-flex; align-items: center; gap: .4rem; padding: .35rem .65rem; border-radius: 999px; | |
| background: #0b1729; border: 1px solid var(--border); font-size: .8rem; color: var(--muted); | |
| } | |
| .badge.ok { color: var(--ok); border-color: rgba(52, 211, 153, .35); } | |
| .badge.err { color: var(--err); border-color: rgba(248, 113, 113, .35); } | |
| .badge.warn { color: var(--warn); border-color: rgba(251, 191, 36, .35); } | |
| code, pre { | |
| background: #020617; border: 1px solid var(--border); border-radius: 10px; color: #e2e8f0; | |
| font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .8rem; | |
| } | |
| pre { padding: .85rem; overflow: auto; max-height: 220px; white-space: pre-wrap; word-break: break-word; } | |
| .muted { color: var(--muted); font-size: .85rem; } | |
| footer { margin-top: 1.5rem; color: var(--muted); font-size: .8rem; text-align: center; } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div class="brand"> | |
| <div class="mark">AT</div> | |
| <div>ATOM<span><small>Command Center · operator workspace</small></span></div> | |
| </div> | |
| <nav> | |
| <a href="/docs">API Docs</a> | |
| <a href="/api/hf/status">HF Status</a> | |
| <a href="/api/healthz">Health</a> | |
| <a href="/clients/">Kliendibaas</a> | |
| <a href="/dashboard.html">AIMF dashboard</a> | |
| <button class="btn" id="logoutBtn" type="button">Logi välja</button> | |
| </nav> | |
| </header> | |
| <main> | |
| <section class="hero"> | |
| <div class="card"> | |
| <h1>Tere tulemast ATOMisse</h1> | |
| <p> | |
| See on <strong>ATOM operaatori hub</strong> (mitte AI Money Flow kliendiportaal). | |
| Pärast sisselogimist jõuad siia. All on live API staatus ja sinu konto. | |
| </p> | |
| <div class="status" id="badges"> | |
| <span class="badge warn">API: kontrollin…</span> | |
| <span class="badge warn">Auth: kontrollin…</span> | |
| </div> | |
| <div style="display:flex; gap:.6rem; flex-wrap:wrap;"> | |
| <a class="btn btn-primary" href="/docs">Ava ATOM API</a> | |
| <a class="btn" href="/login.html">Login leht</a> | |
| <a class="btn" href="/">AIMF avaleht (klient)</a> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h3 style="margin-top:0">Sessioon</h3> | |
| <p class="muted" id="sessionInfo">Tokenit loen…</p> | |
| <pre id="meBox">/api/auth/me</pre> | |
| </div> | |
| </section> | |
| <section class="grid"> | |
| <div class="card tile"> | |
| <h3>API / integratsioonid</h3> | |
| <p>FastAPI backend, OpenAPI, health ja operaatori endpointid.</p> | |
| <a class="btn" href="/docs">/docs</a> | |
| </div> | |
| <div class="card tile"> | |
| <h3>Kliendibaas</h3> | |
| <p>Staatilised kliendi dossierid (HTML).</p> | |
| <a class="btn" href="/clients/">/clients/</a> | |
| </div> | |
| <div class="card tile"> | |
| <h3>AI Money Flow</h3> | |
| <p>Eraldi kliendiportaal (intake + demo dashboard).</p> | |
| <a class="btn" href="/">Avaleht</a> | |
| <a class="btn" href="/dashboard.html">Dashboard</a> | |
| </div> | |
| <div class="card tile"> | |
| <h3>Space health</h3> | |
| <p>Hugging Face konteineri staatus.</p> | |
| <a class="btn" href="/api/hf/status">/api/hf/status</a> | |
| </div> | |
| </section> | |
| <footer> | |
| ATOM Command Center · HF Docker Space · pärast login’it suunatakse siia (/atom.html) | |
| </footer> | |
| </main> | |
| <script> | |
| const badges = document.getElementById('badges'); | |
| const meBox = document.getElementById('meBox'); | |
| const sessionInfo = document.getElementById('sessionInfo'); | |
| const token = localStorage.getItem('token') || localStorage.getItem('auth_token') || ''; | |
| function setBadges(apiOk, authOk, apiText, authText) { | |
| badges.innerHTML = ` | |
| <span class="badge ${apiOk ? 'ok' : 'err'}">API: ${apiText}</span> | |
| <span class="badge ${authOk ? 'ok' : (token ? 'err' : 'warn')}">Auth: ${authText}</span> | |
| `; | |
| } | |
| document.getElementById('logoutBtn').onclick = () => { | |
| localStorage.removeItem('token'); | |
| localStorage.removeItem('auth_token'); | |
| location.href = '/login.html'; | |
| }; | |
| if (!token) { | |
| sessionInfo.textContent = 'Token puudub — suunan loginile…'; | |
| setBadges(false, false, '—', 'puudub'); | |
| setTimeout(() => { location.href = '/login.html?next=/atom.html'; }, 700); | |
| } else { | |
| sessionInfo.textContent = 'Token olemas (localStorage).'; | |
| (async () => { | |
| let apiOk = false, authOk = false, apiText = 'down', authText = 'fail'; | |
| try { | |
| const h = await fetch('/api/hf/status'); | |
| const j = await h.json(); | |
| apiOk = h.ok; | |
| apiText = apiOk ? (j.mode || 'ok') : ('HTTP ' + h.status); | |
| } catch (e) { | |
| apiText = 'error'; | |
| } | |
| try { | |
| const me = await fetch('/api/auth/me', { | |
| headers: { Authorization: 'Bearer ' + token } | |
| }); | |
| const body = await me.json().catch(() => ({})); | |
| if (me.ok) { | |
| authOk = true; | |
| authText = body.email || 'ok'; | |
| meBox.textContent = JSON.stringify(body, null, 2); | |
| } else { | |
| authText = body.detail || ('HTTP ' + me.status); | |
| meBox.textContent = JSON.stringify(body, null, 2); | |
| } | |
| } catch (e) { | |
| authText = String(e); | |
| meBox.textContent = String(e); | |
| } | |
| setBadges(apiOk, authOk, apiText, authText); | |
| })(); | |
| } | |
| </script> | |
| </body> | |
| </html> | |