152 lines
4.5 KiB
JavaScript

// Main Application Module
class MainApp {
constructor() {
this.init();
}
init() {
// Initialize message display system
window.messageDisplay = new MessageDisplay();
// Check API health on startup
this.checkAPIHealth();
// Add global error handling
window.addEventListener('error', (e) => {
console.error('Global error:', e.error);
window.messageDisplay.show('An unexpected error occurred. Please refresh the page and try again.', 'error');
});
// Add unhandled promise rejection handling
window.addEventListener('unhandledrejection', (e) => {
console.error('Unhandled promise rejection:', e.reason);
window.messageDisplay.show('An unexpected error occurred. Please try again.', 'error');
e.preventDefault();
});
}
async checkAPIHealth() {
try {
await window.apiClient.checkHealth();
console.log('API health check passed');
} catch (error) {
console.error('API health check failed:', error);
window.messageDisplay.show('Connection to server failed. Please check your internet connection and try again.', 'error');
}
}
}
// Message Display System
class MessageDisplay {
constructor() {
this.container = document.getElementById('message-display');
this.timeouts = new Map();
}
show(message, type = 'info', duration = 5000) {
// Clear existing timeout for this container
if (this.timeouts.has(this.container)) {
clearTimeout(this.timeouts.get(this.container));
}
// Set message content and type
this.container.innerHTML = message;
this.container.className = `message-display ${type}`;
this.container.style.display = 'block';
// Auto-hide after duration
const timeout = setTimeout(() => {
this.hide();
}, duration);
this.timeouts.set(this.container, timeout);
// Add click to dismiss
this.container.style.cursor = 'pointer';
this.container.onclick = () => this.hide();
}
hide() {
this.container.style.display = 'none';
this.container.onclick = null;
// Clear timeout
if (this.timeouts.has(this.container)) {
clearTimeout(this.timeouts.get(this.container));
this.timeouts.delete(this.container);
}
}
}
// Utility functions
const Utils = {
// Format postal code consistently
formatPostalCode(postalCode) {
const cleaned = postalCode.replace(/\s/g, '').toUpperCase();
if (cleaned.length === 6) {
return `${cleaned.slice(0, 3)} ${cleaned.slice(3)}`;
}
return cleaned;
},
// Sanitize text input
sanitizeText(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
},
// Debounce function for input handling
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
},
// Check if we're on mobile
isMobile() {
return window.innerWidth <= 768;
},
// Format date for display
formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('en-CA', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
};
// Make utils globally available
window.Utils = Utils;
// Initialize app when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
window.mainApp = new MainApp();
// Add some basic accessibility improvements
document.addEventListener('keydown', (e) => {
// Allow Escape to close modals (handled in individual modules)
// Add tab navigation improvements if needed
});
// Add responsive behavior
window.addEventListener('resize', Utils.debounce(() => {
// Handle responsive layout changes if needed
const isMobile = Utils.isMobile();
document.body.classList.toggle('mobile', isMobile);
}, 250));
// Initial mobile class
document.body.classList.toggle('mobile', Utils.isMobile());
});