From 8a9e7394390ff268ca527f087f6b6c78f500f74d Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Thu, 29 Jan 2026 15:56:25 -0500 Subject: [PATCH] chore: add generated header.js file - Add compiled header.js to git ignore - Required for header functionality to work - Generated from TypeScript source --- web/static/header.js | 101 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 web/static/header.js diff --git a/web/static/header.js b/web/static/header.js new file mode 100644 index 0000000..3e833a7 --- /dev/null +++ b/web/static/header.js @@ -0,0 +1,101 @@ +"use strict"; +// Header functionality +const toggleThemeDropdown = () => { + const dropdown = document.getElementById('theme-dropdown'); + if (dropdown) { + dropdown.classList.toggle('hidden'); + // Close user menu if open + const userMenu = document.getElementById('user-menu'); + if (userMenu && !dropdown.classList.contains('hidden')) { + userMenu.classList.add('hidden'); + } + } +}; +const toggleUserMenu = () => { + const menu = document.getElementById('user-menu'); + if (menu) { + menu.classList.toggle('hidden'); + // Close theme dropdown if open + const themeDropdown = document.getElementById('theme-dropdown'); + if (themeDropdown && !menu.classList.contains('hidden')) { + themeDropdown.classList.add('hidden'); + } + } +}; +const changeThemeTo = (theme) => { + // Apply the theme + if (theme.startsWith('wood-')) { + // Apply wood background theme + document.body.className = `theme-${theme}`; + // Set wood background style + let woodGradient = ''; + switch (theme) { + case 'wood-light': + woodGradient = 'linear-gradient(135deg, #deb887 0%, #d2a679 50%, #c9975b 100%)'; + break; + case 'wood-dark': + woodGradient = 'linear-gradient(135deg, #8b7355 0%, #6b5344 50%, #5a4636 100%)'; + break; + case 'wood-mahogany': + woodGradient = 'linear-gradient(135deg, #a0522d 0%, #8b4513 50%, #7a3c10 100%)'; + break; + } + document.body.style.background = woodGradient; + document.body.style.backgroundSize = 'cover'; + document.body.style.backgroundAttachment = 'fixed'; + } + else { + // Apply regular theme + document.body.className = `theme-${theme}`; + document.body.style.background = ''; + document.body.style.backgroundSize = ''; + document.body.style.backgroundAttachment = ''; + } + // Save to localStorage + localStorage.setItem('theme', theme); + // Save to server if logged in + const token = localStorage.getItem('token'); + if (token) { + fetch('/api/auth/theme', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ theme }) + }).catch(err => console.log('Theme save failed', err)); + } + // Close dropdown + const dropdown = document.getElementById('theme-dropdown'); + if (dropdown) { + dropdown.classList.add('hidden'); + } +}; +const logout = () => { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/'; +}; +// Close dropdowns when clicking outside +document.addEventListener('click', (e) => { + const target = e.target; + const themeDropdown = document.getElementById('theme-dropdown'); + const userMenu = document.getElementById('user-menu'); + const themeButton = target?.closest('button[onclick="toggleThemeDropdown()"]'); + const userButton = target?.closest('button[onclick="toggleUserMenu()"]'); + if (!themeButton && themeDropdown && !themeDropdown.classList.contains('hidden')) { + if (!themeDropdown.contains(target)) { + themeDropdown.classList.add('hidden'); + } + } + if (!userButton && userMenu && !userMenu.classList.contains('hidden')) { + if (!userMenu.contains(target)) { + userMenu.classList.add('hidden'); + } + } +}); +// Make functions available globally +window.toggleThemeDropdown = toggleThemeDropdown; +window.toggleUserMenu = toggleUserMenu; +window.changeThemeTo = changeThemeTo; +window.logout = logout;