feat: reservation modal now usable.
This commit is contained in:
@@ -397,13 +397,14 @@
|
||||
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl max-w-lg w-full max-h-[90vh] overflow-y-auto" onclick="event.stopPropagation()">
|
||||
<div class="p-6">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">New Reservation</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white" id="modal-title">New Reservation</h2>
|
||||
<button onclick="closeReservationModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
|
||||
<svg class="w-6 h-6" 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>
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" id="editing-reservation-id" value="">
|
||||
|
||||
<form id="reservation-form" onsubmit="submitReservation(event)">
|
||||
<!-- Name -->
|
||||
@@ -522,7 +523,7 @@
|
||||
class="px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit"
|
||||
<button type="submit" id="modal-submit-btn"
|
||||
class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
|
||||
Create Reservation
|
||||
</button>
|
||||
@@ -600,27 +601,83 @@ function closeDayPanel() {
|
||||
let reservationModeActive = false;
|
||||
|
||||
function openReservationModal() {
|
||||
// Reset to "create" mode
|
||||
document.getElementById('modal-title').textContent = 'New Reservation';
|
||||
document.getElementById('modal-submit-btn').textContent = 'Create Reservation';
|
||||
document.getElementById('editing-reservation-id').value = '';
|
||||
document.getElementById('reservation-form').reset();
|
||||
|
||||
document.getElementById('reservation-modal').classList.remove('hidden');
|
||||
reservationModeActive = true;
|
||||
// Show reservation legend, hide main legend
|
||||
document.getElementById('main-legend').classList.add('md:hidden');
|
||||
document.getElementById('main-legend').classList.remove('md:flex');
|
||||
document.getElementById('reservation-legend').classList.remove('md:hidden');
|
||||
document.getElementById('reservation-legend').classList.add('md:flex');
|
||||
// Trigger availability update
|
||||
updateCalendarAvailability();
|
||||
}
|
||||
|
||||
async function editReservation(id) {
|
||||
try {
|
||||
const response = await fetch(`/api/fleet-calendar/reservations/${id}`);
|
||||
if (!response.ok) { alert('Failed to load reservation'); return; }
|
||||
const res = await response.json();
|
||||
|
||||
// Switch modal to "edit" mode
|
||||
document.getElementById('modal-title').textContent = 'Edit Reservation';
|
||||
document.getElementById('modal-submit-btn').textContent = 'Save Changes';
|
||||
document.getElementById('editing-reservation-id').value = id;
|
||||
|
||||
// Populate fields
|
||||
const form = document.getElementById('reservation-form');
|
||||
form.querySelector('input[name="name"]').value = res.name;
|
||||
form.querySelector('select[name="project_id"]').value = res.project_id || '';
|
||||
form.querySelector('input[name="start_date"]').value = res.start_date;
|
||||
form.querySelector('textarea[name="notes"]').value = res.notes || '';
|
||||
|
||||
// Color radio
|
||||
const colorRadio = form.querySelector(`input[name="color"][value="${res.color}"]`);
|
||||
if (colorRadio) colorRadio.checked = true;
|
||||
|
||||
// Assignment type
|
||||
const atRadio = form.querySelector(`input[name="assignment_type"][value="${res.assignment_type}"]`);
|
||||
if (atRadio) { atRadio.checked = true; toggleAssignmentType(res.assignment_type); }
|
||||
if (res.assignment_type === 'quantity') {
|
||||
form.querySelector('input[name="quantity_needed"]').value = res.quantity_needed || 1;
|
||||
}
|
||||
|
||||
// End date / TBD
|
||||
const tbdCheckbox = document.getElementById('end_date_tbd');
|
||||
if (res.end_date_tbd) {
|
||||
tbdCheckbox.checked = true;
|
||||
form.querySelector('input[name="estimated_end_date"]').value = res.estimated_end_date || '';
|
||||
} else {
|
||||
tbdCheckbox.checked = false;
|
||||
document.getElementById('end_date_input').value = res.end_date || '';
|
||||
}
|
||||
toggleEndDateTBD();
|
||||
|
||||
document.getElementById('reservation-modal').classList.remove('hidden');
|
||||
reservationModeActive = true;
|
||||
document.getElementById('main-legend').classList.add('md:hidden');
|
||||
document.getElementById('main-legend').classList.remove('md:flex');
|
||||
document.getElementById('reservation-legend').classList.remove('md:hidden');
|
||||
document.getElementById('reservation-legend').classList.add('md:flex');
|
||||
updateCalendarAvailability();
|
||||
} catch (error) {
|
||||
console.error('Error loading reservation:', error);
|
||||
alert('Error loading reservation');
|
||||
}
|
||||
}
|
||||
|
||||
function closeReservationModal() {
|
||||
document.getElementById('reservation-modal').classList.add('hidden');
|
||||
document.getElementById('reservation-form').reset();
|
||||
document.getElementById('editing-reservation-id').value = '';
|
||||
reservationModeActive = false;
|
||||
// Restore main legend
|
||||
document.getElementById('main-legend').classList.remove('md:hidden');
|
||||
document.getElementById('main-legend').classList.add('md:flex');
|
||||
document.getElementById('reservation-legend').classList.add('md:hidden');
|
||||
document.getElementById('reservation-legend').classList.remove('md:flex');
|
||||
// Reset calendar colors
|
||||
resetCalendarColors();
|
||||
}
|
||||
|
||||
@@ -752,6 +809,7 @@ async function submitReservation(event) {
|
||||
const form = event.target;
|
||||
const formData = new FormData(form);
|
||||
const endDateTbd = formData.get('end_date_tbd') === 'on';
|
||||
const editingId = document.getElementById('editing-reservation-id').value;
|
||||
|
||||
const data = {
|
||||
name: formData.get('name'),
|
||||
@@ -766,7 +824,6 @@ async function submitReservation(event) {
|
||||
notes: formData.get('notes') || null
|
||||
};
|
||||
|
||||
// Validate: need either end_date or TBD checked
|
||||
if (!data.end_date && !data.end_date_tbd) {
|
||||
alert('Please enter an end date or check "TBD / Ongoing"');
|
||||
return;
|
||||
@@ -778,9 +835,15 @@ async function submitReservation(event) {
|
||||
data.unit_ids = formData.getAll('unit_ids');
|
||||
}
|
||||
|
||||
const isEdit = editingId !== '';
|
||||
const url = isEdit
|
||||
? `/api/fleet-calendar/reservations/${editingId}`
|
||||
: '/api/fleet-calendar/reservations';
|
||||
const method = isEdit ? 'PUT' : 'POST';
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/fleet-calendar/reservations', {
|
||||
method: 'POST',
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
@@ -789,14 +852,13 @@ async function submitReservation(event) {
|
||||
|
||||
if (result.success) {
|
||||
closeReservationModal();
|
||||
// Reload the page to refresh calendar
|
||||
window.location.reload();
|
||||
} else {
|
||||
alert('Error creating reservation: ' + (result.detail || 'Unknown error'));
|
||||
alert(`Error ${isEdit ? 'saving' : 'creating'} reservation: ` + (result.detail || 'Unknown error'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
alert('Error creating reservation');
|
||||
alert(`Error ${isEdit ? 'saving' : 'creating'} reservation`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user