fix: Handle numeric weather values and hide N/A fields in weather view
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 <noreply@anthropic.com>
This commit is contained in:
parent
fd60467da8
commit
e6d8894bf6
2 changed files with 101 additions and 54 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -86,58 +86,75 @@
|
|||
<% end %>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Temperature")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :temperature, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Humidity")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :humidity)}%
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Wind")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {format_weather_value(
|
||||
@weather_packet,
|
||||
:wind_speed,
|
||||
@locale
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Gusts")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :wind_gust, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Pressure")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (1h)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :rain_1h, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (24h)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :rain_24h, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (since midnight)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :rain_since_midnight, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<%= if has_weather_field?(@weather_packet, :temperature) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Temperature")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :temperature, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :humidity) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Humidity")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :humidity)}%
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :wind_direction) || has_weather_field?(@weather_packet, :wind_speed) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Wind")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
<%= 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 %>
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :wind_gust) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Gusts")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :wind_gust, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :pressure) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Pressure")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :rain_1h) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (1h)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :rain_1h, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :rain_24h) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (24h)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :rain_24h, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if has_weather_field?(@weather_packet, :rain_since_midnight) do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (since midnight)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{format_weather_value(@weather_packet, :rain_since_midnight, @locale)}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="col-span-2">
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Raw Packet")}</dt>
|
||||
<dd class="mt-1 text-xs font-mono break-all">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue