mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 18:11:08 -05:00
Refactor search results template to utilize Alpine.js for view switching and state management. Enhanced view mode handling and integrated HTMX for improved search functionality.
This commit is contained in:
@@ -41,9 +41,9 @@
|
|||||||
|
|
||||||
<!-- Right side: View switching buttons -->
|
<!-- Right side: View switching buttons -->
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="flex bg-gray-100 dark:bg-gray-700 rounded-lg p-1" x-data="{ viewMode: '{{ request.GET.view_mode|default:'grid' }}' }">
|
<div class="flex bg-gray-100 dark:bg-gray-700 rounded-lg p-1" x-data="searchViewSwitcher">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
@click="viewMode = 'grid'; switchView('grid')"
|
@click="switchView('grid')"
|
||||||
:class="viewMode === 'grid' ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm' : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'"
|
:class="viewMode === 'grid' ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm' : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'"
|
||||||
class="flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors">
|
class="flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
@click="viewMode = 'list'; switchView('list')"
|
@click="switchView('list')"
|
||||||
:class="viewMode === 'list' ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm' : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'"
|
:class="viewMode === 'list' ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm' : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'"
|
||||||
class="flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors">
|
class="flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Results Container -->
|
<!-- Results Container -->
|
||||||
<div id="results-container" class="divide-y divide-gray-200 dark:divide-gray-700" x-data="{ viewMode: '{{ request.GET.view_mode|default:'grid' }}' }">
|
<div id="results-container" class="divide-y divide-gray-200 dark:divide-gray-700" x-data="searchResults">
|
||||||
<!-- Grid View -->
|
<!-- Grid View -->
|
||||||
<div x-show="viewMode === 'grid'" class="p-6">
|
<div x-show="viewMode === 'grid'" class="p-6">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
@@ -235,64 +235,64 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Include required scripts #}
|
|
||||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
|
||||||
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
|
||||||
<script src="https://unpkg.com/unpoly@3/unpoly.min.js"></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// View switching functionality
|
document.addEventListener('alpine:init', () => {
|
||||||
function switchView(mode) {
|
// Search View Switcher Component
|
||||||
|
Alpine.data('searchViewSwitcher', () => ({
|
||||||
|
viewMode: '{{ request.GET.view_mode|default:"grid" }}',
|
||||||
|
|
||||||
|
init() {
|
||||||
|
// Initialize view mode from URL or localStorage
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const urlViewMode = urlParams.get('view_mode');
|
||||||
|
const savedViewMode = localStorage.getItem('parkViewMode');
|
||||||
|
this.viewMode = urlViewMode || savedViewMode || 'grid';
|
||||||
|
|
||||||
|
// Set initial view mode in URL if not present
|
||||||
|
if (!urlViewMode) {
|
||||||
|
const url = new URL(window.location);
|
||||||
|
url.searchParams.set('view_mode', this.viewMode);
|
||||||
|
window.history.replaceState({}, '', url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
switchView(mode) {
|
||||||
|
this.viewMode = mode;
|
||||||
|
|
||||||
// Update URL parameter
|
// Update URL parameter
|
||||||
const url = new URL(window.location);
|
const url = new URL(window.location);
|
||||||
url.searchParams.set('view_mode', mode);
|
url.searchParams.set('view_mode', mode);
|
||||||
|
|
||||||
// Update the URL without reloading
|
|
||||||
window.history.pushState({}, '', url);
|
window.history.pushState({}, '', url);
|
||||||
|
|
||||||
// Store preference in localStorage
|
// Store preference in localStorage
|
||||||
localStorage.setItem('parkViewMode', mode);
|
localStorage.setItem('parkViewMode', mode);
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize view mode from URL or localStorage
|
// Update results container view mode
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
this.$dispatch('view-mode-changed', { mode });
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
const urlViewMode = urlParams.get('view_mode');
|
|
||||||
const savedViewMode = localStorage.getItem('parkViewMode');
|
|
||||||
const defaultViewMode = urlViewMode || savedViewMode || 'grid';
|
|
||||||
|
|
||||||
// Set initial view mode
|
|
||||||
if (!urlViewMode) {
|
|
||||||
const url = new URL(window.location);
|
|
||||||
url.searchParams.set('view_mode', defaultViewMode);
|
|
||||||
window.history.replaceState({}, '', url);
|
|
||||||
}
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Search Results Component
|
||||||
|
Alpine.data('searchResults', () => ({
|
||||||
|
viewMode: '{{ request.GET.view_mode|default:"grid" }}',
|
||||||
|
|
||||||
|
init() {
|
||||||
|
// Listen for view mode changes
|
||||||
|
this.$el.addEventListener('view-mode-changed', (event) => {
|
||||||
|
this.viewMode = event.detail.mode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enhanced search functionality
|
// Enhanced search functionality with HTMX integration
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const searchInput = document.querySelector('input[name="search"]');
|
const searchInput = document.querySelector('input[name="search"]');
|
||||||
if (searchInput) {
|
if (searchInput) {
|
||||||
let searchTimeout;
|
|
||||||
|
|
||||||
// Preserve view mode in search requests
|
// Preserve view mode in search requests
|
||||||
searchInput.addEventListener('input', function(e) {
|
searchInput.addEventListener('htmx:configRequest', function(event) {
|
||||||
clearTimeout(searchTimeout);
|
|
||||||
searchTimeout = setTimeout(() => {
|
|
||||||
// Get current view mode
|
|
||||||
const currentViewMode = new URLSearchParams(window.location.search).get('view_mode') || 'grid';
|
const currentViewMode = new URLSearchParams(window.location.search).get('view_mode') || 'grid';
|
||||||
|
event.detail.parameters.view_mode = currentViewMode;
|
||||||
// Add view mode to the HTMX request
|
|
||||||
const currentUrl = new URL(e.target.getAttribute('hx-get'), window.location.origin);
|
|
||||||
currentUrl.searchParams.set('view_mode', currentViewMode);
|
|
||||||
currentUrl.searchParams.set('search', e.target.value);
|
|
||||||
|
|
||||||
// Update the hx-get attribute
|
|
||||||
e.target.setAttribute('hx-get', currentUrl.pathname + currentUrl.search);
|
|
||||||
|
|
||||||
// Trigger the HTMX request
|
|
||||||
htmx.trigger(e.target, 'input');
|
|
||||||
}, 500);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user