diff --git a/lib/music_library_web/live/stats_live/data_components.ex b/lib/music_library_web/live/stats_live/data_components.ex
new file mode 100644
index 00000000..e0bfa049
--- /dev/null
+++ b/lib/music_library_web/live/stats_live/data_components.ex
@@ -0,0 +1,42 @@
+defmodule MusicLibraryWeb.StatsLive.DataComponents do
+ use MusicLibraryWeb, :live_component
+
+ attr :data, :list,
+ required: true,
+ doc: """
+ A list of tuples, where the first element is label and the second is the count.
+ """
+
+ attr :title, :string, required: true
+ attr :col_class, :string
+
+ def stats_grid(assigns) do
+ ~H"""
+
+
+ <%= @title %>
+
+
+
+
+
+ """
+ end
+end
diff --git a/lib/music_library_web/live/stats_live/index.ex b/lib/music_library_web/live/stats_live/index.ex
index e52ccce2..e52e11cf 100644
--- a/lib/music_library_web/live/stats_live/index.ex
+++ b/lib/music_library_web/live/stats_live/index.ex
@@ -1,16 +1,20 @@
defmodule MusicLibraryWeb.StatsLive.Index do
use MusicLibraryWeb, :live_view
+ import MusicLibraryWeb.StatsLive.DataComponents
+
alias MusicLibrary.{Records, Wishlist}
alias Records.Record
def mount(_params, _session, socket) do
collection_count_by_format =
Records.count_records_by_format()
+ |> Enum.map(fn {format, count} -> {Record.format_long_label(format), count} end)
|> Enum.sort_by(fn {_format, count} -> count end, :desc)
collection_count_by_type =
Records.count_records_by_type()
+ |> Enum.map(fn {type, count} -> {Record.type_long_label(type), count} end)
|> Enum.sort_by(fn {_type, count} -> count end, :desc)
collection_count =
diff --git a/lib/music_library_web/live/stats_live/index.html.heex b/lib/music_library_web/live/stats_live/index.html.heex
index 6912b120..f08699bb 100644
--- a/lib/music_library_web/live/stats_live/index.html.heex
+++ b/lib/music_library_web/live/stats_live/index.html.heex
@@ -65,44 +65,10 @@
-
-
- <%= gettext("Formats") %>
-
-
-
-
-
+<.stats_grid
+ data={@collection_count_by_format}
+ title={gettext("Formats")}
+ col_class="grid-cols-5"
+/>
-
-
- <%= gettext("Types") %>
-
-
-
-
-
+<.stats_grid data={@collection_count_by_type} title={gettext("Types")} col_class="grid-cols-6" />
diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot
index e7686ef1..930ecf92 100644
--- a/priv/gettext/default.pot
+++ b/priv/gettext/default.pot
@@ -16,89 +16,32 @@ msgstr ""
msgid "Actions"
msgstr ""
+#: lib/music_library_web/live/record_live/index.html.heex:166
+#: lib/music_library_web/live/record_live/show.html.heex:9
+#: lib/music_library_web/live/wishlist_live/index.html.heex:176
+#: lib/music_library_web/live/wishlist_live/show.html.heex:9
+#, elixir-autogen, elixir-format
+msgid "Are you sure?"
+msgstr ""
+
#: lib/music_library_web/components/core_components.ex:169
#, elixir-autogen, elixir-format
msgid "Attempting to reconnect"
msgstr ""
-#: lib/music_library_web/components/core_components.ex:160
+#: lib/music_library_web/live/record_live/show.html.heex:95
#, elixir-autogen, elixir-format
-msgid "Error!"
+msgid "Back to records"
msgstr ""
-#: lib/music_library_web/components/core_components.ex:181
+#: lib/music_library_web/live/wishlist_live/show.html.heex:87
#, elixir-autogen, elixir-format
-msgid "Hang in there while we get back on track"
+msgid "Back to wishlist"
msgstr ""
-#: lib/music_library_web/controllers/session_html/new.html.heex:11
+#: lib/music_library_web/live/stats_live/index.html.heex:3
#, elixir-autogen, elixir-format
-msgid "Password"
-msgstr ""
-
-#: lib/music_library_web/components/core_components.ex:176
-#, elixir-autogen, elixir-format
-msgid "Something went wrong!"
-msgstr ""
-
-#: lib/music_library_web/components/core_components.ex:159
-#, elixir-autogen, elixir-format
-msgid "Success!"
-msgstr ""
-
-#: lib/music_library_web/components/core_components.ex:164
-#, elixir-autogen, elixir-format
-msgid "We can't find the internet"
-msgstr ""
-
-#: lib/music_library_web/controllers/session_html/new.html.heex:5
-#, elixir-autogen, elixir-format
-msgid "Welcome to your Music Library"
-msgstr ""
-
-#: lib/music_library_web/components/core_components.ex:85
-#: lib/music_library_web/components/core_components.ex:139
-#, elixir-autogen, elixir-format
-msgid "close"
-msgstr ""
-
-#: lib/music_library_web/controllers/session_controller.ex:19
-#, elixir-autogen, elixir-format
-msgid "Invalid password"
-msgstr ""
-
-#: lib/music_library_web/plug/require_login.ex:17
-#, elixir-autogen, elixir-format
-msgid "You must be logged in to access this page"
-msgstr ""
-
-#: lib/music_library_web/components/layouts/app.html.heex:13
-#: lib/music_library_web/live/record_live/index.ex:71
-#, elixir-autogen, elixir-format
-msgid "Collection"
-msgstr ""
-
-#: lib/music_library_web/components/layouts/app.html.heex:25
-#, elixir-autogen, elixir-format
-msgid "Logout"
-msgstr ""
-
-#: lib/music_library_web/components/layouts/app.html.heex:7
-#: lib/music_library_web/live/stats_live/index.ex:26
-#, elixir-autogen, elixir-format
-msgid "Stats"
-msgstr ""
-
-#: lib/music_library_web/components/pagination.ex:48
-#: lib/music_library_web/components/pagination.ex:111
-#, elixir-autogen, elixir-format
-msgid "Next"
-msgstr ""
-
-#: lib/music_library_web/components/pagination.ex:35
-#: lib/music_library_web/components/pagination.ex:133
-#, elixir-autogen, elixir-format
-msgid "Previous"
+msgid "Basics"
msgstr ""
#: lib/music_library_web/live/record_live/form_component.ex:35
@@ -107,75 +50,17 @@ msgstr ""
msgid "Choose a value"
msgstr ""
+#: lib/music_library_web/components/layouts/app.html.heex:13
+#: lib/music_library_web/live/record_live/index.ex:71
+#, elixir-autogen, elixir-format
+msgid "Collection"
+msgstr ""
+
#: lib/music_library_web/live/record_live/form_component.ex:55
#, elixir-autogen, elixir-format
msgid "Cover art"
msgstr ""
-#: lib/music_library_web/live/record_live/form_component.ex:41
-#, elixir-autogen, elixir-format
-msgid "Format"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:61
-#, elixir-autogen, elixir-format
-msgid "No cover selected"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:51
-#, elixir-autogen, elixir-format
-msgid "Purchased at"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:117
-#: lib/music_library_web/live/wishlist_live/index.ex:129
-#, elixir-autogen, elixir-format
-msgid "Record updated successfully"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:46
-#, elixir-autogen, elixir-format
-msgid "Release"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:72
-#, elixir-autogen, elixir-format
-msgid "Save"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:72
-#, elixir-autogen, elixir-format
-msgid "Saving..."
-msgstr ""
-
-#: lib/music_library_web/live/record_live/form_component.ex:34
-#, elixir-autogen, elixir-format
-msgid "Type"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/import_component.ex:41
-#, elixir-autogen, elixir-format
-msgid "No results"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/import_component.ex:23
-#, elixir-autogen, elixir-format
-msgid "Search for a record on MusicBrainz"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/import_component.ex:24
-#, elixir-autogen, elixir-format
-msgid "Search for records"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/index.html.heex:166
-#: lib/music_library_web/live/record_live/show.html.heex:9
-#: lib/music_library_web/live/wishlist_live/index.html.heex:176
-#: lib/music_library_web/live/wishlist_live/show.html.heex:9
-#, elixir-autogen, elixir-format
-msgid "Are you sure?"
-msgstr ""
-
#: lib/music_library_web/live/record_live/index.html.heex:168
#: lib/music_library_web/live/record_live/show.html.heex:12
#: lib/music_library_web/live/wishlist_live/index.html.heex:178
@@ -202,6 +87,32 @@ msgstr ""
msgid "Error importing record"
msgstr ""
+#: lib/music_library_web/components/core_components.ex:160
+#, elixir-autogen, elixir-format
+msgid "Error!"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/form_component.ex:41
+#, elixir-autogen, elixir-format
+msgid "Format"
+msgstr ""
+
+#: lib/music_library_web/live/stats_live/index.html.heex:70
+#, elixir-autogen, elixir-format
+msgid "Formats"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/show.html.heex:49
+#: lib/music_library_web/live/wishlist_live/show.html.heex:49
+#, elixir-autogen, elixir-format
+msgid "Genres"
+msgstr ""
+
+#: lib/music_library_web/components/core_components.ex:181
+#, elixir-autogen, elixir-format
+msgid "Hang in there while we get back on track"
+msgstr ""
+
#: lib/music_library_web/live/record_live/index.html.heex:27
#: lib/music_library_web/live/wishlist_live/index.html.heex:27
#, elixir-autogen, elixir-format
@@ -214,6 +125,54 @@ msgstr ""
msgid "Import from MusicBrainz"
msgstr ""
+#: lib/music_library_web/live/record_live/show.html.heex:75
+#: lib/music_library_web/live/wishlist_live/show.html.heex:67
+#, elixir-autogen, elixir-format
+msgid "Inserted at"
+msgstr ""
+
+#: lib/music_library_web/controllers/session_controller.ex:19
+#, elixir-autogen, elixir-format
+msgid "Invalid password"
+msgstr ""
+
+#: lib/music_library_web/live/stats_live/index.html.heex:17
+#, elixir-autogen, elixir-format
+msgid "Latest purchase"
+msgstr ""
+
+#: lib/music_library_web/controllers/session_html/new.html.heex:44
+#, elixir-autogen, elixir-format
+msgid "Login"
+msgstr ""
+
+#: lib/music_library_web/components/layouts/app.html.heex:25
+#, elixir-autogen, elixir-format
+msgid "Logout"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/show.html.heex:57
+#: lib/music_library_web/live/wishlist_live/show.html.heex:57
+#, elixir-autogen, elixir-format
+msgid "MusicBrainz ID"
+msgstr ""
+
+#: lib/music_library_web/components/pagination.ex:48
+#: lib/music_library_web/components/pagination.ex:111
+#, elixir-autogen, elixir-format
+msgid "Next"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/form_component.ex:61
+#, elixir-autogen, elixir-format
+msgid "No cover selected"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/import_component.ex:41
+#, elixir-autogen, elixir-format
+msgid "No results"
+msgstr ""
+
#: lib/music_library_web/live/record_live/import_component.ex:76
#: lib/music_library_web/live/record_live/index.html.heex:99
#: lib/music_library_web/live/wishlist_live/index.html.heex:99
@@ -221,18 +180,75 @@ msgstr ""
msgid "Open options"
msgstr ""
+#: lib/music_library_web/controllers/session_html/new.html.heex:11
+#, elixir-autogen, elixir-format
+msgid "Password"
+msgstr ""
+
+#: lib/music_library_web/components/pagination.ex:35
+#: lib/music_library_web/components/pagination.ex:133
+#, elixir-autogen, elixir-format
+msgid "Previous"
+msgstr ""
+
+#: lib/music_library_web/live/wishlist_live/index.html.heex:167
+#, elixir-autogen, elixir-format
+msgid "Purchase"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/form_component.ex:51
+#, elixir-autogen, elixir-format
+msgid "Purchased at"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/show.html.heex:67
+#, elixir-autogen, elixir-format
+msgid "Purchased on"
+msgstr ""
+
#: lib/music_library_web/live/record_live/index.ex:110
#: lib/music_library_web/live/wishlist_live/index.ex:107
#, elixir-autogen, elixir-format
msgid "Record imported successfully"
msgstr ""
+#: lib/music_library_web/live/record_live/form_component.ex:117
+#: lib/music_library_web/live/wishlist_live/index.ex:129
+#, elixir-autogen, elixir-format
+msgid "Record updated successfully"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/form_component.ex:46
+#, elixir-autogen, elixir-format
+msgid "Release"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/form_component.ex:72
+#, elixir-autogen, elixir-format
+msgid "Save"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/form_component.ex:72
+#, elixir-autogen, elixir-format
+msgid "Saving..."
+msgstr ""
+
#: lib/music_library_web/live/record_live/index.html.heex:20
#: lib/music_library_web/live/wishlist_live/index.html.heex:20
#, elixir-autogen, elixir-format
msgid "Search"
msgstr ""
+#: lib/music_library_web/live/record_live/import_component.ex:23
+#, elixir-autogen, elixir-format
+msgid "Search for a record on MusicBrainz"
+msgstr ""
+
+#: lib/music_library_web/live/record_live/import_component.ex:24
+#, elixir-autogen, elixir-format
+msgid "Search for records"
+msgstr ""
+
#: lib/music_library_web/live/record_live/index.html.heex:137
#: lib/music_library_web/live/record_live/show.ex:49
#: lib/music_library_web/live/wishlist_live/index.html.heex:137
@@ -247,6 +263,22 @@ msgstr ""
msgid "Showing %{visible} of %{total} records"
msgstr ""
+#: lib/music_library_web/components/core_components.ex:176
+#, elixir-autogen, elixir-format
+msgid "Something went wrong!"
+msgstr ""
+
+#: lib/music_library_web/components/layouts/app.html.heex:7
+#: lib/music_library_web/live/stats_live/index.ex:30
+#, elixir-autogen, elixir-format
+msgid "Stats"
+msgstr ""
+
+#: lib/music_library_web/components/core_components.ex:159
+#, elixir-autogen, elixir-format
+msgid "Success!"
+msgstr ""
+
#: lib/music_library_web/live/record_live/index.ex:17
#: lib/music_library_web/live/record_live/show.ex:19
#: lib/music_library_web/live/wishlist_live/index.ex:18
@@ -255,61 +287,6 @@ msgstr ""
msgid "The application has been updated, please reload."
msgstr ""
-#: lib/music_library_web/live/record_live/index.html.heex:147
-#: lib/music_library_web/live/wishlist_live/index.html.heex:147
-#, elixir-autogen, elixir-format
-msgid "View on MusicBrainz"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/show.html.heex:95
-#, elixir-autogen, elixir-format
-msgid "Back to records"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/show.html.heex:49
-#: lib/music_library_web/live/wishlist_live/show.html.heex:49
-#, elixir-autogen, elixir-format
-msgid "Genres"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/show.html.heex:75
-#: lib/music_library_web/live/wishlist_live/show.html.heex:67
-#, elixir-autogen, elixir-format
-msgid "Inserted at"
-msgstr ""
-
-#: lib/music_library_web/live/record_live/show.html.heex:83
-#: lib/music_library_web/live/wishlist_live/show.html.heex:75
-#, elixir-autogen, elixir-format
-msgid "Updated at"
-msgstr ""
-
-#: lib/music_library_web/live/wishlist_live/show.html.heex:87
-#, elixir-autogen, elixir-format
-msgid "Back to wishlist"
-msgstr ""
-
-#: lib/music_library_web/live/wishlist_live/index.html.heex:167
-#, elixir-autogen, elixir-format
-msgid "Purchase"
-msgstr ""
-
-#: lib/music_library_web/components/layouts/app.html.heex:19
-#: lib/music_library_web/live/wishlist_live/index.ex:72
-#, elixir-autogen, elixir-format
-msgid "Wishlist"
-msgstr ""
-
-#: lib/music_library_web/controllers/session_html/new.html.heex:44
-#, elixir-autogen, elixir-format
-msgid "Login"
-msgstr ""
-
-#: lib/music_library_web/live/stats_live/index.html.heex:17
-#, elixir-autogen, elixir-format
-msgid "Latest purchase"
-msgstr ""
-
#: lib/music_library_web/live/stats_live/index.html.heex:38
#, elixir-autogen, elixir-format
msgid "Total collection"
@@ -320,28 +297,51 @@ msgstr ""
msgid "Total wishlist"
msgstr ""
-#: lib/music_library_web/live/stats_live/index.html.heex:3
+#: lib/music_library_web/live/record_live/form_component.ex:34
#, elixir-autogen, elixir-format
-msgid "Basics"
+msgid "Type"
msgstr ""
-#: lib/music_library_web/live/stats_live/index.html.heex:70
-#, elixir-autogen, elixir-format
-msgid "Formats"
-msgstr ""
-
-#: lib/music_library_web/live/stats_live/index.html.heex:91
+#: lib/music_library_web/live/stats_live/index.html.heex:74
#, elixir-autogen, elixir-format
msgid "Types"
msgstr ""
-#: lib/music_library_web/live/record_live/show.html.heex:57
-#: lib/music_library_web/live/wishlist_live/show.html.heex:57
+#: lib/music_library_web/live/record_live/show.html.heex:83
+#: lib/music_library_web/live/wishlist_live/show.html.heex:75
#, elixir-autogen, elixir-format
-msgid "MusicBrainz ID"
+msgid "Updated at"
msgstr ""
-#: lib/music_library_web/live/record_live/show.html.heex:67
+#: lib/music_library_web/live/record_live/index.html.heex:147
+#: lib/music_library_web/live/wishlist_live/index.html.heex:147
#, elixir-autogen, elixir-format
-msgid "Purchased on"
+msgid "View on MusicBrainz"
+msgstr ""
+
+#: lib/music_library_web/components/core_components.ex:164
+#, elixir-autogen, elixir-format
+msgid "We can't find the internet"
+msgstr ""
+
+#: lib/music_library_web/controllers/session_html/new.html.heex:5
+#, elixir-autogen, elixir-format
+msgid "Welcome to your Music Library"
+msgstr ""
+
+#: lib/music_library_web/components/layouts/app.html.heex:19
+#: lib/music_library_web/live/wishlist_live/index.ex:72
+#, elixir-autogen, elixir-format
+msgid "Wishlist"
+msgstr ""
+
+#: lib/music_library_web/plug/require_login.ex:17
+#, elixir-autogen, elixir-format
+msgid "You must be logged in to access this page"
+msgstr ""
+
+#: lib/music_library_web/components/core_components.ex:85
+#: lib/music_library_web/components/core_components.ex:139
+#, elixir-autogen, elixir-format
+msgid "close"
msgstr ""
diff --git a/test/music_library_web/live/stats_index_test.exs b/test/music_library_web/live/stats_index_test.exs
index 98d08ae5..96760031 100644
--- a/test/music_library_web/live/stats_index_test.exs
+++ b/test/music_library_web/live/stats_index_test.exs
@@ -35,15 +35,15 @@ defmodule MusicLibraryWeb.StatsIndexTest do
collection
|> Enum.frequencies_by(& &1.format)
|> Enum.each(fn {format, count} ->
- assert html =~ "\n#{count}\n"
- assert html =~ "\n#{Record.format_long_label(format)}\n"
+ assert html =~ "#{count}\n"
+ assert html =~ "#{Record.format_long_label(format)}\n"
end)
collection
|> Enum.frequencies_by(& &1.type)
|> Enum.each(fn {type, count} ->
- assert html =~ "\n#{count}\n"
- assert html =~ "\n#{Record.type_long_label(type)}\n"
+ assert html =~ "#{count}\n"
+ assert html =~ "#{Record.type_long_label(type)}\n"
end)
end