index.ex 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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("areas_filter_reset", _, socket) do
  59. {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index))}
  60. end
  61. def handle_event("add_location", %{"location_raw" => params}, socket) do
  62. case params |> LocationStore.add_location() do
  63. :ok -> {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index))}
  64. {:error, cs} -> {:noreply, socket |> assign(location_cs: cs)}
  65. end
  66. end
  67. def handle_event("add_location_change", %{"location_raw" => params}, socket) do
  68. {:noreply, socket |> assign(location_cs: params |> LocationStore.change_location())}
  69. end
  70. def handle_event("reload_file", _, socket) do
  71. :ok = LocationStore.reload()
  72. {:noreply, socket |> assign(all_locations: LocationStore.get_locations())}
  73. end
  74. def handle_event("toggle_form", _, socket = %{assigns: %{display_cs: display}}),
  75. do: {:noreply, socket |> assign(display_cs: not display)}
  76. def handle_event("trigger_noob_mode", _, socket = %{assigns: %{noob_mode: true}}),
  77. do:
  78. {:noreply,
  79. socket |> assign(noob_mode: false) |> push_patch(to: Routes.index_path(socket, :index))}
  80. def handle_event("trigger_noob_mode", _, socket = %{assigns: %{noob_mode: false}}),
  81. do: {:noreply, socket |> push_patch(to: Routes.index_path(socket, :index, noob: true))}
  82. @impl true
  83. def handle_info({:location_has_slots, id, true}, socket) do
  84. {:noreply,
  85. socket |> update(:locations_with_early_slots, &(&1 |> MapSet.put(id))) |> set_title}
  86. end
  87. def handle_info({:location_has_slots, id, false}, socket) do
  88. {:noreply, socket |> update(:locations_with_slots, &(&1 |> MapSet.put(id))) |> set_title}
  89. end
  90. def handle_info({:location_no_more_slots, id}, socket) do
  91. {:noreply,
  92. socket
  93. |> update(:locations_with_slots, &(&1 |> MapSet.delete(id)))
  94. |> update(:locations_with_early_slots, &(&1 |> MapSet.delete(id)))
  95. |> set_title}
  96. end
  97. def handle_info({:location_deleted, _}, socket),
  98. do: socket |> push_patch(to: Routes.index_path(socket, :index))
  99. @impl true
  100. def handle_info({:new_availabilities, id, res}, socket) do
  101. if id in (socket.assigns.locations_displayed |> Enum.map(& &1.id)),
  102. do: send_update(VaccinsWeb.LocationComponent, id: id, availabilities: res)
  103. {:noreply, socket}
  104. end
  105. defp locations_by_availability(%{
  106. locations_displayed: locations_displayed,
  107. locations_with_slots: with_slots,
  108. locations_with_early_slots: with_early_slots
  109. }) do
  110. locations_displayed
  111. |> Enum.sort(fn e1, e2 ->
  112. e1_has_early_spot? = e1.id in with_early_slots
  113. e1_has_spot? = e1.id in with_slots
  114. e2_has_early_spot? = e2.id in with_early_slots
  115. e2_has_spot? = e2.id in with_slots
  116. cond do
  117. e2_has_early_spot? -> false
  118. e2_has_spot? and not e1_has_early_spot? -> false
  119. e2_has_spot? and e1_has_spot? -> false
  120. true -> true
  121. end
  122. end)
  123. end
  124. defp set_all_areas(socket), do: socket |> assign(all_areas: socket |> get_all_areas)
  125. defp init_area_filters(socket), do: socket |> update_area_filters(socket.assigns.all_areas)
  126. defp update_area_filters(socket, filter_value),
  127. do:
  128. socket
  129. |> assign(
  130. area_filters: filter_value,
  131. locations_displayed:
  132. socket.assigns.all_locations
  133. |> Enum.filter(&(&1.geographic_area in filter_value))
  134. )
  135. defp get_all_areas(%{assigns: %{all_locations: all_locations}}),
  136. do: all_locations |> Enum.map(& &1.geographic_area) |> MapSet.new()
  137. end