From e2c8ba10ce7c7d37bdb0361c5796ad2fb9397c0e Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Wed, 16 Sep 2026 16:30:23 -0400 Subject: [PATCH] fix(frontend): submit-time data flow (rating scale, table reactivity) - rating submitted doubled: the * 2 belonged to the retired 0-5 slider scale while StarInput already works in backend 0-10 units, so every rating arrived doubled (9 became 18, both backends rejected it); form value now passes through unscaled, display and words map already native 0-10 - StarInput gains an optional name prop rendering a hidden input, restoring the rating form field the old slider exposed; Rating passes name="rating" - table updates go immutable (new array every path): in-place mutation with the same reference never reliably invalidated the Svelte 5 $derived, which left the grid stale after successful submits; replace-or-append semantics unchanged - per-page dropdown reads the event value synchronously (Svelte 5 nulls currentTarget after dispatch, crashing the old read-inside-.then) - detail poster column shares a flex centering context so poster and stars align by construction at every width --- frontend/src/helperComponents/Anime.svelte | 4 +++- .../src/helperComponents/Pagination.svelte | 16 +++++++------- frontend/src/helperComponents/Rating.svelte | 2 +- .../AddAnimeServiceToTable.svelte | 22 +++++++++---------- frontend/src/star-rating/StarInput.svelte | 8 +++++++ 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/frontend/src/helperComponents/Anime.svelte b/frontend/src/helperComponents/Anime.svelte index 4010694..98dfd43 100644 --- a/frontend/src/helperComponents/Anime.svelte +++ b/frontend/src/helperComponents/Anime.svelte @@ -169,7 +169,9 @@ for (let field of formData) { const [key, value] = field; if (key === "rating") { - submitData.rating = Number(value) * 2; + // Form value is already 0-10 (StarInput works in backend units). + // The old * 2 belonged to the retired 0-5 slider scale. + submitData.rating = Number(value); continue; } if (key === "episodes") { diff --git a/frontend/src/helperComponents/Pagination.svelte b/frontend/src/helperComponents/Pagination.svelte index 8112989..46c8b8c 100644 --- a/frontend/src/helperComponents/Pagination.svelte +++ b/frontend/src/helperComponents/Pagination.svelte @@ -43,14 +43,14 @@ function changeCountPerPage( e: Event & { currentTarget: HTMLSelectElement }, ): void { - App.GetAniListUserWatchingList(1, Number(e.currentTarget.value), sort).then( - (result) => { - animePerPage.set(Number(e.currentTarget.value)); - watchListPage.set(1); - aniListWatchlist.set(result); - aniListLoggedIn.set(true); - }, - ); + // Read synchronously: Svelte 5 nulls currentTarget after dispatch. + const count = Number(e.currentTarget.value); + App.GetAniListUserWatchingList(1, count, sort).then((result) => { + animePerPage.set(count); + watchListPage.set(1); + aniListWatchlist.set(result); + aniListLoggedIn.set(true); + }); } diff --git a/frontend/src/helperComponents/Rating.svelte b/frontend/src/helperComponents/Rating.svelte index 64cc1ea..71f37d2 100644 --- a/frontend/src/helperComponents/Rating.svelte +++ b/frontend/src/helperComponents/Rating.svelte @@ -19,7 +19,7 @@
- +

Rating: {score}

{ratingInWords[score]}

diff --git a/frontend/src/helperModules/AddAnimeServiceToTable.svelte b/frontend/src/helperModules/AddAnimeServiceToTable.svelte index 3e4e433..a79f978 100644 --- a/frontend/src/helperModules/AddAnimeServiceToTable.svelte +++ b/frontend/src/helperModules/AddAnimeServiceToTable.svelte @@ -3,19 +3,19 @@ import { tableItems } from "./GlobalVariablesAndHelperFunctions.svelte" export function AddAnimeServiceToTable(animeItem: TableItem) { + // Always return a NEW array: in-place mutation with the same + // reference does not reliably invalidate $derived consumers + // under Svelte 5, which left the table stale after submits. tableItems.update((table) => { - if (table.length === 0) { - table.push(animeItem) - } else { - for (const [index, tableItem] of table.entries()) { - if(tableItem.service === animeItem.service) { - table[index] = animeItem - return table - } - } - table.push(animeItem) + const index = table.findIndex( + (tableItem) => tableItem.service === animeItem.service, + ); + if (index === -1) { + return [...table, animeItem]; } - return table + return table.map((tableItem, i) => + i === index ? animeItem : tableItem, + ); }) } \ No newline at end of file diff --git a/frontend/src/star-rating/StarInput.svelte b/frontend/src/star-rating/StarInput.svelte index 95afa20..70ca297 100644 --- a/frontend/src/star-rating/StarInput.svelte +++ b/frontend/src/star-rating/StarInput.svelte @@ -21,6 +21,7 @@ step = 0.5, count = 5, disabled = false, + name, starConfig = { size: 32, fillColor: '#F9ED4F', @@ -36,6 +37,10 @@ step?: number; count?: number; disabled?: boolean; + // When set, renders a hidden input so the value submits with a + // surrounding
via FormData (the old slider exposed + // name="rating" the same way). + name?: string; starConfig?: StarColors; onchange?: (value: number) => void; } = $props(); @@ -99,6 +104,9 @@ onmouseleave={onHoverLeave} >
+ {#if name !== undefined} + + {/if} {#each Array(count) as _, i}