defmodule VaccinsWeb.IndexLive do use VaccinsWeb, :live_view alias Vaccins.LocationStore @impl true def mount(_params, %{"is_local?" => is_local?}, socket) do locations = LocationStore.get_locations() Phoenix.PubSub.subscribe(Vaccins.PubSub, "locations") {:ok, socket |> assign( noob_mode: false, is_local?: is_local?, locations: locations, locations_with_early_slots: MapSet.new(), locations_with_slots: MapSet.new(), pending: %{}, location_cs: LocationStore.LocationRaw.changeset(%{}), display_cs: false ) |> set_all_areas |> init_area_filters() |> set_title()} end defp set_title(socket = %{assigns: %{locations_with_early_slots: early}}) do if early |> Enum.empty?(), do: socket |> assign(page_title: "Disponibilités vaccins"), else: socket |> assign(page_title: "(!!) Disponibilités vaccins") end @impl true def handle_params(params, _url, socket) when params == %{}, do: {:noreply, socket |> assign(noob_mode: false, area_filters: socket.assigns.all_areas, params: params)} def handle_params(params, _url, socket) when is_map_key(params, "noob") or is_map_key(params, "geographic_areas") do all_areas = socket.assigns.all_areas areas = params |> Map.get("geographic_areas", all_areas) {:noreply, socket |> assign( noob_mode: params |> Map.has_key?("noob"), area_filters: areas |> MapSet.new() |> MapSet.intersection(all_areas), params: params )} end @impl true def handle_event("areas_filter_change", %{"areas_filter" => %{"areas" => areas}}, socket) do {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index, geographic_areas: areas))} end def handle_event("areas_filter_change", params, socket) when not is_map_key(params, "areas_filter") do {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index))} end def handle_event("add_location", %{"location_raw" => params}, socket) do case params |> LocationStore.add_location() do :ok -> {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index))} {:error, cs} -> {:noreply, socket |> assign(location_cs: cs)} end end def handle_event("reload_file", _, socket) do :ok = LocationStore.reload() {:noreply, socket |> assign(locations: LocationStore.get_locations())} end def handle_event("toggle_form", _, socket = %{assigns: %{display_cs: display}}), do: {:noreply, socket |> assign(display_cs: not display)} def handle_event("trigger_noob_mode", _, socket = %{assigns: %{noob_mode: true}}), do: {:noreply, socket |> assign(noob_mode: false) |> push_patch(to: Routes.index_path(socket, :index))} def handle_event("trigger_noob_mode", _, socket = %{assigns: %{noob_mode: false}}), do: {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index, noob: true))} @impl true def handle_info({:location_has_slots, id, true}, socket) do {:noreply, socket |> update(:locations_with_early_slots, &(&1 |> MapSet.put(id))) |> set_title} end def handle_info({:location_has_slots, id, false}, socket) do {:noreply, socket |> update(:locations_with_slots, &(&1 |> MapSet.put(id))) |> set_title} end def handle_info({:location_no_more_slots, id}, socket) do {:noreply, socket |> update(:locations_with_slots, &(&1 |> MapSet.delete(id))) |> update(:locations_with_early_slots, &(&1 |> MapSet.delete(id))) |> set_title} end def handle_info({:location_deleted, _}, socket), do: socket |> push_patch(to: Routes.index_path(socket, :index)) @impl true def handle_info({:new_availabilities, id, res}, socket) do send_update(VaccinsWeb.LocationComponent, id: id, availabilities: res) {:noreply, socket} end defp filter(locations, %{area_filters: filters}), do: locations |> Enum.filter(&(&1.geographic_area in filters)) defp locations_by_availability(%{ locations: locations, locations_with_slots: with_slots, locations_with_early_slots: with_early_slots }) do locations |> Enum.sort(fn e1, e2 -> e1_has_early_spot? = e1.id in with_early_slots e1_has_spot? = e1.id in with_slots e2_has_early_spot? = e2.id in with_early_slots e2_has_spot? = e2.id in with_slots cond do e2_has_early_spot? -> false e2_has_spot? and not e1_has_early_spot? -> false e2_has_spot? and e1_has_spot? -> false true -> true end end) end defp set_all_areas(socket), do: socket |> assign(all_areas: socket |> get_all_areas) defp init_area_filters(socket), do: socket |> assign(area_filters: socket.assigns.all_areas) defp get_all_areas(%{assigns: %{locations: locations}}), do: locations |> Enum.map(& &1.geographic_area) |> MapSet.new() end