mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 02:31:08 -05:00
243 lines
8.7 KiB
HTML
243 lines
8.7 KiB
HTML
{% extends 'base/base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}{{ page_title }} - ThrillWiki{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
<!-- Leaflet CSS -->
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
<!-- Leaflet MarkerCluster CSS -->
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css" />
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css" />
|
|
|
|
<style>
|
|
.map-container {
|
|
height: 70vh;
|
|
min-height: 500px;
|
|
border-radius: 0.5rem;
|
|
overflow: hidden;
|
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.map-controls {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
z-index: 1000;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 0.5rem;
|
|
padding: 1rem;
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.dark .map-controls {
|
|
background: rgba(31, 41, 55, 0.95);
|
|
}
|
|
|
|
.filter-pill {
|
|
@apply inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200 cursor-pointer transition-colors;
|
|
}
|
|
|
|
.filter-pill.active {
|
|
@apply bg-blue-500 text-white dark:bg-blue-600;
|
|
}
|
|
|
|
.filter-pill:hover {
|
|
@apply bg-gray-200 dark:bg-gray-600;
|
|
}
|
|
|
|
.filter-pill.active:hover {
|
|
@apply bg-blue-600 dark:bg-blue-700;
|
|
}
|
|
|
|
.location-info-popup {
|
|
max-width: 300px;
|
|
}
|
|
|
|
.location-info-popup h3 {
|
|
margin: 0 0 0.5rem 0;
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.location-info-popup p {
|
|
margin: 0.25rem 0;
|
|
font-size: 0.9rem;
|
|
color: #666;
|
|
}
|
|
|
|
.dark .location-info-popup p {
|
|
color: #ccc;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container px-4 mx-auto">
|
|
<!-- Header -->
|
|
<div class="flex flex-col items-start justify-between gap-4 mb-6 md:flex-row md:items-center">
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">{{ page_title }}</h1>
|
|
<p class="mt-2 text-gray-600 dark:text-gray-400">
|
|
Explore theme parks, rides, and attractions from around the world
|
|
</p>
|
|
</div>
|
|
<div class="flex gap-3">
|
|
<a href="{% url 'maps:park_map' %}"
|
|
class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors">
|
|
<i class="mr-2 fas fa-map-marker-alt"></i>Parks Only
|
|
</a>
|
|
<a href="{% url 'maps:location_list' %}"
|
|
class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600 transition-colors">
|
|
<i class="mr-2 fas fa-list"></i>List View
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters Panel -->
|
|
<div class="p-4 mb-6 bg-white rounded-lg shadow dark:bg-gray-800">
|
|
<form id="map-filters"
|
|
hx-get="{% url 'maps:htmx_filter' %}"
|
|
hx-trigger="change, submit"
|
|
hx-target="#map-container"
|
|
hx-swap="none"
|
|
hx-push-url="false">
|
|
|
|
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:grid-cols-4">
|
|
<!-- Search -->
|
|
<div>
|
|
<label for="search" class="block mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">Search</label>
|
|
<input type="text" name="q" id="search"
|
|
class="w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white"
|
|
placeholder="Search locations..."
|
|
hx-get="{% url 'maps:htmx_search' %}"
|
|
hx-trigger="input changed delay:500ms"
|
|
hx-target="#search-results"
|
|
hx-indicator="#search-loading">
|
|
</div>
|
|
|
|
<!-- Country -->
|
|
<div>
|
|
<label for="country" class="block mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">Country</label>
|
|
<input type="text" name="country" id="country"
|
|
class="w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white"
|
|
placeholder="Filter by country...">
|
|
</div>
|
|
|
|
<!-- State/Region -->
|
|
<div>
|
|
<label for="state" class="block mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">State/Region</label>
|
|
<input type="text" name="state" id="state"
|
|
class="w-full border-gray-300 rounded-lg form-input dark:border-gray-600 dark:bg-gray-700 dark:text-white"
|
|
placeholder="Filter by state...">
|
|
</div>
|
|
|
|
<!-- Clustering Toggle -->
|
|
<div class="flex items-end">
|
|
<label class="flex items-center cursor-pointer">
|
|
<input type="checkbox" name="cluster" value="true" id="cluster-toggle"
|
|
class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
|
|
checked>
|
|
<span class="ml-2 text-sm font-medium text-gray-700 dark:text-gray-300">Enable Clustering</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Location Type Filters -->
|
|
<div class="mb-4">
|
|
<label class="block mb-2 text-sm font-medium text-gray-700 dark:text-gray-300">Location Types</label>
|
|
<div class="flex flex-wrap gap-2">
|
|
{% for type in location_types %}
|
|
<label class="filter-pill" data-type="{{ type }}">
|
|
<input type="checkbox" name="types" value="{{ type }}"
|
|
class="hidden location-type-checkbox"
|
|
{% if type in initial_location_types %}checked{% endif %}>
|
|
<i class="mr-2 fas fa-{% if type == 'park' %}map-marker-alt{% elif type == 'ride' %}rocket{% elif type == 'company' %}building{% else %}map-pin{% endif %}"></i>
|
|
{{ type|title }}
|
|
</label>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Search Results -->
|
|
<div id="search-results" class="mt-4"></div>
|
|
<div id="search-loading" class="htmx-indicator">
|
|
<div class="flex items-center justify-center p-4">
|
|
<div class="w-6 h-6 border-2 border-blue-500 rounded-full border-t-transparent animate-spin"></div>
|
|
<span class="ml-2 text-sm text-gray-600 dark:text-gray-400">Searching...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Map Container -->
|
|
<div class="relative">
|
|
<div id="map-container" class="map-container"></div>
|
|
|
|
<!-- Map Loading Indicator -->
|
|
<div id="map-loading" class="htmx-indicator absolute inset-0 flex items-center justify-center bg-gray-100 dark:bg-gray-800 rounded-lg">
|
|
<div class="text-center">
|
|
<div class="w-8 h-8 mx-auto mb-4 border-4 border-blue-500 rounded-full border-t-transparent animate-spin"></div>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">Loading map data...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Location Details Modal -->
|
|
<div id="location-modal" class="fixed inset-0 z-50 hidden">
|
|
<!-- Modal content will be loaded here via HTMX -->
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<!-- Leaflet JS -->
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
|
<!-- Leaflet MarkerCluster JS -->
|
|
<script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
|
|
|
|
<!-- AlpineJS Map Component (HTMX + AlpineJS Only) -->
|
|
<div x-data="universalMap" x-init="initMap()" style="display: none;">
|
|
<!-- Map functionality handled by AlpineJS + HTMX -->
|
|
</div>
|
|
|
|
<style>
|
|
.cluster-marker {
|
|
background: transparent;
|
|
border: none;
|
|
}
|
|
|
|
.cluster-marker-inner {
|
|
background: #3b82f6;
|
|
color: white;
|
|
border-radius: 50%;
|
|
width: 40px;
|
|
height: 40px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: bold;
|
|
font-size: 14px;
|
|
border: 3px solid white;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
|
}
|
|
|
|
.location-marker {
|
|
background: transparent;
|
|
border: none;
|
|
}
|
|
|
|
.location-marker-inner {
|
|
font-size: 20px;
|
|
text-align: center;
|
|
line-height: 30px;
|
|
filter: drop-shadow(2px 2px 4px rgba(0,0,0,0.3));
|
|
}
|
|
|
|
.dark .cluster-marker-inner {
|
|
border-color: #374151;
|
|
}
|
|
</style>
|
|
{% endblock %}
|