diff --git a/lib/atomic/activities.ex b/lib/atomic/activities.ex index a0326314b..e194b3145 100644 --- a/lib/atomic/activities.ex +++ b/lib/atomic/activities.ex @@ -398,18 +398,97 @@ defmodule Atomic.Activities do end @doc """ - Returns the count of activities a user has enrolled in. + Returns the list of upcoming activities a user has enrolled in. ## Examples - iex> count_user_activities(user_id) + iex> list_upcoming_user_activities(user_id) + [%Activity{}, ...] + """ + def list_upcoming_user_activities(user_id, params \\ %{}) + + def list_upcoming_user_activities(user_id, opts) when is_list(opts) do + from(a in Activity, + join: e in assoc(a, :activity_enrollments), + where: e.user_id == ^user_id + ) + |> where([a], fragment("? > now()", a.start)) + |> apply_filters(opts) + |> Repo.all() + end + + def list_upcoming_user_activities(user_id, flop) do + from(a in Activity, + join: e in assoc(a, :activity_enrollments), + where: e.user_id == ^user_id + ) + |> where([a], fragment("? > now()", a.start)) + |> Flop.validate_and_run(flop, for: Activity) + end + + def list_upcoming_user_activities(user_id, %{} = flop, opts) when is_list(opts) do + from(a in Activity, + join: e in assoc(a, :activity_enrollments), + where: e.user_id == ^user_id + ) + |> where([a], fragment("? > now()", a.start)) + |> apply_filters(opts) + |> Flop.validate_and_run(flop, for: Activity) + end + + @doc """ + Returns the list of past activities a user has enrolled in. + + ## Examples + + iex> list_past_user_activities(user_id) + [%Activity{}, ...] + """ + def list_past_user_activities(user_id, params \\ %{}) + + def list_past_user_activities(user_id, opts) when is_list(opts) do + from(a in Activity, + join: e in assoc(a, :activity_enrollments), + where: e.user_id == ^user_id + ) + |> where([a], fragment("? < now()", a.start)) + |> apply_filters(opts) + |> Repo.all() + end + + def list_past_user_activities(user_id, flop) do + from(a in Activity, + join: e in assoc(a, :activity_enrollments), + where: e.user_id == ^user_id + ) + |> where([a], fragment("? < now()", a.start)) + |> Flop.validate_and_run(flop, for: Activity) + end + + def list_past_user_activities(user_id, %{} = flop, opts) when is_list(opts) do + from(a in Activity, + join: e in assoc(a, :activity_enrollments), + where: e.user_id == ^user_id + ) + |> where([a], fragment("? < now()", a.start)) + |> apply_filters(opts) + |> Flop.validate_and_run(flop, for: Activity) + end + + @doc """ + Returns the count of upcoming activities a user has enrolled in. + + ## Examples + + iex> user_upcoming_activities_count(user_id) 1 """ - def count_user_activities(user_id) do + def user_upcoming_activities_count(user_id) do from(a in Activity, join: e in assoc(a, :activity_enrollments), where: e.user_id == ^user_id ) + |> where([a], fragment("? > now()", a.start)) |> Repo.aggregate(:count, :id) end diff --git a/lib/atomic_web/live/activity_live/index.ex b/lib/atomic_web/live/activity_live/index.ex index 8031096fe..c1d5bab90 100644 --- a/lib/atomic_web/live/activity_live/index.ex +++ b/lib/atomic_web/live/activity_live/index.ex @@ -22,7 +22,7 @@ defmodule AtomicWeb.ActivityLive.Index do |> assign(:current_tab, current_tab(socket, params)) |> assign(:params, params) |> assign(:has_permissions?, has_permissions?(socket)) - |> assign(:enrolled_count, user_activities_count(socket)) + |> assign(:upcoming_enrolled_count, user_activities_count(socket)) |> assign(list_activities(socket, params)) |> then(fn complete_socket -> assign(complete_socket, :empty?, Enum.empty?(complete_socket.assigns.activities)) @@ -33,14 +33,14 @@ defmodule AtomicWeb.ActivityLive.Index do params = Map.put(params, "page_size", 6) case current_tab(socket, params) do - "all" -> list_all_activities(socket, params) + "discover" -> list_discover_activities(socket, params) "following" -> list_following_activities(socket, params) - "upcoming" -> list_upcoming_activities(socket, params) "enrolled" -> list_enrolled_activities(socket, params) + "past" -> list_past_activities(socket, params) end end - defp list_all_activities(_socket, params) do + defp list_discover_activities(_socket, params) do case Activities.list_activities(params, preloads: [:speakers, :activity_enrollments, :organization] ) do @@ -67,8 +67,8 @@ defmodule AtomicWeb.ActivityLive.Index do end end - defp list_upcoming_activities(_socket, params) do - case Activities.list_upcoming_activities(params, + defp list_enrolled_activities(socket, params) do + case Activities.list_upcoming_user_activities(socket.assigns.current_user.id, params, preloads: [:speakers, :activity_enrollments, :organization] ) do {:ok, {activities, meta}} -> @@ -79,8 +79,8 @@ defmodule AtomicWeb.ActivityLive.Index do end end - defp list_enrolled_activities(socket, params) do - case Activities.list_user_activities(socket.assigns.current_user.id, params, + defp list_past_activities(socket, params) do + case Activities.list_past_user_activities(socket.assigns.current_user.id, params, preloads: [:speakers, :activity_enrollments, :organization] ) do {:ok, {activities, meta}} -> @@ -92,7 +92,7 @@ defmodule AtomicWeb.ActivityLive.Index do end defp current_tab(_socket, params) when is_map_key(params, "tab"), do: params["tab"] - defp current_tab(_socket, _params), do: "upcoming" + defp current_tab(_socket, _params), do: "discover" defp has_permissions?(socket) when not socket.assigns.is_authenticated?, do: false @@ -111,9 +111,19 @@ defmodule AtomicWeb.ActivityLive.Index do defp user_activities_count(socket) do if socket.assigns.is_authenticated? do - Activities.count_user_activities(socket.assigns.current_user.id) + Activities.user_upcoming_activities_count(socket.assigns.current_user.id) else 0 end end + + defp activities_empty_state_description(tab) do + case tab do + "following" -> gettext("The organizations you follow haven't created any activities yet.") + "upcoming" -> gettext("There are no upcoming activities registered.") + "enrolled" -> gettext("When you enroll in new activities they will show up here!") + "past" -> gettext("You haven't participated in any activities yet.") + _ -> "" + end + end end diff --git a/lib/atomic_web/live/activity_live/index.html.heex b/lib/atomic_web/live/activity_live/index.html.heex index 90b8f61c0..25300dc52 100644 --- a/lib/atomic_web/live/activity_live/index.html.heex +++ b/lib/atomic_web/live/activity_live/index.html.heex @@ -7,45 +7,56 @@ <% end %> - <.tabs class="max-w-5-xl mx-auto px-4 sm:px-6 lg:px-8"> - <.link patch="?tab=upcoming" replace={false}> - <.tab active={@current_tab == "upcoming"}> - <%= gettext("Upcoming") %> + <.tabs class="overflow-scroll scrollbar-hide max-w-5-xl mx-auto px-4 sm:px-6 lg:px-8"> + <.link patch="?tab=discover" replace={false}> + <.tab active={@current_tab == "discover"}> + <.icon name={:globe_alt} class="h-5 w-5 mr-1" /> + <%= gettext("Discover") %> <%= if @is_authenticated? do %> <.link patch="?tab=following" replace={false}> <.tab active={@current_tab == "following"}> + <.icon name={:eye} class="h-5 w-5 mr-1" /> <%= gettext("Following") %> <% end %> - <.link patch="?tab=all" replace={false}> - <.tab active={@current_tab == "all"}> - <%= gettext("All") %> - - - <%= if @is_authenticated? do %> <.link patch="?tab=enrolled" replace={false}> - <.tab active={@current_tab == "enrolled"} number={@enrolled_count}> - <%= gettext("Enrolled") %> + <.tab active={@current_tab == "enrolled"} number={@upcoming_enrolled_count}> + <.icon name={:ticket} class="h-5 w-5 mr-1" /> + <%= gettext("Upcoming") %> + + + <.link patch="?tab=past" replace={false}> + <.tab active={@current_tab == "past"}> + <.icon name={:clock} class="h-5 w-5 mr-1" /> + <%= gettext("Past") %> <% end %> - <%= if @empty? and @has_permissions? do %> -
- <.empty_state url={Routes.activity_new_path(@socket, :new, @current_organization)} placeholder="activity" /> -
+ <%= if @empty? do %> + <%= if @has_permissions? do %> +
+ <.empty_state url={Routes.activity_new_path(@socket, :new, @current_organization)} placeholder="activity" /> +
+ <% else %> +
+ <.icon class="w-24" name={:megaphone} /> +

<%= gettext("No activities to show.") %>

+

<%= activities_empty_state_description(@current_tab) %>

+
+ <% end %> <% else %>