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
This commit is contained in:
@@ -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") {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<StarInput bind:value={score} min={0} max={10} step={1} />
|
||||
<StarInput bind:value={score} min={0} max={10} step={1} name="rating" />
|
||||
<p>Rating: {score}</p>
|
||||
<p>{ratingInWords[score]}</p>
|
||||
</div>
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -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 <form> 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}
|
||||
>
|
||||
<div class="stars">
|
||||
{#if name !== undefined}
|
||||
<input type="hidden" name={name} value={value} />
|
||||
{/if}
|
||||
{#each Array(count) as _, i}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user