Overview
The S-Parking dashboard is a modern single-page application built with ES6 modules, leveraging native JavaScript imports for clean dependency management. The architecture follows a modular design with clear separation of concerns across UI, API, map, and utility layers.
Entry Point: main.js
The main.js file serves as the application orchestrator, initializing all modules and managing the global application state.
Module Import Structure
import { CONFIG } from './config/config.js' ;
import { monitorAuthState , logoutUser } from './auth/auth.js' ;
import { fetchParkingStatus , reserveSpot , releaseSpot } from './api/parking.js' ;
import { fetchZones , manageZone } from './api/zones.js' ;
import * as MapCore from './map/core.js' ;
import * as MapMarkers from './map/markers.js' ;
import * as MapAdmin from './map/admin.js' ;
import * as MapBuilder from './map/builder.js' ;
import * as UI_Sidebar from './ui/sidebar.js' ;
import * as UI_Charts from './ui/charts.js' ;
The import system uses:
Named imports for specific functions (auth, API calls)
Namespace imports for feature modules (Map*, UI_*)
Relative paths for all local modules
ES6 modules are loaded natively by the browser - no bundler required during development!
State Management
The application uses a centralized state object for reactive data flow:
const state = {
currentUser: null ,
spots: [],
zones: [],
historyData: null ,
filter: 'all' ,
searchQuery: '' ,
myReservation: null ,
isFetching: false ,
isAdminMode: false ,
mapReady: false ,
isBuilderMode: false ,
bulkSelection: { enabled: false , zoneId: null , selected: new Set () },
zonesSearchQuery: '' ,
adminDragging: false ,
adminLastInteraction: 0
};
// Global exposure for cross-module access
window . appState = state ;
State Properties
Core Data
spots: Array of parking spot objects
zones: Array of zone configurations
historyData: Historical occupancy data with samples and zone breakdowns
UI State
filter: Active filter (‘all’, ‘free’, ‘occupied’, ‘reserved’)
searchQuery: Current search text
myReservation: User’s active reservation
Admin State
isAdminMode: Admin toolbar visibility
isBuilderMode: Visual builder tool active
bulkSelection: Multi-select state for zone operations
Application Lifecycle
The initialization sequence follows a strict order to ensure dependencies are ready:
document . addEventListener ( 'DOMContentLoaded' , async () => {
// 1. Initialize Chart.js visualizations
const ctx = document . getElementById ( 'hourly-chart' );
if ( ctx ) {
UI_Charts . initChart ( ctx );
}
// 2. Monitor authentication state
monitorAuthState (( user ) => {
state . currentUser = user ;
updateUserUI ( user );
// Show admin toolbar for authorized users
if ( user && user . email === '[email protected] ' ) {
state . isAdminMode = true ;
}
});
// 3. Initialize Google Maps
await MapCore . initMap ( 'map' );
state . mapReady = true ;
// 4. Parallel data loading
const [ parkingData , zonesData , historyResponse ] = await Promise . all ([
fetchParkingStatus (),
fetchZones (),
fetchOccupancyHistory ( 2 )
]);
state . spots = parkingData || [];
state . zones = zonesData || [];
// 5. Render initial UI
MapMarkers . updateClusterView ( state . spots , state . zones , handleSpotClick );
UI_Sidebar . renderSidebar ( state . spots , state . zones , state . historyData . zoneData ,
state . filter , state . searchQuery , null , handleSpotClick );
// 6. Start polling loops
fetchData ();
setInterval ( fetchData , pollingInterval );
});
Parallel data loading with Promise.all() reduces initial load time by ~40% compared to sequential requests.
Module Organization
The codebase is organized into logical feature directories:
API Layer
Map Layer
UI Layer
Utilities
api/
├── parking.js # CRUD operations for spots
├── zones.js # Zone management
└── history.js # Occupancy history
Handles all backend communication with caching and localStorage fallbacks. map/
├── core.js # Google Maps initialization
├── markers.js # Marker rendering & clustering
├── builder.js # Visual spot builder tool
└── admin.js # Admin drag-and-drop
Encapsulates all Google Maps API interactions. ui/
├── sidebar.js # Spot list with zones
├── charts.js # Chart.js wrappers
├── modals.js # Modal dialogs
├── toasts.js # Toast notifications
└── sounds.js # Audio feedback
Pure UI components with no business logic. utils/
├── formatters.js # Date/time formatting
├── validators.js # Input validation
├── helpers.js # Debounce, throttle
└── logger.js # Structured logging
Reusable helper functions.
Event Handling Patterns
Global Function Exposure
For functions called from HTML onclick handlers:
function focusOnSpot ( spotId ) {
const spot = window . appState . spots . find ( s => s . id === spotId );
if ( ! spot ) return false ;
MapCore . mapState . map . panTo ({ lat: spot . lat , lng: spot . lng });
setTimeout (() => MapCore . mapState . map . setZoom ( 20 ), 400 );
MapMarkers . highlightSpot ( spotId );
return true ;
}
// Expose globally BEFORE rendering UI
window . focusOnSpot = focusOnSpot ;
Event Delegation
For dynamically rendered content:
document . addEventListener ( 'DOMContentLoaded' , () => {
document . addEventListener ( 'click' , ( e ) => {
const card = e . target . closest ( '.spot-card' );
if ( ! card ) return ;
const spotId = card . dataset . spotId ;
if ( window . focusOnSpot ) {
window . focusOnSpot ( spotId );
}
});
});
Admin Mode Features
Admin capabilities are conditionally enabled based on user permissions:
monitorAuthState (( user ) => {
const toolbar = document . getElementById ( 'admin-toolbar' );
if ( ! toolbar ) return ;
if ( user && user . email === '[email protected] ' ) {
toolbar . classList . remove ( 'hidden' );
toolbar . classList . add ( 'show' );
state . isAdminMode = true ;
} else {
toolbar . classList . remove ( 'show' );
toolbar . classList . add ( 'hidden' );
state . isAdminMode = false ;
}
});
Admin features include:
Drag-and-drop spot repositioning
Visual builder for creating spot grids
Bulk zone assignment
Spot CRUD operations
Debugging & Development
The logger utility provides structured console output:
import { logger } from './utils/logger.js' ;
logger . debug ( '✅ Google Maps initialized' );
logger . error ( '❌ Failed to fetch parking data:' , error );
Global state inspection:
// In browser console:
window . appState
// Shows current spots, zones, filters, etc.
Map Integration Learn about Google Maps API setup and custom overlays
Builder Mode Visual tool for creating parking spot layouts
Performance Caching strategies and polling control