From 480480bde394ae0e1cd00d5d104ea13edb9680f1 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sun, 29 Mar 2026 14:33:14 -0500 Subject: [PATCH] Fix QSO show page weather lookup and add expandable sounding profiles Fix pos1 longitude key mismatch (lng vs lon) that caused empty weather results for all QSOs. Bump search radius to 300km for sounding coverage. Soundings now show as expandable cards with full elevation profile data. --- lib/microwaveprop_web/live/qso_live/show.ex | 120 ++++++++++++++------ 1 file changed, 88 insertions(+), 32 deletions(-) diff --git a/lib/microwaveprop_web/live/qso_live/show.ex b/lib/microwaveprop_web/live/qso_live/show.ex index d2986d81..f4df42f5 100644 --- a/lib/microwaveprop_web/live/qso_live/show.ex +++ b/lib/microwaveprop_web/live/qso_live/show.ex @@ -22,7 +22,8 @@ defmodule MicrowavepropWeb.QsoLive.Show do obs_sort_by: "station_name", obs_sort_order: "asc", sounding_sort_by: "station_name", - sounding_sort_order: "asc" + sounding_sort_order: "asc", + expanded_soundings: MapSet.new() )} end @@ -41,6 +42,17 @@ defmodule MicrowavepropWeb.QsoLive.Show do )} end + def handle_event("toggle_profile", %{"id" => id}, socket) do + expanded = + if MapSet.member?(socket.assigns.expanded_soundings, id) do + MapSet.delete(socket.assigns.expanded_soundings, id) + else + MapSet.put(socket.assigns.expanded_soundings, id) + end + + {:noreply, assign(socket, expanded_soundings: expanded)} + end + def handle_event("sort", %{"field" => field, "table" => "soundings"}, socket) do {sort_by, sort_order} = toggle_sort(socket.assigns.sounding_sort_by, socket.assigns.sounding_sort_order, field) @@ -91,12 +103,15 @@ defmodule MicrowavepropWeb.QsoLive.Show do defp sounding_sort_key(_), do: fn s -> s.station.name || s.station.station_code end defp load_weather(qso) do - case qso.pos1 do - %{"lat" => lat, "lon" => lon} -> - Weather.weather_for_qso(%{lat: lat, lon: lon, timestamp: qso.qso_timestamp}) + lat = qso.pos1 && qso.pos1["lat"] + lon = qso.pos1 && (qso.pos1["lon"] || qso.pos1["lng"]) - _ -> - %{surface_observations: [], soundings: []} + if lat && lon do + Weather.weather_for_qso(%{lat: lat, lon: lon, timestamp: qso.qso_timestamp}, + radius_km: 300 + ) + else + %{surface_observations: [], soundings: []} end end @@ -175,32 +190,67 @@ defmodule MicrowavepropWeb.QsoLive.Show do <%= if @soundings == [] do %>

No soundings found nearby.

<% else %> - <.table - id="soundings" - rows={@soundings} - row_id={fn s -> "sounding-#{s.id}" end} - sort_by={@sounding_sort_by} - sort_order={@sounding_sort_order} - sort_target="soundings" - > - <:col :let={s} label="Station" sort_field="station_name"> - {s.station.name || s.station.station_code} - - <:col :let={s} label="Time" sort_field="observed_at"> - {Calendar.strftime(s.observed_at, "%H:%M")} - - <:col :let={s} label="Sfc Temp (C)" sort_field="surface_temp_c"> - {s.surface_temp_c || "—"} - - <:col :let={s} label="Refractivity" sort_field="surface_refractivity"> - {format_number(s.surface_refractivity)} - - <:col :let={s} label="Ducting">{if s.ducting_detected, do: "Yes", else: "No"} - <:col :let={s} label="K-Index" sort_field="k_index">{format_number(s.k_index)} - <:col :let={s} label="Lifted Index" sort_field="lifted_index"> - {format_number(s.lifted_index)} - - + <%= for s <- @soundings do %> +
+ + + <%= if MapSet.member?(@expanded_soundings, s.id) do %> +
+
+ + + + + + + + + + + + + <%= for level <- filter_profile(s.profile) do %> + + + + + + + + + <% end %> + +
Pressure (mb)Height (m)Temp (°C)Dewpoint (°C)Wind Dir (°)Wind Spd (kts)
{format_number(level["pres"])}{format_number(level["hght"])}{format_number(level["tmpc"])}{format_number(level["dwpc"])}{format_number(level["drct"])}{format_number(level["sknt"])}
+
+
+ <% end %> +
+ <% end %> <% end %>
@@ -231,6 +281,12 @@ defmodule MicrowavepropWeb.QsoLive.Show do end end + defp filter_profile(profile) do + Enum.filter(profile, fn level -> + level["tmpc"] != nil || level["dwpc"] != nil + end) + end + defp format_kp(nil), do: "—" defp format_kp(values) when is_list(values), do: Enum.map_join(values, ", ", &format_number/1) end