defmodule ToweropsWeb.StatusPageLive do @moduledoc """ Public unauthenticated status page. Renders at /status/:slug with a standalone layout (no sidebar). Mobile-responsive for customers checking during outages. """ use ToweropsWeb, :live_view alias Towerops.StatusPages @impl true def mount(%{"slug" => slug}, _session, socket) do case StatusPages.get_config_by_slug(slug) do nil -> {:ok, socket |> put_flash(:error, "Status page not found") |> assign(:not_found, true) |> assign(:page_title, "Not Found")} config -> _ = if connected?(socket) do _ = Phoenix.PubSub.subscribe(Towerops.PubSub, "status_page:#{config.id}") end components = StatusPages.list_components(config.id) active_incidents = StatusPages.list_active_incidents(config.id) recent_incidents = StatusPages.list_incidents(config.id, limit: 10) overall = StatusPages.overall_status(components) {:ok, socket |> assign(:config, config) |> assign(:components, components) |> assign(:active_incidents, active_incidents) |> assign(:recent_incidents, recent_incidents) |> assign(:overall_status, overall) |> assign(:not_found, false) |> assign(:page_title, "#{config.company_name || "Status"} — System Status"), layout: false} end end @impl true def handle_info({:status_updated, _}, socket) do config = socket.assigns.config components = StatusPages.list_components(config.id) active_incidents = StatusPages.list_active_incidents(config.id) overall = StatusPages.overall_status(components) {:noreply, assign(socket, components: components, active_incidents: active_incidents, overall_status: overall )} end def handle_info(_, socket), do: {:noreply, socket} # -- Helpers -- @doc false def overall_color(:operational), do: "bg-green-500" def overall_color(:degraded), do: "bg-yellow-500" def overall_color(:partial_outage), do: "bg-orange-500" def overall_color(:major_outage), do: "bg-red-500" def overall_color(:maintenance), do: "bg-blue-500" def overall_color(_), do: "bg-gray-500" @doc false def overall_text(:operational), do: "All Systems Operational" def overall_text(:degraded), do: "Degraded Performance" def overall_text(:partial_outage), do: "Partial System Outage" def overall_text(:major_outage), do: "Major System Outage" def overall_text(:maintenance), do: "Scheduled Maintenance" def overall_text(_), do: "Unknown" @doc false def component_color("operational"), do: "bg-green-500" def component_color("degraded"), do: "bg-yellow-500" def component_color("partial_outage"), do: "bg-orange-500" def component_color("major_outage"), do: "bg-red-500" def component_color("maintenance"), do: "bg-blue-500" def component_color(_), do: "bg-gray-400" @doc false def component_label("operational"), do: "Operational" def component_label("degraded"), do: "Degraded" def component_label("partial_outage"), do: "Partial Outage" def component_label("major_outage"), do: "Major Outage" def component_label("maintenance"), do: "Maintenance" def component_label(s), do: s @doc false def severity_color("critical"), do: "text-red-600" def severity_color("major"), do: "text-orange-600" def severity_color(_), do: "text-yellow-600" @doc false def incident_status_label("investigating"), do: "Investigating" def incident_status_label("identified"), do: "Identified" def incident_status_label("monitoring"), do: "Monitoring" def incident_status_label("resolved"), do: "Resolved" def incident_status_label(s), do: s end