diff --git a/lib/music_library_web/live/stats_live/index.ex b/lib/music_library_web/live/stats_live/index.ex
index dbe9538f..5ece9bbe 100644
--- a/lib/music_library_web/live/stats_live/index.ex
+++ b/lib/music_library_web/live/stats_live/index.ex
@@ -152,10 +152,8 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp top_release_years(assigns) do
~H"""
-
-
- {gettext("Top 20 Release Years")}
-
+ <.section>
+ <:title>{gettext("Top 20 Release Years")}
<.vertical_bar_chart
data={@records_by_release_year}
@@ -170,7 +168,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
class="w-full"
/>
-
+
"""
end
@@ -178,10 +176,8 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp top_collection_genres(assigns) do
~H"""
-
-
- {gettext("Top %{n} Collection Genres", %{n: length(@records_by_genre)})}
-
+ <.section>
+ <:title>{gettext("Top %{n} Collection Genres", %{n: length(@records_by_genre)})}
<.vertical_bar_chart
data={@records_by_genre}
@@ -196,7 +192,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
class="w-full"
/>
-
+
"""
end
@@ -204,10 +200,8 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp top_collection_artists(assigns) do
~H"""
-
-
- {gettext("Top %{n} Collection Artists", %{n: length(@records_by_artist)})}
-
+ <.section>
+ <:title>{gettext("Top %{n} Collection Artists", %{n: length(@records_by_artist)})}
<.vertical_bar_chart
data={@records_by_artist}
@@ -222,7 +216,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
class="w-full"
/>
-
+
"""
end
@@ -428,11 +422,9 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp on_this_day(assigns) do
~H"""
-
-
-
- {gettext("On This day")}
-
+ <.section container_class="order-first lg:order-last">
+ <:title>{gettext("On This day")}
+ <:side_actions>
<.form
:let={f}
for={to_form(%{"current_date" => @current_date})}
@@ -450,7 +442,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
-
+
<.records_on_this_day
current_date={@current_date}
@@ -458,7 +450,7 @@ defmodule MusicLibraryWeb.StatsLive.Index do
record_show_path={fn record -> ~p"/collection/#{record}" end}
/>
-
+
"""
end
@@ -466,16 +458,14 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp types_stats(assigns) do
~H"""
-
-
- {gettext("Types")}
-
+ <.section>
+ <:title>{gettext("Types")}
<.counters_by_category
categories_with_counts={@collection_count_by_type}
category_format_fn={&type_label/1}
category_path_fn={fn type -> ~p"/collection?query=type:#{type}" end}
/>
-
+
"""
end
@@ -483,16 +473,14 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp formats_stats(assigns) do
~H"""
-
-
- {gettext("Formats")}
-
+ <.section>
+ <:title>{gettext("Formats")}
<.counters_by_category
categories_with_counts={@collection_count_by_format}
category_format_fn={&format_label/1}
category_path_fn={fn format -> ~p"/collection?query=format:#{format}" end}
/>
-
+
"""
end
@@ -503,10 +491,8 @@ defmodule MusicLibraryWeb.StatsLive.Index do
defp record_stats(assigns) do
~H"""
-
-
- {gettext("Records")}
-
+ <.section>
+ <:title>{gettext("Records")}
<.album_preview
record={@latest_record}
@@ -526,6 +512,25 @@ defmodule MusicLibraryWeb.StatsLive.Index do
path={~p"/scrobbled-tracks"}
/>
+
+ """
+ end
+
+ attr :container_class, :string, default: nil
+ slot :title, required: true
+ slot :side_actions
+ slot :inner_block, required: true
+
+ defp section(assigns) do
+ ~H"""
+
+
+
+ {render_slot(@title)}
+
+ {render_slot(@side_actions)}
+
+ {render_slot(@inner_block)}
"""
end
diff --git a/lib/music_library_web/live/stats_live/top_by_period.ex b/lib/music_library_web/live/stats_live/top_by_period.ex
index 8bba3520..909dbf45 100644
--- a/lib/music_library_web/live/stats_live/top_by_period.ex
+++ b/lib/music_library_web/live/stats_live/top_by_period.ex
@@ -19,7 +19,7 @@ defmodule MusicLibraryWeb.StatsLive.TopByPeriod do
@impl true
def render(assigns) do
~H"""
-