Add advanced search and trending parks features; update frontend dependencies and enhance home page layout

This commit is contained in:
pacnpal
2025-09-27 09:42:12 -04:00
parent e1cb76f1c6
commit 6575ea68c7
10 changed files with 233 additions and 65 deletions

View File

@@ -48,7 +48,6 @@
<!-- Preload Critical Resources -->
{% block critical_resources %}
<link rel="preload" href="{% static 'css/tailwind.css' %}" as="style" />
<link rel="preload" href="{% static 'js/alpine.min.js' %}?v={{ version|default:'1.0' }}" as="script" />
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" as="style" />
{% endblock %}
@@ -62,10 +61,10 @@
/>
<!-- HTMX -->
<script src="https://unpkg.com/htmx.org@1.9.6" integrity="sha384-FhXw7b6AlE/jyjlZH5iHa/tTe9EpJ1Y55RjcgPbjeWMskSxZt1v9qkxLJWNJaGni" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js" integrity="sha384-yWakaGAFicqusuwOYEmoRjLNOC+6OFsdmwC2lbGQaRELtuVEqNzt11c2J711DeCZ" crossorigin="anonymous"></script>
<!-- Alpine.js (must load after components) -->
<script defer src="{% static 'js/alpine.min.js' %}?v={{ version|default:'1.0' }}"></script>
<script src="//unpkg.com/alpinejs" defer></script>
<!-- Tailwind CSS -->
<link href="{% static 'css/tailwind.css' %}" rel="stylesheet" />
@@ -173,40 +172,60 @@
<c-toast_container />
<!-- 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: []
});
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);
<script>
document.addEventListener('alpine:init', () => {
// Configure HTMX 2.x globally with proper defaults
htmx.config.globalViewTransitions = true;
// HTMX 2.x Migration: Maintain 1.x behavior for smooth scrolling
htmx.config.scrollBehavior = 'smooth';
// HTMX 2.x Migration: Keep DELETE requests using form-encoded body (like 1.x)
htmx.config.methodsThatUseUrlParams = ["get"];
// HTMX 2.x Migration: Allow cross-domain requests (like 1.x)
htmx.config.selfRequestsOnly = false;
// Enhanced HTMX event handling for better UX
document.body.addEventListener('htmx:configRequest', function(evt) {
// Add CSRF token to all HTMX requests
const csrfToken = document.querySelector('meta[name="csrf-token"]');
if (csrfToken) {
evt.detail.headers['X-CSRFToken'] = csrfToken.getAttribute('content');
}
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);
});
// Initialize Alpine stores
Alpine.store('app', {
user: null,
theme: localStorage.getItem('theme') || 'system',
searchQuery: '',
notifications: []
});
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>
</script>
{% block extra_js %}{% endblock %}
</body>

View File

@@ -51,9 +51,9 @@
<span class="absolute -bottom-1 left-0 w-0 h-0.5 bg-gradient-to-r from-thrill-primary to-purple-500 transition-all duration-300 group-hover:w-full"></span>
</a>
<a href="{% url 'rides:list' %}"
<a href="{% url 'rides:global_ride_list' %}"
class="nav-link group relative"
hx-get="{% url 'rides:list' %}"
hx-get="{% url 'rides:global_ride_list' %}"
hx-target="#main-content"
hx-swap="innerHTML transition:true">
<i class="fas fa-rocket mr-2 text-thrill-secondary"></i>
@@ -367,7 +367,7 @@
<span class="font-medium">Parks</span>
</a>
<a href="{% url 'rides:ride_list' %}"
<a href="{% url 'rides:global_ride_list' %}"
class="flex items-center p-3 rounded-lg hover:bg-neutral-100/50 dark:hover:bg-neutral-700/50 transition-colors"
@click="isOpen = false">
<i class="fas fa-rocket mr-3 text-thrill-secondary"></i>

View File

@@ -98,46 +98,67 @@
</div>
<!-- Featured Parks Grid -->
<div class="grid-auto-fit-lg"
hx-get="/api/parks/featured/"
hx-trigger="revealed"
hx-swap="innerHTML">
<!-- Loading Skeletons -->
<div class="grid-auto-fit-lg">
<!-- Static placeholder content -->
<div class="card hover-lift">
<div class="loading-skeleton aspect-video rounded-t-2xl"></div>
<div class="p-6 space-y-4">
<div class="loading-skeleton h-6 w-3/4 rounded"></div>
<div class="loading-skeleton h-4 w-full rounded"></div>
<div class="loading-skeleton h-4 w-2/3 rounded"></div>
<div class="aspect-video rounded-t-2xl bg-gradient-to-br from-thrill-primary to-purple-500 flex items-center justify-center">
<i class="fas fa-map-marked-alt text-4xl text-white"></i>
</div>
<div class="p-6">
<h3 class="text-xl font-bold mb-2">Explore Amazing Parks</h3>
<p class="text-neutral-600 dark:text-neutral-400 mb-4">
Discover incredible theme parks from around the world with detailed guides and insider tips.
</p>
<div class="flex justify-between items-center">
<div class="loading-skeleton h-6 w-20 rounded-full"></div>
<div class="loading-skeleton h-8 w-24 rounded-lg"></div>
<span class="badge badge-primary">Featured</span>
<button class="btn-primary btn-sm"
hx-get="/parks/"
hx-target="#main-content"
hx-swap="innerHTML transition:true">
View All
</button>
</div>
</div>
</div>
<div class="card hover-lift">
<div class="loading-skeleton aspect-video rounded-t-2xl"></div>
<div class="p-6 space-y-4">
<div class="loading-skeleton h-6 w-3/4 rounded"></div>
<div class="loading-skeleton h-4 w-full rounded"></div>
<div class="loading-skeleton h-4 w-2/3 rounded"></div>
<div class="aspect-video rounded-t-2xl bg-gradient-to-br from-thrill-secondary to-red-500 flex items-center justify-center">
<i class="fas fa-rocket text-4xl text-white"></i>
</div>
<div class="p-6">
<h3 class="text-xl font-bold mb-2">Thrilling Rides</h3>
<p class="text-neutral-600 dark:text-neutral-400 mb-4">
From heart-pounding roller coasters to magical dark rides, find your next adventure.
</p>
<div class="flex justify-between items-center">
<div class="loading-skeleton h-6 w-20 rounded-full"></div>
<div class="loading-skeleton h-8 w-24 rounded-lg"></div>
<span class="badge badge-secondary">Popular</span>
<button class="btn-secondary btn-sm"
hx-get="/rides/"
hx-target="#main-content"
hx-swap="innerHTML transition:true">
Explore
</button>
</div>
</div>
</div>
<div class="card hover-lift">
<div class="loading-skeleton aspect-video rounded-t-2xl"></div>
<div class="p-6 space-y-4">
<div class="loading-skeleton h-6 w-3/4 rounded"></div>
<div class="loading-skeleton h-4 w-full rounded"></div>
<div class="loading-skeleton h-4 w-2/3 rounded"></div>
<div class="aspect-video rounded-t-2xl bg-gradient-to-br from-thrill-success to-teal-500 flex items-center justify-center">
<i class="fas fa-search text-4xl text-white"></i>
</div>
<div class="p-6">
<h3 class="text-xl font-bold mb-2">Advanced Search</h3>
<p class="text-neutral-600 dark:text-neutral-400 mb-4">
Find exactly what you're looking for with our powerful search and filtering tools.
</p>
<div class="flex justify-between items-center">
<div class="loading-skeleton h-6 w-20 rounded-full"></div>
<div class="loading-skeleton h-8 w-24 rounded-lg"></div>
<span class="badge badge-success">Tools</span>
<button class="btn-success btn-sm"
hx-get="/search/"
hx-target="#main-content"
hx-swap="innerHTML transition:true">
Search
</button>
</div>
</div>
</div>