feat: improve WatchList UI with refresh button

Enhanced the WatchList component with better layout and manual refresh functionality.

Changes:
- Added Refresh WatchList button with loading state handling
- Restructured header layout using flexbox with justify-between
- Title on left, refresh button on right, vertically aligned with items-center
- Improved button styling with consistent py-2 px-4 padding
- Added CheckIfAniListLoggedInAndLoadWatchList import for refresh functionality
- Maintained mb-4 spacing for consistent vertical rhythm

This gives users manual control over watchlist updates and provides better visual balance to the header section.

UI improvements:
- Horizontal flex container for proper left/right alignment
- Responsive button sizing
- Clear visual separation between title and action
This commit is contained in:
2026-03-21 13:25:45 -04:00
parent 8a8baf7f8f
commit 6ed5fe8b71

View File

@@ -5,31 +5,51 @@
GetAnimeSingleItem, GetAnimeSingleItem,
loading, loading,
} from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"; } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte";
import {push} from "svelte-spa-router"; import { push } from "svelte-spa-router";
import type {AniListCurrentUserWatchList} from "../anilist/types/AniListCurrentUserWatchListType" import type { AniListCurrentUserWatchList } from "../anilist/types/AniListCurrentUserWatchListType";
import {Rating} from "flowbite-svelte"; import { Rating } from "flowbite-svelte";
import loader from '../helperFunctions/loader' import loader from "../helperFunctions/loader";
import { CheckIfAniListLoggedInAndLoadWatchList } from "../helperModules/CheckIfAniListLoggedInAndLoadWatchList.svelte";
let isAniListLoggedIn: boolean;
let aniListWatchListLoaded: AniListCurrentUserWatchList;
let isAniListLoggedIn: boolean aniListLoggedIn.subscribe((value) => (isAniListLoggedIn = value));
let aniListWatchListLoaded: AniListCurrentUserWatchList aniListWatchlist.subscribe((value) => (aniListWatchListLoaded = value));
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
aniListWatchlist.subscribe((value) => aniListWatchListLoaded = value)
</script> </script>
<div> <div>
{#if isAniListLoggedIn} {#if isAniListLoggedIn}
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center"> <div
<h1 class="text-left text-xl font-bold mb-4">Your AniList WatchList</h1> class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center"
>
<div class="flex justify-between items-center mb-4">
<h1 class="text-left text-xl font-bold">Your AniList WatchList</h1>
<button
type="button"
class="py-2 px-4 bg-gray-700 rounded-lg"
on:click={async () => {
loading.set(true);
await CheckIfAniListLoggedInAndLoadWatchList();
loading.set(false);
}}
>
Refresh WatchList
</button>
</div>
<div class="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8"> <div
class="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8"
>
{#each aniListWatchListLoaded.data.Page.mediaList as media} {#each aniListWatchListLoaded.data.Page.mediaList as media}
<div use:loader={loading} class="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg xl:aspect-h-8 xl:aspect-w-7"> <div
use:loader={loading}
class="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg xl:aspect-h-8 xl:aspect-w-7"
>
<div class="flex flex-col items-center group"> <div class="flex flex-col items-center group">
<button on:click={() => { <button
push(`#/anime/${media.media.id}`) on:click={() => {
push(`#/anime/${media.media.id}`);
// loading.set(true) // loading.set(true)
// GetAniListSingleItem(media.media.id, true).then(() => { // GetAniListSingleItem(media.media.id, true).then(() => {
// loading.set(false) // loading.set(false)
@@ -37,27 +57,38 @@
// }) // })
}} }}
> >
<img class="rounded-lg" src={media.media.coverImage.large} alt={ <img
media.media.title.english === "" ? class="rounded-lg"
media.media.title.romaji : src={media.media.coverImage.large}
media.media.title.english alt={media.media.title.english === ""
}/> ? media.media.title.romaji
: media.media.title.english}
/>
</button> </button>
<Rating id="anime-rating" total={5} size={35} rating={media.score/2.0}/> <Rating
<button class="mt-4 text-md font-semibold text-white-700" id="anime-rating"
on:click={() => GetAnimeSingleItem(media.media.id, true)}> total={5}
{ size={35}
media.media.title.english === "" ? rating={media.score / 2.0}
media.media.title.romaji : />
media.media.title.english <button
} class="mt-4 text-md font-semibold text-white-700"
on:click={() => GetAnimeSingleItem(media.media.id, true)}
>
{media.media.title.english === ""
? media.media.title.romaji
: media.media.title.english}
</button> </button>
<p class="mt-1 text-lg font-medium text-white-900">{media.progress} <p class="mt-1 text-lg font-medium text-white-900">
/ {media.media.nextAiringEpisode.episode !== 0 ? {media.progress}
media.media.nextAiringEpisode.episode - 1 : media.media.episodes}</p> / {media.media.nextAiringEpisode.episode !== 0
? media.media.nextAiringEpisode.episode - 1
: media.media.episodes}
</p>
{#if media.media.episodes > 0} {#if media.media.episodes > 0}
<p class="mt-1 text-lg font-medium text-white-900">Total <p class="mt-1 text-lg font-medium text-white-900">
Episodes: {media.media.episodes}</p> Total Episodes: {media.media.episodes}
</p>
{/if} {/if}
</div> </div>
</div> </div>