style: reformat watchlist template with multiline attributes

This commit is contained in:
2026-04-20 16:33:46 +02:00
parent 4be1062fd2
commit 953e2a067e

View File

@@ -8,34 +8,117 @@ import (
"math" "math"
) )
templ Watchlist(entries []db.GetUserWatchListRow, layout string, currentStatus string, sortBy string, sortOrder string) { templ Watchlist(
entries []db.GetUserWatchListRow,
layout string,
currentStatus string,
sortBy string,
sortOrder string,
) {
@Layout("mal - watchlist", true) { @Layout("mal - watchlist", true) {
<div class="mb-4 flex items-end justify-between gap-4 max-lg:flex-col max-lg:items-start"> <div
class="mb-4 flex items-end justify-between gap-4 max-lg:flex-col max-lg:items-start"
>
<div class="grid gap-1"> <div class="grid gap-1">
<h2>Watchlist</h2> <h2>Watchlist</h2>
<p class="m-0 text-sm text-(--text-muted)">Track what you're watching with less noise.</p> <p class="m-0 text-sm text-(--text-muted)">
Track what you're watching with less noise.
</p>
</div> </div>
<div class="flex flex-wrap items-center justify-end gap-2 max-lg:w-full max-lg:justify-start"> <div
<a href="/api/watchlist/export" class="inline-flex min-w-16 items-center justify-center px-2 py-1 text-center text-xs leading-tight text-(--text-muted) no-underline hover:text-(--accent) hover:no-underline">Export</a> class="flex flex-wrap items-center justify-end gap-2 max-lg:w-full max-lg:justify-start"
<button class="inline-flex min-w-16 cursor-pointer items-center justify-center border-0 bg-transparent px-2 py-1 text-center text-xs leading-tight text-(--text-muted) hover:text-(--accent)" type="button" onclick="document.getElementById('import-file').click()">Import</button> >
<form id="import-form" hx-post="/api/watchlist/import" hx-encoding="multipart/form-data" class="hidden"> <a
<input type="file" id="import-file" name="file" accept=".json" onchange="htmx.trigger('#import-form', 'submit')"/> href="/api/watchlist/export"
class="inline-flex min-w-16 items-center justify-center px-2 py-1 text-center text-xs leading-tight text-(--text-muted) no-underline hover:text-(--accent) hover:no-underline"
>
Export
</a>
<button
class="inline-flex min-w-16 cursor-pointer items-center justify-center border-0 bg-transparent px-2 py-1 text-center text-xs leading-tight text-(--text-muted) hover:text-(--accent)"
type="button"
onclick="document.getElementById('import-file').click()"
>
Import
</button>
<form
id="import-form"
hx-post="/api/watchlist/import"
hx-encoding="multipart/form-data"
class="hidden"
>
<input
type="file"
id="import-file"
name="file"
accept=".json"
onchange="htmx.trigger('#import-form', 'submit')"
/>
</form> </form>
<div class="flex flex-wrap gap-2 max-md:flex-nowrap max-md:overflow-x-auto max-md:pb-1"> <div
<a href={ templ.URL(watchlistURL("grid", currentStatus, sortBy, sortOrder)) } class={ tabClass(layout == "grid") }>Grid</a> class="flex flex-wrap gap-2 max-md:flex-nowrap max-md:overflow-x-auto max-md:pb-1"
<a href={ templ.URL(watchlistURL("table", currentStatus, sortBy, sortOrder)) } class={ tabClass(layout == "table") }>Table</a> >
<a
href={ templ.URL(watchlistURL("grid", currentStatus, sortBy, sortOrder)) }
class={ tabClass(layout == "grid") }
>
Grid
</a>
<a
href={ templ.URL(watchlistURL("table", currentStatus, sortBy, sortOrder)) }
class={ tabClass(layout == "table") }
>
Table
</a>
</div> </div>
</div> </div>
</div> </div>
<div class="mb-3 flex flex-wrap gap-2 max-md:flex-nowrap max-md:overflow-x-auto max-md:pb-1"> <div
<a href={ templ.URL(watchlistURL(layout, "all", sortBy, sortOrder)) } class={ tabClass(currentStatus == "all") }>All</a> class="mb-3 flex flex-wrap gap-2 max-md:flex-nowrap max-md:overflow-x-auto max-md:pb-1"
<a href={ templ.URL(watchlistURL(layout, "watching", sortBy, sortOrder)) } class={ tabClass(currentStatus == "watching") }>Watching</a> >
<a href={ templ.URL(watchlistURL(layout, "on_hold", sortBy, sortOrder)) } class={ tabClass(currentStatus == "on_hold") }>On hold</a> <a
<a href={ templ.URL(watchlistURL(layout, "plan_to_watch", sortBy, sortOrder)) } class={ tabClass(currentStatus == "plan_to_watch") }>Plan to watch</a> href={ templ.URL(watchlistURL(layout, "all", sortBy, sortOrder)) }
<a href={ templ.URL(watchlistURL(layout, "dropped", sortBy, sortOrder)) } class={ tabClass(currentStatus == "dropped") }>Dropped</a> class={ tabClass(currentStatus == "all") }
<a href={ templ.URL(watchlistURL(layout, "completed", sortBy, sortOrder)) } class={ tabClass(currentStatus == "completed") }>Completed</a> >
All
</a>
<a
href={ templ.URL(watchlistURL(layout, "watching", sortBy, sortOrder)) }
class={ tabClass(currentStatus == "watching") }
>
Watching
</a>
<a
href={ templ.URL(watchlistURL(layout, "on_hold", sortBy, sortOrder)) }
class={ tabClass(currentStatus == "on_hold") }
>
On hold
</a>
<a
href={ templ.URL(watchlistURL(layout, "plan_to_watch", sortBy, sortOrder)) }
class={ tabClass(currentStatus == "plan_to_watch") }
>
Plan to watch
</a>
<a
href={ templ.URL(watchlistURL(layout, "dropped", sortBy, sortOrder)) }
class={ tabClass(currentStatus == "dropped") }
>
Dropped
</a>
<a
href={ templ.URL(watchlistURL(layout, "completed", sortBy, sortOrder)) }
class={ tabClass(currentStatus == "completed") }
>
Completed
</a>
</div> </div>
@components.SortFilter(components.SortFilterOptions{Sort: sortBy, Order: sortOrder, View: layout, Status: currentStatus}) @components.SortFilter(components.SortFilterOptions{
Sort: sortBy,
Order: sortOrder,
View: layout,
Status: currentStatus,
})
if len(entries) == 0 { if len(entries) == 0 {
@components.EmptyState("Nothing here yet") { @components.EmptyState("Nothing here yet") {
if currentStatus == "all" { if currentStatus == "all" {
@@ -46,30 +129,46 @@ templ Watchlist(entries []db.GetUserWatchListRow, layout string, currentStatus s
} }
} else { } else {
if layout == "grid" { if layout == "grid" {
<div class="grid grid-cols-2 gap-3 sm:grid-cols-3 md:gap-4 lg:grid-cols-4 xl:grid-cols-5"> <div
class="grid grid-cols-2 gap-3 sm:grid-cols-3 md:gap-4 lg:grid-cols-4 xl:grid-cols-5"
>
for _, entry := range entries { for _, entry := range entries {
<div class="group relative min-w-0" id={ fmt.Sprintf("watchlist-entry-%d", entry.AnimeID) }> <div
<a href={ templ.URL(watchURL(entry)) } class="flex flex-col bg-transparent text-inherit no-underline"> class="group relative min-w-0"
id={ fmt.Sprintf("watchlist-entry-%d", entry.AnimeID) }
>
<a
href={ templ.URL(watchURL(entry)) }
class="flex flex-col bg-transparent text-inherit no-underline"
>
<div class="flex w-full aspect-2/3 justify-center overflow-hidden"> <div class="flex w-full aspect-2/3 justify-center overflow-hidden">
<img src={ entry.ImageUrl } alt={ entry.DisplayTitle() } class="block w-full object-cover object-center" loading="lazy"/> <img
src={ entry.ImageUrl }
alt={ entry.DisplayTitle() }
class="block w-full object-cover object-center"
loading="lazy"
/>
</div> </div>
<div class="mt-2 line-clamp-2 text-sm leading-snug text-(--text)"> <div class="mt-2 line-clamp-2 text-sm leading-snug text-(--text)">
{ entry.DisplayTitle() } { entry.DisplayTitle() }
</div> </div>
@watchlist.Progress(entry) @watchlist.Progress(entry)
</a> </a>
<button <button
class="absolute right-2 top-2 h-6 w-6 cursor-pointer border-0 bg-(--overlay-subtle) text-(--text-muted) opacity-0 transition-opacity duration-150 group-hover:opacity-100 hover:text-(--danger)" class="absolute right-2 top-2 h-6 w-6 cursor-pointer border-0 bg-(--overlay-subtle) text-(--text-muted) opacity-0 transition-opacity duration-150 group-hover:opacity-100 hover:text-(--danger)"
hx-delete={ string(templ.URL(fmt.Sprintf("/api/watchlist/%d?from=watchlist", entry.AnimeID))) } hx-delete={ string(templ.URL(fmt.Sprintf("/api/watchlist/%d?from=watchlist", entry.AnimeID))) }
hx-target={ fmt.Sprintf("#watchlist-entry-%d", entry.AnimeID) } hx-target={ fmt.Sprintf("#watchlist-entry-%d", entry.AnimeID) }
hx-swap="delete" hx-swap="delete"
>&times;</button> >
</div> &times;
} </button>
</div> </div>
}
</div> </div>
} else { } else {
<table class="block w-full overflow-x-auto whitespace-nowrap bg-(--panel) md:table md:overflow-visible md:whitespace-normal"> <table
class="block w-full overflow-x-auto whitespace-nowrap bg-(--panel) md:table md:overflow-visible md:whitespace-normal"
>
<thead> <thead>
<tr> <tr>
<th class="p-2.5"></th> <th class="p-2.5"></th>
@@ -79,10 +178,18 @@ templ Watchlist(entries []db.GetUserWatchListRow, layout string, currentStatus s
</thead> </thead>
<tbody> <tbody>
for _, entry := range entries { for _, entry := range entries {
<tr class="hover:bg-(--panel-soft)" id={ fmt.Sprintf("watchlist-entry-%d", entry.AnimeID) }> <tr
class="hover:bg-(--panel-soft)"
id={ fmt.Sprintf("watchlist-entry-%d", entry.AnimeID) }
>
<td class="p-2.5"> <td class="p-2.5">
<a href={ templ.URL(watchURL(entry)) }> <a href={ templ.URL(watchURL(entry)) }>
<img src={ entry.ImageUrl } alt={ entry.DisplayTitle() } class="aspect-2/3 w-9 object-cover" loading="lazy"/> <img
src={ entry.ImageUrl }
alt={ entry.DisplayTitle() }
class="aspect-2/3 w-9 object-cover"
loading="lazy"
/>
</a> </a>
</td> </td>
<td class="p-2.5 font-medium"> <td class="p-2.5 font-medium">
@@ -97,7 +204,9 @@ templ Watchlist(entries []db.GetUserWatchListRow, layout string, currentStatus s
hx-delete={ string(templ.URL(fmt.Sprintf("/api/watchlist/%d?from=watchlist", entry.AnimeID))) } hx-delete={ string(templ.URL(fmt.Sprintf("/api/watchlist/%d?from=watchlist", entry.AnimeID))) }
hx-target={ fmt.Sprintf("#watchlist-entry-%d", entry.AnimeID) } hx-target={ fmt.Sprintf("#watchlist-entry-%d", entry.AnimeID) }
hx-swap="delete" hx-swap="delete"
>Remove</button> >
Remove
</button>
</td> </td>
</tr> </tr>
} }