Add Mapbox static map generation for non-JavaScript users

- Implement MapImageService using Mapbox Static Images API
- Add server-side /table route with HTML form submission
- Generate static map images with auto-fit positioning based on actual location coordinates
- Add progressive enhancement with noscript fallbacks and Basic View button
- Update map center coordinates to proper Grand Rapids location
- Add numbered pins with color coding (red for regular, orange for persistent reports)
- Remove server-side caching to ensure fresh map images
- Fix theme toggle icon centering in CSS mixins

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude Code 2025-07-06 00:09:23 -04:00
parent 6cb165a3c3
commit 96dc6bde42
8 changed files with 1015 additions and 18 deletions

View file

@ -1,5 +1,5 @@
document.addEventListener('DOMContentLoaded', () => {
const map = L.map('map').setView([42.9634, -85.6681], 10);
const map = L.map('map').setView([42.960081464833195, -85.67402711517647], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,

View file

@ -20,6 +20,20 @@
}
})();
</script>
<noscript>
<style>
.js-only { display: none !important; }
.nojs-fallback { display: block !important; }
.nojs-notice {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 15px;
margin: 20px 0;
text-align: center;
}
</style>
</noscript>
</head>
<body>
<div class="container">
@ -29,23 +43,31 @@
<h1>❄️ Great Lakes Ice Report</h1>
<p>Community-reported ICEy road conditions and winter hazards (auto-expire after 48 hours)</p>
</div>
<button id="theme-toggle" class="theme-toggle" title="Toggle dark mode">
<button id="theme-toggle" class="theme-toggle js-only" title="Toggle dark mode">
<span class="theme-icon">🌙</span>
</button>
</div>
</header>
<div class="content">
<!-- Non-JavaScript fallback notice -->
<noscript>
<div class="nojs-notice">
<p><strong>JavaScript is disabled.</strong> For the best experience with interactive maps, please enable JavaScript.</p>
<p><a href="/table" style="color: #007bff; text-decoration: underline;">Click here to view the table-only version →</a></p>
</div>
</noscript>
<div class="form-section">
<h2>Report ICEy Conditions</h2>
<form id="location-form">
<form id="location-form" method="POST" action="/submit-report">
<div class="form-group">
<label for="address">Address or Location *</label>
<div class="autocomplete-container">
<input type="text" id="address" name="address" required
placeholder="Enter address, intersection (e.g., Main St & Second St, City), or landmark"
autocomplete="off">
<div id="autocomplete-list" class="autocomplete-list"></div>
<div id="autocomplete-list" class="autocomplete-list js-only"></div>
</div>
<small class="input-help">Examples: "123 Main St, City" or "Main St & Oak Ave, City" or "CVS Pharmacy, City"</small>
</div>
@ -59,23 +81,38 @@ placeholder="Enter address, intersection (e.g., Main St & Second St, City), or l
<button type="submit" id="submit-btn">
<span id="submit-text">Report Location</span>
<span id="submit-loading" style="display: none;">Submitting...</span>
<span id="submit-loading" style="display: none;" class="js-only">Submitting...</span>
</button>
</form>
<div id="message" class="message"></div>
<div id="message" class="message js-only"></div>
</div>
<div class="map-section">
<div class="reports-header">
<h2>Current Reports</h2>
<div class="view-toggle">
<div class="view-toggle js-only">
<button id="map-view-btn" class="toggle-btn active">📍 Map View</button>
<button id="table-view-btn" class="toggle-btn">📋 Table View</button>
<a href="/table" class="toggle-btn" style="text-decoration: none; line-height: normal;" title="Server-side view that works without JavaScript">📊 Basic View</a>
</div>
<noscript>
<div class="nojs-fallback" style="display: block;">
<div style="text-align: center; margin: 24px 0;">
<h3>Static Map Overview</h3>
<img src="/map-image.png?width=600&height=400"
alt="Static map showing ice report locations"
style="max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<p style="font-size: 14px; color: #666; margin-top: 8px;">
Red markers: Regular reports | Orange markers: Persistent reports
</p>
</div>
<p style="text-align: center;"><a href="/table" style="color: #007bff; text-decoration: underline;">📋 View Detailed Table Format →</a></p>
</div>
</noscript>
</div>
<div id="map-view" class="view-container">
<div id="map-view" class="view-container js-only">
<div id="map"></div>
<div class="map-info">
<p><strong>🔴 Red markers:</strong> Icy conditions reported</p>
@ -84,7 +121,7 @@ placeholder="Enter address, intersection (e.g., Main St & Second St, City), or l
</div>
</div>
<div id="table-view" class="view-container" style="display: none;">
<div id="table-view" class="view-container js-only" style="display: none;">
<div class="table-controls">
<div class="table-info">
<p id="table-location-count">Loading locations...</p>