'use strict'; function adminApp() { return { me: null, users: [], schemes: [], error: '', tab: 'users', user: { id: null, username: '', email: '', password: '', role: 'user', active: true }, scheme: { id: null, name: '', seed_color: '#1565c0', mode: 'light', is_default: false }, async init() { try { const me = await API.get('/api/me'); this.me = me.user; if (me.user.role !== 'admin') { window.location.href = '/'; return; } } catch (_) { window.location.href = '/login.html'; return; } await this.loadSchemes(); await this.loadUsers(); const scheme = Theme.resolve(this.schemes, this.me.preferred_scheme_id); await Theme.apply(scheme); }, async loadUsers() { try { this.users = (await API.get('/api/users')).users; } catch (e) { this.toast(e.message); } }, async loadSchemes() { try { this.schemes = (await API.get('/api/schemes')).schemes; } catch (e) { this.toast(e.message); } }, schemeName(id) { const s = this.schemes.find((x) => x.id === id); return s ? s.name : '—'; }, // ---- Users ---- openNewUser() { this.user = { id: null, username: '', email: '', password: '', role: 'user', active: true }; this.$refs.userDialog.showModal(); }, openEditUser(u) { this.user = { id: u.id, username: u.username, email: u.email || '', password: '', role: u.role, active: !!u.active }; this.$refs.userDialog.showModal(); }, async saveUser() { try { if (this.user.id) { const body = { email: this.user.email, role: this.user.role, active: this.user.active }; if (this.user.password) body.password = this.user.password; await API.patch(`/api/users/${this.user.id}`, body); } else { await API.post('/api/users', { username: this.user.username, email: this.user.email, password: this.user.password, role: this.user.role, active: this.user.active, }); } this.$refs.userDialog.close(); await this.loadUsers(); } catch (e) { this.toast(e.message); } }, async deleteUser(u) { if (!confirm(`Delete user "${u.username}"? Their projects and KPIs will also be removed.`)) return; try { await API.del(`/api/users/${u.id}`); await this.loadUsers(); } catch (e) { this.toast(e.message); } }, // ---- Schemes ---- openNewScheme() { this.scheme = { id: null, name: '', seed_color: '#1565c0', mode: 'light', is_default: false }; this.$refs.schemeDialog.showModal(); }, openEditScheme(s) { this.scheme = { id: s.id, name: s.name, seed_color: s.seed_color, mode: s.mode, is_default: !!s.is_default }; this.$refs.schemeDialog.showModal(); }, previewScheme() { Theme.apply({ seed_color: this.scheme.seed_color, mode: this.scheme.mode }); }, async saveScheme() { try { const body = { name: this.scheme.name, seed_color: this.scheme.seed_color, mode: this.scheme.mode, is_default: this.scheme.is_default, }; if (this.scheme.id) await API.patch(`/api/schemes/${this.scheme.id}`, body); else await API.post('/api/schemes', body); this.$refs.schemeDialog.close(); await this.loadSchemes(); // Restore the admin's own theme after previewing. await Theme.apply(Theme.resolve(this.schemes, this.me.preferred_scheme_id)); } catch (e) { this.toast(e.message); } }, async deleteScheme(s) { if (!confirm(`Delete scheme "${s.name}"?`)) return; try { await API.del(`/api/schemes/${s.id}`); await this.loadSchemes(); } catch (e) { this.toast(e.message); } }, toast(msg) { this.error = msg; if (typeof window.ui === 'function') window.ui('#snackbar'); }, }; } window.adminApp = adminApp;