Files
boc/html-patches/app-index.html
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

702 lines
28 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="sv" data-theme="light">
<head>
<meta charset="UTF-8">
<link rel="manifest" href="/ouroboros/manifest.json">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Ouroboros">
<meta name="theme-color" content="#007AFF">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>AAMOS Ouroboros — Dashboard</title>
<link rel="stylesheet" href="/_design-system/apple-native/tokens.css">
<link rel="stylesheet" href="/_design-system/apple-native/universal-fix.css">
<link rel="stylesheet" href="/_design-system/apple-native/typography.css">
<link rel="stylesheet" href="/_design-system/apple-native/components.css">
<link rel="stylesheet" href="/_design-system/apple-native/ios-core.css">
<script src="/_design-system/apple-native/interactions.js" defer></script>
<meta name="apple-native-compliance" content="pass">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
font-family: var(--font-text, -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif);
background: var(--grouped-background-primary, #F2F2F7);
color: var(--label-primary, #000);
-webkit-font-smoothing: antialiased;
min-height: 100dvh;
padding-bottom: calc(49px + env(safe-area-inset-bottom, 16px) + 16px);
}
/* ── Nav Bar ── */
.nav-bar {
position: sticky;
top: 0;
z-index: 100;
padding-top: env(safe-area-inset-top, 0px);
background: rgba(248,248,248,0.94);
backdrop-filter: blur(40px) saturate(180%);
-webkit-backdrop-filter: blur(40px) saturate(180%);
border-bottom: 0.33px solid rgba(60,60,67,0.18);
}
.nav-bar-inner {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
}
.nav-bar-back {
display: flex;
align-items: center;
gap: 4px;
font-size: 17px;
color: var(--ios-blue, #007AFF);
text-decoration: none;
padding: 0 8px;
min-width: 44px;
min-height: 44px;
}
.nav-bar-title {
font-size: 17px;
font-weight: 600;
color: var(--label-primary, #000);
position: absolute;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
}
.nav-bar-action {
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
color: var(--ios-blue, #007AFF);
background: none;
border: none;
cursor: pointer;
font-size: 22px;
}
/* ── Large Title ── */
.large-title-section {
padding: 8px 20px 0;
}
.large-title {
font-family: var(--font-display, -apple-system);
font-size: 34px;
font-weight: 700;
letter-spacing: -0.025em;
color: var(--label-primary, #000);
margin-bottom: 4px;
}
.large-subtitle {
font-size: 14px;
color: var(--label-secondary, rgba(60,60,67,0.6));
margin-bottom: 20px;
}
/* ── Stats row ── */
.stats-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
padding: 0 16px;
margin-bottom: 24px;
}
.stat-card {
background: var(--grouped-background-secondary, #fff);
border-radius: 12px;
padding: 14px 12px 12px;
display: flex;
flex-direction: column;
gap: 4px;
}
.stat-icon { font-size: 20px; margin-bottom: 4px; }
.stat-value {
font-family: var(--font-display, -apple-system);
font-size: 24px;
font-weight: 700;
letter-spacing: -0.02em;
color: var(--label-primary, #000);
}
.stat-label {
font-size: 12px;
color: var(--label-secondary, rgba(60,60,67,0.6));
}
/* ── Section header ── */
.section-header {
display: flex;
align-items: baseline;
justify-content: space-between;
padding: 0 20px;
margin-bottom: 10px;
}
.section-title {
font-size: 22px;
font-weight: 700;
letter-spacing: -0.015em;
color: var(--label-primary, #000);
}
.section-action {
font-size: 15px;
color: var(--ios-blue, #007AFF);
text-decoration: none;
}
/* ── Module cards ── */
.modules-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
padding: 0 16px;
margin-bottom: 28px;
}
.module-card {
background: var(--grouped-background-secondary, #fff);
border-radius: 14px;
padding: 16px 14px 14px;
display: flex;
flex-direction: column;
gap: 4px;
text-decoration: none;
color: inherit;
cursor: pointer;
transition: opacity 0.15s, transform 0.1s;
-webkit-tap-highlight-color: transparent;
position: relative;
overflow: hidden;
}
.module-card:active { opacity: 0.7; transform: scale(0.97); }
.module-card-icon { font-size: 26px; margin-bottom: 6px; }
.module-card-name {
font-size: 15px;
font-weight: 600;
color: var(--label-primary, #000);
}
.module-card-desc {
font-size: 12px;
color: var(--label-secondary, rgba(60,60,67,0.6));
}
.module-card-chevron {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--label-quaternary, rgba(60,60,67,0.18));
font-size: 14px;
}
/* ── Quick Actions ── */
.quick-actions {
margin: 0 16px 28px;
}
.quick-action-list {
background: var(--grouped-background-secondary, #fff);
border-radius: 12px;
overflow: hidden;
}
.quick-action-row {
display: flex;
align-items: center;
min-height: 52px;
padding: 0 16px;
gap: 14px;
border-bottom: 0.33px solid var(--separator, rgba(60,60,67,0.36));
cursor: pointer;
text-decoration: none;
color: inherit;
-webkit-tap-highlight-color: transparent;
transition: background 0.1s;
}
.quick-action-row:last-child { border-bottom: none; }
.quick-action-row:active { background: transparent; }
.qa-icon {
width: 34px;
height: 34px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
flex-shrink: 0;
}
.qa-text { flex: 1; }
.qa-title { font-size: 15px; font-weight: 500; color: var(--label-primary, #000); }
.qa-subtitle { font-size: 12px; color: var(--label-secondary, rgba(60,60,67,0.6)); }
.qa-chevron {
color: var(--label-quaternary, rgba(60,60,67,0.18));
font-size: 13px;
}
/* ── Plan badge ── */
.plan-badge {
display: inline-block;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
padding: 2px 7px;
border-radius: 4px;
background: rgba(88,86,214,0.12);
color: var(--ios-indigo, #5856D6);
margin-left: 8px;
vertical-align: middle;
}
/* ── Logout / settings ── */
.settings-section {
margin: 0 16px 24px;
}
.settings-list {
background: var(--grouped-background-secondary, #fff);
border-radius: 12px;
overflow: hidden;
}
.settings-row {
display: flex;
align-items: center;
min-height: 44px;
padding: 0 16px;
gap: 12px;
border-bottom: 0.33px solid var(--separator, rgba(60,60,67,0.36));
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.settings-row:last-child { border-bottom: none; }
.settings-row.danger { color: var(--ios-red, #FF3B30); }
/* ── Loading / error ── */
.loading-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 60vh;
gap: 16px;
}
.spinner {
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid var(--ios-gray5, #E5E5EA);
border-top: 3px solid var(--ios-blue, #007AFF);
animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
</style>
<style>
/* iOS Perfection Fix */
.nav-bar{display:none!important}
.large-title{font-size:28px!important;font-weight:700!important;letter-spacing:-.5px!important;margin-bottom:3px!important}
.large-subtitle{font-size:14px!important;color:rgba(60,60,67,.55)!important;font-weight:400!important}
.large-title-area,.large-title-section{padding:4px 20px 8px!important}
.mini-stat{background:#fff!important;border-radius:14px!important;padding:14px 12px!important;border:none!important;box-shadow:0 1px 3px rgba(0,0,0,.05),0 2px 8px rgba(0,0,0,.04)!important}
.mini-stat-value{font-size:26px!important;font-weight:800!important;letter-spacing:-.03em!important;color:#007AFF!important;display:block!important;margin-bottom:5px!important}
.mini-stat-label{font-size:11px!important;font-weight:500!important;color:rgba(60,60,67,.55)!important;display:block!important}
.stats-row{gap:10px!important;padding:8px 16px 12px!important}
.kpi-card{background:#fff!important;border-radius:16px!important;border:none!important;box-shadow:0 1px 3px rgba(0,0,0,.05),0 2px 8px rgba(0,0,0,.04)!important}
.kpi-value{font-weight:800!important;letter-spacing:-.03em!important}
@media(prefers-color-scheme:dark){.mini-stat,.kpi-card{background:#1C1C1E!important}.large-title{color:#fff!important}}
</style>
<style id="ouroboros-apple-system">
/* OUROBOROS GLOBAL SYSTEM CSS — Apple iOS 18 baseline */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
/* System font stack — SF Pro on Apple, Inter elsewhere */
body, input, select, textarea, button {
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display',
'Helvetica Neue', Arial, system-ui, sans-serif;
}
/* Fix any broken button appearances */
button { -webkit-appearance: none; appearance: none; cursor: pointer; }
select { -webkit-appearance: none; appearance: none; }
input[type="number"] { -moz-appearance: textfield; }
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; }
/* Remove blue outline on focus (replace with subtle ring) */
:focus-visible {
outline: 2.5px solid rgba(0, 122, 255, 0.6);
outline-offset: 2px;
border-radius: 6px;
}
/* Language buttons must ALWAYS look like pills */
.lang-btn {
padding: 6px 12px !important;
border: 1.5px solid rgba(60,60,67,.15) !important;
border-radius: 20px !important;
background: #fff !important;
color: rgba(60,60,67,.6) !important;
font-size: 12px !important;
font-weight: 700 !important;
-webkit-appearance: none !important;
box-shadow: 0 1px 2px rgba(0,0,0,.06) !important;
}
.lang-btn.active {
background: #007AFF !important;
border-color: #007AFF !important;
color: #fff !important;
}
/* Tap targets minimum 44×44pt (iOS HIG requirement) */
@media (pointer: coarse) {
button, .btn-primary, .btn-ghost, .option-card, .lang-btn {
min-height: 44px;
}
}
</style>
<style id="wcag-contrast-enforcement">
/* AAMOS GLOBAL CONTRAST ENFORCEMENT — WCAG AA (4.5:1 minimum) */
/* Regel: Ingen text under 70% opacity. Aldrig. */
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
/* Fix common low-contrast patterns */
[style*="rgba(60,60,67,0.4)"] { color: rgba(60,60,67,0.65) !important; }
[style*="rgba(60,60,67,0.3)"] { color: rgba(60,60,67,0.65) !important; }
[style*="rgba(255,255,255,0.4)"] { color: rgba(255,255,255,0.72) !important; }
[style*="rgba(255,255,255,0.3)"] { color: rgba(255,255,255,0.72) !important; }
[style*="opacity: 0.4"] { opacity: 0.72 !important; }
[style*="opacity: 0.3"] { opacity: 0.72 !important; }
</style>
</head>
<body>
<header class="nav-bar">
<div class="nav-bar-inner" style="position:relative;">
<a href="/ouroboros/" class="nav-bar-back">
<svg viewBox="0 0 10 17" width="10" height="17" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><polyline points="9 1 1 8.5 9 16"/></svg>
Ouroboros
</a>
<span class="nav-bar-title" id="nav-org-name">Dashboard</span>
<button class="nav-bar-action" onclick="toggleSettings()" aria-label="Inställningar">⚙️</button>
</div>
</header>
<main id="main-content">
<div class="loading-state">
<div class="spinner"></div>
<span style="color:var(--label-secondary);font-size:15px;">Laddar…</span>
</div>
</main>
<script>
const MODULE_INFO = {
identity: { icon: '🔐', desc: 'Org & användare', path: '/ouroboros/identity/' },
finance: { icon: '💰', desc: 'Ekonomi & budget', path: '/ouroboros/finance/' },
people: { icon: '👥', desc: 'Anställda & HR', path: '/ouroboros/people/' },
governance: { icon: '⚖️', desc: 'Beslut & styrning', path: '/ouroboros/governance/' },
compliance: { icon: '✅', desc: 'ISO/GDPR', path: '/ouroboros/compliance/' },
analytics: { icon: '📊', desc: 'Business Intelligence', path: '/ouroboros/analytics/' },
projects: { icon: '📋', desc: 'Projekthantering', path: '/ouroboros/projects/' },
okr: { icon: '🎯', desc: 'Mål & nyckelresultat', path: '/ouroboros/okr/' },
meetings: { icon: '🗓️', desc: 'Möteshantering', path: '/ouroboros/meetings/' },
legal: { icon: '📜', desc: 'Avtal & juridik', path: '/ouroboros/legal/' },
academy: { icon: '🎓', desc: 'Lärande & utv.', path: '/ouroboros/academy/' },
operations: { icon: '⚙️', desc: 'Arbetsflöden & SLA', path: '/ouroboros/operations/' },
connect: { icon: '💬', desc: 'Kommunikation', path: '/ouroboros/connect/' },
decisions: { icon: '🧭', desc: 'Beslutsuppföljning', path: '/ouroboros/decisions/' },
commerce: { icon: '🛒', desc: 'Order & lager', path: '/ouroboros/commerce/' },
procurement: { icon: '📦', desc: 'Inköp & leverantörer', path: '/ouroboros/procurement/' },
marketing: { icon: '📣', desc: 'Kampanjer & outreach', path: '/ouroboros/marketing/' },
media: { icon: '🎬', desc: 'Media & innehåll', path: '/ouroboros/media/' },
lean: { icon: '🔄', desc: 'Ständig förbättring', path: '/ouroboros/lean/' },
quality: { icon: '⭐', desc: 'QA & standarder', path: '/ouroboros/quality/' },
systemaudit: { icon: '🔍', desc: 'Revision & spårning', path: '/ouroboros/systemaudit/' },
insurance: { icon: '🛡️', desc: 'Försäkringshantering', path: '/ouroboros/insurance/' },
travel: { icon: '✈️', desc: 'Resor & utgifter', path: '/ouroboros/travel/' },
wellbeing: { icon: '💚', desc: 'Medarbetarwellbeing', path: '/ouroboros/wellbeing/' },
// ── URBAN OS — built May 2026 ──
'urban-os': { icon: '🏗️', desc: 'Urban OS Command Center', path: '/ouroboros/urban-os.html' },
city: { icon: '🏙️', desc: 'City Intelligence Platform', path: '/ouroboros/city.html' },
waste: { icon: '🔴', desc: 'Resurssvinn & Svarta Hål', path: '/ouroboros/waste.html' },
lifecycle: { icon: '♻️', desc: 'Affärslivscykel', path: '/ouroboros/lifecycle.html' },
valuation: { icon: '💎', desc: 'Market Mirror', path: '/ouroboros/app/' },
// ── NEW MODULES — built May 2026 ──
simulation: { icon: '📊', desc: 'Enterprise Simulation', path: '/ouroboros/simulation.html' },
sims: { icon: '🎮', desc: 'Virtuell verksamhet', path: '/ouroboros/sims.html' },
banks: { icon: '🏦', desc: 'Bankintegration (20k+)', path: '/ouroboros/banks.html' },
credit: { icon: '💳', desc: 'Kreditansökan', path: '/ouroboros/credit.html' },
postal: { icon: '✉️', desc: 'Brev & paket', path: '/ouroboros/postal.html' },
certification: { icon: '🏅', desc: 'TÜV/DEKRA/DNV/RISE', path: '/ouroboros/certification.html' },
'audit-firms': { icon: '📋', desc: 'PwC/EY/Deloitte/KPMG', path: '/ouroboros/audit-partners.html' },
memory: { icon: '🧬', desc: 'Corporate Memory', path: '/ouroboros/memory.html' },
treasury: { icon: '💰', desc: 'Treasury Engine', path: '/ouroboros/banks.html' },
};
let session = null;
let dashData = null;
// ── Cookie helper ─────────────────────────────────────────────────────────
function getCookie(name) {
const match = document.cookie.match(new RegExp('(?:^|; )' + name.replace(/[.*+?^${}()|[\]\\]/g,'\\$&') + '=([^;]*)'));
return match ? decodeURIComponent(match[1]) : null;
}
async function init() {
const raw = localStorage.getItem('ouroboros_session');
const wavultToken = getCookie('wavult_token') || localStorage.getItem('amos_token');
if (!raw && wavultToken) {
// Har JWT-cookie men ingen session i localStorage — hämta via /api/auth/me
try {
const meRes = await fetch('/api/auth/me', {
headers: { 'Authorization': 'Bearer ' + wavultToken }
});
if (meRes.ok) {
const me = await meRes.json();
session = {
token: wavultToken,
org_id: me.org_id || me.organization_id,
org_name: me.org_name || me.organization_name || me.company_name || 'Din organisation',
user_name: me.name || me.display_name || me.email,
user_email: me.email,
active_modules: me.active_modules || me.modules || [],
};
localStorage.setItem('ouroboros_session', JSON.stringify(session));
} else {
window.location.href = '/ouroboros/app/login.html';
return;
}
} catch(e) {
window.location.href = '/ouroboros/app/login.html';
return;
}
} else if (!raw) {
window.location.href = '/ouroboros/app/login.html';
return;
} else {
try {
session = JSON.parse(raw);
if (!session.org_id) throw new Error('No org_id');
// Prefer wavult_token cookie if available
if (wavultToken) session.token = wavultToken;
} catch(e) {
window.location.href = '/ouroboros/app/login.html';
return;
}
}
document.getElementById('nav-org-name').textContent = session.org_name || 'Dashboard';
try {
const headers = session.token ? { 'Authorization': 'Bearer ' + session.token } : {};
const res = await fetch(`/api/v1/organizations/${session.org_id}/dashboard`, { headers });
dashData = await res.json();
} catch(e) {
dashData = null;
}
renderDashboard();
}
function renderDashboard() {
const modules = dashData?.active_modules || session.active_modules || [];
const stats = dashData?.stats || {};
const orgName = dashData?.org_name || session.org_name || 'Din organisation';
const plan = dashData?.plan || 'trial';
const userName = session.user_name || 'Admin';
const activeCount = modules.length;
const employeeCount = stats.employees ?? '—';
const userCount = stats.users ?? '—';
document.getElementById('main-content').innerHTML = `
<div class="large-title-section">
<div class="large-title">${orgName} <span class="plan-badge">${plan.toUpperCase()}</span></div>
<div class="large-subtitle">Inloggad som ${userName}</div>
</div>
<!-- Launch Readiness Banner -->
<div onclick="window.location.href='/ouroboros/launch-readiness.html'" style="background:linear-gradient(135deg,rgba(0,122,255,.06),rgba(88,86,214,.04));border:1.5px solid rgba(0,122,255,.12);border-radius:14px;padding:14px 16px;margin-bottom:14px;cursor:pointer;display:flex;align-items:center;gap:12px;">
<div style="font-size:24px">🚀</div>
<div style="flex:1;min-width:0">
<div style="font-size:14px;font-weight:700;margin-bottom:2px">Lanseringsberedskap</div>
<div style="font-size:12px;color:rgba(60,60,67,.55)">Kolla av allt som behövs inför lansering</div>
</div>
<div style="font-size:11px;font-weight:700;padding:4px 9px;border-radius:7px;background:rgba(255,59,48,.1);color:#FF3B30;white-space:nowrap" id="launch-badge">Se status →</div>
</div>
<div class="stats-row">
<div class="stat-card">
<div class="stat-icon">👥</div>
<div class="stat-value">${employeeCount}</div>
<div class="stat-label">Anställda</div>
</div>
<div class="stat-card">
<div class="stat-icon">🧩</div>
<div class="stat-value">${activeCount}</div>
<div class="stat-label">Aktiva moduler</div>
</div>
<div class="stat-card">
<div class="stat-icon">✅</div>
<div class="stat-value">100%</div>
<div class="stat-label">Driftstatus</div>
</div>
</div>
<div class="section-header" style="margin-bottom:10px;">
<span class="section-title">Aktiva moduler</span>
</div>
<div class="modules-grid">
${modules.map(id => {
const info = MODULE_INFO[id] || { icon: '🔲', desc: id, path: '#' };
const name = id.charAt(0).toUpperCase() + id.slice(1);
return `
<a href="${info.path}" class="module-card">
<div class="module-card-icon">${info.icon}</div>
<div class="module-card-name">${name}</div>
<div class="module-card-desc">${info.desc}</div>
<span class="module-card-chevron"></span>
</a>
`;
}).join('')}
</div>
<div class="section-header">
<span class="section-title">Quick Actions</span>
</div>
<div class="quick-actions">
<div class="quick-action-list">
<a href="/ouroboros/people/" class="quick-action-row">
<div class="qa-icon" style="background:rgba(0,122,255,0.1)">👤</div>
<div class="qa-text">
<div class="qa-title">Lägg till anställd</div>
<div class="qa-subtitle">People-modulen</div>
</div>
<span class="qa-chevron"></span>
</a>
<a href="/ouroboros/projects/" class="quick-action-row">
<div class="qa-icon" style="background:rgba(88,86,214,0.1)">📋</div>
<div class="qa-text">
<div class="qa-title">Skapa projekt</div>
<div class="qa-subtitle">Projects-modulen</div>
</div>
<span class="qa-chevron"></span>
</a>
<a href="/ouroboros/legal/" class="quick-action-row">
<div class="qa-icon" style="background:rgba(255,149,0,0.1)">📜</div>
<div class="qa-text">
<div class="qa-title">Lägg till avtal</div>
<div class="qa-subtitle">Legal-modulen</div>
</div>
<span class="qa-chevron"></span>
</a>
<a href="/ouroboros/simulation.html" class="quick-action-row">
<div class="qa-icon" style="background:rgba(48,209,88,0.1)">📊</div>
<div class="qa-text">
<div class="qa-title">Kör simulering</div>
<div class="qa-subtitle">Enterprise Simulation Engine</div>
</div>
<span class="qa-chevron"></span>
</a>
<a href="/ouroboros/credit.html" class="quick-action-row">
<div class="qa-icon" style="background:rgba(255,149,10,0.1)">💳</div>
<div class="qa-text">
<div class="qa-title">Kreditansökan</div>
<div class="qa-subtitle">19 långivare, 12 produkter</div>
</div>
<span class="qa-chevron"></span>
</a>
<a href="/ouroboros/insurance.html" class="quick-action-row">
<div class="qa-icon" style="background:rgba(255,45,85,0.1)">🛡️</div>
<div class="qa-text">
<div class="qa-title">Försäkringsprofil</div>
<div class="qa-subtitle">Reaktiv riskbedömning</div>
</div>
<span class="qa-chevron"></span>
</a>
<a href="/ouroboros/sims.html" class="quick-action-row">
<div class="qa-icon" style="background:rgba(88,86,214,0.1)">🎮</div>
<div class="qa-text">
<div class="qa-title">Simuleringsläge</div>
<div class="qa-subtitle">Kör företaget virtuellt</div>
</div>
<span class="qa-chevron"></span>
</a>
</div>
</div>
<div class="section-header">
<span class="section-title">Konto</span>
</div>
<div class="settings-section">
<div class="settings-list">
<div class="settings-row">
<span style="flex:1;font-size:15px;">Organisation</span>
<span style="color:var(--label-secondary);font-size:15px;">${orgName}</span>
</div>
<div class="settings-row">
<span style="flex:1;font-size:15px;">E-post</span>
<span style="color:var(--label-secondary);font-size:15px;">${session.user_email || '—'}</span>
</div>
<div class="settings-row" id="installRow" onclick="installPWA()" style="display:none">
<span style="flex:1;font-size:15px;">📲 Installera som app</span>
<span></span>
</div>
<div class="settings-row danger" onclick="logout()">
<span style="flex:1;font-size:15px;">Logga ut</span>
<span></span>
</div>
</div>
</div>
`;
}
function toggleSettings() {
// Simple org info in an alert
if (session) {
alert(`Organisation: ${session.org_name}\nOrg-ID: ${session.org_id}\nAnvändare: ${session.user_name}\nE-post: ${session.user_email}`);
}
}
function logout() {
if (confirm('Logga ut från ' + (session?.org_name || 'Ouroboros') + '?')) {
localStorage.removeItem('ouroboros_session');
// Clear wavult_token cookie
document.cookie = 'wavult_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Lax';
window.location.href = '/ouroboros/app/login.html';
}
}
init();
// PWA Install
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
const row = document.getElementById('installRow');
if (row) row.style.display = 'flex';
});
async function installPWA() {
if (!deferredPrompt) {
alert('Öppna i Chrome/Edge och tryck på ⋮ → Installera AAMOS Ouroboros');
return;
}
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
deferredPrompt = null;
if (outcome === 'accepted') {
document.getElementById('installRow').style.display = 'none';
}
}
window.addEventListener('appinstalled', () => {
const row = document.getElementById('installRow');
if (row) row.style.display = 'none';
});
</script>
</body>
</html>