import { addRoute, startRouter, navigate } from './router.js'; import { loginPage } from './pages/login.js'; import { homeDashboardPage } from './pages/home.js'; import { questionnairesPage } from './pages/questionnaires.js'; import { editorPage } from './pages/editor.js'; import { resultsPage } from './pages/results.js'; import { exportPage } from './pages/export.js'; import { usersPage } from './pages/users.js'; import { assignmentsPage } from './pages/assignments.js'; import { clientsPage } from './pages/clients.js'; import { translationsPage } from './pages/translations.js'; import { devPage } from './pages/dev.js'; import { insightsPage } from './pages/insights.js'; import { coachesPage } from './pages/coaches.js'; // Auth state export function isLoggedIn() { return !!localStorage.getItem('qdb_token'); } export function getRole() { return localStorage.getItem('qdb_role') || ''; } export function getUser() { return localStorage.getItem('qdb_user') || ''; } const WEBSITE_ROLES = ['admin', 'supervisor']; export function canAccessWebsite() { return WEBSITE_ROLES.includes(getRole()); } export function canEdit() { return canAccessWebsite(); } function clearSession() { localStorage.removeItem('qdb_token'); localStorage.removeItem('qdb_role'); localStorage.removeItem('qdb_user'); } function logout() { clearSession(); navigate('#/login'); } function rejectCoachSession() { clearSession(); showToast('Coach accounts must use the mobile app.', 'error'); navigate('#/login'); } /** Link to home dashboard (#/). */ export const HOME_HREF = '#/'; const HOME_ICON_SVG = ``; /** House icon button — returns to dashboard. */ export function homeNavButton(title = 'Dashboard') { return `${HOME_ICON_SVG}`; } /** * Standard page header with home button. * @param {string} title HTML-safe title text * @param {string} [actionsHTML] optional buttons inside .actions * @param {{ subtitle?: string }} [opts] */ export function pageHeaderHTML(title, actionsHTML = '', opts = {}) { const subtitle = opts.subtitle ? `

${opts.subtitle}

` : ''; return ` `; } export function showToast(message, type = 'info') { const container = document.getElementById('toastContainer'); const toast = document.createElement('div'); toast.className = `toast toast-${type}`; toast.textContent = message; container.appendChild(toast); requestAnimationFrame(() => toast.classList.add('show')); setTimeout(() => { toast.classList.remove('show'); setTimeout(() => toast.remove(), 300); }, 3000); } function authGuard(handler) { return (params) => { if (!isLoggedIn()) { navigate('#/login'); return; } if (!canAccessWebsite()) { rejectCoachSession(); return; } return handler(params); }; } function updateNav() { const nav = document.getElementById('mainNav'); const userInfo = document.getElementById('userInfo'); document.body.classList.toggle('logged-in', isLoggedIn()); if (isLoggedIn()) { nav.style.display = ''; const role = getRole(); userInfo.textContent = `${getUser()} (${role})`; // Show/hide role-gated nav items document.querySelectorAll('[data-nav-roles]').forEach(li => { const allowed = li.dataset.navRoles.split(' '); li.style.display = allowed.includes(role) ? '' : 'none'; }); // Highlight active nav link const hash = window.location.hash.slice(1) || '/'; document.querySelectorAll('.sidebar-nav a').forEach(a => { const href = a.getAttribute('href').slice(1); let active = hash === href; if (!active && href === '/questionnaires' && hash.startsWith('/questionnaire')) { active = true; } if (!active && href !== '/' && hash.startsWith(href)) { active = true; } a.classList.toggle('active', active); }); } else { nav.style.display = 'none'; userInfo.textContent = ''; } } function roleGuard(roles, handler) { return (params) => { if (!isLoggedIn()) { navigate('#/login'); return; } if (!roles.includes(getRole())) { navigate('#/'); return; } return handler(params); }; } // Routes addRoute('/login', loginPage); addRoute('/', roleGuard(['admin', 'supervisor'], homeDashboardPage)); addRoute('/questionnaires', authGuard(questionnairesPage)); addRoute('/questionnaire/new', authGuard(editorPage)); addRoute('/questionnaire/:id/results', authGuard(resultsPage)); addRoute('/questionnaire/:id', authGuard(editorPage)); addRoute('/export', authGuard(exportPage)); addRoute('/users', roleGuard(['admin', 'supervisor'], usersPage)); addRoute('/assignments', roleGuard(['admin', 'supervisor'], assignmentsPage)); addRoute('/clients', roleGuard(['admin', 'supervisor'], clientsPage)); addRoute('/translations', roleGuard(['admin', 'supervisor'], translationsPage)); addRoute('/insights', roleGuard(['admin', 'supervisor'], insightsPage)); addRoute('/coaches', roleGuard(['admin', 'supervisor'], coachesPage)); addRoute('/dev', roleGuard(['admin'], devPage)); // Nav link handling & logout document.addEventListener('DOMContentLoaded', () => { const bindLogout = (el) => { if (!el) return; el.addEventListener('click', (e) => { e.preventDefault(); logout(); }); }; bindLogout(document.getElementById('logoutBtn')); bindLogout(document.getElementById('mobileLogoutBtn')); if (isLoggedIn() && !canAccessWebsite()) { clearSession(); } window.addEventListener('hashchange', updateNav); updateNav(); startRouter(); });