From e6d8894bf6e539e7ffdacd1f801487c2ff0c4697 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sun, 3 Aug 2025 15:33:09 -0500 Subject: [PATCH] fix: Handle numeric weather values and hide N/A fields in weather view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The weather view was crashing with CaseClauseError when receiving numeric values (like 83.0) from the database instead of strings. Also improved the UI to only show weather fields that have valid data. Changes: - Added support for numeric values in format_weather_value function - Added has_weather_field? helper to check for valid weather data - Updated template to conditionally display weather fields - Fields with nil, "N/A", or empty values are now hidden - Wind field shows direction and speed independently if available This prevents crashes and provides a cleaner UI by only showing available weather data instead of displaying N/A values. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../live/weather_live/callsign_view.ex | 34 ++++- .../live/weather_live/callsign_view.html.heex | 121 ++++++++++-------- 2 files changed, 101 insertions(+), 54 deletions(-) diff --git a/lib/aprsme_web/live/weather_live/callsign_view.ex b/lib/aprsme_web/live/weather_live/callsign_view.ex index c932a6b..9be2f17 100644 --- a/lib/aprsme_web/live/weather_live/callsign_view.ex +++ b/lib/aprsme_web/live/weather_live/callsign_view.ex @@ -195,6 +195,20 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do rain_since_midnight: {&WeatherUnits.format_rain/2, " "} } + @doc """ + Checks if a weather field has a valid value (not nil, "N/A", or empty). + """ + def has_weather_field?(packet, field) do + value = PacketUtils.get_weather_field(packet, field) + + case value do + nil -> false + "N/A" -> false + "" -> false + _ -> true + end + end + @doc """ Formats weather values with appropriate units based on locale. """ @@ -202,8 +216,21 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do value = PacketUtils.get_weather_field(packet, key) case value do + nil -> + nil + "N/A" -> - "N/A" + nil + + value when is_number(value) -> + case @weather_formatters[key] do + {formatter, separator} -> + {converted_value, unit} = formatter.(value, locale) + "#{converted_value}#{separator}#{unit}" + + nil -> + "#{value}" + end value when is_binary(value) -> case @weather_formatters[key] do @@ -214,12 +241,15 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do "#{converted_value}#{separator}#{unit}" :error -> - value + nil end nil -> "#{value}" end + + _ -> + nil end end end diff --git a/lib/aprsme_web/live/weather_live/callsign_view.html.heex b/lib/aprsme_web/live/weather_live/callsign_view.html.heex index bd5a66a..e87e743 100644 --- a/lib/aprsme_web/live/weather_live/callsign_view.html.heex +++ b/lib/aprsme_web/live/weather_live/callsign_view.html.heex @@ -86,58 +86,75 @@ <% end %> -
-
{gettext("Temperature")}
-
- {format_weather_value(@weather_packet, :temperature, @locale)} -
-
-
-
{gettext("Humidity")}
-
- {PacketUtils.get_weather_field(@weather_packet, :humidity)}% -
-
-
-
{gettext("Wind")}
-
- {PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {format_weather_value( - @weather_packet, - :wind_speed, - @locale - )} -
-
-
-
{gettext("Gusts")}
-
- {format_weather_value(@weather_packet, :wind_gust, @locale)} -
-
-
-
{gettext("Pressure")}
-
- {PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa -
-
-
-
{gettext("Rain (1h)")}
-
- {format_weather_value(@weather_packet, :rain_1h, @locale)} -
-
-
-
{gettext("Rain (24h)")}
-
- {format_weather_value(@weather_packet, :rain_24h, @locale)} -
-
-
-
{gettext("Rain (since midnight)")}
-
- {format_weather_value(@weather_packet, :rain_since_midnight, @locale)} -
-
+ <%= if has_weather_field?(@weather_packet, :temperature) do %> +
+
{gettext("Temperature")}
+
+ {format_weather_value(@weather_packet, :temperature, @locale)} +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :humidity) do %> +
+
{gettext("Humidity")}
+
+ {PacketUtils.get_weather_field(@weather_packet, :humidity)}% +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :wind_direction) || has_weather_field?(@weather_packet, :wind_speed) do %> +
+
{gettext("Wind")}
+
+ <%= if has_weather_field?(@weather_packet, :wind_direction) do %> + {PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° + <% end %> + <%= if has_weather_field?(@weather_packet, :wind_speed) do %> + @ {format_weather_value(@weather_packet, :wind_speed, @locale)} + <% end %> +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :wind_gust) do %> +
+
{gettext("Gusts")}
+
+ {format_weather_value(@weather_packet, :wind_gust, @locale)} +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :pressure) do %> +
+
{gettext("Pressure")}
+
+ {PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :rain_1h) do %> +
+
{gettext("Rain (1h)")}
+
+ {format_weather_value(@weather_packet, :rain_1h, @locale)} +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :rain_24h) do %> +
+
{gettext("Rain (24h)")}
+
+ {format_weather_value(@weather_packet, :rain_24h, @locale)} +
+
+ <% end %> + <%= if has_weather_field?(@weather_packet, :rain_since_midnight) do %> +
+
{gettext("Rain (since midnight)")}
+
+ {format_weather_value(@weather_packet, :rain_since_midnight, @locale)} +
+
+ <% end %>
{gettext("Raw Packet")}