Files
Inventory/public/assets/js/app.js

467 lines
13 KiB
JavaScript

/**
* Asset Management System - JavaScript
*/
document.addEventListener('DOMContentLoaded', function() {
// Initialize all components
initAlerts();
initDropdowns();
initForms();
initTables();
initModals();
initFileUploads();
});
/**
* Alert handling
*/
function initAlerts() {
// Auto-hide alerts after 5 seconds
const alerts = document.querySelectorAll('.alert');
alerts.forEach(alert => {
setTimeout(() => {
if (alert.parentElement) {
alert.style.opacity = '0';
setTimeout(() => {
alert.remove();
}, 300);
}
}, 5000);
});
// Close button functionality
document.addEventListener('click', function(e) {
if (e.target.classList.contains('alert-close')) {
const alert = e.target.closest('.alert');
if (alert) {
alert.style.opacity = '0';
setTimeout(() => {
alert.remove();
}, 300);
}
}
});
}
/**
* Dropdown handling
*/
function initDropdowns() {
// Close dropdowns when clicking outside
document.addEventListener('click', function(e) {
if (!e.target.closest('.nav-dropdown, .user-dropdown')) {
const dropdowns = document.querySelectorAll('.nav-dropdown-menu, .user-dropdown-menu');
dropdowns.forEach(dropdown => {
dropdown.style.opacity = '0';
dropdown.style.visibility = 'hidden';
dropdown.style.transform = 'translateY(-10px)';
});
}
});
}
/**
* Form handling
*/
function initForms() {
// Form validation
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
const requiredFields = form.querySelectorAll('[required]');
let isValid = true;
requiredFields.forEach(field => {
if (!field.value.trim()) {
isValid = false;
field.classList.add('error');
} else {
field.classList.remove('error');
}
});
if (!isValid) {
e.preventDefault();
showAlert('Bitte füllen Sie alle erforderlichen Felder aus.', 'error');
}
});
});
// Real-time validation
document.addEventListener('input', function(e) {
if (e.target.hasAttribute('required')) {
if (e.target.value.trim()) {
e.target.classList.remove('error');
} else {
e.target.classList.add('error');
}
}
});
}
/**
* Table handling
*/
function initTables() {
// Sortable tables
const sortableHeaders = document.querySelectorAll('.table th[data-sort]');
sortableHeaders.forEach(header => {
header.addEventListener('click', function() {
const table = this.closest('.table');
const column = this.dataset.sort;
const currentOrder = this.dataset.order || 'asc';
const newOrder = currentOrder === 'asc' ? 'desc' : 'asc';
// Update URL with sort parameters
const url = new URL(window.location);
url.searchParams.set('sort', column);
url.searchParams.set('order', newOrder);
window.location.href = url.toString();
});
});
// Bulk actions
const bulkCheckbox = document.getElementById('bulk-select-all');
if (bulkCheckbox) {
bulkCheckbox.addEventListener('change', function() {
const checkboxes = document.querySelectorAll('.bulk-select');
checkboxes.forEach(checkbox => {
checkbox.checked = this.checked;
});
updateBulkActions();
});
}
document.addEventListener('change', function(e) {
if (e.target.classList.contains('bulk-select')) {
updateBulkActions();
}
});
}
/**
* Update bulk actions visibility
*/
function updateBulkActions() {
const selectedItems = document.querySelectorAll('.bulk-select:checked');
const bulkActions = document.querySelector('.bulk-actions');
if (bulkActions) {
if (selectedItems.length > 0) {
bulkActions.style.display = 'block';
bulkActions.querySelector('.selected-count').textContent = selectedItems.length;
} else {
bulkActions.style.display = 'none';
}
}
}
/**
* Modal handling
*/
function initModals() {
// Open modal
document.addEventListener('click', function(e) {
if (e.target.hasAttribute('data-modal')) {
const modalId = e.target.dataset.modal;
const modal = document.getElementById(modalId);
if (modal) {
modal.style.display = 'block';
document.body.style.overflow = 'hidden';
}
}
});
// Close modal
document.addEventListener('click', function(e) {
if (e.target.classList.contains('modal-close') || e.target.classList.contains('modal')) {
const modal = e.target.closest('.modal');
if (modal) {
modal.style.display = 'none';
document.body.style.overflow = 'auto';
}
}
});
// Close modal with Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
const openModal = document.querySelector('.modal[style*="display: block"]');
if (openModal) {
openModal.style.display = 'none';
document.body.style.overflow = 'auto';
}
}
});
}
/**
* File upload handling
*/
function initFileUploads() {
const fileInputs = document.querySelectorAll('input[type="file"]');
fileInputs.forEach(input => {
input.addEventListener('change', function() {
const files = Array.from(this.files);
const maxSize = this.dataset.maxSize || 52428800; // 50MB default
const allowedTypes = this.dataset.allowedTypes ? this.dataset.allowedTypes.split(',') : [];
files.forEach(file => {
// Check file size
if (file.size > maxSize) {
showAlert(`Datei "${file.name}" ist zu groß. Maximale Größe: ${formatBytes(maxSize)}`, 'error');
this.value = '';
return;
}
// Check file type
if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) {
showAlert(`Dateityp "${file.type}" ist nicht erlaubt.`, 'error');
this.value = '';
return;
}
});
});
});
}
/**
* Search functionality
*/
function initSearch() {
const searchInput = document.getElementById('search-input');
if (searchInput) {
let searchTimeout;
searchInput.addEventListener('input', function() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
const query = this.value.trim();
if (query.length >= 2 || query.length === 0) {
performSearch(query);
}
}, 300);
});
}
}
/**
* Perform search
*/
function performSearch(query) {
const url = new URL(window.location);
if (query) {
url.searchParams.set('search', query);
} else {
url.searchParams.delete('search');
}
url.searchParams.delete('page'); // Reset to first page
window.location.href = url.toString();
}
/**
* Export functionality
*/
function exportData(format) {
const url = new URL(window.location);
url.searchParams.set('export', format);
window.location.href = url.toString();
}
/**
* Print functionality
*/
function printPage() {
window.print();
}
/**
* QR Code scanner
*/
function initQRScanner() {
const scanButton = document.getElementById('scan-qr');
if (scanButton) {
scanButton.addEventListener('click', function() {
// This would integrate with a QR code scanner library
// For now, we'll show a prompt
const code = prompt('Bitte QR-Code scannen oder Inventarnummer eingeben:');
if (code) {
document.getElementById('inventory-number').value = code;
document.getElementById('scan-form').submit();
}
});
}
}
/**
* Asset assignment
*/
function assignAsset(assetId) {
const userId = prompt('Bitte Benutzer-ID eingeben:');
if (userId) {
const form = document.createElement('form');
form.method = 'POST';
form.action = `/assets/${assetId}/assign`;
const csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = 'csrf_token';
csrfInput.value = document.querySelector('input[name="csrf_token"]').value;
const userInput = document.createElement('input');
userInput.type = 'hidden';
userInput.name = 'user_id';
userInput.value = userId;
form.appendChild(csrfInput);
form.appendChild(userInput);
document.body.appendChild(form);
form.submit();
}
}
/**
* Delete confirmation
*/
function confirmDelete(message = 'Sind Sie sicher, dass Sie diesen Eintrag löschen möchten?') {
return confirm(message);
}
/**
* Show alert message
*/
function showAlert(message, type = 'info') {
const alertContainer = document.querySelector('.flash-messages') || document.body;
const alert = document.createElement('div');
alert.className = `alert alert-${type}`;
alert.innerHTML = `
${message}
<button type="button" class="alert-close">&times;</button>
`;
alertContainer.appendChild(alert);
// Auto-hide after 5 seconds
setTimeout(() => {
alert.style.opacity = '0';
setTimeout(() => {
alert.remove();
}, 300);
}, 5000);
}
/**
* Format bytes to human readable
*/
function formatBytes(bytes) {
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(2)} ${units[unitIndex]}`;
}
/**
* Debounce function
*/
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* Throttle function
*/
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
/**
* AJAX helper
*/
function ajax(url, options = {}) {
const defaultOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
}
};
const config = { ...defaultOptions, ...options };
return fetch(url, config)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error('AJAX error:', error);
throw error;
});
}
/**
* Local storage helper
*/
const Storage = {
set: function(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
console.error('Error saving to localStorage', e);
}
},
get: function(key, defaultValue = null) {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : defaultValue;
} catch (e) {
console.error('Error reading from localStorage', e);
return defaultValue;
}
},
remove: function(key) {
try {
localStorage.removeItem(key);
} catch (e) {
console.error('Error removing from localStorage', e);
}
}
};
// Initialize search if on a page with search
if (document.getElementById('search-input')) {
initSearch();
}
// Initialize QR scanner if on inventory page
if (document.getElementById('scan-qr')) {
initQRScanner();
}