// ── Register all custom elements ────────────────────────────────────────────── import './components/shared/ui-badge.mjs'; import './components/shared/ui-button.mjs'; import './components/shared/ui-spinner.mjs'; import './components/shared/ui-toast.mjs'; import './components/shared/ui-empty.mjs'; import './components/shared/ui-dialog.mjs'; import './components/layout/app-root.mjs'; import './components/layout/app-sidebar.mjs'; import './components/layout/app-topbar.mjs'; import './components/layout/app-mobile-nav.mjs'; import './components/work-orders/wo-list.mjs'; import './components/work-orders/wo-kanban.mjs'; import './components/work-orders/wo-form.mjs'; import './components/work-orders/wo-detail.mjs'; import { getUser, setToken, clearToken } from './lib/auth.mjs'; import { api } from './lib/api.mjs'; import { router } from './lib/router.mjs'; import { showToast } from './components/shared/ui-toast.mjs'; const root = document.getElementById('root'); window.addEventListener('auth:expired', () => { clearToken(); showLoginPage(); }); window.addEventListener('auth:logout', () => { clearToken(); showLoginPage(); }); const user = getUser(); if (user) { startApp(); } else { showLoginPage(); } // ── Login page ──────────────────────────────────────────────────────────────── function showLoginPage() { root.innerHTML = `
`; if (window.lucide) lucide.createIcons({ nodes: [root] }); root.querySelector('#login-form').addEventListener('submit', async e => { e.preventDefault(); const btn = root.querySelector('#login-btn'); const err = root.querySelector('#login-error'); const username = root.querySelector('#login-user').value.trim(); const password = root.querySelector('#login-pass').value; btn.disabled = true; btn.textContent = 'Signing in…'; err.textContent = ''; try { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); const json = await res.json(); if (!res.ok) throw new Error(json.error || 'Login failed'); setToken(json.data.token); startApp(); } catch (ex) { err.textContent = ex.message; btn.disabled = false; btn.textContent = 'Sign In'; } }); } // ── Main app ────────────────────────────────────────────────────────────────── function startApp() { root.innerHTML = ''; const appRoot = root.querySelector('app-root'); router .on('/', () => appRoot.setPage('')) .on('/work-orders', () => appRoot.setPage('')) .on('/work-orders/new', () => appRoot.setPage('')) .on('/work-orders/:id/edit', ({ id }) => appRoot.setPage(``)) .on('/work-orders/:id', ({ id }) => appRoot.setPage(``)) .on('/registry/people', () => appRoot.setPage('

People registry — Phase 2

')) .on('/registry/vehicles', () => appRoot.setPage('

Vehicles registry — Phase 2

')) .on('/registry/equipment', () => appRoot.setPage('

Equipment registry — Phase 2

')) .on('/registry/materials', () => appRoot.setPage('

Materials registry — Phase 2

')) .on('/reports', () => appRoot.setPage('

Reports — Phase 3

')) .on('/users', () => appRoot.setPage('

User management — Phase 3

')) .on('/settings', () => appRoot.setPage('

Settings — Phase 4

')) .start(); // Global navigation events from WO components window.addEventListener('wo:navigate', e => router.navigate(e.detail.path)); window.addEventListener('wo:toast', e => showToast(e.detail.message, e.detail.type)); }