Refactor: Complete codebase reorganization and modernization

- Split server.js routes into modular files (server/routes/)
  - departures.js: Departure data endpoints
  - sites.js: Site search and nearby sites
  - config.js: Configuration endpoints

- Reorganized file structure following Node.js best practices:
  - Moved sites-config.json to config/sites.json
  - Moved API_RESPONSE_DOCUMENTATION.md to docs/
  - Moved raspberry-pi-setup.sh to scripts/
  - Archived legacy files to archive/ directory

- Updated all code references to new file locations
- Added archive/ to .gitignore to exclude legacy files from repo
- Updated README.md with new structure and organization
- All functionality tested and working correctly

Version: 1.2.0
This commit is contained in:
2026-01-01 10:51:58 +01:00
parent d15142f1c6
commit 392a50b535
28 changed files with 3197 additions and 3295 deletions

122
public/js/main.js Normal file
View File

@@ -0,0 +1,122 @@
/**
* Main application entry point
* Initializes all components when the DOM is ready
*/
/**
* Function to ensure content wrapper exists for rotated orientations
*/
function ensureContentWrapper() {
if (!document.getElementById('content-wrapper')) {
if (window.logger) {
window.logger.info('Creating content wrapper');
} else {
console.log('Creating content wrapper');
}
const wrapper = document.createElement('div');
wrapper.id = 'content-wrapper';
// Move all body children to the wrapper except excluded elements
const excludedElements = ['config-button', 'config-modal', 'background-overlay'];
// Create an array of nodes to move (can't modify while iterating)
const nodesToMove = [];
for (let i = 0; i < document.body.children.length; i++) {
const child = document.body.children[i];
if (!excludedElements.includes(child.id) && child.id !== 'content-wrapper') {
nodesToMove.push(child);
}
}
// Move the nodes to the wrapper
nodesToMove.forEach(node => {
wrapper.appendChild(node);
});
// Add the wrapper back to the body
document.body.appendChild(wrapper);
}
}
// Initialize components when the DOM is loaded
document.addEventListener('DOMContentLoaded', async function() {
if (window.logger) {
window.logger.info('DOM fully loaded');
} else {
console.log('DOM fully loaded');
}
try {
// Initialize ConfigManager first
if (window.logger) {
window.logger.info('Creating ConfigManager...');
} else {
console.log('Creating ConfigManager...');
}
window.configManager = new ConfigManager({
defaultOrientation: 'normal',
defaultDarkMode: 'auto'
});
// Note: ConfigManager already creates the config button and modal
// Initialize Clock
const timezone = window.Constants?.TIMEZONE || 'Europe/Stockholm';
window.clock = new Clock({
elementId: 'clock',
timezone: timezone
});
// Initialize WeatherManager with location from window config or constants
const defaultLat = window.DEFAULT_LOCATION?.latitude ||
(window.Constants?.DEFAULT_LOCATION?.LATITUDE) || 59.3293;
const defaultLon = window.DEFAULT_LOCATION?.longitude ||
(window.Constants?.DEFAULT_LOCATION?.LONGITUDE) || 18.0686;
window.weatherManager = new WeatherManager({
latitude: defaultLat,
longitude: defaultLon
});
// Initialize departures - use DeparturesManager
if (typeof DeparturesManager !== 'undefined') {
window.departuresManager = new DeparturesManager({
containerId: 'departures',
statusId: 'status',
lastUpdatedId: 'last-updated'
});
} else if (typeof initDepartures === 'function') {
// Fallback to legacy function if DeparturesManager not available
initDepartures();
}
// Set up event listeners
document.addEventListener('darkModeChanged', event => {
document.body.classList.toggle('dark-mode', event.detail.isDarkMode);
});
document.addEventListener('configChanged', event => {
if (['vertical', 'upsidedown', 'vertical-reverse'].includes(event.detail.config.orientation)) {
ensureContentWrapper();
}
});
// Ensure content wrapper exists initially
ensureContentWrapper();
if (window.logger) {
window.logger.info('All components initialized successfully');
} else {
console.log('All components initialized successfully');
}
} catch (error) {
if (window.logger) {
window.logger.error('Error during initialization:', error);
} else {
console.error('Error during initialization:', error);
}
const errorDiv = document.createElement('div');
errorDiv.className = 'error';
errorDiv.textContent = `Initialization error: ${error.message}`;
document.body.appendChild(errorDiv);
}
});