diff --git a/lib/bike_brigade_web/helpers/campaign_helpers.ex b/lib/bike_brigade_web/helpers/campaign_helpers.ex index 5403570e..60945467 100644 --- a/lib/bike_brigade_web/helpers/campaign_helpers.ex +++ b/lib/bike_brigade_web/helpers/campaign_helpers.ex @@ -1,6 +1,10 @@ defmodule BikeBrigadeWeb.CampaignHelpers do alias BikeBrigade.Delivery.Task alias BikeBrigade.Riders.Rider + alias BikeBrigade.Delivery + alias BikeBrigade.Utils + + use BikeBrigadeWeb, :live_component alias BikeBrigade.LocalizedDateTime @@ -128,4 +132,50 @@ defmodule BikeBrigadeWeb.CampaignHelpers do defp print_item(task_item) do "#{task_item.count} #{Inflex.inflect(task_item.item.name, task_item.count)}" end + + attr :filled_tasks, :integer, required: true + attr :total_tasks, :integer, required: true + attr :campaign, :any, required: true + + @doc """ + Renders possible states of campaign "Fullness" in styled text. + """ + def tasks_filled_text(assigns) do + {class, copy} = + cond do + assigns.filled_tasks == nil -> + {"text-gray-600", "N/A"} + + campaign_in_past(assigns.campaign) -> + {"text-gray-600", "Campaign over"} + + assigns.total_tasks - assigns.filled_tasks == 0 -> + {"text-gray-600", "Fully Assigned"} + + true -> + {"text-red-400", "#{assigns.total_tasks - assigns.filled_tasks} Available"} + end + + assigns = + assigns + |> assign(:class, class) + |> assign(:copy, copy) + + ~H""" +

+ + + <%= @copy %> + +

+ """ + end + + # Use this to determine if we need to refetch data to update the liveview. + # ex: dispatcher changes riders/tasks, or another rider signs up -> refetch. + def entity_in_campaigns?(campaigns, entity_campaign_id) do + campaigns + |> Enum.flat_map(fn {_date, campaigns} -> campaigns end) + |> Enum.any?(fn c -> c.id == entity_campaign_id end) + end end diff --git a/lib/bike_brigade_web/live/campaign_live/index.ex b/lib/bike_brigade_web/live/campaign_live/index.ex index 79d7f127..f6acaf38 100644 --- a/lib/bike_brigade_web/live/campaign_live/index.ex +++ b/lib/bike_brigade_web/live/campaign_live/index.ex @@ -7,11 +7,16 @@ defmodule BikeBrigadeWeb.CampaignLive.Index do alias BikeBrigade.Delivery alias BikeBrigade.Delivery.Campaign alias BikeBrigade.Messaging.SmsMessage + alias BikeBrigadeWeb.Components.CampaignComponents import BikeBrigadeWeb.CampaignHelpers @impl true def mount(_params, _session, socket) do + if connected?(socket) do + Delivery.subscribe() + end + current_week = LocalizedDateTime.today() |> Date.beginning_of_week() @@ -21,7 +26,8 @@ defmodule BikeBrigadeWeb.CampaignLive.Index do |> assign(:page, :campaigns) |> assign(:page_title, "Campaigns") |> assign(:current_week, current_week) - |> assign(:campaigns, fetch_campaigns(current_week))} + |> assign(:campaigns, fetch_campaigns(current_week)) + |> assign(:campaign_task_counts, Delivery.get_total_tasks_and_open_tasks(current_week))} end @impl true @@ -37,6 +43,27 @@ defmodule BikeBrigadeWeb.CampaignLive.Index do {:noreply, assign(socket, :campaigns, fetch_campaigns(socket.assigns.current_week))} end + @broadcasted_infos [ + :task_created, + :task_deleted, + :task_updated, + :campaign_rider_created, + :campaign_rider_deleted + ] + + @impl Phoenix.LiveView + def handle_info({event, entity}, socket) when event in @broadcasted_infos do + if entity_in_campaigns?(socket.assigns.campaigns, entity.campaign_id) do + {:noreply, refetch_and_assign_data(socket)} + else + {:noreply, socket} + end + end + + @impl Phoenix.LiveView + @doc "silently ignore other kinds of messages" + def handle_info(_, socket), do: {:noreply, socket} + defp apply_action(socket, :edit, %{"id" => id}) do socket |> assign(:page_title, "Edit Campaign") @@ -123,4 +150,12 @@ defmodule BikeBrigadeWeb.CampaignLive.Index do def message_info(assigns) do ~H"" end + + defp refetch_and_assign_data(socket) do + week = socket.assigns.current_week + + socket + |> assign(:campaign_task_counts, Delivery.get_total_tasks_and_open_tasks(week)) + |> assign(:campaigns, fetch_campaigns(week)) + end end diff --git a/lib/bike_brigade_web/live/campaign_live/index.html.heex b/lib/bike_brigade_web/live/campaign_live/index.html.heex index ec044205..0aca13f5 100644 --- a/lib/bike_brigade_web/live/campaign_live/index.html.heex +++ b/lib/bike_brigade_web/live/campaign_live/index.html.heex @@ -127,10 +127,15 @@ /> <%= pickup_window(c) %>

+

- - <%= c.stats.signed_up_rider_count %> + <.tasks_filled_text + filled_tasks={@campaign_task_counts[c.id][:filled_tasks]} + total_tasks={@campaign_task_counts[c.id][:total_tasks]} + campaign={c} + />

+

assign(:campaigns, fetch_campaigns(campaign_filter)) end - # Use this to determine if we need to refetch data to update the liveview. - # ex: dispatcher changes riders/tasks, or another rider signs up -> refetch. - defp entity_in_campaigns?(socket, entity_campaign_id) do - socket.assigns.campaigns - |> Enum.flat_map(fn {_date, campaigns} -> campaigns end) - |> Enum.any?(fn c -> c.id == entity_campaign_id end) - end - - attr :filled_tasks, :integer, required: true - attr :total_tasks, :integer, required: true - attr :campaign, :any, required: true - - defp tasks_filled_text(assigns) do - {class, copy} = - cond do - assigns.filled_tasks == nil -> - {"text-gray-600", "N/A"} - - campaign_in_past(assigns.campaign) -> - {"text-gray-600", "Campaign over"} - - assigns.total_tasks - assigns.filled_tasks == 0 -> - {"text-gray-600", "Fully Assigned"} - - true -> - {"text-red-400", "#{assigns.total_tasks - assigns.filled_tasks} Available"} - end - - assigns = - assigns - |> assign(:class, class) - |> assign(:copy, copy) - - ~H""" -

- - - <%= @copy %> - -

- """ - end - attr :campaign, :any, required: true attr :rider_id, :integer, required: true attr :campaign_task_counts, :any, required: true