index.ex 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. defmodule VaccinsWeb.IndexLive do
  2. use VaccinsWeb, :live_view
  3. alias Vaccins.LocationStore
  4. @impl true
  5. def mount(_params, %{"is_local?" => is_local?}, socket) do
  6. all_locations = LocationStore.get_locations()
  7. Phoenix.PubSub.subscribe(Vaccins.PubSub, "locations")
  8. {:ok,
  9. socket
  10. |> assign(
  11. noob_mode: false,
  12. is_local?: is_local?,
  13. all_locations: all_locations,
  14. locations_displayed: all_locations,
  15. locations_with_early_slots: MapSet.new(),
  16. locations_with_slots: MapSet.new(),
  17. pending: %{},
  18. location_cs: LocationStore.LocationRaw.changeset(%{}),
  19. display_cs: false
  20. )
  21. |> set_all_areas
  22. |> init_area_filters()
  23. |> set_title()}
  24. end
  25. defp set_title(socket = %{assigns: %{locations_with_early_slots: early}}) do
  26. if early |> Enum.empty?(),
  27. do: socket |> assign(page_title: "Disponibilités vaccins"),
  28. else: socket |> assign(page_title: "(!!) Disponibilités vaccins")
  29. end
  30. @impl true
  31. def handle_params(params, _url, socket) when params == %{},
  32. do:
  33. {:noreply,
  34. socket
  35. |> assign(noob_mode: false, params: params)
  36. |> update_area_filters(socket.assigns.all_areas)}
  37. def handle_params(params, _url, socket)
  38. when is_map_key(params, "noob") or is_map_key(params, "geographic_areas") do
  39. all_areas = socket.assigns.all_areas
  40. areas = params |> Map.get("geographic_areas", all_areas)
  41. {:noreply,
  42. socket
  43. |> assign(
  44. noob_mode: params |> Map.has_key?("noob"),
  45. params: params
  46. )
  47. |> update_area_filters(areas |> MapSet.new() |> MapSet.intersection(all_areas))}
  48. end
  49. @impl true
  50. def handle_event("areas_filter_change", %{"areas_filter" => %{"areas" => areas}}, socket) do
  51. {:noreply,
  52. socket |> push_patch(to: Routes.index_path(socket, :index, geographic_areas: areas))}
  53. end
  54. def handle_event("areas_filter_change", params, socket)
  55. when not is_map_key(params, "areas_filter") do
  56. {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index))}
  57. end
  58. def handle_event("add_location", %{"location_raw" => params}, socket) do
  59. case params |> LocationStore.add_location() do
  60. :ok -> {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index))}
  61. {:error, cs} -> {:noreply, socket |> assign(location_cs: cs)}
  62. end
  63. end
  64. def handle_event("reload_file", _, socket) do
  65. :ok = LocationStore.reload()
  66. {:noreply, socket |> assign(all_locations: LocationStore.get_locations())}
  67. end
  68. def handle_event("toggle_form", _, socket = %{assigns: %{display_cs: display}}),
  69. do: {:noreply, socket |> assign(display_cs: not display)}
  70. def handle_event("trigger_noob_mode", _, socket = %{assigns: %{noob_mode: true}}),
  71. do:
  72. {:noreply,
  73. socket |> assign(noob_mode: false) |> push_patch(to: Routes.index_path(socket, :index))}
  74. def handle_event("trigger_noob_mode", _, socket = %{assigns: %{noob_mode: false}}),
  75. do: {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index, noob: true))}
  76. @impl true
  77. def handle_info({:location_has_slots, id, true}, socket) do
  78. {:noreply,
  79. socket |> update(:locations_with_early_slots, &(&1 |> MapSet.put(id))) |> set_title}
  80. end
  81. def handle_info({:location_has_slots, id, false}, socket) do
  82. {:noreply, socket |> update(:locations_with_slots, &(&1 |> MapSet.put(id))) |> set_title}
  83. end
  84. def handle_info({:location_no_more_slots, id}, socket) do
  85. {:noreply,
  86. socket
  87. |> update(:locations_with_slots, &(&1 |> MapSet.delete(id)))
  88. |> update(:locations_with_early_slots, &(&1 |> MapSet.delete(id)))
  89. |> set_title}
  90. end
  91. def handle_info({:location_deleted, _}, socket),
  92. do: socket |> push_patch(to: Routes.index_path(socket, :index))
  93. @impl true
  94. def handle_info({:new_availabilities, id, res}, socket) do
  95. if id in (socket.assigns.locations_displayed |> Enum.map(& &1.id)),
  96. do: send_update(VaccinsWeb.LocationComponent, id: id, availabilities: res)
  97. {:noreply, socket}
  98. end
  99. defp locations_by_availability(%{
  100. locations_displayed: locations_displayed,
  101. locations_with_slots: with_slots,
  102. locations_with_early_slots: with_early_slots
  103. }) do
  104. locations_displayed
  105. |> Enum.sort(fn e1, e2 ->
  106. e1_has_early_spot? = e1.id in with_early_slots
  107. e1_has_spot? = e1.id in with_slots
  108. e2_has_early_spot? = e2.id in with_early_slots
  109. e2_has_spot? = e2.id in with_slots
  110. cond do
  111. e2_has_early_spot? -> false
  112. e2_has_spot? and not e1_has_early_spot? -> false
  113. e2_has_spot? and e1_has_spot? -> false
  114. true -> true
  115. end
  116. end)
  117. end
  118. defp set_all_areas(socket), do: socket |> assign(all_areas: socket |> get_all_areas)
  119. defp init_area_filters(socket), do: socket |> update_area_filters(socket.assigns.all_areas)
  120. defp update_area_filters(socket, filter_value),
  121. do:
  122. socket
  123. |> assign(
  124. area_filters: filter_value,
  125. locations_displayed:
  126. socket.assigns.all_locations
  127. |> Enum.filter(&(&1.geographic_area in filter_value))
  128. )
  129. defp get_all_areas(%{assigns: %{all_locations: all_locations}}),
  130. do: all_locations |> Enum.map(& &1.geographic_area) |> MapSet.new()
  131. end