bae705aa97
- 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
118 lines
3.7 KiB
JavaScript
118 lines
3.7 KiB
JavaScript
// ═══════════════════════════════════════════════════════════════════════════
|
|
// LandveX Finance — Core App
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
import { API } from './api.js';
|
|
import { Router } from './router.js';
|
|
import { Dashboard } from './views/dashboard.js';
|
|
import { Accounts } from './views/accounts.js';
|
|
import { Journal } from './views/journal.js';
|
|
import { Reports } from './views/reports.js';
|
|
|
|
const app = {
|
|
api: null,
|
|
router: null,
|
|
tenant: 'landvex',
|
|
|
|
async init() {
|
|
// Dölj loading
|
|
document.getElementById('loading').style.display = 'none';
|
|
|
|
// Init API
|
|
this.api = new API({
|
|
baseUrl: '/api/ledger',
|
|
tenant: this.tenant,
|
|
getToken: () => localStorage.getItem('lv_token')
|
|
});
|
|
|
|
// Testa auth
|
|
try {
|
|
await this.api.get('/health');
|
|
} catch (e) {
|
|
if (e.status === 401) {
|
|
window.location.href = '/login?return=' + encodeURIComponent(window.location.pathname);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Init router
|
|
this.router = new Router({
|
|
routes: {
|
|
'dashboard': () => Dashboard.render(this),
|
|
'accounts': () => Accounts.render(this),
|
|
'journal': () => Journal.render(this),
|
|
'reports': () => Reports.render(this),
|
|
},
|
|
default: 'dashboard'
|
|
});
|
|
|
|
// Render app shell
|
|
this.renderShell();
|
|
|
|
// Start router
|
|
this.router.start();
|
|
|
|
console.log('[LandveX Finance] App initierad');
|
|
},
|
|
|
|
renderShell() {
|
|
document.getElementById('app').innerHTML = `
|
|
<header class="topbar">
|
|
<div class="topbar-main">
|
|
<div class="brand">
|
|
<div class="brand-logo">LV</div>
|
|
<span class="brand-name">LandveX Finance</span>
|
|
</div>
|
|
</div>
|
|
<nav class="topbar-tabs" id="main-tabs">
|
|
<button class="tab-btn active" data-route="dashboard">Översikt</button>
|
|
<button class="tab-btn" data-route="accounts">Konton</button>
|
|
<button class="tab-btn" data-route="journal">Verifikationer</button>
|
|
<button class="tab-btn" data-route="reports">Rapporter</button>
|
|
</nav>
|
|
</header>
|
|
<main id="main-content"></main>
|
|
<nav class="bottom-nav">
|
|
<button class="nav-item active" data-route="dashboard">
|
|
<span class="nav-icon">◈</span>
|
|
<span>Översikt</span>
|
|
</button>
|
|
<button class="nav-item" data-route="accounts">
|
|
<span class="nav-icon">⊞</span>
|
|
<span>Konton</span>
|
|
</button>
|
|
<button class="nav-item" data-route="journal">
|
|
<span class="nav-icon">≡</span>
|
|
<span>Verifik.</span>
|
|
</button>
|
|
<button class="nav-item" data-route="reports">
|
|
<span class="nav-icon">◧</span>
|
|
<span>Rapporter</span>
|
|
</button>
|
|
</nav>
|
|
`;
|
|
|
|
// Tab handlers
|
|
document.querySelectorAll('[data-route]').forEach(el => {
|
|
el.addEventListener('click', (e) => {
|
|
const route = e.currentTarget.dataset.route;
|
|
this.router.navigate(route);
|
|
this.updateActiveTab(route);
|
|
});
|
|
});
|
|
},
|
|
|
|
updateActiveTab(route) {
|
|
document.querySelectorAll('.tab-btn, .nav-item').forEach(el => {
|
|
el.classList.toggle('active', el.dataset.route === route);
|
|
});
|
|
},
|
|
|
|
render(content) {
|
|
document.getElementById('main-content').innerHTML = content;
|
|
}
|
|
};
|
|
|
|
// Start
|
|
app.init();
|