<%!-- ═══════════════════════════════════════════════ NOC HEADER — dense, zero chrome ═══════════════════════════════════════════════ --%>

{@current_scope.organization.name}

NOC
Live
<%= if !assigns[:summary] do %> <.skeleton_dashboard /> <% end %> <%!-- Empty State --%> <%= if assigns[:summary] && @device_count == 0 do %>
<.icon name="hero-light-bulb" class="mx-auto h-14 w-14 text-blue-500 dark:text-blue-400" />

{t("Let's get started!")}

{t("Set up your network monitoring in a few steps.")}

<%= if @current_scope.organization.use_sites do %>
1

{t("Create a Site")}

{t("Sites represent your physical locations")}

2

{t("Add Devices")}

{t("Add routers, switches, and servers to your sites")}

<% else %>
1

{t("Add Devices")}

{t("Add network devices to monitor")}

<% end %>
{if @current_scope.organization.use_sites, do: "3", else: "2"}

{t("Monitor & Receive Alerts")}

{t("TowerOps automatically monitors your devices and alerts you of issues")}

<%= if @current_scope.organization.use_sites do %> <.button navigate={~p"/sites/new"} variant="primary"> <.icon name="hero-plus" class="h-5 w-5" /> Create Your First Site <% else %> <.button navigate={~p"/devices/new"} variant="primary"> <.icon name="hero-plus" class="h-5 w-5" /> Add Your First Device <% end %>
<% end %> <%!-- Setup Checklist — shown when devices exist but setup isn't complete --%> <%= if assigns[:setup_checklist] && !@setup_checklist.all_done && @device_count > 0 do %>
<.icon name="hero-rocket-launch" class="h-5 w-5 text-blue-600 dark:text-blue-400" />

{t("Setup Progress")}

{@setup_checklist.completed}/{@setup_checklist.total}
<%!-- Progress bar --%>
<%= for step <- @setup_checklist.steps do %> <.link navigate={step.link} class={[ "flex items-center gap-2.5 rounded-md px-3 py-2 text-sm transition-colors", if(step.done, do: "text-gray-400 dark:text-gray-500", else: "text-gray-700 dark:text-gray-300 hover:bg-blue-100/50 dark:hover:bg-blue-900/20" ) ]} > <%= if step.done do %> <.icon name="hero-check-circle-solid" class="h-5 w-5 text-green-500 shrink-0" /> <% else %>
<% end %> {step.label} <%= if step[:optional] do %> optional <% end %> <% end %>
<% end %> <%= if assigns[:summary] && @device_count > 0 do %> <%!-- ═══════════════════════════════════════════════ CONDENSED STATUS BAR — single dense line ═══════════════════════════════════════════════ --%>
<%!-- Health --%>
80 -> "bg-green-100/80 dark:bg-green-900/30" @summary.health_score > 50 -> "bg-yellow-100/80 dark:bg-yellow-900/30" true -> "bg-red-100/80 dark:bg-red-900/30" end ]}> Health {@summary.health_score} {cond do @summary.health_score > 80 -> "▲" @summary.health_score > 50 -> "▬" true -> "▼" end}
<%!-- Uptime --%>
Up {if @uptime_percentage == 100.0, do: "100", else: :erlang.float_to_binary(@uptime_percentage, decimals: 1)}% {@device_up}/{@device_count} <%= if @device_down > 0 do %> {@device_down}↓ <% end %>
<%!-- Alerts --%> <.link navigate={~p"/alerts"} class="flex items-center gap-1.5 px-2.5 py-1.5 rounded hover:bg-gray-200/50 dark:hover:bg-white/5 transition" > Alerts <%= if @total_alert_count > 0 do %> {@total_alert_count} {String.duplicate("●", min(@total_alert_count, 5))} <% else %> 0 <% end %> <%= if @current_scope.organization.use_sites && @sites_count > 0 do %> <.link navigate={~p"/sites"} class="flex items-center gap-1.5 px-2.5 py-1.5 rounded hover:bg-gray-200/50 dark:hover:bg-white/5 transition" > Sites {@sites_count} <% end %> <%= if @has_subscribers do %>
Subs {format_number(@summary.subscribers.total)} <%!-- Financial data: role-gated --%> <%= if @can_view_financials do %> {format_mrr(@summary.subscribers.total_mrr)}/mo <% end %>
<%!-- Financial data: role-gated --%> <%= if @can_view_financials and mrr_at_risk_positive?(@impact_summary.mrr_at_risk) do %>
At Risk {format_mrr(@impact_summary.mrr_at_risk)} <%= if @impact_summary.subscribers_affected > 0 do %> {format_number(@impact_summary.subscribers_affected)} subs <% end %>
<% end %> <% end %> <%!-- Insights count --%> <.link navigate={~p"/insights"} class="flex items-center gap-1.5 px-2.5 py-1.5 rounded hover:bg-gray-200/50 dark:hover:bg-white/5 transition" > Insights {@summary.insights.critical + @summary.insights.warning + @summary.insights.info} 0} class="text-red-500 text-[10px]"> {@summary.insights.critical}c 0} class="text-yellow-500 text-[10px]"> {@summary.insights.warning}w
<%!-- ═══════════════════════════════════════════════ ACTIVE ISSUES — merged incidents + alerts ═══════════════════════════════════════════════ --%> <%= if @active_incidents != [] || @active_alerts != [] do %>

{t("Active Issues")}

{length(@active_incidents) + @deduped_alert_count}
<%!-- Incidents (highest priority) --%> <%= if @active_incidents != [] do %>
<%!-- severity bar --%>
= 1000 -> "bg-red-500" decimal_to_float(incident.mrr_at_risk) >= 100 -> "bg-orange-500" decimal_to_float(incident.mrr_at_risk) > 0 -> "bg-yellow-500" true -> "bg-gray-400" end else "bg-gray-400" end ]} />
<.icon name="hero-exclamation-triangle" class="h-3.5 w-3.5 text-red-500 flex-shrink-0" /> <.link navigate={~p"/devices/#{incident.device_id}"} class="text-sm font-semibold text-gray-900 hover:text-blue-600 dark:text-white dark:hover:text-blue-400" > {incident.device_name} @ {incident.site_name}
{format_duration(incident.duration_seconds)} <%= if incident.subscribers_affected > 0 do %> {format_number(incident.subscribers_affected)}s <% end %> <%!-- Financial data: role-gated --%> <%= if @can_view_financials and mrr_at_risk_positive?(incident.mrr_at_risk) do %> {format_mrr(incident.mrr_at_risk)} <% end %>
<% end %> <%!-- Alerts table --%> <%= if @active_alerts != [] do %>
{t("Device")} {t("Alert")}
10 -> "bg-red-500" alert.gaiia_impact && alert.gaiia_impact["total_subscribers"] && alert.gaiia_impact["total_subscribers"] > 0 -> "bg-orange-500" true -> "bg-yellow-500" end ]} />
<.link navigate={~p"/devices/#{alert.device.id}"} class="text-sm font-medium text-gray-900 hover:text-blue-600 dark:text-white dark:hover:text-blue-400" > {alert.device.name}
{alert.device.site.name}
{alert.message}
<%= if @total_alert_count > 20 do %>
<.link navigate={~p"/alerts"} class="text-[10px] font-medium text-blue-600 dark:text-blue-400 hover:underline" > +{@total_alert_count - 20} more alerts →
<% end %>
<% end %>
<% end %> <%!-- ═══════════════════════════════════════════════ SITE HEALTH TABLE ═══════════════════════════════════════════════ --%> <%= if @current_scope.organization.use_sites && @site_impact_summaries != [] do %>

{t("Site Health")}

<.link navigate={~p"/sites"} class="text-[10px] font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400" > all sites →
0, do: "bg-red-50/50 dark:bg-red-950/10", else: "") ]} >
{t("Site")} {t("Devices")} {t("Down")}
<.link navigate={~p"/sites/#{site.site_id}"} class="flex items-center gap-1.5 text-sm font-medium text-gray-900 hover:text-blue-600 dark:text-white dark:hover:text-blue-400" > {site.name} {site.device_count} <%= if site.devices_down > 0 do %> {site.devices_down} <% else %> 0 <% end %>
<% end %> <%!-- ═══════════════════════════════════════════════ INSIGHTS — actionable, grouped by urgency ═══════════════════════════════════════════════ --%> <%= if @insights != [] do %>

{t("Insights")}

<.link patch={~p"/dashboard"} class={[ "rounded px-1.5 py-0.5 text-[10px] font-medium transition", if(is_nil(@insight_source), do: "bg-gray-900 text-white dark:bg-white dark:text-gray-900", else: "text-gray-400 hover:bg-gray-100 dark:hover:bg-white/10" ) ]} > all <.link :for={source <- ~w(preseem snmp gaiia system)} patch={~p"/dashboard?insight_source=#{source}"} class={[ "rounded px-1.5 py-0.5 text-[10px] font-medium transition", if(@insight_source == source, do: "bg-gray-900 text-white dark:bg-white dark:text-gray-900", else: "text-gray-400 hover:bg-gray-100 dark:hover:bg-white/10" ) ]} > {source}
<.link navigate={~p"/insights"} class="text-[10px] font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400" > all insights →
<%!-- Urgency indicator --%> "bg-red-500" "warning" -> "bg-yellow-500" "info" -> "bg-blue-500" _ -> "bg-gray-400" end ]} /> "text-red-600 dark:text-red-400" "warning" -> "text-yellow-600 dark:text-yellow-400" "info" -> "text-blue-600 dark:text-blue-400" _ -> "text-gray-500 dark:text-gray-400" end ]}> {case insight.urgency do "critical" -> "CRIT" "warning" -> "WARN" "info" -> "INFO" _ -> "—" end} {insight.source} <.link navigate={~p"/insights?source=#{insight.source}"} class="text-sm text-gray-900 dark:text-white hover:text-blue-600 dark:hover:text-blue-400 truncate" > {insight.title}
<.link navigate={~p"/insights?source=#{insight.source}"} class="rounded px-1.5 py-0.5 text-[10px] font-medium text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 opacity-0 group-hover:opacity-100 transition" > View
<% end %> <%!-- ═══════════════════════════════════════════════ NETWORK PULSE + CONFIG CHANGES — side by side ═══════════════════════════════════════════════ --%>
<%!-- Network Pulse --%>

{t("Network Pulse")}

Devices monitored {@device_count}
Online {@device_up}
Down 0, do: "text-red-600 dark:text-red-400 font-bold", else: "text-gray-400" ) ]}> {@device_down}
Unknown 0, do: "text-yellow-600 dark:text-yellow-400", else: "text-gray-400" ) ]}> {@device_unknown}
<%!-- Config changes row hidden — feature temporarily disabled --%>
Active incidents 0, do: "text-red-600 dark:text-red-400 font-bold", else: "text-gray-400" ) ]}> {length(@active_incidents)}
<%!-- Config Changes — hidden, feature temporarily disabled --%>
<%!-- ═══════════════════════════════════════════════ RECENT ACTIVITY ═══════════════════════════════════════════════ --%> <%= if assigns[:recent_activity] && @recent_activity != [] do %>

{t("Recent Activity")}

<.link navigate={~p"/activity"} class="text-[10px] font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400" > all activity →

{activity.summary}

{format_short_datetime(activity.timestamp, @timezone)}
<% end %> <%!-- ═══════════════════════════════════════════════ FOOTER — Command palette hint ═══════════════════════════════════════════════ --%>
⌘K to search · <.link navigate={~p"/devices/new"} class="hover:text-gray-500 dark:text-gray-400 dark:hover:text-gray-400" > + device · <.link navigate={~p"/trace"} class="hover:text-gray-500 dark:text-gray-400 dark:hover:text-gray-400" > trace · <.link navigate={~p"/network-map"} class="hover:text-gray-500 dark:text-gray-400 dark:hover:text-gray-400" > map
<% end %>