/** * Main JavaScript * Kayal Kalmeen Kadai - Fish Stall Management System */ // Wait for DOM to be ready document.addEventListener('DOMContentLoaded', function() { // Mobile navigation toggle const navToggle = document.querySelector('.nav-toggle'); const navList = document.querySelector('.nav-list'); if (navToggle) { navToggle.addEventListener('click', function() { navList.classList.toggle('active'); }); } // Theme settings toggle const themeBtn = document.querySelector('.theme-btn'); const themeDropdown = document.querySelector('.theme-dropdown'); if (themeBtn && themeDropdown) { themeBtn.addEventListener('click', function(e) { e.stopPropagation(); themeDropdown.classList.toggle('active'); }); // Close dropdown when clicking outside document.addEventListener('click', function(e) { if (!themeDropdown.contains(e.target) && !themeBtn.contains(e.target)) { themeDropdown.classList.remove('active'); } }); } // Apply theme changes const primaryColorInput = document.getElementById('primary-color'); const secondaryColorInput = document.getElementById('secondary-color'); const fontSizeInput = document.getElementById('font-size'); const fontSizeValue = document.getElementById('font-size-value'); if (primaryColorInput) { primaryColorInput.addEventListener('input', function() { document.documentElement.style.setProperty('--primary-color', this.value); saveThemePreferences(); }); } if (secondaryColorInput) { secondaryColorInput.addEventListener('input', function() { document.documentElement.style.setProperty('--secondary-color', this.value); saveThemePreferences(); }); } if (fontSizeInput) { fontSizeInput.addEventListener('input', function() { const size = this.value + 'px'; document.documentElement.style.setProperty('--font-size-base', size); fontSizeValue.textContent = this.value + 'px'; saveThemePreferences(); }); } // Confirmation dialogs const deleteButtons = document.querySelectorAll('.btn-delete-confirm'); deleteButtons.forEach(button => { button.addEventListener('click', function(e) { const message = this.getAttribute('data-confirm') || 'Are you sure you want to delete this item?'; if (!confirm(message)) { e.preventDefault(); } }); }); // Auto-calculate totals setupAutoCalculation(); // Date validations setupDateValidations(); // Load subcategories when category changes const categorySelect = document.getElementById('category_id'); if (categorySelect) { categorySelect.addEventListener('change', loadSubcategories); } // Initialize tooltips (if needed) initializeTooltips(); // Auto-dismiss alerts after 5 seconds const alerts = document.querySelectorAll('.alert'); alerts.forEach(alert => { setTimeout(() => { alert.style.transition = 'opacity 0.5s'; alert.style.opacity = '0'; setTimeout(() => alert.remove(), 500); }, 5000); }); }); // Save theme preferences to server function saveThemePreferences() { const primaryColor = document.getElementById('primary-color')?.value; const secondaryColor = document.getElementById('secondary-color')?.value; const fontSize = document.getElementById('font-size')?.value; if (primaryColor && secondaryColor && fontSize) { fetch('save_preferences.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ primary_color: primaryColor, secondary_color: secondaryColor, font_size: fontSize }) }).catch(error => console.error('Error saving preferences:', error)); } } // Auto-calculate totals for forms function setupAutoCalculation() { // For supply/sales forms: weight * rate = total const weightInput = document.getElementById('weight_kg'); const rateInput = document.getElementById('rate_per_kg'); const totalInput = document.getElementById('total_amount'); if (weightInput && rateInput && totalInput) { const calculateTotal = () => { const weight = parseFloat(weightInput.value) || 0; const rate = parseFloat(rateInput.value) || 0; const total = (weight * rate).toFixed(2); totalInput.value = total; }; weightInput.addEventListener('input', calculateTotal); rateInput.addEventListener('input', calculateTotal); } // For expense forms: units * unit_cost = total const unitsInput = document.getElementById('units'); const unitCostInput = document.getElementById('unit_cost'); const expenseTotalInput = document.getElementById('expense_total'); if (unitsInput && unitCostInput && expenseTotalInput) { const calculateExpenseTotal = () => { const units = parseFloat(unitsInput.value) || 0; const unitCost = parseFloat(unitCostInput.value) || 0; const total = (units * unitCost).toFixed(2); expenseTotalInput.value = total; }; unitsInput.addEventListener('input', calculateExpenseTotal); unitCostInput.addEventListener('input', calculateExpenseTotal); } } // Date validations function setupDateValidations() { const dateInputs = document.querySelectorAll('input[type="date"]'); dateInputs.forEach(input => { // Set max date to today if (input.hasAttribute('data-max-today')) { const today = new Date().toISOString().split('T')[0]; input.setAttribute('max', today); } // Validate date range if (input.hasAttribute('data-min-date')) { const minDate = input.getAttribute('data-min-date'); input.setAttribute('min', minDate); } }); // Date range validation (from-to dates) const fromDate = document.getElementById('from_date'); const toDate = document.getElementById('to_date'); if (fromDate && toDate) { fromDate.addEventListener('change', function() { toDate.setAttribute('min', this.value); if (toDate.value && toDate.value < this.value) { toDate.value = this.value; } }); toDate.addEventListener('change', function() { if (fromDate.value && this.value < fromDate.value) { alert('End date cannot be before start date'); this.value = fromDate.value; } }); } } // Load subcategories based on selected category function loadSubcategories() { const categoryId = this.value; const subcategorySelect = document.getElementById('subcategory_id'); if (!subcategorySelect) return; // Clear existing options except the first one subcategorySelect.innerHTML = ''; if (!categoryId) return; // Fetch subcategories fetch(`get_subcategories.php?category_id=${categoryId}`) .then(response => response.json()) .then(data => { data.forEach(subcategory => { const option = document.createElement('option'); option.value = subcategory.subcategory_id; option.textContent = subcategory.subcategory_name; subcategorySelect.appendChild(option); }); }) .catch(error => console.error('Error loading subcategories:', error)); } // Initialize tooltips function initializeTooltips() { const tooltipElements = document.querySelectorAll('[data-tooltip]'); tooltipElements.forEach(element => { element.style.position = 'relative'; element.style.cursor = 'help'; element.addEventListener('mouseenter', function() { const tooltip = document.createElement('div'); tooltip.className = 'tooltip'; tooltip.textContent = this.getAttribute('data-tooltip'); tooltip.style.cssText = ` position: absolute; background: rgba(0, 0, 0, 0.8); color: white; padding: 0.5rem 1rem; border-radius: 5px; font-size: 0.875rem; white-space: nowrap; z-index: 1000; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 0.5rem; `; this.appendChild(tooltip); }); element.addEventListener('mouseleave', function() { const tooltip = this.querySelector('.tooltip'); if (tooltip) { tooltip.remove(); } }); }); } // Format currency input function formatCurrencyInput(input) { let value = input.value.replace(/[^\d.]/g, ''); const parts = value.split('.'); if (parts.length > 2) { value = parts[0] + '.' + parts.slice(1).join(''); } if (parts[1] && parts[1].length > 2) { value = parts[0] + '.' + parts[1].substring(0, 2); } input.value = value; } // Apply currency formatting to all currency inputs const currencyInputs = document.querySelectorAll('.currency-input'); currencyInputs.forEach(input => { input.addEventListener('input', function() { formatCurrencyInput(this); }); }); // Export table to CSV function exportTableToCSV(tableId, filename) { const table = document.getElementById(tableId); if (!table) return; let csv = []; const rows = table.querySelectorAll('tr'); rows.forEach(row => { const cols = row.querySelectorAll('td, th'); const rowData = Array.from(cols).map(col => { let data = col.textContent.trim(); data = data.replace(/"/g, '""'); // Escape quotes return `"${data}"`; }); csv.push(rowData.join(',')); }); const csvContent = csv.join('\n'); const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); if (navigator.msSaveBlob) { navigator.msSaveBlob(blob, filename); } else { link.href = URL.createObjectURL(blob); link.download = filename; link.click(); } } // Print function function printPage() { window.print(); } // Form validation helper function validateForm(formId) { const form = document.getElementById(formId); if (!form) return false; const requiredFields = form.querySelectorAll('[required]'); let isValid = true; requiredFields.forEach(field => { if (!field.value.trim()) { isValid = false; field.style.borderColor = 'red'; // Remove red border when user starts typing field.addEventListener('input', function() { this.style.borderColor = ''; }, { once: true }); } }); if (!isValid) { alert('Please fill in all required fields'); } return isValid; } // Number formatting function formatNumber(num, decimals = 2) { return parseFloat(num).toFixed(decimals); } // Debounce function for search inputs function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Quick search functionality const searchInputs = document.querySelectorAll('.quick-search'); searchInputs.forEach(input => { input.addEventListener('input', debounce(function() { const searchTerm = this.value.toLowerCase(); const targetTable = document.getElementById(this.getAttribute('data-target')); if (targetTable) { const rows = targetTable.querySelectorAll('tbody tr'); rows.forEach(row => { const text = row.textContent.toLowerCase(); row.style.display = text.includes(searchTerm) ? '' : 'none'; }); } }, 300)); });