mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 15:51:09 -05:00
Refactor park listing templates: implement grid and list view modes, enhance search results rendering, and improve error handling in search functionality
This commit is contained in:
@@ -20,8 +20,16 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block list_header %}
|
||||
<div class="flex items-center space-x-2">
|
||||
<button hx-get="{% url 'parks:park_list' %}?view_mode=grid" hx-target="#results-container" hx-push-url="true" class="p-2 rounded {% if request.GET.view_mode == 'grid' or not request.GET.view_mode %}bg-gray-200{% endif %}">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
|
||||
</button>
|
||||
<button hx-get="{% url 'parks:park_list' %}?view_mode=list" hx-target="#results-container" hx-push-url="true" class="p-2 rounded {% if request.GET.view_mode == 'list' %}bg-gray-200{% endif %}">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h7"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="text-2xl font-bold text-gray-900">Parks</h1>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mr-4">Parks</h1>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'parks:park_create' %}" class="btn btn-primary">
|
||||
Add Park
|
||||
@@ -122,10 +130,8 @@ Browse and filter amusement parks, theme parks, and water parks from around the
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block results_section %}
|
||||
<div class="space-y-6">
|
||||
{% for park in parks %}
|
||||
{% include "parks/partials/park_list_item.html" with park=park %}
|
||||
{% endfor %}
|
||||
{% block results_list %}
|
||||
<div class="bg-white rounded-lg shadow">
|
||||
{% include "parks/partials/park_list_item.html" with parks=parks %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
58
parks/templates/parks/partials/park_card.html
Normal file
58
parks/templates/parks/partials/park_card.html
Normal file
@@ -0,0 +1,58 @@
|
||||
{% load static %}
|
||||
{% load filter_utils %}
|
||||
|
||||
<div class="park-card group relative border rounded-lg p-4 transition-all duration-200 ease-in-out {% if view_mode == 'grid' %}grid-item hover:shadow-lg{% else %}flex items-start space-x-4 hover:bg-gray-50{% endif %}">
|
||||
<a href="{% url 'parks:park_detail' park.slug %}" class="absolute inset-0 z-0"></a>
|
||||
|
||||
<div class="relative z-10">
|
||||
{% if park.photos.exists %}
|
||||
<img src="{{ park.photos.first.image.url }}"
|
||||
alt="{{ park.name }}"
|
||||
class="{% if view_mode == 'grid' %}w-full h-48 object-cover rounded-lg mb-4{% else %}w-24 h-24 object-cover rounded-lg{% endif %}">
|
||||
{% else %}
|
||||
<div class="{% if view_mode == 'grid' %}w-full h-48 bg-gray-100 rounded-lg mb-4{% else %}w-24 h-24 bg-gray-100 rounded-lg{% endif %} flex items-center justify-center">
|
||||
<span class="text-2xl font-medium text-gray-400">{{ park.name|first|upper }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="{% if view_mode != 'grid' %}flex-1 min-w-0{% endif %}">
|
||||
<h3 class="text-lg font-semibold truncate">
|
||||
{{ park.name }}
|
||||
</h3>
|
||||
|
||||
<div class="mt-1 text-sm text-gray-500 truncate">
|
||||
{% with location=park.location.first %}
|
||||
{% if location %}
|
||||
{{ location.city }}{% if location.state %}, {{ location.state }}{% endif %}{% if location.country %}, {{ location.country }}{% endif %}
|
||||
{% else %}
|
||||
Location unknown
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<div class="mt-2 flex flex-wrap gap-2">
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium {{ park.get_status_color }}">
|
||||
{{ park.get_status_display }}
|
||||
</span>
|
||||
|
||||
{% if park.opening_date %}
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
||||
Opened {{ park.opening_date|date:"Y" }}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if park.ride_count %}
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||
{{ park.ride_count }} rides
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if park.coaster_count %}
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
|
||||
{{ park.coaster_count }} coasters
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,67 +8,9 @@
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="divide-y">
|
||||
<div class="{% if view_mode == 'grid' %}grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6{% else %}space-y-6{% endif %}">
|
||||
{% for park in object_list|default:parks %}
|
||||
<div role="option"
|
||||
id="result-{{ forloop.counter0 }}"
|
||||
:class="{ 'bg-gray-50 dark:bg-gray-800': selectedIndex === {{ forloop.counter0 }} }"
|
||||
class="p-4 flex items-start space-x-4">
|
||||
{% if park.photos.exists %}
|
||||
<img src="{{ park.photos.first.image.url }}"
|
||||
alt="{{ park.name }}"
|
||||
class="w-24 h-24 object-cover rounded-lg">
|
||||
{% else %}
|
||||
<div class="w-24 h-24 bg-gray-100 rounded-lg flex items-center justify-center">
|
||||
<span class="text-2xl font-medium text-gray-400">{{ park.name|first|upper }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="text-lg font-semibold truncate">
|
||||
<a href="{% url 'parks:park_detail' park.slug %}"
|
||||
x-ref="result-{{ forloop.counter0 }}"
|
||||
:class="{ 'bg-gray-50 dark:bg-gray-800': selectedIndex === {{ forloop.counter0 }} }"
|
||||
class="hover:text-blue-600 block w-full py-1 px-2 -mx-2 rounded">
|
||||
{{ park.name }}
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
<div class="mt-1 text-sm text-gray-500 truncate">
|
||||
{% with location=park.location.first %}
|
||||
{% if location %}
|
||||
{{ location.city }}{% if location.state %}, {{ location.state }}{% endif %}{% if location.country %}, {{ location.country }}{% endif %}
|
||||
{% else %}
|
||||
Location unknown
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<div class="mt-2 flex flex-wrap gap-2">
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium {{ park.get_status_color }}">
|
||||
{{ park.get_status_display }}
|
||||
</span>
|
||||
|
||||
{% if park.opening_date %}
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">
|
||||
Opened {{ park.opening_date|date:"Y" }}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if park.ride_count %}
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||
{{ park.ride_count }} rides
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{% if park.coaster_count %}
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800">
|
||||
{{ park.coaster_count }} coasters
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "parks/partials/park_card.html" with park=park view_mode=view_mode %}
|
||||
{% empty %}
|
||||
<div class="p-4 text-sm text-gray-500 text-center">
|
||||
No parks found matching your search.
|
||||
|
||||
Reference in New Issue
Block a user