Files
boc/html-patches/app-index.html
T

702 lines
28 KiB
HTML
Raw Normal View History

<!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>