180 lines
5.8 KiB
JavaScript
180 lines
5.8 KiB
JavaScript
// Equipment Management JavaScript
|
|
|
|
// File Upload with Drag & Drop
|
|
function initializeFileUpload() {
|
|
const fileInput = document.getElementById('manualFile');
|
|
const uploadForm = document.getElementById('uploadManualForm');
|
|
|
|
if (!fileInput || !uploadForm) return;
|
|
|
|
// Drag and drop handlers
|
|
const dropZone = uploadForm.querySelector('.file-upload-zone');
|
|
if (dropZone) {
|
|
dropZone.addEventListener('dragover', (e) => {
|
|
e.preventDefault();
|
|
dropZone.classList.add('dragover');
|
|
});
|
|
|
|
dropZone.addEventListener('dragleave', () => {
|
|
dropZone.classList.remove('dragover');
|
|
});
|
|
|
|
dropZone.addEventListener('drop', (e) => {
|
|
e.preventDefault();
|
|
dropZone.classList.remove('dragover');
|
|
|
|
const files = e.dataTransfer.files;
|
|
if (files.length > 0) {
|
|
fileInput.files = files;
|
|
uploadForm.dispatchEvent(new Event('submit', { bubbles: true }));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Client-side Cost Calculation
|
|
function initializeCostCalculation() {
|
|
const laborCostInput = document.querySelector('input[name="LaborCost"]');
|
|
const partsCostInput = document.querySelector('input[name="PartsCost"]');
|
|
const totalCostDisplay = document.getElementById('totalCostDisplay');
|
|
|
|
if (!laborCostInput || !partsCostInput) return;
|
|
|
|
function calculateTotal() {
|
|
const laborCost = parseFloat(laborCostInput.value) || 0;
|
|
const partsCost = parseFloat(partsCostInput.value) || 0;
|
|
const totalCost = laborCost + partsCost;
|
|
|
|
if (totalCostDisplay) {
|
|
totalCostDisplay.textContent = totalCost.toLocaleString('en-US', {
|
|
style: 'currency',
|
|
currency: 'USD'
|
|
});
|
|
}
|
|
}
|
|
|
|
laborCostInput.addEventListener('input', calculateTotal);
|
|
partsCostInput.addEventListener('input', calculateTotal);
|
|
|
|
// Calculate on page load
|
|
calculateTotal();
|
|
}
|
|
|
|
// Equipment Status Change Handler
|
|
function initializeStatusChangeHandler() {
|
|
const statusSelect = document.querySelector('select[name="Status"]');
|
|
|
|
if (!statusSelect) return;
|
|
|
|
statusSelect.addEventListener('change', function() {
|
|
const selectedStatus = this.value;
|
|
|
|
// Add visual feedback based on status
|
|
const card = this.closest('.card');
|
|
if (card) {
|
|
card.classList.remove('border-success', 'border-warning', 'border-danger', 'border-info');
|
|
|
|
switch(selectedStatus) {
|
|
case 'Operational':
|
|
card.classList.add('border-success');
|
|
break;
|
|
case 'NeedsMaintenance':
|
|
card.classList.add('border-warning');
|
|
break;
|
|
case 'UnderMaintenance':
|
|
card.classList.add('border-info');
|
|
break;
|
|
case 'OutOfService':
|
|
card.classList.add('border-danger');
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Maintenance Due Reminder
|
|
function checkMaintenanceDue() {
|
|
const daysUntilMaintenance = document.querySelector('[data-days-until-maintenance]');
|
|
|
|
if (!daysUntilMaintenance) return;
|
|
|
|
const days = parseInt(daysUntilMaintenance.dataset.daysUntilMaintenance);
|
|
|
|
if (days !== null && days < 7 && days >= 0) {
|
|
showToast(`Maintenance due in ${days} days!`, 'warning');
|
|
} else if (days < 0) {
|
|
showToast(`Maintenance is overdue by ${Math.abs(days)} days!`, 'danger');
|
|
}
|
|
}
|
|
|
|
// Show Toast Notification
|
|
function showToast(message, type = 'info') {
|
|
const toastHTML = `
|
|
<div class="toast align-items-center text-white bg-${type} border-0 position-fixed bottom-0 end-0 m-3" role="alert" aria-live="assertive" aria-atomic="true">
|
|
<div class="d-flex">
|
|
<div class="toast-body">
|
|
${message}
|
|
</div>
|
|
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.body.insertAdjacentHTML('beforeend', toastHTML);
|
|
const toastElement = document.querySelector('.toast:last-child');
|
|
const toast = new bootstrap.Toast(toastElement);
|
|
toast.show();
|
|
|
|
// Remove from DOM after hidden
|
|
toastElement.addEventListener('hidden.bs.toast', () => {
|
|
toastElement.remove();
|
|
});
|
|
}
|
|
|
|
// Confirm Delete with Modal
|
|
function confirmDelete(event, itemName, itemType) {
|
|
if (!confirm(`Are you sure you want to delete this ${itemType}: ${itemName}?\n\nThis action cannot be undone.`)) {
|
|
event.preventDefault();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Search and Filter Tables
|
|
function initializeTableSearch(inputId, tableId) {
|
|
const searchInput = document.getElementById(inputId);
|
|
const table = document.getElementById(tableId);
|
|
|
|
if (!searchInput || !table) return;
|
|
|
|
searchInput.addEventListener('input', function() {
|
|
const searchTerm = this.value.toLowerCase();
|
|
const rows = table.querySelectorAll('tbody tr');
|
|
|
|
rows.forEach(row => {
|
|
const text = row.textContent.toLowerCase();
|
|
row.style.display = text.includes(searchTerm) ? '' : 'none';
|
|
});
|
|
});
|
|
}
|
|
|
|
// Initialize all features on page load
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initializeFileUpload();
|
|
initializeCostCalculation();
|
|
initializeStatusChangeHandler();
|
|
checkMaintenanceDue();
|
|
|
|
// Initialize table searches if present
|
|
initializeTableSearch('searchInput', 'equipmentTable');
|
|
initializeTableSearch('searchInput', 'maintenanceTable');
|
|
});
|
|
|
|
// Export functions for use in other scripts
|
|
window.EquipmentManagement = {
|
|
showToast,
|
|
confirmDelete,
|
|
initializeFileUpload,
|
|
initializeCostCalculation
|
|
};
|