diff --git a/lib/bike_brigade/riders/rider_search.ex b/lib/bike_brigade/riders/rider_search.ex
index 14c941a9..515464c1 100644
--- a/lib/bike_brigade/riders/rider_search.ex
+++ b/lib/bike_brigade/riders/rider_search.ex
@@ -357,4 +357,31 @@ defmodule BikeBrigade.Riders.RiderSearch do
query
|> where(as(:latest_campaign).delivery_start > ago(1, ^period))
end
+
+ defp apply_filter(%Filter{type: :signed_up, search: period}, query, _filters)
+ when period in ~w(today yesterday) do
+ today = Date.utc_today()
+
+ {start_date, end_date} =
+ case period do
+ "yesterday" -> {Date.add(today, -1), today}
+ _today -> {today, Date.add(today, 1)}
+ end
+
+ start_dt = DateTime.new!(start_date, ~T[00:00:00])
+ end_dt = DateTime.new!(end_date, ~T[00:00:00])
+
+ query
+ |> where(as(:rider).signed_up_on >= ^start_dt and as(:rider).signed_up_on < ^end_dt)
+ end
+
+ defp apply_filter(%Filter{type: :signed_up, search: period}, query, _filters)
+ when period in ~w(week month year) do
+ query
+ |> where(as(:rider).signed_up_on > ago(1, ^period))
+ end
+
+ defp apply_filter(%Filter{type: :signed_up}, query, _filters) do
+ query
+ end
end
diff --git a/lib/bike_brigade_web/live/rider_live/index.ex b/lib/bike_brigade_web/live/rider_live/index.ex
index e844c480..5d2663d5 100644
--- a/lib/bike_brigade_web/live/rider_live/index.ex
+++ b/lib/bike_brigade_web/live/rider_live/index.ex
@@ -26,20 +26,29 @@ defmodule BikeBrigadeWeb.RiderLive.Index do
|> Enum.map(&%Filter{type: :active, search: &1})
@capacities ~w(large medium small)
|> Enum.map(&%Filter{type: :capacity, search: &1})
+ @signed_ups ~w(today yesterday week month year)
+ |> Enum.map(&%Filter{type: :signed_up, search: &1})
- defstruct name: nil, phone: nil, tags: [], programs: [], active: [], capacity: []
+ defstruct name: nil,
+ phone: nil,
+ tags: [],
+ programs: [],
+ active: [],
+ capacity: [],
+ signed_up: []
@type t :: %__MODULE__{
name: Filter.t() | nil,
tags: list(Filter.t()),
programs: list(Filter.t()),
active: list(Filter.t()),
- capacity: list(Filter.t())
+ capacity: list(Filter.t()),
+ signed_up: list(Filter.t())
}
@spec suggest(t(), String.t()) :: t()
def suggest(suggestions, "") do
- %{suggestions | name: nil, tags: [], programs: [], active: [], capacity: []}
+ %{suggestions | name: nil, tags: [], programs: [], active: [], capacity: [], signed_up: []}
end
def suggest(suggestions, search) do
@@ -72,6 +81,13 @@ defmodule BikeBrigadeWeb.RiderLive.Index do
%__MODULE__{capacity: capacity}
+ ["signed_up", signed_up] ->
+ signed_ups =
+ @signed_ups
+ |> Enum.filter(&String.starts_with?(&1.search, signed_up))
+
+ %__MODULE__{signed_up: signed_ups}
+
[search] ->
tags =
if String.length(search) < 3 do
@@ -105,7 +121,8 @@ defmodule BikeBrigadeWeb.RiderLive.Index do
tags: tags,
programs: programs,
active: @actives,
- capacity: @capacities
+ capacity: @capacities,
+ signed_up: @signed_ups
}
[_, _] ->
@@ -498,6 +515,14 @@ defmodule BikeBrigadeWeb.RiderLive.Index do
<% end %>
<% end %>
+ <%= if @suggestions.signed_up != [] do %>
+
+ Signed Up
+
+
+ <.suggestion filter={period} />
+
+ <% end %>
<%= if @suggestions.capacity != [] do %>
@@ -631,6 +656,7 @@ defmodule BikeBrigadeWeb.RiderLive.Index do
:active -> "text-amber-900 bg-amber-100"
:capacity -> "text-rose-900 bg-rose-100"
:phone -> "text-cyan-900 bg-cyan-100"
+ :signed_up -> "text-blue-900 bg-blue-100"
end
end
diff --git a/lib/bike_brigade_web/live/rider_live/index.html.heex b/lib/bike_brigade_web/live/rider_live/index.html.heex
index f19862a4..a5e538eb 100644
--- a/lib/bike_brigade_web/live/rider_live/index.html.heex
+++ b/lib/bike_brigade_web/live/rider_live/index.html.heex
@@ -10,7 +10,7 @@
value={display_search(@search)}
autocomplete="off"
class="w-full placeholder-gray-400 border-transparent appearance-none focus:border-transparent outline-transparent ring-transparent focus:ring-0"
- placeholder="Name, tag, capacity, last active"
+ placeholder="Name, tag, capacity, last active, signed up"
tabindex="1"
/>
<%= if @rider_search.filters != [] do %>
diff --git a/test/bike_brigade/riders/rider_search_test.exs b/test/bike_brigade/riders/rider_search_test.exs
index 7bb0e2cb..9086f59a 100644
--- a/test/bike_brigade/riders/rider_search_test.exs
+++ b/test/bike_brigade/riders/rider_search_test.exs
@@ -175,7 +175,103 @@ defmodule BikeBrigade.Riders.RiderSearchTest do
link_rider_to_campaign(rider_id, campaign.id)
end
+ describe "signed_up filter" do
+ test "today - includes rider who signed up today" do
+ today_start = DateTime.new!(Date.utc_today(), ~T[00:00:00])
+ rider = fixture(:rider, %{signed_up_on: DateTime.add(today_start, 1, :hour)})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "today"}])
+ |> RiderSearch.fetch()
+
+ assert rider_in_results?(results, rider.id)
+ end
+
+ test "today - excludes rider who signed up yesterday" do
+ yesterday = Date.add(Date.utc_today(), -1)
+ yesterday_time = DateTime.new!(yesterday, ~T[12:00:00])
+ rider = fixture(:rider, %{signed_up_on: yesterday_time})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "today"}])
+ |> RiderSearch.fetch()
+
+ refute rider_in_results?(results, rider.id)
+ end
+
+ test "yesterday - includes rider who signed up yesterday" do
+ yesterday = Date.add(Date.utc_today(), -1)
+ yesterday_time = DateTime.new!(yesterday, ~T[12:00:00])
+ rider = fixture(:rider, %{signed_up_on: yesterday_time})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "yesterday"}])
+ |> RiderSearch.fetch()
+
+ assert rider_in_results?(results, rider.id)
+ end
+
+ test "yesterday - excludes rider who signed up today" do
+ today_start = DateTime.new!(Date.utc_today(), ~T[00:00:00])
+ rider = fixture(:rider, %{signed_up_on: DateTime.add(today_start, 1, :hour)})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "yesterday"}])
+ |> RiderSearch.fetch()
+
+ refute rider_in_results?(results, rider.id)
+ end
+
+ test "week - includes rider who signed up within the past week" do
+ rider = fixture(:rider, %{signed_up_on: signed_up_ago(5, :day)})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "week"}])
+ |> RiderSearch.fetch()
+
+ assert rider_in_results?(results, rider.id)
+ end
+
+ test "week - excludes rider who signed up more than a week ago" do
+ rider = fixture(:rider, %{signed_up_on: signed_up_ago(8, :day)})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "week"}])
+ |> RiderSearch.fetch()
+
+ refute rider_in_results?(results, rider.id)
+ end
+
+ test "month - includes rider who signed up within the past month" do
+ rider = fixture(:rider, %{signed_up_on: signed_up_ago(14, :day)})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "month"}])
+ |> RiderSearch.fetch()
+
+ assert rider_in_results?(results, rider.id)
+ end
+
+ test "year - includes rider who signed up within the past year" do
+ rider = fixture(:rider, %{signed_up_on: signed_up_ago(180, :day)})
+
+ {_rs, results} =
+ RiderSearch.new(filters: [%Filter{type: :signed_up, search: "year"}])
+ |> RiderSearch.fetch()
+
+ assert rider_in_results?(results, rider.id)
+ end
+ end
+
defp rider_in_results?(results, id) do
Enum.find(results.page, &(&1.id == id))
end
+
+ # Helper to create a DateTime a specified duration in the past
+ # @param amount - number of time units (positive, will be negated)
+ # @param unit - time unit (:day, :hour, :second, etc.)
+ # @return DateTime in UTC
+ defp signed_up_ago(amount, unit) do
+ DateTime.utc_now() |> DateTime.add(-amount, unit)
+ end
end