aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Tools/Wrapped
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-01-03 22:05:24 -0800
committerFuwn <[email protected]>2024-01-03 22:05:24 -0800
commit1d0ffdba530fa166ac577ef1fba3b5a0a959959a (patch)
treed9264c043a7ee39d982654e88b766e51a217fe16 /src/lib/Tools/Wrapped
parentfeat(badges): put returns badges (diff)
downloaddue.moe-1d0ffdba530fa166ac577ef1fba3b5a0a959959a.tar.xz
due.moe-1d0ffdba530fa166ac577ef1fba3b5a0a959959a.zip
refactor(wrapped): move panels to components
Diffstat (limited to 'src/lib/Tools/Wrapped')
-rw-r--r--src/lib/Tools/Wrapped/ActivityHistory.svelte21
-rw-r--r--src/lib/Tools/Wrapped/Media.svelte98
-rw-r--r--src/lib/Tools/Wrapped/MediaExtras.svelte74
-rw-r--r--src/lib/Tools/Wrapped/Top/Activity.svelte43
-rw-r--r--src/lib/Tools/Wrapped/Top/Anime.svelte20
-rw-r--r--src/lib/Tools/Wrapped/Top/Manga.svelte22
-rw-r--r--src/lib/Tools/Wrapped/Watermark.svelte5
-rw-r--r--src/lib/Tools/Wrapped/wrapped.css100
8 files changed, 383 insertions, 0 deletions
diff --git a/src/lib/Tools/Wrapped/ActivityHistory.svelte b/src/lib/Tools/Wrapped/ActivityHistory.svelte
new file mode 100644
index 00000000..7c972eb9
--- /dev/null
+++ b/src/lib/Tools/Wrapped/ActivityHistory.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+ import type { ActivityHistoryEntry } from '$lib/AniList/activity';
+ import type { AniListAuthorisation } from '$lib/AniList/identity';
+ import ActivityHistoryGrid from '../ActivityHistory/Grid.svelte';
+
+ export let user: AniListAuthorisation;
+ export let activities: ActivityHistoryEntry[];
+ export let year: number;
+ export let activityHistoryPosition: 'TOP' | 'BELOW_TOP' | 'ORIGINAL';
+</script>
+
+<div
+ class="categories-grid"
+ style={`padding-${activityHistoryPosition === 'ORIGINAL' ? 'top' : 'bottom'}: 0;`}
+>
+ <div class="category-grid bottom-category pure-category category">
+ <div id="activity-history">
+ <ActivityHistoryGrid {user} activityData={activities} currentYear={year} />
+ </div>
+ </div>
+</div>
diff --git a/src/lib/Tools/Wrapped/Media.svelte b/src/lib/Tools/Wrapped/Media.svelte
new file mode 100644
index 00000000..08092a28
--- /dev/null
+++ b/src/lib/Tools/Wrapped/Media.svelte
@@ -0,0 +1,98 @@
+<script lang="ts">
+ import type { Media } from '$lib/AniList/media';
+ import type { Wrapped } from '$lib/AniList/wrapped';
+ import MediaTitleDisplay from '$lib/List/MediaTitleDisplay.svelte';
+ import proxy from '$lib/Utility/proxy';
+
+ export let animeList: Media[] | undefined;
+ export let mangaList: Media[] | undefined;
+ export let wrapped: Wrapped;
+ export let updateWidth: () => void;
+ export let highestRatedMediaPercentage: boolean;
+ export let highestRatedCount: number;
+ export let animeMostTitle: string;
+ export let mangaMostTitle: string;
+</script>
+
+{#if animeList !== undefined || mangaList !== undefined}
+ <div class="categories-grid">
+ <div class="category-grid pure-category category middle-category">
+ <div class="grid-item image-grid">
+ <a
+ href={animeList && animeList[0] ? `https://anilist.co/anime/${animeList[0].id}` : '#'}
+ target="_blank"
+ >
+ <img
+ src={proxy(
+ animeList && animeList[0] ? animeList[0].coverImage.extraLarge : wrapped.avatar.large
+ )}
+ alt="Highest Rated Anime Cover"
+ class="cover-image"
+ on:load={updateWidth}
+ />
+ </a>
+ <div>
+ <b>{animeMostTitle} Anime</b>
+ <ol>
+ {#if animeList !== undefined && animeList.length !== 0}
+ {#each animeList?.slice(0, highestRatedCount) as anime}
+ <li>
+ <a href={`https://anilist.co/anime/${anime.id}`} target="_blank">
+ <MediaTitleDisplay title={anime.title} />
+ </a>{highestRatedMediaPercentage &&
+ anime.mediaListEntry &&
+ anime.mediaListEntry?.score > 0
+ ? `: ${anime.mediaListEntry?.score}%`
+ : ''}
+ </li>
+ {/each}
+ {:else}
+ <li>
+ <p style="opacity: 50%;">(⌣_⌣”)</p>
+ </li>
+ {/if}
+ </ol>
+ </div>
+ </div>
+ </div>
+ <div class="category-grid pure-category category middle-category">
+ <div class="grid-item image-grid">
+ <a
+ href={mangaList && mangaList[0] ? `https://anilist.co/manga/${mangaList[0].id}` : '#'}
+ target="_blank"
+ >
+ <img
+ src={proxy(
+ mangaList && mangaList[0] ? mangaList[0].coverImage.extraLarge : wrapped.avatar.large
+ )}
+ alt="Highest Rated Manga Cover"
+ class="cover-image"
+ on:load={updateWidth}
+ />
+ </a>
+ <div>
+ <b>{mangaMostTitle} Manga</b>
+ <ol>
+ {#if mangaList !== undefined && mangaList.length !== 0}
+ {#each mangaList?.slice(0, highestRatedCount) as manga}
+ <li>
+ <a href={`https://anilist.co/manga/${manga.id}`} target="_blank">
+ <MediaTitleDisplay title={manga.title} />
+ </a>{highestRatedMediaPercentage &&
+ manga.mediaListEntry &&
+ manga.mediaListEntry?.score > 0
+ ? `: ${manga.mediaListEntry?.score}%`
+ : ''}
+ </li>
+ {/each}
+ {:else}
+ <li>
+ <p style="opacity: 50%;">(⌣_⌣”)</p>
+ </li>
+ {/if}
+ </ol>
+ </div>
+ </div>
+ </div>
+ </div>
+{/if}
diff --git a/src/lib/Tools/Wrapped/MediaExtras.svelte b/src/lib/Tools/Wrapped/MediaExtras.svelte
new file mode 100644
index 00000000..00417c54
--- /dev/null
+++ b/src/lib/Tools/Wrapped/MediaExtras.svelte
@@ -0,0 +1,74 @@
+<script lang="ts">
+ import type { TopMedia } from '$lib/AniList/wrapped';
+ import proxy from '$lib/Utility/proxy';
+
+ export let topMedia: TopMedia;
+ export let updateWidth: () => void;
+ export let highestRatedGenreTagPercentage: boolean;
+ export let genreTagTitle: string;
+</script>
+
+<div class="categories-grid" style="padding-top: 0;">
+ {#if topMedia.topGenreMedia && topMedia.genres.length > 0}
+ <div class="category-grid pure-category category">
+ <div class="grid-item image-grid">
+ <a
+ href={`https://anilist.co/${topMedia.topGenreMedia.type.toLowerCase()}/${
+ topMedia.topGenreMedia.id
+ }`}
+ target="_blank"
+ >
+ <img
+ src={proxy(topMedia.topGenreMedia.coverImage.extraLarge)}
+ alt="Highest Rated Genre Cover"
+ class="cover-image"
+ on:load={updateWidth}
+ />
+ </a>
+ <div>
+ <b>{genreTagTitle} Genres</b>
+ <ol>
+ {#each topMedia.genres as genre}
+ <li>
+ <a href={`https://anilist.co/search/anime?genres=${genre.genre}`} target="_blank">
+ {genre.genre}{highestRatedGenreTagPercentage ? `: ${genre.averageScore}%` : ''}
+ </a>
+ </li>
+ {/each}
+ </ol>
+ </div>
+ </div>
+ </div>
+ {/if}
+ {#if topMedia.topTagMedia && topMedia.tags.length > 0}
+ <div class="category-grid pure-category category">
+ <div class="grid-item image-grid">
+ <a
+ href={`https://anilist.co/${topMedia.topTagMedia.type.toLowerCase()}/${
+ topMedia.topTagMedia.id
+ }`}
+ target="_blank"
+ >
+ <img
+ src={proxy(topMedia.topTagMedia.coverImage.extraLarge)}
+ alt="Highest Rated Tag Cover"
+ class="cover-image"
+ on:load={updateWidth}
+ />
+ </a>
+ <div>
+ <b>{genreTagTitle} Tags</b>
+ <ol>
+ {#each topMedia.tags as tag}
+ <li>
+ <a href={`https://anilist.co/search/anime?genres=${tag.tag}`} target="_blank">
+ {tag.tag}{highestRatedGenreTagPercentage ? `: ${tag.averageScore}%` : ''}
+ </a>
+ </li>
+ {/each}
+ </ol>
+ </div>
+ </div>
+ </div>
+ {/if}
+</div>
diff --git a/src/lib/Tools/Wrapped/Top/Activity.svelte b/src/lib/Tools/Wrapped/Top/Activity.svelte
new file mode 100644
index 00000000..a000389c
--- /dev/null
+++ b/src/lib/Tools/Wrapped/Top/Activity.svelte
@@ -0,0 +1,43 @@
+<script lang="ts">
+ import type { ActivityHistoryEntry } from '$lib/AniList/activity';
+ import type { UserIdentity } from '$lib/AniList/identity';
+ import type { Wrapped } from '$lib/AniList/wrapped';
+ import proxy from '$lib/Utility/proxy';
+
+ export let wrapped: Wrapped;
+ export let identity: UserIdentity;
+ export let year: number;
+ export let activities: ActivityHistoryEntry[];
+ export let useFullActivityHistory: boolean;
+ export let updateWidth: () => void;
+
+ const currentYear = new Date(Date.now()).getFullYear();
+</script>
+
+<div class="grid-item image-grid avatar-grid category top-category">
+ <a href={`https://anilist.co/user/${identity.name}`} target="_blank">
+ <img src={proxy(wrapped.avatar.large)} alt="User Avatar" on:load={updateWidth} />
+ </a>
+ <div>
+ <div>
+ <a href={`https://anilist.co/user/${identity.name}`} target="_blank">
+ <b>
+ {identity.name}
+ </b>
+ </a>
+ </div>
+ <div>
+ Status Posts: {wrapped.activities.statusCount}
+ </div>
+ <div>
+ Messages: {wrapped.activities.messageCount}
+ </div>
+ <div>
+ Days Active: {#if year !== currentYear}
+ ?/365
+ {:else}
+ {activities.length}/{useFullActivityHistory ? 365 : 189}
+ {/if}
+ </div>
+ </div>
+</div>
diff --git a/src/lib/Tools/Wrapped/Top/Anime.svelte b/src/lib/Tools/Wrapped/Top/Anime.svelte
new file mode 100644
index 00000000..8ea1277f
--- /dev/null
+++ b/src/lib/Tools/Wrapped/Top/Anime.svelte
@@ -0,0 +1,20 @@
+<script lang="ts">
+ import type { Media } from '$lib/AniList/media';
+
+ export let minutesWatched: number;
+ export let animeList: Media[] | undefined;
+ export let episodes: number;
+</script>
+
+<div class="category-grid pure-category category top-category">
+ <div class="grid-item">
+ <b>Anime</b>
+ </div>
+ <div class="grid-item">
+ Time Watched: {((minutesWatched || 0) / 60 / 24).toFixed(2)} days
+ </div>
+ <div class="grid-item">
+ Completed: {animeList?.length || 0}
+ </div>
+ <div class="grid-item">Episodes: {episodes}</div>
+</div>
diff --git a/src/lib/Tools/Wrapped/Top/Manga.svelte b/src/lib/Tools/Wrapped/Top/Manga.svelte
new file mode 100644
index 00000000..b0d78b6e
--- /dev/null
+++ b/src/lib/Tools/Wrapped/Top/Manga.svelte
@@ -0,0 +1,22 @@
+<script lang="ts">
+ import type { Media } from '$lib/AniList/media';
+ import { estimatedDayReading } from '$lib/Media/Manga/time';
+
+ export let mangaList: Media[] | undefined;
+ export let chapters: number;
+</script>
+
+<div class="category-grid pure-category category top-category">
+ <div class="grid-item">
+ <b>Manga</b>
+ </div>
+ <div class="grid-item">
+ Time Read: {estimatedDayReading(chapters).toFixed(2)} days
+ </div>
+ <div class="grid-item">
+ Completed: {mangaList?.length || 0}
+ </div>
+ <div class="grid-item">
+ Chapters: {chapters}
+ </div>
+</div>
diff --git a/src/lib/Tools/Wrapped/Watermark.svelte b/src/lib/Tools/Wrapped/Watermark.svelte
new file mode 100644
index 00000000..2e8dd838
--- /dev/null
+++ b/src/lib/Tools/Wrapped/Watermark.svelte
@@ -0,0 +1,5 @@
+<div class="categories-grid" style="padding-top: 0;">
+ <div class="category-grid pure-category" id="watermark">
+ <a href="https://due.moe/wrapped" target="_blank">due.moe/wrapped</a>
+ </div>
+</div>
diff --git a/src/lib/Tools/Wrapped/wrapped.css b/src/lib/Tools/Wrapped/wrapped.css
new file mode 100644
index 00000000..1ac01d85
--- /dev/null
+++ b/src/lib/Tools/Wrapped/wrapped.css
@@ -0,0 +1,100 @@
+@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700');
+@import url('https://fonts.googleapis.com/css?family=Overpass:400,600,700,800');
+
+.categories-grid {
+ display: flex;
+ flex-wrap: wrap;
+ row-gap: 1.5em;
+ column-gap: 1.5em;
+ padding: 2%;
+ justify-content: center;
+ font-family: Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell,
+ Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ background-color: #0b1622;
+}
+
+.categories-grid b {
+ font-family: Overpass, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell,
+ Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ font-weight: 600;
+}
+
+.category-grid,
+.image-grid {
+ background-color: #151f2e;
+ border-radius: 4px;
+ color: rgb(159, 173, 189);
+}
+
+.pure-category,
+.avatar-grid {
+ padding: 1.5%;
+}
+
+.category-grid {
+ display: grid;
+}
+
+.image-grid {
+ display: flex;
+ column-gap: 1em;
+ flex-wrap: wrap;
+}
+
+.image-grid img {
+ width: 6em;
+ height: auto;
+ border-radius: 3px;
+}
+
+.categories-grid a {
+ text-decoration: none;
+ color: unset;
+}
+
+.transparent .categories-grid {
+ background-color: transparent !important;
+}
+
+.light-theme .categories-grid {
+ background-color: #edf1f5;
+}
+
+.light-theme .category-grid {
+ background-color: #fafafa;
+ color: rgb(92, 114, 138);
+}
+
+.light-theme .image-grid {
+ background-color: #fafafa;
+ color: rgb(92, 114, 138);
+}
+
+ol {
+ margin: 0 !important;
+}
+
+#watermark {
+ color: rgb(61, 180, 242);
+}
+
+#wrapped-final {
+ height: auto;
+ width: 50%;
+}
+
+#list-container {
+ display: flex;
+ gap: 1rem;
+ flex-wrap: wrap;
+ align-items: start;
+}
+
+.list {
+ flex-grow: 1;
+ flex-basis: 1%;
+}
+
+#wrapped {
+ overflow-y: scroll;
+}