mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 05:31:09 -05:00
- Implemented a new HTML template for the Road Trip Planner. - Integrated Leaflet.js for interactive mapping and routing. - Added functionality for searching and selecting parks to include in a trip. - Enabled drag-and-drop reordering of selected parks. - Included trip optimization and route calculation features. - Created a summary display for trip statistics. - Added functionality to save trips and manage saved trips. - Enhanced UI with responsive design and dark mode support.
165 lines
6.0 KiB
Python
165 lines
6.0 KiB
Python
from django.views.generic import TemplateView
|
|
from django.http import JsonResponse
|
|
from django.contrib.gis.geos import Point
|
|
from django.contrib.gis.measure import Distance
|
|
from parks.models import Park
|
|
from parks.filters import ParkFilter
|
|
from core.services.location_search import location_search_service, LocationSearchFilters
|
|
from core.forms.search import LocationSearchForm
|
|
|
|
class AdaptiveSearchView(TemplateView):
|
|
template_name = "core/search/results.html"
|
|
|
|
def get_queryset(self):
|
|
"""
|
|
Get the base queryset, optimized with select_related and prefetch_related
|
|
"""
|
|
return Park.objects.select_related('operator', 'property_owner').prefetch_related(
|
|
'location',
|
|
'photos'
|
|
).all()
|
|
|
|
def get_filterset(self):
|
|
"""
|
|
Get the filterset instance
|
|
"""
|
|
return ParkFilter(self.request.GET, queryset=self.get_queryset())
|
|
|
|
def get_context_data(self, **kwargs):
|
|
"""
|
|
Add filtered results and filter form to context
|
|
"""
|
|
context = super().get_context_data(**kwargs)
|
|
filterset = self.get_filterset()
|
|
|
|
# Check if location-based search is being used
|
|
location_search = self.request.GET.get('location_search', '').strip()
|
|
near_location = self.request.GET.get('near_location', '').strip()
|
|
|
|
# Add location search context
|
|
context.update({
|
|
'results': filterset.qs,
|
|
'filters': filterset,
|
|
'applied_filters': bool(self.request.GET), # Check if any filters are applied
|
|
'is_location_search': bool(location_search or near_location),
|
|
'location_search_query': location_search or near_location,
|
|
})
|
|
|
|
return context
|
|
|
|
class FilterFormView(TemplateView):
|
|
"""
|
|
View for rendering just the filter form for HTMX updates
|
|
"""
|
|
template_name = "core/search/filters.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
filterset = ParkFilter(self.request.GET, queryset=Park.objects.all())
|
|
context['filters'] = filterset
|
|
return context
|
|
|
|
|
|
class LocationSearchView(TemplateView):
|
|
"""
|
|
Enhanced search view with comprehensive location search capabilities.
|
|
"""
|
|
template_name = "core/search/location_results.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
# Build search filters from request parameters
|
|
filters = self._build_search_filters()
|
|
|
|
# Perform search
|
|
results = location_search_service.search(filters)
|
|
|
|
# Group results by type for better presentation
|
|
grouped_results = {
|
|
'parks': [r for r in results if r.content_type == 'park'],
|
|
'rides': [r for r in results if r.content_type == 'ride'],
|
|
'companies': [r for r in results if r.content_type == 'company'],
|
|
}
|
|
|
|
context.update({
|
|
'results': results,
|
|
'grouped_results': grouped_results,
|
|
'total_results': len(results),
|
|
'search_filters': filters,
|
|
'has_location_filter': bool(filters.location_point),
|
|
'search_form': LocationSearchForm(self.request.GET),
|
|
})
|
|
|
|
return context
|
|
|
|
def _build_search_filters(self) -> LocationSearchFilters:
|
|
"""Build LocationSearchFilters from request parameters."""
|
|
form = LocationSearchForm(self.request.GET)
|
|
form.is_valid() # Populate cleaned_data
|
|
|
|
# Parse location coordinates if provided
|
|
location_point = None
|
|
lat = form.cleaned_data.get('lat')
|
|
lng = form.cleaned_data.get('lng')
|
|
if lat and lng:
|
|
try:
|
|
location_point = Point(float(lng), float(lat), srid=4326)
|
|
except (ValueError, TypeError):
|
|
location_point = None
|
|
|
|
# Parse location types
|
|
location_types = set()
|
|
if form.cleaned_data.get('search_parks'):
|
|
location_types.add('park')
|
|
if form.cleaned_data.get('search_rides'):
|
|
location_types.add('ride')
|
|
if form.cleaned_data.get('search_companies'):
|
|
location_types.add('company')
|
|
|
|
# If no specific types selected, search all
|
|
if not location_types:
|
|
location_types = {'park', 'ride', 'company'}
|
|
|
|
# Parse radius
|
|
radius_km = None
|
|
radius_str = form.cleaned_data.get('radius_km', '').strip()
|
|
if radius_str:
|
|
try:
|
|
radius_km = float(radius_str)
|
|
radius_km = max(1, min(500, radius_km)) # Clamp between 1-500km
|
|
except (ValueError, TypeError):
|
|
radius_km = None
|
|
|
|
return LocationSearchFilters(
|
|
search_query=form.cleaned_data.get('q', '').strip() or None,
|
|
location_point=location_point,
|
|
radius_km=radius_km,
|
|
location_types=location_types if location_types else None,
|
|
country=form.cleaned_data.get('country', '').strip() or None,
|
|
state=form.cleaned_data.get('state', '').strip() or None,
|
|
city=form.cleaned_data.get('city', '').strip() or None,
|
|
park_status=self.request.GET.getlist('park_status') or None,
|
|
include_distance=True,
|
|
max_results=int(self.request.GET.get('limit', 100))
|
|
)
|
|
|
|
|
|
class LocationSuggestionsView(TemplateView):
|
|
"""
|
|
AJAX endpoint for location search suggestions.
|
|
"""
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
query = request.GET.get('q', '').strip()
|
|
limit = int(request.GET.get('limit', 10))
|
|
|
|
if len(query) < 2:
|
|
return JsonResponse({'suggestions': []})
|
|
|
|
try:
|
|
suggestions = location_search_service.suggest_locations(query, limit)
|
|
return JsonResponse({'suggestions': suggestions})
|
|
except Exception as e:
|
|
return JsonResponse({'error': str(e)}, status=500)
|