freightdesk/webapp/src/public/js/app.js
FreightDesk 1a4eaaa040 Initial commit: FreightDesk v1.0
- Express + EJS server-rendered app
- Supabase PostgreSQL database
- Auth: username/password with bcrypt
- Dashboard with business stats
- Load CRUD with filters
- WhatsApp message parser
- Payment tracking
- Shipper & vehicle management
- Reports (monthly, top shippers, routes)
- Government-app aesthetic (tricolor theme)
- Dark mode support
- Docker + Coolify deployment ready
- Seed data from existing business ledger (88 loads, 41 shippers, 70 vehicles)
2026-06-07 18:57:24 +00:00

59 lines
1.7 KiB
JavaScript

// FreightDesk — Client-side JavaScript
// Theme toggle
function toggleTheme() {
const html = document.documentElement;
const current = html.getAttribute('data-theme');
const next = current === 'dark' ? 'light' : 'dark';
html.setAttribute('data-theme', next);
localStorage.setItem('fd-theme', next);
}
// Restore theme
(function() {
const saved = localStorage.getItem('fd-theme');
if (saved) document.documentElement.setAttribute('data-theme', saved);
})();
// Auto-hide alerts after 5 seconds
document.addEventListener('DOMContentLoaded', function() {
const alerts = document.querySelectorAll('.alert');
alerts.forEach(function(alert) {
setTimeout(function() {
alert.style.opacity = '0';
alert.style.transition = 'opacity 0.5s';
setTimeout(function() { alert.remove(); }, 500);
}, 5000);
});
});
// Confirm delete actions
document.querySelectorAll('form[onsubmit]').forEach(function(form) {
form.addEventListener('submit', function(e) {
const msg = form.getAttribute('onsubmit');
if (msg && msg.includes('confirm')) {
const question = msg.match(/confirm\('(.+?)'\)/);
if (question && !confirm(question[1])) {
e.preventDefault();
}
}
});
});
// WhatsApp parser (inline function for form page)
// parseWhatsApp() and applyParsed() are defined inline in the form view
// Format number as INR
function formatINR(num) {
if (num === null || num === undefined || isNaN(num)) return '—';
return '₹' + parseFloat(num).toLocaleString('en-IN');
}
// Debounce helper
function debounce(fn, ms) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), ms);
};
}