refactor: remove table view from watchlist, keep only grid
This commit is contained in:
@@ -211,11 +211,6 @@ func (h *Handler) HandleGetWatchlist(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
layout := r.URL.Query().Get("view")
|
||||
if layout != "grid" && layout != "table" {
|
||||
layout = "grid"
|
||||
}
|
||||
|
||||
statusFilter := r.URL.Query().Get("status")
|
||||
sortBy := r.URL.Query().Get("sort")
|
||||
sortOrder := r.URL.Query().Get("order")
|
||||
@@ -255,7 +250,7 @@ func (h *Handler) HandleGetWatchlist(w http.ResponseWriter, r *http.Request) {
|
||||
// Sort entries
|
||||
h.sortEntries(filteredEntries, sortBy, sortOrder)
|
||||
|
||||
if err := templates.Watchlist(filteredEntries, layout, statusFilter, sortBy, sortOrder).Render(r.Context(), w); err != nil {
|
||||
if err := templates.Watchlist(filteredEntries, statusFilter, sortBy, sortOrder).Render(r.Context(), w); err != nil {
|
||||
log.Printf("render error: %v", err)
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package ui
|
||||
type SortFilterOptions struct {
|
||||
Sort string // "title", "date"
|
||||
Order string // "asc", "desc"
|
||||
View string // for watchlist: "grid", "table"
|
||||
Status string // for watchlist: "all", "watching", etc
|
||||
}
|
||||
|
||||
@@ -27,9 +26,6 @@ templ SortFilter(opts SortFilterOptions) {
|
||||
<form id="sort-form" method="get" class="hidden">
|
||||
<input type="hidden" name="sort" id="sort-input" value={ opts.Sort }/>
|
||||
<input type="hidden" name="order" id="order-input" value={ opts.Order }/>
|
||||
if opts.View != "" {
|
||||
<input type="hidden" name="view" value={ opts.View }/>
|
||||
}
|
||||
if opts.Status != "" {
|
||||
<input type="hidden" name="status" value={ opts.Status }/>
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ func FormatEstablishedDate(date string) string {
|
||||
}
|
||||
|
||||
// WatchlistURL builds the watchlist URL with query parameters
|
||||
func WatchlistURL(view string, status string, sortBy string, sortOrder string) string {
|
||||
return fmt.Sprintf("/watchlist?view=%s&status=%s&sort=%s&order=%s", view, status, sortBy, sortOrder)
|
||||
func WatchlistURL(status string, sortBy string, sortOrder string) string {
|
||||
return fmt.Sprintf("/watchlist?status=%s&sort=%s&order=%s", status, sortBy, sortOrder)
|
||||
}
|
||||
|
||||
// AnimeURL builds the anime detail URL
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
templ Watchlist(
|
||||
entries []db.GetUserWatchListRow,
|
||||
viewLayout string,
|
||||
currentStatus string,
|
||||
sortBy string,
|
||||
sortOrder string,
|
||||
@@ -57,59 +56,44 @@ templ Watchlist(
|
||||
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(viewLayout, "all", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(viewLayout == "grid") }
|
||||
>
|
||||
Grid
|
||||
</a>
|
||||
<a
|
||||
href={ templ.URL(shared.WatchlistURL(viewLayout, "table", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(viewLayout == "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(viewLayout, "all", sortBy, sortOrder)) }
|
||||
href={ templ.URL(shared.WatchlistURL("all", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(currentStatus == "all") }
|
||||
>
|
||||
All
|
||||
</a>
|
||||
<a
|
||||
href={ templ.URL(shared.WatchlistURL(viewLayout, "watching", sortBy, sortOrder)) }
|
||||
href={ templ.URL(shared.WatchlistURL("watching", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(currentStatus == "watching") }
|
||||
>
|
||||
Watching
|
||||
</a>
|
||||
<a
|
||||
href={ templ.URL(shared.WatchlistURL(viewLayout, "on_hold", sortBy, sortOrder)) }
|
||||
href={ templ.URL(shared.WatchlistURL("on_hold", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(currentStatus == "on_hold") }
|
||||
>
|
||||
On hold
|
||||
</a>
|
||||
<a
|
||||
href={ templ.URL(shared.WatchlistURL(viewLayout, "plan_to_watch", sortBy, sortOrder)) }
|
||||
href={ templ.URL(shared.WatchlistURL("plan_to_watch", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(currentStatus == "plan_to_watch") }
|
||||
>
|
||||
Plan to watch
|
||||
</a>
|
||||
<a
|
||||
href={ templ.URL(shared.WatchlistURL(viewLayout, "dropped", sortBy, sortOrder)) }
|
||||
href={ templ.URL(shared.WatchlistURL("dropped", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(currentStatus == "dropped") }
|
||||
>
|
||||
Dropped
|
||||
</a>
|
||||
<a
|
||||
href={ templ.URL(shared.WatchlistURL(viewLayout, "completed", sortBy, sortOrder)) }
|
||||
href={ templ.URL(shared.WatchlistURL("completed", sortBy, sortOrder)) }
|
||||
class={ shared.TabClass(currentStatus == "completed") }
|
||||
>
|
||||
Completed
|
||||
@@ -118,7 +102,6 @@ templ Watchlist(
|
||||
@components.SortFilter(components.SortFilterOptions{
|
||||
Sort: sortBy,
|
||||
Order: sortOrder,
|
||||
View: viewLayout,
|
||||
Status: currentStatus,
|
||||
})
|
||||
if len(entries) == 0 {
|
||||
@@ -130,92 +113,43 @@ templ Watchlist(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if viewLayout == "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) }
|
||||
<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(int(entry.AnimeID))) }
|
||||
class="flex flex-col bg-transparent text-inherit no-underline"
|
||||
>
|
||||
<a
|
||||
href={ templ.URL(shared.AnimeURL(int(entry.AnimeID))) }
|
||||
class="flex flex-col bg-transparent text-inherit no-underline"
|
||||
>
|
||||
<div class="relative 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 class="absolute inset-0 bg-black/0 transition-colors duration-200 group-hover:bg-black/40"></div>
|
||||
</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(int(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(int(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>
|
||||
}
|
||||
<div class="relative 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 class="absolute inset-0 bg-black/0 transition-colors duration-200 group-hover:bg-black/40"></div>
|
||||
</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>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user