mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 09:11:08 -05:00
143 lines
6.6 KiB
HTML
143 lines
6.6 KiB
HTML
{% comment %}
|
|
Reusable search form component with filtering capabilities.
|
|
Usage: {% include 'components/search_form.html' with placeholder="Search parks..." filters=filter_options %}
|
|
{% endcomment %}
|
|
|
|
<form method="get" class="bg-white p-6 rounded-lg shadow-sm border border-gray-200 mb-6">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
<!-- Search Input -->
|
|
<div class="col-span-1 md:col-span-2">
|
|
<label for="search" class="block text-sm font-medium text-gray-700 mb-1">
|
|
Search
|
|
</label>
|
|
<div class="relative">
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
|
<svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
</svg>
|
|
</div>
|
|
<input
|
|
type="text"
|
|
name="search"
|
|
id="search"
|
|
value="{{ request.GET.search }}"
|
|
placeholder="{{ placeholder|default:'Search...' }}"
|
|
class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
{% if filters %}
|
|
{% for filter in filters %}
|
|
<div>
|
|
<label for="{{ filter.name }}" class="block text-sm font-medium text-gray-700 mb-1">
|
|
{{ filter.label }}
|
|
</label>
|
|
|
|
{% if filter.type == 'select' %}
|
|
<select
|
|
name="{{ filter.name }}"
|
|
id="{{ filter.name }}"
|
|
class="block w-full px-3 py-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
<option value="">All {{ filter.label }}</option>
|
|
{% for option in filter.options %}
|
|
<option
|
|
value="{{ option.value }}"
|
|
{% if request.GET|get_item:filter.name == option.value %}selected{% endif %}
|
|
>
|
|
{{ option.label }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
|
|
{% elif filter.type == 'checkbox' %}
|
|
<div class="space-y-2">
|
|
{% for option in filter.options %}
|
|
<label class="flex items-center">
|
|
<input
|
|
type="checkbox"
|
|
name="{{ filter.name }}"
|
|
value="{{ option.value }}"
|
|
{% if option.value in request.GET|getlist:filter.name %}checked{% endif %}
|
|
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
|
>
|
|
<span class="ml-2 text-sm text-gray-700">{{ option.label }}</span>
|
|
</label>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
{% elif filter.type == 'range' %}
|
|
<div class="flex space-x-2">
|
|
<input
|
|
type="number"
|
|
name="{{ filter.name }}_min"
|
|
value="{{ request.GET|get_item:filter.name_min }}"
|
|
placeholder="Min"
|
|
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
<input
|
|
type="number"
|
|
name="{{ filter.name }}_max"
|
|
value="{{ request.GET|get_item:filter.name_max }}"
|
|
placeholder="Max"
|
|
class="block w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="mt-4 flex items-center justify-between">
|
|
<div class="flex space-x-3">
|
|
<button
|
|
type="submit"
|
|
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors"
|
|
>
|
|
<svg class="-ml-1 mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
</svg>
|
|
Search
|
|
</button>
|
|
|
|
{% if request.GET.urlencode %}
|
|
<a
|
|
href="{{ request.path }}"
|
|
class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors"
|
|
>
|
|
<svg class="-ml-1 mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
Clear
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if show_sort %}
|
|
<div class="flex items-center space-x-2">
|
|
<label for="ordering" class="text-sm font-medium text-gray-700">Sort by:</label>
|
|
<select
|
|
name="ordering"
|
|
id="ordering"
|
|
onchange="this.form.submit()"
|
|
class="block px-3 py-2 border border-gray-300 rounded-md bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
|
>
|
|
{% for option in sort_options|default:"name,Name (A-Z);-name,Name (Z-A);created_at,Newest First;-created_at,Oldest First" %}
|
|
{% with option_parts=option|split:"," %}
|
|
<option
|
|
value="{{ option_parts.0 }}"
|
|
{% if request.GET.ordering == option_parts.0 %}selected{% endif %}
|
|
>
|
|
{{ option_parts.1 }}
|
|
</option>
|
|
{% endwith %}
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</form>
|