defmodule MicrowavepropWeb.RoverPlanningLive.PathShow do @moduledoc """ Stable permalink for one rover-planning Path. Resolves the saved rover-location, station, band, and antenna heights into the full `/path` URL so the operator sees the same terrain chart, conditions readout, link / power budget, and forecast that the Path Calculator renders. The cached `result` map on the Path row is still consulted by the rover-planning show table — this LiveView just bridges the row click back to the canonical `/path` view. """ use MicrowavepropWeb, :live_view import Ecto.Query alias Microwaveprop.Radio.Maidenhead alias Microwaveprop.Repo alias Microwaveprop.RoverPlanning.Mission alias Microwaveprop.RoverPlanning.Path @impl true def mount(%{"id" => mission_id, "path_id" => path_id}, _session, socket) do case load_path(mission_id, path_id) do nil -> {:ok, socket |> put_flash(:error, "Path profile not found.") |> push_navigate(to: ~p"/rover-planning/#{mission_id}")} %Path{} = path -> {:ok, push_navigate(socket, to: live_path_url(path))} end end # Builds the `/path` URL with the rover/station/band/heights baked # in. Source uses a 10-char Maidenhead grid (max precision) so the # rover spot resolves precisely; destination prefers the station's # callsign, falling back to grid or coordinates. defp live_path_url(%Path{} = path) do %Path{rover_location: rover, station: station, mission: %Mission{} = mission} = path src = Maidenhead.from_latlon(rover.lat, rover.lon, 10) dst = station_endpoint(station) band = path.band_mhz || mission.band_mhz query = URI.encode_query(%{ "source" => src, "destination" => dst, "band" => Integer.to_string(band), "src_height_ft" => Float.to_string((mission.rover_height_ft || 8.0) * 1.0), "dst_height_ft" => Float.to_string((mission.station_height_ft || 30.0) * 1.0) }) "/path?" <> query end defp station_endpoint(%{callsign: c}) when is_binary(c) and c != "", do: c defp station_endpoint(%{grid: g}) when is_binary(g) and g != "", do: g defp station_endpoint(%{lat: lat, lon: lon}) when is_number(lat) and is_number(lon), do: Maidenhead.from_latlon(lat, lon, 8) defp station_endpoint(_), do: "" defp load_path(mission_id, path_id) do with {:ok, mission_uuid} <- Ecto.UUID.cast(mission_id), {:ok, path_uuid} <- Ecto.UUID.cast(path_id) do Path |> where([p], p.id == ^path_uuid and p.mission_id == ^mission_uuid) |> preload([:rover_location, :station, :mission]) |> Repo.one() else _ -> nil end end @impl true def render(assigns) do ~H"""

Opening Path Calculator…

""" end end