152 lines
4.5 KiB
JavaScript
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());
|
|
}); |