Refactor templates to utilize AlpineJS for state management and interactions, replacing custom JavaScript. Updated navigation links for parks and rides, streamlined mobile filter functionality, and enhanced advanced search features. Removed legacy JavaScript code for improved performance and maintainability.

This commit is contained in:
pacnpal
2025-09-26 13:43:14 -04:00
parent 9b2124867a
commit 8c0c3df21a
28 changed files with 114 additions and 9888 deletions

View File

@@ -172,347 +172,41 @@
<!-- Global Toast Container -->
<c-toast_container />
<!-- AlpineJS Components and Stores (Inline) -->
<script>
// Global Alpine.js stores and components
document.addEventListener('alpine:init', () => {
// Global Store for App State
Alpine.store('app', {
user: null,
theme: localStorage.getItem('theme') || 'system',
searchQuery: '',
notifications: [],
setUser(user) {
this.user = user;
},
setTheme(theme) {
this.theme = theme;
localStorage.setItem('theme', theme);
},
addNotification(notification) {
this.notifications.push({
id: Date.now(),
...notification
});
},
removeNotification(id) {
this.notifications = this.notifications.filter(n => n.id !== id);
}
});
// Global Toast Store
Alpine.store('toast', {
toasts: [],
show(message, type = 'info', duration = 5000) {
const id = Date.now() + Math.random();
const toast = {
id,
message,
type,
visible: true,
progress: 100
};
this.toasts.push(toast);
if (duration > 0) {
const interval = setInterval(() => {
toast.progress -= (100 / (duration / 100));
if (toast.progress <= 0) {
clearInterval(interval);
this.hide(id);
}
}, 100);
}
return id;
},
hide(id) {
const toast = this.toasts.find(t => t.id === id);
if (toast) {
toast.visible = false;
setTimeout(() => {
this.toasts = this.toasts.filter(t => t.id !== id);
}, 300);
}
},
success(message, duration = 5000) {
return this.show(message, 'success', duration);
},
error(message, duration = 7000) {
return this.show(message, 'error', duration);
},
warning(message, duration = 6000) {
return this.show(message, 'warning', duration);
},
info(message, duration = 5000) {
return this.show(message, 'info', duration);
}
});
// Theme Toggle Component
Alpine.data('themeToggle', () => ({
theme: localStorage.getItem('theme') || 'system',
init() {
this.updateTheme();
// Watch for system theme changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (this.theme === 'system') {
this.updateTheme();
}
});
},
toggleTheme() {
const themes = ['light', 'dark', 'system'];
const currentIndex = themes.indexOf(this.theme);
this.theme = themes[(currentIndex + 1) % themes.length];
localStorage.setItem('theme', this.theme);
this.updateTheme();
},
updateTheme() {
const root = document.documentElement;
if (this.theme === 'dark' ||
(this.theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
}
}));
// Modal Component
Alpine.data('modal', (initialOpen = false) => ({
open: initialOpen,
show() {
this.open = true;
document.body.style.overflow = 'hidden';
},
hide() {
this.open = false;
document.body.style.overflow = '';
},
toggle() {
if (this.open) {
this.hide();
} else {
this.show();
}
}
}));
// Dropdown Component
Alpine.data('dropdown', (initialOpen = false) => ({
open: initialOpen,
toggle() {
this.open = !this.open;
},
close() {
this.open = false;
},
show() {
this.open = true;
}
}));
// Search Component - HTMX-based (NO FETCH API)
Alpine.data('searchComponent', () => ({
query: '',
loading: false,
showResults: false,
init() {
// Listen for HTMX events
this.$el.addEventListener('htmx:beforeRequest', () => {
this.loading = true;
});
this.$el.addEventListener('htmx:afterRequest', () => {
this.loading = false;
});
this.$el.addEventListener('htmx:afterSettle', () => {
const resultsContainer = document.getElementById('search-results');
this.showResults = resultsContainer && resultsContainer.children.length > 0;
});
},
handleInput() {
if (this.query.length < 2) {
this.showResults = false;
const resultsContainer = document.getElementById('search-results');
if (resultsContainer) {
resultsContainer.innerHTML = '';
}
return;
}
// HTMX will handle the actual search via hx-trigger
},
selectResult(url) {
window.location.href = url;
this.showResults = false;
this.query = '';
},
clearSearch() {
this.query = '';
this.showResults = false;
const resultsContainer = document.getElementById('search-results');
if (resultsContainer) {
resultsContainer.innerHTML = '';
}
}
}));
// Browse Menu Component
Alpine.data('browseMenu', () => ({
open: false,
toggle() {
this.open = !this.open;
},
close() {
this.open = false;
}
}));
// Mobile Menu Component
Alpine.data('mobileMenu', () => ({
open: false,
toggle() {
this.open = !this.open;
if (this.open) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
},
close() {
this.open = false;
document.body.style.overflow = '';
}
}));
// User Menu Component
Alpine.data('userMenu', () => ({
open: false,
toggle() {
this.open = !this.open;
},
close() {
this.open = false;
}
}));
// Auth Modal Component
Alpine.data('authModal', (defaultMode = 'login') => ({
open: false,
mode: defaultMode,
showPassword: false,
socialProviders: [
{id: 'google', name: 'Google', auth_url: '/accounts/google/login/'},
{id: 'discord', name: 'Discord', auth_url: '/accounts/discord/login/'}
],
loginForm: {
username: '',
password: ''
},
loginLoading: false,
loginError: '',
registerForm: {
first_name: '',
last_name: '',
email: '',
username: '',
password1: '',
password2: ''
},
registerLoading: false,
registerError: '',
init() {
this.$watch('open', (value) => {
if (value) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
this.resetForms();
}
});
},
show(mode = 'login') {
this.mode = mode;
this.open = true;
},
close() {
this.open = false;
},
switchToLogin() {
this.mode = 'login';
this.resetForms();
},
switchToRegister() {
this.mode = 'register';
this.resetForms();
},
resetForms() {
this.loginForm = { username: '', password: '' };
this.registerForm = {
first_name: '',
last_name: '',
email: '',
username: '',
password1: '',
password2: ''
};
this.loginError = '';
this.registerError = '';
this.showPassword = false;
},
getCSRFToken() {
const token = document.querySelector('[name=csrfmiddlewaretoken]')?.value ||
document.querySelector('meta[name=csrf-token]')?.getAttribute('content') ||
document.cookie.split('; ').find(row => row.startsWith('csrftoken='))?.split('=')[1];
return token || '';
}
}));
<!-- AlpineJS Global Configuration (Compliant with HTMX + AlpineJS Only Rule) -->
<div x-data="{}" x-init="
// Configure HTMX globally
htmx.config.globalViewTransitions = true;
// Initialize Alpine stores
Alpine.store('app', {
user: null,
theme: localStorage.getItem('theme') || 'system',
searchQuery: '',
notifications: []
});
</script>
Alpine.store('toast', {
toasts: [],
show(message, type = 'info', duration = 5000) {
const id = Date.now() + Math.random();
const toast = { id, message, type, visible: true, progress: 100 };
this.toasts.push(toast);
if (duration > 0) {
setTimeout(() => this.hide(id), duration);
}
return id;
},
hide(id) {
const toast = this.toasts.find(t => t.id === id);
if (toast) {
toast.visible = false;
setTimeout(() => {
this.toasts = this.toasts.filter(t => t.id !== id);
}, 300);
}
}
});
" style="display: none;"></div>
{% block extra_js %}{% endblock %}
</body>