From 6f452e71392fa784cfef4dc891335b63daab4a63 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 17 Apr 2026 08:28:07 -0500 Subject: [PATCH] feat(map): show CONUS-only banner for visitors outside continental US MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Visitor geolocation already flows via the Cloudflare CF-IPLatitude / CF-IPLongitude headers into the session; MapLive centers the map on the visitor's location (or DFW as fallback). Add a banner that appears above the map when those coords are outside the CONUS bbox (lat 24.5-49.5, lon -125 to -66.5), letting overseas visitors know propagation data won't be available at their location yet. Map still centers on the visitor's actual location — this is a note, not a re-center. Banner is fully absent from the DOM when not needed (:if conditional). --- lib/microwaveprop_web/live/map_live.ex | 45 +++++++++++++++++++ test/microwaveprop_web/live/map_live_test.exs | 24 ++++++++++ 2 files changed, 69 insertions(+) diff --git a/lib/microwaveprop_web/live/map_live.ex b/lib/microwaveprop_web/live/map_live.ex index a3bbe388..40f645b7 100644 --- a/lib/microwaveprop_web/live/map_live.ex +++ b/lib/microwaveprop_web/live/map_live.ex @@ -15,6 +15,14 @@ defmodule MicrowavepropWeb.MapLive do @default_center %{lat: 32.897, lon: -97.038} @default_zoom 7 + # Continental-US bounding box (excludes Alaska, Hawaii, Puerto Rico). Used + # to decide whether to show the "data is CONUS-only" banner to visitors + # whose Cloudflare geolocation falls outside the dataset's coverage. + @conus_lat_min 24.5 + @conus_lat_max 49.5 + @conus_lon_min -125.0 + @conus_lon_max -66.5 + # How often to re-query oban_jobs for pipeline state while the map is # open. Short enough that the "Updating…" chip shows up within a page- # visit for an in-progress hourly run, long enough to be cheap. @@ -53,6 +61,7 @@ defmodule MicrowavepropWeb.MapLive do valid_times = Propagation.available_valid_times(selected_band) selected_time = recovered_time || closest_to_now(valid_times) center = initial_center(session) + visitor = visitor_location(session) bounds = bounds_around(center) initial_scores = Propagation.scores_at(selected_band, selected_time, bounds) @@ -73,6 +82,7 @@ defmodule MicrowavepropWeb.MapLive do bounds: bounds, initial_center: center, initial_zoom: @default_zoom, + outside_conus: outside_conus?(visitor), grid_visible: false, radar_visible: false, antenna_height_ft: 33 @@ -86,6 +96,25 @@ defmodule MicrowavepropWeb.MapLive do defp initial_center(_session), do: @default_center + # Return the visitor's Cloudflare geolocation as a %{lat:, lon:} map, or + # nil when the CF headers weren't set (local dev, direct connect, tests + # without a stubbed session). + defp visitor_location(%{"cf_lat" => lat, "cf_lon" => lon}) when is_float(lat) and is_float(lon) do + %{lat: lat, lon: lon} + end + + defp visitor_location(_session), do: nil + + # True when the visitor's location is known and falls outside the CONUS + # bounding box. Missing geolocation returns false so we don't flash a + # banner at anyone we can't actually place. + defp outside_conus?(nil), do: false + + defp outside_conus?(%{lat: lat, lon: lon}) do + lat < @conus_lat_min or lat > @conus_lat_max or + lon < @conus_lon_min or lon > @conus_lon_max + end + # Build a bounding box roughly matching the hardcoded default (~3.4° × 9°) # around a given center so the initial HRRR score query still returns a # useful tile set for the visible area. @@ -486,6 +515,22 @@ defmodule MicrowavepropWeb.MapLive do
<%!-- Map container --%>
+ <%!-- CONUS-only data banner (shown only when visitor geolocation is + outside the continental US) --%> +
+ <.icon name="hero-information-circle" class="size-5 shrink-0" /> + + This data set currently covers the continental United States only. + You're viewing the map centered on your location, but propagation + data won't be available there yet. + +
+ <%!-- Full-page map --%>