site.device is %Ecto.Association.NotLoaded{} since list_organization_sites/1
only preloads :parent_site, causing length/1 to crash the LiveView mount.
65 lines
1.6 KiB
Elixir
65 lines
1.6 KiB
Elixir
defmodule ToweropsWeb.MapLive.Index do
|
|
@moduledoc """
|
|
Geographic map showing sites with latitude/longitude coordinates using Leaflet.js
|
|
"""
|
|
use ToweropsWeb, :live_view
|
|
|
|
alias Towerops.Sites
|
|
|
|
@impl true
|
|
def mount(_params, _session, socket) do
|
|
organization = socket.assigns.current_scope.organization
|
|
|
|
{:ok,
|
|
socket
|
|
|> assign(:page_title, t("Sites Map"))
|
|
|> assign(:organization, organization)
|
|
|> load_sites()}
|
|
end
|
|
|
|
@impl true
|
|
def handle_params(_params, _url, socket) do
|
|
{:noreply, socket}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("site_clicked", %{"site_id" => site_id}, socket) do
|
|
# Navigate to site detail page
|
|
{:noreply, push_navigate(socket, to: ~p"/sites/#{site_id}")}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("refresh_map", _params, socket) do
|
|
{:noreply,
|
|
socket
|
|
|> load_sites()
|
|
|> put_flash(:info, t("Sites map refreshed"))}
|
|
end
|
|
|
|
defp load_sites(socket) do
|
|
organization = socket.assigns.organization
|
|
sites = Sites.list_organization_sites(organization.id)
|
|
|
|
# Filter sites that have geographic coordinates
|
|
sites_with_coords =
|
|
Enum.filter(sites, fn site ->
|
|
site.latitude != nil && site.longitude != nil
|
|
end)
|
|
|
|
# Prepare sites data for the map
|
|
sites_data =
|
|
Enum.map(sites_with_coords, fn site ->
|
|
%{
|
|
id: site.id,
|
|
name: site.name,
|
|
description: site.description,
|
|
address: site.address,
|
|
latitude: site.latitude,
|
|
longitude: site.longitude,
|
|
device_count: if(is_list(site.device), do: length(site.device), else: 0)
|
|
}
|
|
end)
|
|
|
|
assign(socket, :sites, sites_data)
|
|
end
|
|
end
|