defmodule VaccinsWeb.LocationComponent do
use VaccinsWeb, :live_component
alias Vaccins.{LocationStore, Search}
@impl true
def mount(socket),
do:
{:ok,
socket
|> assign(
has_availabilities: false,
slots_after: [],
slots_before: [],
loading: false
)}
@impl true
def update(assigns, socket) do
{force_refresh, assigns} = assigns |> Map.pop(:force_refresh)
assigns = assigns |> integrate_availabilities
if is_nil(force_refresh) do
{:ok, socket |> assign(assigns) |> assign(loading: false)}
else
trigger_and_signal_query(
assigns |> Map.get(:location, socket.assigns.location),
assigns.id
)
{:ok, socket |> assign(assigns) |> assign(loading: true)}
end
end
@impl true
def handle_event("trigger_query", _, socket = %{assigns: %{id: id, location: location}}) do
trigger_and_signal_query(location, id)
{:noreply, socket |> assign(loading: true)}
end
@impl true
def render(assigns) do
~L"""
- id
- <%= @location.id %>
- Status
-
<%= cond do %>
<%= @loading -> %>...
<%= not has_slots?(assigns) -> %>Pas de créneau
<%= has_slots?(assigns) -> %>Des dispos !
<% end %>
- booking page
- <%= link @location.booking_page, to: @location.booking_page %>
<%= if has_slots?(assigns) do %>
- Avant 24h
-
<%= for d <- @slots_before do %>- <%= d |> DateTime.to_string %>
<% end %>
- Après 24h
-
<%= for d <- @slots_after do %>- <%= d |> DateTime.to_string %>
<% end %>
<% end %>
- test availability
"""
end
defp integrate_availabilities(assigns = %{availabilities: {:error, reason}}),
do: assigns |> Map.put(:has_availabilities, false)
defp integrate_availabilities(assigns = %{availabilities: {:ok, after_slots}})
when is_list(after_slots),
do:
assigns
|> Map.put(:has_availabilities, true)
|> Map.put(:slots_after, after_slots |> Enum.take(5))
defp integrate_availabilities(assigns = %{availabilities: {:ok, before_slots, after_slots}})
when is_list(before_slots),
do:
assigns
|> Map.put(:has_availabilities, true)
|> Map.put(:slots_after, after_slots |> Enum.take(5))
|> Map.put(:slots_before, before_slots)
defp integrate_availabilities(assigns), do: assigns
defp has_slots?(assigns = %{slots_before: before, slots_after: after_}),
do: not (before |> Enum.empty?() and after_ |> Enum.empty?())
defp trigger_and_signal_query(location, id) do
ref = Search.async_trigger_query(location)
send(self(), {:query_sent, id, ref})
end
end