220 lines
6.3 KiB
Plaintext
220 lines
6.3 KiB
Plaintext
package templates
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"mal/internal/db"
|
|
"mal/web/components"
|
|
"mal/web/components/watchlist"
|
|
"mal/web/shared"
|
|
)
|
|
|
|
templ Watchlist(
|
|
entries []db.GetUserWatchListRow,
|
|
layout string,
|
|
currentStatus string,
|
|
sortBy string,
|
|
sortOrder string,
|
|
) {
|
|
@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="grid gap-1">
|
|
<h2>Watchlist</h2>
|
|
<p class="m-0 text-sm text-(--text-muted)">
|
|
Track what you're watching with less noise.
|
|
</p>
|
|
</div>
|
|
<div
|
|
class="flex flex-wrap items-center justify-end gap-2 max-lg:w-full max-lg:justify-start"
|
|
>
|
|
<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>
|
|
<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>
|
|
<div
|
|
class="flex flex-wrap gap-2 max-md:flex-nowrap max-md:overflow-x-auto max-md:pb-1"
|
|
>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL("grid", currentStatus, sortBy, sortOrder)) }
|
|
class={ shared.TabClass(layout == "grid") }
|
|
>
|
|
Grid
|
|
</a>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL("table", currentStatus, sortBy, sortOrder)) }
|
|
class={ shared.TabClass(layout == "table") }
|
|
>
|
|
Table
|
|
</a>
|
|
</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"
|
|
>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL(layout, "all", sortBy, sortOrder)) }
|
|
class={ shared.TabClass(currentStatus == "all") }
|
|
>
|
|
All
|
|
</a>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL(layout, "watching", sortBy, sortOrder)) }
|
|
class={ shared.TabClass(currentStatus == "watching") }
|
|
>
|
|
Watching
|
|
</a>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL(layout, "on_hold", sortBy, sortOrder)) }
|
|
class={ shared.TabClass(currentStatus == "on_hold") }
|
|
>
|
|
On hold
|
|
</a>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL(layout, "plan_to_watch", sortBy, sortOrder)) }
|
|
class={ shared.TabClass(currentStatus == "plan_to_watch") }
|
|
>
|
|
Plan to watch
|
|
</a>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL(layout, "dropped", sortBy, sortOrder)) }
|
|
class={ shared.TabClass(currentStatus == "dropped") }
|
|
>
|
|
Dropped
|
|
</a>
|
|
<a
|
|
href={ templ.URL(shared.WatchlistURL(layout, "completed", sortBy, sortOrder)) }
|
|
class={ shared.TabClass(currentStatus == "completed") }
|
|
>
|
|
Completed
|
|
</a>
|
|
</div>
|
|
@components.SortFilter(components.SortFilterOptions{
|
|
Sort: sortBy,
|
|
Order: sortOrder,
|
|
View: layout,
|
|
Status: currentStatus,
|
|
})
|
|
if len(entries) == 0 {
|
|
@components.EmptyState("Nothing here yet") {
|
|
if currentStatus == "all" {
|
|
Your watchlist is empty. <a href="/">Search for anime</a> to get started.
|
|
} else {
|
|
No anime in this category.
|
|
}
|
|
}
|
|
} else {
|
|
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"
|
|
>
|
|
for _, entry := range entries {
|
|
<div
|
|
class="group relative min-w-0"
|
|
id={ fmt.Sprintf("watchlist-entry-%d", entry.AnimeID) }
|
|
>
|
|
<a
|
|
href={ templ.URL(shared.AnimeURL(entry.AnimeID)) }
|
|
class="flex flex-col bg-transparent text-inherit no-underline"
|
|
>
|
|
<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"
|
|
/>
|
|
</div>
|
|
<div class="mt-2 line-clamp-2 text-sm leading-snug text-(--text)">
|
|
{ entry.DisplayTitle() }
|
|
</div>
|
|
@watchlist.Progress(entry)
|
|
</a>
|
|
<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)"
|
|
hx-delete={ string(templ.URL(fmt.Sprintf("/api/watchlist/%d?from=watchlist", entry.AnimeID))) }
|
|
hx-target={ fmt.Sprintf("#watchlist-entry-%d", entry.AnimeID) }
|
|
hx-swap="delete"
|
|
>
|
|
×
|
|
</button>
|
|
</div>
|
|
}
|
|
</div>
|
|
} else {
|
|
<table
|
|
class="block w-full overflow-x-auto whitespace-nowrap bg-(--panel) md:table md:overflow-visible md:whitespace-normal"
|
|
>
|
|
<thead>
|
|
<tr>
|
|
<th class="p-2.5"></th>
|
|
<th class="p-2.5 text-left text-xs text-(--text-faint)">Title</th>
|
|
<th class="p-2.5"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
for _, entry := range entries {
|
|
<tr
|
|
class="hover:bg-(--panel-soft)"
|
|
id={ fmt.Sprintf("watchlist-entry-%d", entry.AnimeID) }
|
|
>
|
|
<td class="p-2.5">
|
|
<a href={ templ.URL(shared.AnimeURL(entry.AnimeID)) }>
|
|
<img
|
|
src={ entry.ImageUrl }
|
|
alt={ entry.DisplayTitle() }
|
|
class="aspect-2/3 w-9 object-cover"
|
|
loading="lazy"
|
|
/>
|
|
</a>
|
|
</td>
|
|
<td class="p-2.5 font-medium">
|
|
<a href={ templ.URL(shared.AnimeURL(entry.AnimeID)) }>
|
|
{ entry.DisplayTitle() }
|
|
</a>
|
|
@watchlist.Progress(entry)
|
|
</td>
|
|
<td class="w-24 p-2.5">
|
|
<button
|
|
class="cursor-pointer border-0 bg-transparent p-0 text-xs text-(--text-muted) hover:text-(--danger)"
|
|
hx-delete={ string(templ.URL(fmt.Sprintf("/api/watchlist/%d?from=watchlist", entry.AnimeID))) }
|
|
hx-target={ fmt.Sprintf("#watchlist-entry-%d", entry.AnimeID) }
|
|
hx-swap="delete"
|
|
>
|
|
Remove
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
}
|
|
}
|
|
}
|
|
}
|