Skip to content

Commit

Permalink
feat: improve activities index tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
joaodiaslobo committed Jul 5, 2024
1 parent cc40c0c commit 5cde7c4
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 30 deletions.
85 changes: 82 additions & 3 deletions lib/atomic/activities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
30 changes: 20 additions & 10 deletions lib/atomic_web/live/activity_live/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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}} ->
Expand All @@ -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}} ->
Expand All @@ -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

Expand All @@ -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
45 changes: 28 additions & 17 deletions lib/atomic_web/live/activity_live/index.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,56 @@
<% end %>
</:actions>
<!-- Tabs -->
<.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") %>
</.tab>
</.link>

<%= 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") %>
</.tab>
</.link>
<% end %>

<.link patch="?tab=all" replace={false}>
<.tab active={@current_tab == "all"}>
<%= gettext("All") %>
</.tab>
</.link>

<%= 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") %>
</.tab>
</.link>
<.link patch="?tab=past" replace={false}>
<.tab active={@current_tab == "past"}>
<.icon name={:clock} class="h-5 w-5 mr-1" />
<%= gettext("Past") %>
</.tab>
</.link>
<% end %>
</.tabs>
<!-- Activities index -->
<%= if @empty? and @has_permissions? do %>
<div class="mt-32">
<.empty_state url={Routes.activity_new_path(@socket, :new, @current_organization)} placeholder="activity" />
</div>
<%= if @empty? do %>
<%= if @has_permissions? do %>
<div class="mt-32">
<.empty_state url={Routes.activity_new_path(@socket, :new, @current_organization)} placeholder="activity" />
</div>
<% else %>
<div class="text-zinc-600 mt-32 flex flex-col items-center w-full justify-center">
<.icon class="w-24" name={:megaphone} />
<p class="pt-4"><%= gettext("No activities to show.") %></p>
<p><%= activities_empty_state_description(@current_tab) %></p>
</div>
<% end %>
<% else %>
<div class="overflow-hidden bg-white">
<ul role="list" class="p-4 overflow-auto grid sm:grid-cols-2 gap-4">
<%= for activity <- @activities do %>
<li id={activity.id}>
<li id={activity.id} class={@current_tab == "past" && "opacity-70"}>
<.activity_card activity={activity} />
</li>
<% end %>
Expand Down

0 comments on commit 5cde7c4

Please sign in to comment.