diff --git a/app/webui/components/app-shell.js b/app/webui/components/app-shell.js new file mode 100644 index 0000000..307eff8 --- /dev/null +++ b/app/webui/components/app-shell.js @@ -0,0 +1,47 @@ +/** + * app-shell.js — Layout-Shell for the protected area. + * + * Each protected page (dashboard, accounts, etc.) renders the sidebar + + * topbar via x-data="appShell('')". The shell owns: + * - the active nav state + * - the title text (derived from the page key) + * - the Logout button handler (delegates to the auth store) + * - the admin-only nav items (uses $store.auth.isAdmin) + * + * The auth-gate itself (redirect to /index.html when no JWT) is enforced + * by store.js on the `Alpine.store('auth').init()` call, which every + * protected page invokes from its outermost x-data. + */ + +const TITLES = { + 'dashboard': 'Dashboard', + 'accounts': 'Accounts', + 'accounts-detail': 'Account-Detail', + 'contacts': 'Contacts', + 'contacts-detail': 'Contact-Detail', + 'pipeline': 'Pipeline', + 'activities': 'Activities', + 'settings-profile': 'Mein Profil', + 'settings-users': 'User-Verwaltung', + 'settings-org': 'Org-Einstellungen', +}; + + +export function appShell(active) { + return { + active: active || 'dashboard', + + get title() { + return TITLES[this.active] || 'CRM'; + }, + + async logout() { + await Alpine.store('auth').logout(); + }, + }; +} + +// Global registration for the inline `x-data="appShell('…')"` usage. +document.addEventListener('alpine:init', () => { + Alpine.data('appShell', (active) => appShell(active)); +});