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