Przeglądaj źródła

Order locations by availability

theenglishway (time) 4 lat temu
rodzic
commit
e08eab372a

+ 39 - 0
lib/vaccins_web/live/index.ex

@@ -12,6 +12,8 @@ defmodule VaccinsWeb.IndexLive do
      socket
      |> assign(
        locations: locations,
+       locations_with_early_slots: MapSet.new(),
+       locations_with_slots: MapSet.new(),
        pending: %{},
        location_cs: LocationStore.LocationRaw.changeset(%{}),
        display_cs: false
@@ -47,6 +49,21 @@ defmodule VaccinsWeb.IndexLive do
        |> trigger_global_refresh
        |> trigger_periodic_refresh}
 
+  def handle_info({:location_has_slots, id, true}, socket) do
+    {:noreply, socket |> update(:locations_with_early_slots, &(&1 |> MapSet.put(id)))}
+  end
+
+  def handle_info({:location_has_slots, id, false}, socket) do
+    {:noreply, socket |> update(:locations_with_slots, &(&1 |> MapSet.put(id)))}
+  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)))}
+  end
+
   @impl true
   def handle_info(
         {:query_result, ref, res},
@@ -68,4 +85,26 @@ defmodule VaccinsWeb.IndexLive do
     Process.send_after(self(), :periodic_refresh, @refresh_period_ms)
     socket
   end
+
+  defp locations_by_availability(
+         assigns = %{
+           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 in with_early_slots
+      e1_has_spot? = e1 in with_slots
+      e2_has_early_spot? = e2 in with_early_slots
+      e2_has_spot? = e2 in with_slots
+
+      cond do
+        e1_has_early_spot? and not e2_has_early_spot? -> true
+        e1_has_spot? and not e2_has_early_spot? and not e2_has_spot? -> true
+        true -> false
+      end
+    end)
+  end
 end

+ 1 - 1
lib/vaccins_web/live/index_live.html.leex

@@ -20,7 +20,7 @@
 <% end %>
 
 <ul class="locations-list">
-  <%= for l <- @locations do %>
+  <%= for l <- assigns |> locations_by_availability do %>
     <li><%= live_component @socket, VaccinsWeb.LocationComponent, id: l.id, location: l %></li>
   <% end %>
 </ul>

+ 15 - 1
lib/vaccins_web/live/location_component.ex

@@ -20,7 +20,7 @@ defmodule VaccinsWeb.LocationComponent do
     assigns = assigns |> integrate_availabilities
 
     if is_nil(force_refresh) do
-      {:ok, socket |> assign(assigns) |> assign(loading: false)}
+      {:ok, socket |> assign(assigns) |> assign(loading: false) |> signal_availabilities}
     else
       trigger_and_signal_query(
         assigns |> Map.get(:location, socket.assigns.location),
@@ -101,4 +101,18 @@ defmodule VaccinsWeb.LocationComponent do
            DateTime.utc_now() |> DateTime.shift_zone("Europe/Paris", Tzdata.TimeZoneDatabase),
          do: now |> DateTime.to_time() |> Time.truncate(:second)
   end
+
+  defp signal_availabilities(socket = %{assigns: %{loading: false, slots_after: slots_after}}) do
+    cond do
+      socket.assigns |> has_slots? ->
+        send(self(), {:location_has_slots, socket.assigns.id, not (slots_after |> Enum.empty?())})
+
+      true ->
+        send(self(), {:location_no_more_slots, socket.assigns.id})
+    end
+
+    socket
+  end
+
+  defp signal_availabilities(socket), do: socket
 end