Make top albums lazy load each tab

This commit is contained in:
Claudio Ortolina
2025-08-17 23:18:46 +03:00
parent af7e48507d
commit 30eddd983a
2 changed files with 96 additions and 66 deletions
+15 -13
View File
@@ -328,18 +328,23 @@ defmodule MusicLibrary.ScrobbleActivity do
end end
@doc """ @doc """
Gets top albums for multiple time periods (30, 90, 365 days) and all time. Gets top albums for the specified time periods (30, 90, 365 days) and all
Returns a map with the results for each period, along with collected and time. Returns a map with the results, along with collected and wishlisted
wishlisted releases. releases.
""" """
def get_top_albums_by_periods(opts) do def get_top_albums_by_period(opts) do
last_30_days = get_top_albums_by_days(30, opts) period = Keyword.get(opts, :period, :last_30_days)
last_90_days = get_top_albums_by_days(90, opts)
last_365_days = get_top_albums_by_days(365, opts) albums =
all_time = get_top_albums(opts) case period do
:all_time -> get_top_albums(opts)
:last_30_days -> get_top_albums_by_days(30, opts)
:last_90_days -> get_top_albums_by_days(90, opts)
:last_365_days -> get_top_albums_by_days(365, opts)
end
all_album_ids = all_album_ids =
(last_30_days ++ last_90_days ++ last_365_days ++ all_time) albums
|> Enum.map(fn t -> t.album_musicbrainz_id end) |> Enum.map(fn t -> t.album_musicbrainz_id end)
|> Enum.uniq() |> Enum.uniq()
|> Enum.reject(fn musicbrainz_id -> musicbrainz_id == "" end) |> Enum.reject(fn musicbrainz_id -> musicbrainz_id == "" end)
@@ -350,10 +355,7 @@ defmodule MusicLibrary.ScrobbleActivity do
%{ %{
collected_releases: collected_releases, collected_releases: collected_releases,
wishlisted_releases: wishlisted_releases, wishlisted_releases: wishlisted_releases,
last_30_days: last_30_days, albums: albums
last_90_days: last_90_days,
last_365_days: last_365_days,
all_time: all_time
} }
end end
@@ -18,53 +18,67 @@ defmodule MusicLibraryWeb.StatsLive.TopAlbums do
<h1 class="text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold"> <h1 class="text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
{gettext("Top Albums")} {gettext("Top Albums")}
</h1> </h1>
<.async_result :let={top_albums} assign={@top_albums}> <.tabs class="mt-4">
<:loading> <.tabs_list active_tab={name_from_period(@period)} variant="segmented">
<div class="h-192 flex items-center justify-center"> <:tab
<.loading /> class="flex-1"
</div> name="top_albums_last_30_days"
</:loading> phx-click={JS.push("set_period", value: %{period: "last_30_days"})}
<.tabs class="mt-4"> phx-target={@myself}
<.tabs_list active_tab="top_albums_last_30_days" variant="segmented"> >
<:tab class="flex-1" name="top_albums_last_30_days">{gettext("Last 30 days")}</:tab> {gettext("Last 30 days")}
<:tab class="flex-1" name="top_albums_last_90_days">{gettext("Last 90 days")}</:tab> </:tab>
<:tab class="flex-1" name="top_albums_last_365_days">{gettext("Last year")}</:tab> <:tab
<:tab class="flex-1" name="top_albums_all_time">{gettext("All time")}</:tab> class="flex-1"
</.tabs_list> name="top_albums_last_90_days"
<.tabs_panel active name="top_albums_last_30_days"> phx-click={JS.push("set_period", value: %{period: "last_90_days"})}
<.top_albums_by_period phx-target={@myself}
albums={top_albums.last_30_days} >
collected_releases={top_albums.collected_releases} {gettext("Last 90 days")}
wishlisted_releases={top_albums.wishlisted_releases} </:tab>
/> <:tab
</.tabs_panel> class="flex-1"
<.tabs_panel name="top_albums_last_90_days"> name="top_albums_last_365_days"
<.top_albums_by_period phx-click={JS.push("set_period", value: %{period: "last_365_days"})}
albums={top_albums.last_90_days} phx-target={@myself}
collected_releases={top_albums.collected_releases} >
wishlisted_releases={top_albums.wishlisted_releases} {gettext("Last year")}
/> </:tab>
</.tabs_panel> <:tab
<.tabs_panel name="top_albums_last_365_days"> class="flex-1"
<.top_albums_by_period name="top_albums_all_time"
albums={top_albums.last_365_days} phx-click={JS.push("set_period", value: %{period: "all_time"})}
collected_releases={top_albums.collected_releases} phx-target={@myself}
wishlisted_releases={top_albums.wishlisted_releases} >
/> {gettext("All time")}
</.tabs_panel> </:tab>
<.tabs_panel name="top_albums_all_time"> </.tabs_list>
<.top_albums_by_period <.async_result :let={top_albums} assign={@top_albums}>
albums={top_albums.all_time} <:loading>
collected_releases={top_albums.collected_releases} <div class="h-182 flex items-center justify-center">
wishlisted_releases={top_albums.wishlisted_releases} <.loading />
/> </div>
</.tabs_panel> </:loading>
</.tabs> <.top_albums_by_period
</.async_result> albums={top_albums.albums}
collected_releases={top_albums.collected_releases}
wishlisted_releases={top_albums.wishlisted_releases}
/>
</.async_result>
</.tabs>
</div> </div>
""" """
end end
defp name_from_period(period), do: "top_albums_#{period}"
@impl true
def mount(socket) do
{:ok,
socket
|> assign(:period, :last_30_days)}
end
@impl true @impl true
def update(assigns, socket) do def update(assigns, socket) do
{:ok, {:ok,
@@ -73,6 +87,14 @@ defmodule MusicLibraryWeb.StatsLive.TopAlbums do
|> assign_top_albums()} |> assign_top_albums()}
end end
@impl true
def handle_event("set_period", %{"period" => period}, socket) do
{:noreply,
socket
|> assign(:period, String.to_existing_atom(period))
|> assign_top_albums()}
end
attr :albums, :list, required: true attr :albums, :list, required: true
attr :collected_releases, :list, required: true attr :collected_releases, :list, required: true
attr :wishlisted_releases, :list, required: true attr :wishlisted_releases, :list, required: true
@@ -136,19 +158,25 @@ defmodule MusicLibraryWeb.StatsLive.TopAlbums do
end end
defp assign_top_albums(socket) do defp assign_top_albums(socket) do
timezone = socket.assigns.timezone %{timezone: timezone, period: period} = socket.assigns
current_time = DateTime.utc_now() current_time = DateTime.utc_now()
assign_async(socket, :top_albums, fn -> assign_async(
top_albums = socket,
ScrobbleActivity.get_top_albums_by_periods( :top_albums,
limit: 10, fn ->
current_time: current_time, top_albums =
timezone: timezone ScrobbleActivity.get_top_albums_by_period(
) limit: 10,
current_time: current_time,
timezone: timezone,
period: period
)
{:ok, %{top_albums: top_albums}} {:ok, %{top_albums: top_albums}}
end) end,
reset: true
)
end end
defp navigate_to_record(collected_releases, wishlisted_releases, musicbrainz_id) do defp navigate_to_record(collected_releases, wishlisted_releases, musicbrainz_id) do