Refactor ride form template to utilize Alpine.js for state management. Enhanced form submission handling and improved search result clearing functionality for better user experience.

This commit is contained in:
pacnpal
2025-09-26 14:27:47 -04:00
parent b9377ead37
commit 40e5cf3162
2 changed files with 107 additions and 68 deletions

View File

@@ -199,24 +199,31 @@
</div> </div>
<script> <script>
document.body.addEventListener('htmx:afterRequest', function(evt) { document.addEventListener('alpine:init', () => {
if (evt.detail.successful) { Alpine.data('moderationDashboard', () => ({
const path = evt.detail.requestConfig.path; init() {
let event; // Handle HTMX events using AlpineJS approach
document.body.addEventListener('htmx:afterRequest', (evt) => {
if (evt.detail.successful) {
const path = evt.detail.requestConfig.path;
let eventName;
if (path.includes('approve')) { if (path.includes('approve')) {
event = new CustomEvent('submission-approved'); eventName = 'submission-approved';
} else if (path.includes('reject')) { } else if (path.includes('reject')) {
event = new CustomEvent('submission-rejected'); eventName = 'submission-rejected';
} else if (path.includes('escalate')) { } else if (path.includes('escalate')) {
event = new CustomEvent('submission-escalated'); eventName = 'submission-escalated';
} else if (path.includes('edit')) { } else if (path.includes('edit')) {
event = new CustomEvent('submission-updated'); eventName = 'submission-updated';
} }
if (event) { if (eventName) {
window.dispatchEvent(event); this.$dispatch(eventName);
} }
}
});
} }
}); }));
});
</script> </script>

View File

@@ -1,59 +1,85 @@
{% load static %} {% load static %}
<script> <script>
function selectManufacturer(id, name) { document.addEventListener('alpine:init', () => {
document.getElementById('id_manufacturer').value = id; Alpine.data('rideForm', () => ({
document.getElementById('id_manufacturer_search').value = name; init() {
document.getElementById('manufacturer-search-results').innerHTML = ''; // Handle form submission cleanup
this.$el.addEventListener('submit', () => {
this.clearAllSearchResults();
});
},
// Update ride model search to include manufacturer selectManufacturer(id, name) {
const rideModelSearch = document.getElementById('id_ride_model_search'); const manufacturerInput = document.getElementById('id_manufacturer');
if (rideModelSearch) { const manufacturerSearch = document.getElementById('id_manufacturer_search');
rideModelSearch.setAttribute('hx-include', '[name="manufacturer"]'); const manufacturerResults = document.getElementById('manufacturer-search-results');
}
}
function selectDesigner(id, name) { if (manufacturerInput) manufacturerInput.value = id;
document.getElementById('id_designer').value = id; if (manufacturerSearch) manufacturerSearch.value = name;
document.getElementById('id_designer_search').value = name; if (manufacturerResults) manufacturerResults.innerHTML = '';
document.getElementById('designer-search-results').innerHTML = '';
}
function selectRideModel(id, name) { // Update ride model search to include manufacturer
document.getElementById('id_ride_model').value = id; const rideModelSearch = document.getElementById('id_ride_model_search');
document.getElementById('id_ride_model_search').value = name; if (rideModelSearch) {
document.getElementById('ride-model-search-results').innerHTML = ''; rideModelSearch.setAttribute('hx-include', '[name="manufacturer"]');
} }
},
// Handle form submission selectDesigner(id, name) {
document.addEventListener('submit', function(e) { const designerInput = document.getElementById('id_designer');
if (e.target.id === 'ride-form') { const designerSearch = document.getElementById('id_designer_search');
// Clear search results const designerResults = document.getElementById('designer-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 if (designerInput) designerInput.value = id;
document.addEventListener('click', function(e) { if (designerSearch) designerSearch.value = name;
const manufacturerResults = document.getElementById('manufacturer-search-results'); if (designerResults) designerResults.innerHTML = '';
const designerResults = document.getElementById('designer-search-results'); },
const rideModelResults = document.getElementById('ride-model-search-results');
if (!e.target.closest('#manufacturer-search-container')) { selectRideModel(id, name) {
manufacturerResults.innerHTML = ''; const rideModelInput = document.getElementById('id_ride_model');
} const rideModelSearch = document.getElementById('id_ride_model_search');
if (!e.target.closest('#designer-search-container')) { const rideModelResults = document.getElementById('ride-model-search-results');
designerResults.innerHTML = '';
} if (rideModelInput) rideModelInput.value = id;
if (!e.target.closest('#ride-model-search-container')) { if (rideModelSearch) rideModelSearch.value = name;
rideModelResults.innerHTML = ''; if (rideModelResults) rideModelResults.innerHTML = '';
} },
clearAllSearchResults() {
const manufacturerResults = document.getElementById('manufacturer-search-results');
const designerResults = document.getElementById('designer-search-results');
const rideModelResults = document.getElementById('ride-model-search-results');
if (manufacturerResults) manufacturerResults.innerHTML = '';
if (designerResults) designerResults.innerHTML = '';
if (rideModelResults) rideModelResults.innerHTML = '';
},
clearManufacturerResults() {
const manufacturerResults = document.getElementById('manufacturer-search-results');
if (manufacturerResults) manufacturerResults.innerHTML = '';
},
clearDesignerResults() {
const designerResults = document.getElementById('designer-search-results');
if (designerResults) designerResults.innerHTML = '';
},
clearRideModelResults() {
const rideModelResults = document.getElementById('ride-model-search-results');
if (rideModelResults) rideModelResults.innerHTML = '';
}
}));
}); });
</script> </script>
<form method="post" id="ride-form" class="space-y-6" enctype="multipart/form-data"> <form method="post"
id="ride-form"
class="space-y-6"
enctype="multipart/form-data"
x-data="rideForm"
x-init="init()">
{% csrf_token %} {% csrf_token %}
<!-- Park Area --> <!-- Park Area -->
@@ -86,7 +112,9 @@ document.addEventListener('click', function(e) {
<!-- Manufacturer --> <!-- Manufacturer -->
<div class="space-y-2"> <div class="space-y-2">
<div id="manufacturer-search-container" class="relative"> <div id="manufacturer-search-container"
class="relative"
@click.outside="clearManufacturerResults()">
<label for="{{ form.manufacturer_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300"> <label for="{{ form.manufacturer_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
Manufacturer Manufacturer
</label> </label>
@@ -103,7 +131,9 @@ document.addEventListener('click', function(e) {
<!-- Designer --> <!-- Designer -->
<div class="space-y-2"> <div class="space-y-2">
<div id="designer-search-container" class="relative"> <div id="designer-search-container"
class="relative"
@click.outside="clearDesignerResults()">
<label for="{{ form.designer_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300"> <label for="{{ form.designer_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
Designer Designer
</label> </label>
@@ -120,7 +150,9 @@ document.addEventListener('click', function(e) {
<!-- Ride Model --> <!-- Ride Model -->
<div class="space-y-2"> <div class="space-y-2">
<div id="ride-model-search-container" class="relative"> <div id="ride-model-search-container"
class="relative"
@click.outside="clearRideModelResults()">
<label for="{{ form.ride_model_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300"> <label for="{{ form.ride_model_search.id_for_label }}" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
Ride Model Ride Model
</label> </label>