Files
music_library/lib/music_library_web/live/stats_live/index.html.heex
T
Claudio Ortolina 24319b1bff Annotate templates with TODOs for markup replacement
To open source the project down the line, it makes sense to have either
everything custom or using OSS components in order to keep licensing as
simple as possible.
2024-12-04 14:43:07 +00:00

222 lines
8.3 KiB
Plaintext

<div>
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
{gettext("Basics")}
</h1>
<%!-- TODO: replace with OSS version --%>
<dl class="mt-5 grid grid-cols-2 gap-5 sm:grid-cols-5">
<.album_preview
record={@latest_record}
title={gettext("Latest purchase")}
class="col-span-2 sm:col-span-3"
/>
<.counter
title={gettext("Total collection")}
count={@collection_count}
path={~p"/collection"}
/>
<.counter title={gettext("Total wishlist")} count={@wishlist_count} path={~p"/wishlist"} />
</dl>
</div>
<div>
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
{gettext("Formats")}
</h1>
<%!-- TODO: replace with OSS version --%>
<dl class={[
"mt-5 grid divide-zinc-200 dark:divide-slate-300/50 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow divide-x",
stats_class(@collection_count_by_format)
]}>
<div :for={{format, count} <- @collection_count_by_format} class="px-2 py-5 sm:px-4">
<dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep">
{Record.format_long_label(format)}
</dt>
<dd class="mt-1 text-center">
<a
class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
href={~p"/collection?query=format:#{format}"}
>
{count}
</a>
</dd>
</div>
</dl>
</div>
<div>
<h1 class="mt-5 text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
{gettext("Types")}
</h1>
<%!-- TODO: replace with OSS version --%>
<dl class={[
"mt-5 grid divide-zinc-200 dark:divide-slate-300/50 overflow-hidden rounded-md bg-white dark:bg-zinc-800 shadow divide-x",
stats_class(@collection_count_by_type)
]}>
<div :for={{type, count} <- @collection_count_by_type} class="px-2 py-5 sm:px-4">
<dt class="text-sm font-medium text-zinc-500 dark:text-zinc-400 text-center max-sm:text-xs break-keep">
{Record.type_long_label(type)}
</dt>
<dd class="mt-1 text-center">
<a
class="text-xl lg:text-2xl font-semibold hover:text-zinc-500 dark:text-zinc-300 dark:hover:text-zinc-200"
href={~p"/collection?query=type:#{type}"}
>
{count}
</a>
</dd>
</div>
</dl>
</div>
<div class="flow-root">
<div class="mt-5 flex justify-between items-center">
<h1 class="text-base lg:text-2xl text-zinc-900 dark:text-zinc-200 font-semibold">
{gettext("Scrobble activity")}
</h1>
<button
type="button"
class="phx-click-loading:animate-spin text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300"
phx-click={JS.push("refresh_lastfm_feed")}
>
<span class="sr-only">{gettext("Refresh LastFm Feed")}</span>
<.icon name="hero-arrow-path" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
</button>
</div>
<%!-- TODO: replace with OSS version --%>
<ul
id="scrobble-activity"
role="list"
class="mt-5 rounded-md px-4 py-5 shadow"
phx-update="stream"
>
<li :for={{id, track} <- @streams.recent_tracks} id={id} class="group">
<div class="relative pb-8 group-last:pb-0">
<span
class="group-last:hidden absolute left-6 top-6 -ml-px h-full w-0.5 bg-zinc-200"
aria-hidden="true"
>
</span>
<div class="relative flex space-x-3 items-center justify-between">
<div class="flex min-w-0 justify-between space-x-4 items-center">
<img class="h-12 w-12 rounded-md shadow" src={track.cover_url} alt={track.title} />
<div>
<p class="font-semibold text-sm block text-zinc-500 dark:text-zinc-400">
{track.artist.name}
</p>
<p class="font-semibold text-sm md:text-base text-zinc-700 dark:text-zinc-300">
{track.title}
</p>
<p class="font-semibold text-sm text-zinc-500 dark:text-zinc-400">
{track.album.title}
</p>
<time
datetime={format_scrobbled_at_uts(track.scrobbled_at_uts)}
class="whitespace-nowrap text-right text-xs sm:text-sm text-zinc-500 dark:text-zinc-400"
>
{track.scrobbled_at_label}
</time>
</div>
</div>
<span
:if={track.album.musicbrainz_id == ""}
class={[
"inline-flex items-center rounded-md",
"px-2 py-1 text-xs font-medium",
"ring-1 ring-inset",
"bg-zinc-50 dark:bg-zinc-500/10",
"text-zinc-700 dark:text-zinc-400",
"ring-zinc-600/20 dark:ring-zinc-500/20"
]}
>
{gettext("No MB ID")}
</span>
<span
:if={track.album.musicbrainz_id in @collected_release_ids}
class={[
"inline-flex items-center rounded-md",
"px-2 py-1 text-xs font-medium",
"ring-1 ring-inset",
"bg-green-50 dark:bg-green-500/10",
"text-green-700 dark:text-green-400",
"ring-green-600/20 dark:ring-green-500/20"
]}
>
{gettext("Collected")}
</span>
<span
:if={track.album.musicbrainz_id in @wishlisted_release_ids}
class={[
"inline-flex items-center rounded-md",
"px-2 py-1 text-xs font-medium",
"ring-1 ring-inset",
"bg-yellow-50 dark:bg-yellow-400/10",
"text-yellow-800 dark:text-yellow-500",
"ring-yellow-600/20 dark:ring-yellow-400/20"
]}
>
{gettext("Wishlisted")}
</span>
<div
:if={
track.album.musicbrainz_id !== "" and
track.album.musicbrainz_id not in @collected_release_ids and
track.album.musicbrainz_id not in @wishlisted_release_ids
}
class="relative flex-none"
>
<button
type="button"
class="text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300"
aria-expanded="false"
aria-haspopup="true"
phx-click={toggle_actions_menu(track.scrobbled_at_uts)}
phx-click-away={close_actions_menu(track.scrobbled_at_uts)}
>
<span class="sr-only">{gettext("Choose which format to import")}</span>
<.icon name="hero-star" class="-mt-1 h-5 w-5" aria-hidden="true" data-slot="icon" />
</button>
<!--
Dropdown menu, show/hide based on menu state.
Entering: "transition ease-out duration-100"
From: "transform opacity-0 scale-95"
To: "transform opacity-100 scale-100"
Leaving: "transition ease-in duration-75"
From: "transform opacity-100 scale-100"
To: "transform opacity-0 scale-95"
-->
<.focus_wrap
id={"actions-#{track.scrobbled_at_uts}"}
class={[
"hidden pointer-events-auto absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white dark:bg-zinc-800 py-2 shadow-lg ring-1 ring-zinc-900/5 focus:outline-none"
]}
role="menu"
aria-orientation="vertical"
aria-labelledby="options-menu-0-button"
tabindex="-1"
>
<.link
:for={format <- Records.Record.formats()}
class="block px-3 py-1 text-sm leading-6 text-zinc-900 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:text-zinc-300 dark:hover:bg-zinc-700"
role="menuitem"
tabindex="-1"
id={"actions-#{track.scrobbled_at_uts}-#{format}-import"}
phx-click={
JS.push("import",
value: %{id: track.album.musicbrainz_id, format: format},
page_loading: true
)
}
>
{Records.Record.format_long_label(format)}
</.link>
</.focus_wrap>
</div>
</div>
</div>
</li>
</ul>
</div>