| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- defmodule VaccinsWeb.IndexLive do
- use VaccinsWeb, :live_view
- alias Vaccins.{LocationStore, Search}
- @refresh_period_ms 30 * 1000
- @impl true
- def mount(_params, _session, socket) do
- locations = LocationStore.get_locations()
- {:ok,
- socket
- |> assign(
- locations: locations,
- locations_with_early_slots: MapSet.new(),
- locations_with_slots: MapSet.new(),
- pending: %{},
- location_cs: LocationStore.LocationRaw.changeset(%{}),
- display_cs: false
- )
- |> trigger_global_refresh
- |> trigger_periodic_refresh}
- end
- @impl true
- def handle_params(%{}, _url, socket), do: {:noreply, socket}
- @impl true
- 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("trigger_all", _, socket) do
- {:noreply, socket |> trigger_global_refresh}
- end
- def handle_event("toggle_form", _, socket = %{assigns: %{display_cs: display}}),
- do: {:noreply, socket |> assign(display_cs: not display)}
- @impl true
- def handle_info({:query_sent, id, ref}, socket = %{assigns: %{pending: pending}}) do
- {:noreply, socket |> assign(pending: pending |> Map.put(ref, id))}
- end
- def handle_info(:periodic_refresh, socket),
- do:
- {:noreply,
- socket
- |> 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
- def handle_info({:location_deleted, _}, socket),
- do: socket |> push_patch(to: Routes.index_path(socket, :index))
- @impl true
- def handle_info(
- {:query_result, ref, res},
- socket = %{assigns: %{locations: valid, pending: pending}}
- ) do
- id = pending |> Map.get(ref)
- send_update(VaccinsWeb.LocationComponent, id: id, availabilities: res)
- {:noreply, socket |> assign(pending: pending |> Map.delete(ref))}
- end
- defp trigger_global_refresh(socket = %{assigns: %{locations: locations}}) do
- locations
- |> Enum.each(&send_update(VaccinsWeb.LocationComponent, id: &1.id, force_refresh: true))
- socket
- end
- defp trigger_periodic_refresh(socket) 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.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
- res =
- 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
- end
|