Use explicit Phoenix 1.8 style layouts

This commit is contained in:
Claudio Ortolina
2025-09-21 21:11:17 +03:00
parent 0071d45998
commit 64cb917a4e
11 changed files with 1907 additions and 1882 deletions
@@ -1,160 +1,162 @@
<div>
<header class="gap-6">
<div class="mb-2 mt-2">
<.search_form query={@track_list_params.query} />
</div>
</header>
<Layouts.app flash={@flash} current_section={@current_section} socket={@socket}>
<div>
<header class="gap-6">
<div class="mb-2 mt-2">
<.search_form query={@track_list_params.query} />
</div>
</header>
<div class="flex items-end gap-6 mt-8 justify-center sm:justify-start">
<.button_group>
<.button
patch={order_path(@track_list_params, :scrobbled_at)}
size="xs"
class={[
@track_list_params.order == :scrobbled_at && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon
name="hero-clock-solid"
class="icon"
aria-hidden="true"
data-slot="icon"
/>
{gettext("Scrobbled")}
</.button>
<.button
patch={order_path(@track_list_params, :title)}
size="xs"
class={[
@track_list_params.order == :title && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Title")}
</.button>
<.button
patch={order_path(@track_list_params, :artist)}
size="xs"
class={[
@track_list_params.order == :artist && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-user-solid" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Artist")}
</.button>
<.button
patch={order_path(@track_list_params, :album)}
size="xs"
class={[
@track_list_params.order == :album && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Album")}
</.button>
</.button_group>
</div>
</div>
<div class="mt-6">
<ul
class="divide-y divide-zinc-100 dark:divide-zinc-300/20 mt-5"
role="list"
id="tracks"
phx-update="stream"
>
<li
id="no-scrobbled-tracks"
class="hidden only:block p-8 text-center bg-zinc-50 dark:bg-zinc-800 rounded-lg"
>
<.icon name="hero-musical-note" class="h-12 w-12 text-zinc-400 mx-auto mb-4" />
<p class="text-zinc-600 dark:text-zinc-400">
{gettext("No scrobbled tracks found")}
</p>
</li>
<li
:for={{id, track} <- @streams.tracks}
id={id}
class="flex justify-between gap-x-6 py-5 hover:bg-zinc-50 dark:hover:bg-zinc-800 px-2 -mx-2 md:px-4 md:-mx-4 cursor-pointer"
>
<div class="flex items-center space-x-4 flex-1 min-w-0">
<div :if={track.cover_url && track.cover_url != ""} class="flex-shrink-0">
<img
class="w-12 h-12 rounded-md object-cover"
src={track.cover_url}
alt={"Cover for " <> track.album.title}
onerror={"this.src = '" <> ~p"/images/cover-not-found.png" <> "';"}
<div class="flex items-end gap-6 mt-8 justify-center sm:justify-start">
<.button_group>
<.button
patch={order_path(@track_list_params, :scrobbled_at)}
size="xs"
class={[
@track_list_params.order == :scrobbled_at && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon
name="hero-clock-solid"
class="icon"
aria-hidden="true"
data-slot="icon"
/>
</div>
<div :if={!track.cover_url || track.cover_url == ""} class="flex-shrink-0">
<div class="w-12 h-12 bg-zinc-200 dark:bg-zinc-600 rounded-md flex items-center justify-center">
<.icon name="hero-musical-note" class="h-6 w-6 text-zinc-400" />
{gettext("Scrobbled")}
</.button>
<.button
patch={order_path(@track_list_params, :title)}
size="xs"
class={[
@track_list_params.order == :title && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Title")}
</.button>
<.button
patch={order_path(@track_list_params, :artist)}
size="xs"
class={[
@track_list_params.order == :artist && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-user-solid" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Artist")}
</.button>
<.button
patch={order_path(@track_list_params, :album)}
size="xs"
class={[
@track_list_params.order == :album && "!bg-zinc-100 dark:!bg-zinc-700"
]}
>
<.icon name="hero-musical-note-solid" class="icon" aria-hidden="true" data-slot="icon" />
{gettext("Album")}
</.button>
</.button_group>
</div>
</div>
<div class="mt-6">
<ul
class="divide-y divide-zinc-100 dark:divide-zinc-300/20 mt-5"
role="list"
id="tracks"
phx-update="stream"
>
<li
id="no-scrobbled-tracks"
class="hidden only:block p-8 text-center bg-zinc-50 dark:bg-zinc-800 rounded-lg"
>
<.icon name="hero-musical-note" class="h-12 w-12 text-zinc-400 mx-auto mb-4" />
<p class="text-zinc-600 dark:text-zinc-400">
{gettext("No scrobbled tracks found")}
</p>
</li>
<li
:for={{id, track} <- @streams.tracks}
id={id}
class="flex justify-between gap-x-6 py-5 hover:bg-zinc-50 dark:hover:bg-zinc-800 px-2 -mx-2 md:px-4 md:-mx-4 cursor-pointer"
>
<div class="flex items-center space-x-4 flex-1 min-w-0">
<div :if={track.cover_url && track.cover_url != ""} class="flex-shrink-0">
<img
class="w-12 h-12 rounded-md object-cover"
src={track.cover_url}
alt={"Cover for " <> track.album.title}
onerror={"this.src = '" <> ~p"/images/cover-not-found.png" <> "';"}
/>
</div>
<div :if={!track.cover_url || track.cover_url == ""} class="flex-shrink-0">
<div class="w-12 h-12 bg-zinc-200 dark:bg-zinc-600 rounded-md flex items-center justify-center">
<.icon name="hero-musical-note" class="h-6 w-6 text-zinc-400" />
</div>
</div>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate">
{track.title}
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400 truncate">
{track.artist.name}
</p>
<p class="text-sm text-zinc-500 dark:text-zinc-500 truncate">
{track.album.title}
</p>
<p class="text-xs text-zinc-400 dark:text-zinc-600 mt-1">
{track.scrobbled_at_label}
</p>
</div>
</div>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate">
{track.title}
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400 truncate">
{track.artist.name}
</p>
<p class="text-sm text-zinc-500 dark:text-zinc-500 truncate">
{track.album.title}
</p>
<p class="text-xs text-zinc-400 dark:text-zinc-600 mt-1">
{track.scrobbled_at_label}
</p>
<div class="flex items-center">
<.dropdown id={"actions-#{track.scrobbled_at_uts}"} placement="bottom-end">
<:toggle>
<div>
<span class="sr-only">{gettext("Actions")}</span>
<.icon
name="hero-ellipsis-vertical"
class="-mt-1 h-5 w-5 text-zinc-500 dark:text-zinc-400 cursor-pointer"
aria-hidden="true"
data-slot="icon"
/>
</div>
</:toggle>
<.dropdown_link patch={~p"/scrobbled-tracks/#{track.scrobbled_at_uts}/edit"}>
{gettext("Edit")}
</.dropdown_link>
<.dropdown_button
phx-click={
JS.push("delete", value: %{"scrobbled-at-uts": track.scrobbled_at_uts})
|> JS.hide(to: "##{id}")
}
data-confirm={gettext("Are you sure?")}
class={[
"text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
]}
>
{gettext("Delete")}
</.dropdown_button>
</.dropdown>
</div>
</div>
</li>
</ul>
<div class="flex items-center">
<.dropdown id={"actions-#{track.scrobbled_at_uts}"} placement="bottom-end">
<:toggle>
<div>
<span class="sr-only">{gettext("Actions")}</span>
<.icon
name="hero-ellipsis-vertical"
class="-mt-1 h-5 w-5 text-zinc-500 dark:text-zinc-400 cursor-pointer"
aria-hidden="true"
data-slot="icon"
/>
</div>
</:toggle>
<.dropdown_link patch={~p"/scrobbled-tracks/#{track.scrobbled_at_uts}/edit"}>
{gettext("Edit")}
</.dropdown_link>
<.dropdown_button
phx-click={
JS.push("delete", value: %{"scrobbled-at-uts": track.scrobbled_at_uts})
|> JS.hide(to: "##{id}")
}
data-confirm={gettext("Are you sure?")}
class={[
"text-red-900! hover:bg-red-50! dark:text-red-500! dark:hover:bg-red-900/30! dark:hover:text-red-600!"
]}
>
{gettext("Delete")}
</.dropdown_button>
</.dropdown>
</div>
</li>
</ul>
<.pagination id={:bottom_pagination} pagination_params={@track_list_params} />
</div>
<.pagination id={:bottom_pagination} pagination_params={@track_list_params} />
</div>
<.structured_modal
:if={@live_action == :edit}
id="track-modal"
on_close={JS.patch(back_path(@track_list_params))}
>
<.live_component
module={MusicLibraryWeb.ScrobbledTracksLive.FormComponent}
id={@track.scrobbled_at_uts}
action={@live_action}
track={@track}
patch={back_path(@track_list_params)}
/>
</.structured_modal>
<.structured_modal
:if={@live_action == :edit}
id="track-modal"
on_close={JS.patch(back_path(@track_list_params))}
>
<.live_component
module={MusicLibraryWeb.ScrobbledTracksLive.FormComponent}
id={@track.scrobbled_at_uts}
action={@live_action}
track={@track}
patch={back_path(@track_list_params)}
/>
</.structured_modal>
</Layouts.app>