diff --git a/assets/css/src/input.css b/assets/css/src/input.css index 80806056..a2468263 100644 --- a/assets/css/src/input.css +++ b/assets/css/src/input.css @@ -6,7 +6,22 @@ .btn-primary { @apply inline-flex items-center px-6 py-2.5 border border-transparent rounded-full shadow-md text-sm font-medium text-white bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-105 transition-all; } + /* Default icon style (moon icon) */ + #theme-toggle+.theme-toggle-btn i::before { + content: "\f186"; + /* Moon icon */ + font-family: "Font Awesome 5 Free"; + font-weight: 900; + /* Solid icon */ + } + /* Change to sun icon and color when checkbox is checked */ + #theme-toggle:checked+.theme-toggle-btn i::before { + content: "\f185"; + /* Sun icon */ + color: theme('colors.yellow.400'); + /* Tailwind yellow-400 color */ + } .btn-secondary { @apply inline-flex items-center px-6 py-2.5 border border-gray-200 dark:border-gray-700 rounded-full shadow-md text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-105 transition-all; } @@ -137,6 +152,6 @@ /* Turnstile Widget */ .turnstile { - @apply flex justify-center items-center my-4; + @apply flex items-center justify-center my-4; } } diff --git a/core/__pycache__/views.cpython-312.pyc b/core/__pycache__/views.cpython-312.pyc index d3f05fea..20f83571 100644 Binary files a/core/__pycache__/views.cpython-312.pyc and b/core/__pycache__/views.cpython-312.pyc differ diff --git a/static/css/tailwind.css b/static/css/tailwind.css index 28cc1094..db00e0da 100644 --- a/static/css/tailwind.css +++ b/static/css/tailwind.css @@ -1435,6 +1435,25 @@ select { --tw-ring-offset-width: 2px; } +/* Default icon style (moon icon) */ + +#theme-toggle+.theme-toggle-btn i::before { + content: "\f186"; + /* Moon icon */ + font-family: "Font Awesome 5 Free"; + font-weight: 900; + /* Solid icon */ +} + +/* Change to sun icon and color when checkbox is checked */ + +#theme-toggle:checked+.theme-toggle-btn i::before { + content: "\f185"; + /* Sun icon */ + color: #facc15; + /* Tailwind yellow-400 color */ +} + .btn-secondary { display: inline-flex; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -2098,18 +2117,10 @@ select { position: relative; } -.right-3 { - right: 0.75rem; -} - .top-1\/2 { top: 50%; } -.top-2\.5 { - top: 0.625rem; -} - .col-span-2 { grid-column: span 2 / span 2; } @@ -2305,6 +2316,10 @@ select { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.cursor-pointer { + cursor: pointer; +} + .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -2567,10 +2582,6 @@ select { background-color: rgb(255 255 255 / 0.7); } -.bg-white\/80 { - background-color: rgb(255 255 255 / 0.8); -} - .bg-white\/90 { background-color: rgb(255 255 255 / 0.9); } @@ -3156,10 +3167,6 @@ select { background-color: rgb(55 65 81 / 0.5); } -.dark\:bg-gray-700\/80:is(.dark *) { - background-color: rgb(55 65 81 / 0.8); -} - .dark\:bg-gray-800:is(.dark *) { --tw-bg-opacity: 1; background-color: rgb(31 41 55 / var(--tw-bg-opacity)); diff --git a/static/js/main.js b/static/js/main.js index e184c4cd..bed4458a 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -1,12 +1,28 @@ -// Initialize dark mode from localStorage +// Theme handling document.addEventListener('DOMContentLoaded', () => { - // Check if dark mode was previously enabled - const darkMode = localStorage.getItem('darkMode') === 'true'; - if (darkMode) { - document.documentElement.classList.add('dark'); - toggleIcons(true); // Ensure correct icon is shown - } else { - toggleIcons(false); + const themeToggle = document.getElementById('theme-toggle'); + const html = document.documentElement; + + // Initialize toggle state based on current theme + if (themeToggle) { + themeToggle.checked = html.classList.contains('dark'); + + // Handle toggle changes + themeToggle.addEventListener('change', function() { + const isDark = this.checked; + html.classList.toggle('dark', isDark); + localStorage.setItem('theme', isDark ? 'dark' : 'light'); + }); + + // Listen for system theme changes + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + mediaQuery.addEventListener('change', (e) => { + if (!localStorage.getItem('theme')) { + const isDark = e.matches; + html.classList.toggle('dark', isDark); + themeToggle.checked = isDark; + } + }); } }); @@ -20,18 +36,40 @@ document.addEventListener('submit', (e) => { } }); -// Close mobile menu when clicking outside -document.addEventListener('click', (e) => { - const mobileMenu = document.querySelector('[x-show="mobileMenuOpen"]'); - const menuButton = document.querySelector('[x-on\\:click="mobileMenuOpen = !mobileMenuOpen"]'); - - if (mobileMenu && menuButton && !mobileMenu.contains(e.target) && !menuButton.contains(e.target)) { - const alpineData = mobileMenu._x_dataStack && mobileMenu._x_dataStack[0]; - if (alpineData && alpineData.mobileMenuOpen) { - alpineData.mobileMenuOpen = false; +// Mobile menu toggle +const mobileMenuBtn = document.getElementById('mobileMenuBtn'); +const mobileMenu = document.getElementById('mobileMenu'); + +if (mobileMenuBtn && mobileMenu) { + mobileMenuBtn.addEventListener('click', () => { + mobileMenu.classList.toggle('hidden'); + }); +} + +// User dropdown toggle +const userMenuBtn = document.getElementById('userMenuBtn'); +const userDropdown = document.getElementById('userDropdown'); + +if (userMenuBtn && userDropdown) { + userMenuBtn.addEventListener('click', (e) => { + e.stopPropagation(); + userDropdown.classList.toggle('active'); + }); + + // Close dropdown when clicking outside + document.addEventListener('click', (e) => { + if (!userMenuBtn.contains(e.target) && !userDropdown.contains(e.target)) { + userDropdown.classList.remove('active'); } - } -}); + }); + + // Close dropdown when pressing escape + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + userDropdown.classList.remove('active'); + } + }); +} // Handle flash messages document.addEventListener('DOMContentLoaded', () => { @@ -51,7 +89,7 @@ document.addEventListener('DOMContentLoaded', () => { tooltip.addEventListener('mouseenter', (e) => { const text = e.target.getAttribute('data-tooltip'); const tooltipEl = document.createElement('div'); - tooltipEl.className = 'tooltip bg-gray-900 text-white px-2 py-1 rounded text-sm absolute z-50'; + tooltipEl.className = 'absolute z-50 px-2 py-1 text-sm text-white bg-gray-900 rounded tooltip'; tooltipEl.textContent = text; document.body.appendChild(tooltipEl); @@ -66,79 +104,3 @@ document.addEventListener('DOMContentLoaded', () => { }); }); }); - -// Handle dropdown menus -document.addEventListener('click', (e) => { - const dropdowns = document.querySelectorAll('[x-show]'); - dropdowns.forEach(dropdown => { - if (!dropdown.contains(e.target) && - !e.target.matches('[x-on\\:click*="open = !open"]')) { - const alpineData = dropdown._x_dataStack && dropdown._x_dataStack[0]; - if (alpineData && alpineData.open) { - alpineData.open = false; - } - } - }); -}); - -// Theme management -const themeManager = { - init() { - // Set up toggle button when DOM is loaded - document.addEventListener('DOMContentLoaded', () => { - const toggleBtn = document.getElementById('theme-toggle'); - if (toggleBtn) { - toggleBtn.addEventListener('click', () => { - this.toggleTheme(); - }); - } - - // Watch for system theme changes - window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { - if (!localStorage.theme) { - this.setTheme(e.matches ? 'dark' : 'light'); - } - }); - - // Set initial theme icon state - this.updateThemeIcon(); - }); - }, - - setTheme(theme) { - if (theme === 'dark') { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - - localStorage.setItem('theme', theme); - this.updateThemeIcon(); - }, - - toggleTheme() { - const isDark = document.documentElement.classList.contains('dark'); - this.setTheme(isDark ? 'light' : 'dark'); - }, - - updateThemeIcon() { - const isDark = document.documentElement.classList.contains('dark'); - const sunIcon = document.querySelector('#theme-toggle .fa-sun'); - const moonIcon = document.querySelector('#theme-toggle .fa-moon'); - - if (sunIcon && moonIcon) { - // Show sun icon in dark mode (to indicate you can switch to light) - // Show moon icon in light mode (to indicate you can switch to dark) - if (isDark) { - sunIcon.classList.remove('hidden'); - moonIcon.classList.add('hidden'); - } else { - sunIcon.classList.add('hidden'); - moonIcon.classList.remove('hidden'); - } - } - } -}; - -// Initialize theme management -themeManager.init(); diff --git a/templates/base/base.html b/templates/base/base.html index b6c64c4e..60fe9f37 100644 --- a/templates/base/base.html +++ b/templates/base/base.html @@ -1,252 +1,271 @@ {% load static %} -
- - + + +