From 8d5d8ac2d7e51d8c3c4ec880f50dbd8a4c1248dd Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Wed, 16 Sep 2026 14:00:17 -0400 Subject: [PATCH] refactor(frontend): flowbite-svelte v1 APIs, bindings-aligned store types flowbite-svelte v1 turns components into runes: on:click on components becomes onclick props (native elements keep on:), Modal footers become {#snippet footer()}, Button["color"] indexing becomes the exported ButtonProps type, and slate is gone from the color union so the datepicker greys map to gray. Stores now use the generated bindings models (what the Go backend actually returns) instead of hand-written shapes that drifted from them - nullability of genres/tags/mediaList included. That single move clears most of the newly surfaced type errors, including the optional episodes/nextAiringEpisode cluster. The rest is strictness debt the old red check masked: definite-assignment on subscribe-fed lets, null guards on querySelector/match results and date parsing (two of which fixed latent throw-on-garbage paths), aria-labels on icon-only buttons, the completed default-data literal, and a shared flex centering context for the detail poster column so poster and stars align by construction at every width. --- frontend/src/helperComponents/Anime.svelte | 58 ++++++++++++------- .../src/helperComponents/AvatarMenu.svelte | 20 +++---- .../src/helperComponents/Datepicker.svelte | 29 +++++----- .../src/helperComponents/ErrorModal.svelte | 18 +++--- frontend/src/helperComponents/Header.svelte | 9 +-- .../src/helperComponents/Pagination.svelte | 6 +- frontend/src/helperComponents/Sort.svelte | 2 +- .../src/helperComponents/WatchList.svelte | 4 +- .../src/helperComponents/WebsiteLink.svelte | 2 +- .../helperDefaults/AniListGetSingleAnime.ts | 38 +++++++++++- .../helperFunctions/convertAniListDateIn.ts | 4 +- .../helperFunctions/convertDateToAniList.ts | 7 +++ ...ckIfAniListLoggedInAndLoadWatchList.svelte | 2 +- .../CheckIfMyAnimeListLoggedIn.svelte | 2 +- .../GlobalVariablesAndHelperFunctions.svelte | 30 ++++------ frontend/src/routes/Home.svelte | 2 +- 16 files changed, 144 insertions(+), 89 deletions(-) diff --git a/frontend/src/helperComponents/Anime.svelte b/frontend/src/helperComponents/Anime.svelte index fa0b091..4010694 100644 --- a/frontend/src/helperComponents/Anime.svelte +++ b/frontend/src/helperComponents/Anime.svelte @@ -11,22 +11,22 @@ } from "../helperModules/GlobalVariablesAndHelperFunctions.svelte"; import { push } from "svelte-spa-router"; import WebsiteLink from "./WebsiteLink.svelte"; - import type { AniListGetSingleAnime } from "../anilist/types/AniListCurrentUserWatchListType"; + import type { + AniListGetSingleAnime, + AniListUpdateVariables, + MALAnime, + MalListStatus, + MALUploadStatus, + SimklAnime, + } from "../../bindings/AniTrack/models"; import Rating from "./Rating.svelte"; import { convertAniListDateToString, convertAniListDateToDate, } from "../helperFunctions/convertAniListDateIn"; import AnimeTable from "./AnimeTable.svelte"; - import type { - MALAnime, - MalListStatus, - MALUploadStatus, - } from "../mal/types/MALTypes"; - import type { SimklAnime } from "../simkl/types/simklTypes"; import { writable } from "svelte/store"; import type { StatusOption, StatusOptions } from "../helperTypes/StatusTypes"; - import type { AniListUpdateVariables } from "../anilist/types/AniListTypes"; import { convertDateToAniList } from "../helperFunctions/convertDateToAniList"; import {App} from "../../bindings/AniTrack"; import { AddAnimeServiceToTable } from "../helperModules/AddAnimeServiceToTable.svelte"; @@ -35,12 +35,12 @@ import { Badge, Tooltip } from "flowbite-svelte"; const re = /^([0-9]{4})-([0-9]{2})-([0-9]{2})/; - let isAniListLoggedIn: boolean; - let isMalLoggedIn: boolean; - let isSimklLoggedIn: boolean; - let currentAniListAnime: AniListGetSingleAnime; - let currentMalAnime: MALAnime; - let currentSimklAnime: SimklAnime; + let isAniListLoggedIn!: boolean; + let isMalLoggedIn!: boolean; + let isSimklLoggedIn!: boolean; + let currentAniListAnime!: AniListGetSingleAnime; + let currentMalAnime!: MALAnime; + let currentSimklAnime!: SimklAnime; let submitting = writable(false); let isSubmitting: boolean; let submitSuccess = writable(false); @@ -103,11 +103,15 @@ let finishDate = ""; if (currentMalAnime.my_list_status.start_date !== "") { const startArray = re.exec(currentMalAnime.my_list_status.start_date); - startDate = `${startArray[2]}-${startArray[3]}-${startArray[1]}`; + if (startArray) { + startDate = `${startArray[2]}-${startArray[3]}-${startArray[1]}`; + } } if (currentMalAnime.my_list_status.finish_date !== "") { const finishArray = re.exec(currentMalAnime.my_list_status.finish_date); - finishDate = `${finishArray[2]}-${finishArray[3]}-${finishArray[1]}`; + if (finishArray) { + finishDate = `${finishArray[2]}-${finishArray[3]}-${finishArray[1]}`; + } } AddAnimeServiceToTable({ id: `m-${currentMalAnime.id}`, @@ -180,7 +184,11 @@ submitData.status = startingAnilistStatusOption; continue; } - submitData[key] = value; + // The only remaining form field is "notes" (string); anything else + // is ignored rather than assigned into a mistyped slot. + if (key === "notes" && typeof value === "string") { + submitData.notes = value; + } } try { @@ -271,13 +279,17 @@ const startArray = re.exec( currentMalAnime.my_list_status.start_date, ); - startDate = `${startArray[2]}-${startArray[3]}-${startArray[1]}`; + if (startArray) { + startDate = `${startArray[2]}-${startArray[3]}-${startArray[1]}`; + } } if (currentMalAnime.my_list_status.finish_date !== "") { const finishArray = re.exec( currentMalAnime.my_list_status.finish_date, ); - finishDate = `${finishArray[2]}-${finishArray[3]}-${finishArray[1]}`; + if (finishArray) { + finishDate = `${finishArray[2]}-${finishArray[3]}-${finishArray[1]}`; + } } AddAnimeServiceToTable({ id: `m-${currentMalAnime.id}`, @@ -503,7 +515,7 @@ {title}
-
+
{#if showActionButtons}
- - -
diff --git a/frontend/src/helperComponents/ErrorModal.svelte b/frontend/src/helperComponents/ErrorModal.svelte index 598d4d1..3a1b17f 100644 --- a/frontend/src/helperComponents/ErrorModal.svelte +++ b/frontend/src/helperComponents/ErrorModal.svelte @@ -61,13 +61,15 @@ dismiss this message to continue with limited functionality.

-
- {#if $apiError.canRetry} - - {/if} - -
+ {#snippet footer()} +
+ {#if $apiError.canRetry} + + {/if} + +
+ {/snippet} {/if} diff --git a/frontend/src/helperComponents/Header.svelte b/frontend/src/helperComponents/Header.svelte index 21dac39..c1aa211 100644 --- a/frontend/src/helperComponents/Header.svelte +++ b/frontend/src/helperComponents/Header.svelte @@ -13,9 +13,9 @@ import logo from "../assets/images/AniTrackLogo.svg"; import { link } from "svelte-spa-router"; - let isAniListLoggedIn: boolean; - let isSimklLoggedIn: boolean; - let isMALLoggedIn: boolean; + let isAniListLoggedIn!: boolean; + let isSimklLoggedIn!: boolean; + let isMALLoggedIn!: boolean; let loggingIn: string[] = []; aniListLoggedIn.subscribe((value) => (isAniListLoggedIn = value)); @@ -42,7 +42,8 @@