Initial commit

This commit is contained in:
2026-04-23 21:38:24 -04:00
commit 63e12a9636
1762 changed files with 1672620 additions and 0 deletions
@@ -0,0 +1,188 @@
<!-- Quick Create Appointment Modal -->
<div class="modal fade" id="quickCreateModal" tabindex="-1" aria-labelledby="quickCreateModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="quickCreateModalLabel">
<i class="bi bi-calendar-plus me-2"></i>Quick Create Appointment
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form id="quickCreateForm">
<div class="modal-body">
<div class="alert alert-danger d-none" id="quickCreateError"></div>
<!-- Title -->
<div class="mb-3">
<label for="quickTitle" class="form-label">Title <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="quickTitle" name="Title" required placeholder="e.g., Customer Drop-Off">
</div>
<!-- Customer -->
<div class="mb-3">
<label for="quickCustomer" class="form-label">Customer</label>
<select class="form-select" id="quickCustomer" name="CustomerId">
<option value="">-- Select Customer (Optional) --</option>
@foreach (var customer in (SelectList)ViewBag.Customers)
{
<option value="@customer.Value">@customer.Text</option>
}
</select>
</div>
<!-- Appointment Type -->
<div class="mb-3">
<label for="quickType" class="form-label">Type <span class="text-danger">*</span></label>
<select class="form-select" id="quickType" name="AppointmentTypeId" required>
<option value="">-- Select Type --</option>
@foreach (var type in (SelectList)ViewBag.AppointmentTypes)
{
<option value="@type.Value">@type.Text</option>
}
</select>
</div>
<!-- All Day -->
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="quickAllDay" name="IsAllDay">
<label class="form-check-label" for="quickAllDay">
All Day Event
</label>
</div>
<div class="row">
<!-- Start Date/Time -->
<div class="col-md-6 mb-3">
<label for="quickStart" class="form-label">Start <span class="text-danger">*</span></label>
<input type="datetime-local" class="form-control" id="quickStart" name="ScheduledStartTime" required>
</div>
<!-- End Date/Time -->
<div class="col-md-6 mb-3">
<label for="quickEnd" class="form-label">End <span class="text-danger">*</span></label>
<input type="datetime-local" class="form-control" id="quickEnd" name="ScheduledEndTime" required>
</div>
</div>
<p class="text-muted small mb-0">
<i class="bi bi-info-circle"></i> For more options, use the <a asp-action="Create">full create form</a>.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary" id="quickCreateSubmit">
<i class="bi bi-check-circle"></i> Create Appointment
</button>
</div>
</form>
</div>
</div>
</div>
<script>
// Quick Create Modal Logic
document.getElementById('quickCreateForm').addEventListener('submit', async function(e) {
e.preventDefault();
const submitBtn = document.getElementById('quickCreateSubmit');
const errorDiv = document.getElementById('quickCreateError');
errorDiv.classList.add('d-none');
// Disable submit button
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Creating...';
try {
const formData = new FormData(this);
const data = Object.fromEntries(formData.entries());
// Convert checkbox to boolean
data.IsAllDay = formData.get('IsAllDay') === 'on';
const response = await fetch('@Url.Action("QuickCreate")', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success) {
// Close modal
const modal = bootstrap.Modal.getInstance(document.getElementById('quickCreateModal'));
modal.hide();
// Show success toast
showToast('success', result.message || 'Appointment created successfully');
// Reload calendar events
if (typeof loadCalendarEvents === 'function') {
loadCalendarEvents();
}
// Reset form
this.reset();
} else {
errorDiv.textContent = result.message || 'An error occurred';
errorDiv.classList.remove('d-none');
}
} catch (error) {
console.error('Error:', error);
errorDiv.textContent = 'An unexpected error occurred';
errorDiv.classList.remove('d-none');
} finally {
// Re-enable submit button
submitBtn.disabled = false;
submitBtn.innerHTML = '<i class="bi bi-check-circle"></i> Create Appointment';
}
});
// Toggle datetime/date input based on All Day checkbox
document.getElementById('quickAllDay').addEventListener('change', function() {
const startInput = document.getElementById('quickStart');
const endInput = document.getElementById('quickEnd');
if (this.checked) {
startInput.type = 'date';
endInput.type = 'date';
} else {
startInput.type = 'datetime-local';
endInput.type = 'datetime-local';
}
});
// Auto-update end time when start time changes
document.getElementById('quickStart').addEventListener('change', function() {
const endInput = document.getElementById('quickEnd');
const isAllDay = document.getElementById('quickAllDay').checked;
// Always update end time based on start time
if (isAllDay) {
endInput.value = this.value;
} else {
const newEndTime = new Date(this.value);
newEndTime.setHours(newEndTime.getHours() + 1);
endInput.value = newEndTime.toISOString().slice(0, 16);
}
});
// Helper function to show toast notifications
function showToast(type, message) {
// Simple toast implementation - can be enhanced with Bootstrap Toast component
const alertDiv = document.createElement('div');
alertDiv.className = `alert alert-${type} alert-dismissible fade show position-fixed top-0 start-50 translate-middle-x mt-3`;
alertDiv.style.zIndex = '9999';
alertDiv.innerHTML = `
<i class="bi bi-${type === 'success' ? 'check-circle' : 'exclamation-triangle'} me-2"></i>${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(alertDiv);
setTimeout(() => {
alertDiv.remove();
}, 5000);
}
</script>