defmodule ToweropsWeb.DeviceLive.Components.PreseemTab do @moduledoc """ LiveComponent for the device Preseem integration tab. Displays Preseem access point data, subscriber metrics, and device insights. """ use ToweropsWeb, :live_component alias ToweropsWeb.DeviceLive.Helpers.DataLoaders @impl true def update(assigns, socket) do {:ok, socket |> assign(assigns) |> load_preseem_data()} end defp load_preseem_data(socket) do device = socket.assigns.device preseem_data = DataLoaders.load_preseem_data(device) socket |> assign(:preseem_access_point, preseem_data.preseem_access_point) |> assign(:preseem_metrics, preseem_data.preseem_metrics) |> assign(:preseem_insights, preseem_data.preseem_insights) end @impl true def render(assigns) do ~H"""
<%= if @preseem_access_point do %>
<%!-- Insights section --%> <%= if @preseem_insights != [] do %>
<%= for insight <- @preseem_insights do %>
"bg-red-50 border-red-200 dark:bg-red-900/20 dark:border-red-800" "warning" -> "bg-yellow-50 border-yellow-200 dark:bg-yellow-900/20 dark:border-yellow-800" _ -> "bg-blue-50 border-blue-200 dark:bg-blue-900/20 dark:border-blue-800" end ]}>
"text-red-500" "warning" -> "text-yellow-500" _ -> "text-blue-500" end ]}> <%= case insight.urgency do %> <% "critical" -> %> <.icon name="hero-exclamation-triangle" class="h-5 w-5" /> <% "warning" -> %> <.icon name="hero-exclamation-circle" class="h-5 w-5" /> <% _ -> %> <.icon name="hero-information-circle" class="h-5 w-5" /> <% end %>

{insight.title}

{insight.description}

<% end %>
<% end %> <%!-- Score cards --%>
QoE Score
{if @preseem_access_point.qoe_score, do: Float.round(@preseem_access_point.qoe_score, 1), else: "---"}
{t("Capacity Score")}
{if @preseem_access_point.capacity_score, do: Float.round(@preseem_access_point.capacity_score, 1), else: "---"}
RF Score
{if @preseem_access_point.rf_score, do: Float.round(@preseem_access_point.rf_score, 1), else: "---"}
<%!-- Details card --%>

{t("Access Point Details")}

Name
{@preseem_access_point.name || "---"}
{t("Preseem ID")}
{@preseem_access_point.preseem_id}
{t("Subscribers")}
{@preseem_access_point.subscriber_count || "---"}
{t("Busy Hours")}
<%= if @preseem_access_point.busy_hours do %> {@preseem_access_point.busy_hours} hrs/day <% else %> --- <% end %>
{t("Airtime Utilization")}
<%= if @preseem_access_point.airtime_utilization do %> {Float.round(@preseem_access_point.airtime_utilization, 1)}% <% else %> --- <% end %>
{t("Match Type")}
{@preseem_access_point.match_confidence}
<%!-- Recent metrics table --%> <%= if @preseem_metrics != [] do %>

{t("Recent QoE Metrics")}

<%= for metric <- @preseem_metrics do %> <% end %>
{t("Time")} {t("Latency (ms)")} {t("P95 Latency")} {t("Jitter (ms)")} {t("Loss (%)")} {t("Throughput")} {t("Subscribers")}
{ToweropsWeb.TimeHelpers.format_iso8601( metric.recorded_at, @current_scope.timezone, @current_scope.time_format )} {if metric.avg_latency, do: Float.round(metric.avg_latency, 1), else: "---"} {if metric.p95_latency, do: Float.round(metric.p95_latency, 1), else: "---"} {if metric.avg_jitter, do: Float.round(metric.avg_jitter, 1), else: "---"} {if metric.avg_loss, do: Float.round(metric.avg_loss, 2), else: "---"} {if metric.avg_throughput, do: "#{Float.round(metric.avg_throughput, 1)} Mbps", else: "---"} {metric.subscriber_count || "---"}
<% end %>
<% else %>

{t("No Preseem data linked to this device.")}

<% end %>
""" end @impl true def handle_event("dismiss_insight", %{"id" => insight_id}, socket) do case Towerops.Preseem.dismiss_insight(insight_id) do {:ok, _} -> # Reload preseem data after dismissing insight {:noreply, load_preseem_data(socket)} {:error, _} -> {:noreply, put_flash(socket, :error, "Failed to dismiss insight")} end end end