mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 10:31:09 -05:00
- Add HTMX-powered filtering with instant updates - Add smooth transitions and loading states - Improve visual hierarchy and styling - Add review notes functionality - Add confirmation dialogs for actions - Make navigation sticky - Add hover effects and visual feedback - Improve dark mode support
292 lines
10 KiB
HTML
292 lines
10 KiB
HTML
{% load static %}
|
|
|
|
<script>
|
|
function selectManufacturer(id, name) {
|
|
document.getElementById('id_manufacturer').value = id;
|
|
document.getElementById('id_manufacturer_search').value = name;
|
|
document.getElementById('manufacturer-search-results').innerHTML = '';
|
|
|
|
// Update ride model search to include manufacturer
|
|
const rideModelSearch = document.getElementById('id_ride_model_search');
|
|
if (rideModelSearch) {
|
|
rideModelSearch.setAttribute('hx-include', '[name="manufacturer"]');
|
|
}
|
|
}
|
|
|
|
function selectDesigner(id, name) {
|
|
document.getElementById('id_designer').value = id;
|
|
document.getElementById('id_designer_search').value = name;
|
|
document.getElementById('designer-search-results').innerHTML = '';
|
|
}
|
|
|
|
function selectRideModel(id, name) {
|
|
document.getElementById('id_ride_model').value = id;
|
|
document.getElementById('id_ride_model_search').value = name;
|
|
document.getElementById('ride-model-search-results').innerHTML = '';
|
|
}
|
|
|
|
// Handle form submission
|
|
document.addEventListener('submit', function(e) {
|
|
if (e.target.id === 'ride-form') {
|
|
// Clear search results
|
|
document.getElementById('manufacturer-search-results').innerHTML = '';
|
|
document.getElementById('designer-search-results').innerHTML = '';
|
|
document.getElementById('ride-model-search-results').innerHTML = '';
|
|
}
|
|
});
|
|
|
|
// Handle clicks outside search results
|
|
document.addEventListener('click', function(e) {
|
|
const manufacturerResults = document.getElementById('manufacturer-search-results');
|
|
const designerResults = document.getElementById('designer-search-results');
|
|
const rideModelResults = document.getElementById('ride-model-search-results');
|
|
|
|
if (!e.target.closest('#manufacturer-search-container')) {
|
|
manufacturerResults.innerHTML = '';
|
|
}
|
|
if (!e.target.closest('#designer-search-container')) {
|
|
designerResults.innerHTML = '';
|
|
}
|
|
if (!e.target.closest('#ride-model-search-container')) {
|
|
rideModelResults.innerHTML = '';
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<form method="post" id="ride-form" class="space-y-6" enctype="multipart/form-data">
|
|
{% csrf_token %}
|
|
|
|
<!-- Park Area -->
|
|
{% if form.park_area %}
|
|
<div class="space-y-2">
|
|
<label for="{{ form.park_area.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Park Area
|
|
</label>
|
|
{{ form.park_area }}
|
|
{% if form.park_area.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.park_area.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Name -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.name.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Name *
|
|
</label>
|
|
{{ form.name }}
|
|
{% if form.name.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.name.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Manufacturer -->
|
|
<div class="space-y-2">
|
|
<div id="manufacturer-search-container" class="relative">
|
|
<label for="{{ form.manufacturer_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Manufacturer
|
|
</label>
|
|
{{ form.manufacturer_search }}
|
|
{{ form.manufacturer }}
|
|
<div id="manufacturer-search-results" class="relative"></div>
|
|
{% if form.manufacturer.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.manufacturer.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Designer -->
|
|
<div class="space-y-2">
|
|
<div id="designer-search-container" class="relative">
|
|
<label for="{{ form.designer_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Designer
|
|
</label>
|
|
{{ form.designer_search }}
|
|
{{ form.designer }}
|
|
<div id="designer-search-results" class="relative"></div>
|
|
{% if form.designer.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.designer.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Ride Model -->
|
|
<div class="space-y-2">
|
|
<div id="ride-model-search-container" class="relative">
|
|
<label for="{{ form.ride_model_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Ride Model
|
|
</label>
|
|
{{ form.ride_model_search }}
|
|
{{ form.ride_model }}
|
|
<div id="ride-model-search-results" class="relative"></div>
|
|
{% if form.ride_model.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.ride_model.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Model Name -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.model_name.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Model Name
|
|
</label>
|
|
{{ form.model_name }}
|
|
{% if form.model_name.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.model_name.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Category -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.category.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Category *
|
|
</label>
|
|
{{ form.category }}
|
|
{% if form.category.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.category.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Coaster Fields -->
|
|
<div id="coaster-fields"></div>
|
|
|
|
<!-- Status -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.status.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Status
|
|
</label>
|
|
{{ form.status }}
|
|
{% if form.status.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.status.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Opening Date -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.opening_date.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Opening Date
|
|
</label>
|
|
{{ form.opening_date }}
|
|
{% if form.opening_date.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.opening_date.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Closing Date -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.closing_date.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Closing Date
|
|
</label>
|
|
{{ form.closing_date }}
|
|
{% if form.closing_date.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.closing_date.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Status Since -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.status_since.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Status Since
|
|
</label>
|
|
{{ form.status_since }}
|
|
{% if form.status_since.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.status_since.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Min Height -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.min_height_in.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Minimum Height (inches)
|
|
</label>
|
|
{{ form.min_height_in }}
|
|
{% if form.min_height_in.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.min_height_in.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Max Height -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.max_height_in.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Maximum Height (inches)
|
|
</label>
|
|
{{ form.max_height_in }}
|
|
{% if form.max_height_in.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.max_height_in.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Capacity -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.capacity_per_hour.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Hourly Capacity
|
|
</label>
|
|
{{ form.capacity_per_hour }}
|
|
{% if form.capacity_per_hour.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.capacity_per_hour.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Ride Duration -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.ride_duration_seconds.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Ride Duration (seconds)
|
|
</label>
|
|
{{ form.ride_duration_seconds }}
|
|
{% if form.ride_duration_seconds.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.ride_duration_seconds.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
<div class="space-y-2">
|
|
<label for="{{ form.description.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
|
Description
|
|
</label>
|
|
{{ form.description }}
|
|
{% if form.description.errors %}
|
|
<div class="text-sm text-red-600 dark:text-red-400">
|
|
{{ form.description.errors }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Submit Button -->
|
|
<div class="flex justify-end">
|
|
<button type="submit"
|
|
class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-blue-500 dark:hover:bg-blue-600">
|
|
{% if is_edit %}Save Changes{% else %}Add Ride{% endif %}
|
|
</button>
|
|
</div>
|
|
</form>
|