diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index ef73ced..bf75f42 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -6,20 +6,13 @@ interface FetchOptions extends RequestInit { export async function fetchApi(endpoint: string, options: FetchOptions = {}): Promise { const { params = {}, token, ...fetchOptions } = options; - const url = new URL(`${window.location.origin}/api${endpoint}`); - Object.keys(params).forEach((key) => url.searchParams.append(key, params[key])); + const base = `/api${endpoint}`; + const query = new URLSearchParams(params).toString(); + const url = query ? `${base}${base.includes("?") ? "&" : "?"}${query}` : base; - const init = { - headers: { - ...fetchOptions.headers, - }, - ...fetchOptions, - }; + const init: RequestInit = { ...fetchOptions }; if (token) { - init.headers = { - ...init.headers, - Authorization: `Basic ${token}`, - }; + init.headers = { ...init.headers, Authorization: `Basic ${token}` }; } return await fetch(url, init); } diff --git a/web/src/lib/components/LabeledCheckbox.svelte b/web/src/lib/components/LabeledCheckbox.svelte index 0e0b80a..69f8c8c 100644 --- a/web/src/lib/components/LabeledCheckbox.svelte +++ b/web/src/lib/components/LabeledCheckbox.svelte @@ -13,19 +13,17 @@ - {#snippet children({ checked })} - - {labelText} - -
+ {labelText} + +
+
- {/snippet} + > +
diff --git a/web/src/lib/components/PatchesStats.svelte b/web/src/lib/components/PatchesStats.svelte index d88a556..5408b4b 100644 --- a/web/src/lib/components/PatchesStats.svelte +++ b/web/src/lib/components/PatchesStats.svelte @@ -73,7 +73,7 @@
- {#if !data?.total} + {#if !data}
Loading statistics... @@ -111,8 +111,15 @@ Time Spent: {Duration.fromISO(data.timeSpent).toHuman()}
-
-
+
+
diff --git a/web/src/lib/components/PatchesTable.svelte b/web/src/lib/components/PatchesTable.svelte index de9e6f3..b781183 100644 --- a/web/src/lib/components/PatchesTable.svelte +++ b/web/src/lib/components/PatchesTable.svelte @@ -67,6 +67,3 @@
- - diff --git a/web/src/lib/components/settings-popover/SettingsPopoverGroup.svelte b/web/src/lib/components/settings-popover/SettingsPopoverGroup.svelte index a8a2517..415b112 100644 --- a/web/src/lib/components/settings-popover/SettingsPopoverGroup.svelte +++ b/web/src/lib/components/settings-popover/SettingsPopoverGroup.svelte @@ -1,6 +1,3 @@ - - -{#snippet renderChildren()} - {#if children} - {@render children()} - {/if} -{/snippet} -
{title} - {@render renderChildren()} + {@render children?.()}
diff --git a/web/src/lib/index.svelte.ts b/web/src/lib/index.svelte.ts index d500457..b04d908 100644 --- a/web/src/lib/index.svelte.ts +++ b/web/src/lib/index.svelte.ts @@ -53,9 +53,9 @@ export class PatchRouletteState { return; } - const patchResponse = await fetchApi(`/get-all-patches?minecraftVersion=${mcVersion}`, { + const patchResponse = await fetchApi(`/get-all-patches?minecraftVersion=${encodeURIComponent(mcVersion)}`, { method: "GET", - token: localStorage.getItem("token")!, + token: token.value ?? undefined, }); if (patchResponse.ok) { @@ -64,9 +64,9 @@ export class PatchRouletteState { alert("Failed to fetch patches. Please try again."); } - const statsResponse = await fetchApi(`/stats?minecraftVersion=${mcVersion}`, { + const statsResponse = await fetchApi(`/stats?minecraftVersion=${encodeURIComponent(mcVersion)}`, { method: "GET", - token: localStorage.getItem("token")!, + token: token.value ?? undefined, }); if (statsResponse.ok) { diff --git a/web/src/lib/theme.svelte.ts b/web/src/lib/theme.svelte.ts index af1fd00..d9015f3 100644 --- a/web/src/lib/theme.svelte.ts +++ b/web/src/lib/theme.svelte.ts @@ -18,6 +18,7 @@ function initialTheme() { return "auto"; } +// Module state is safe here only because the app is fully prerendered; revisit if SSR is introduced. let theme: Theme = $state(initialTheme()); const prefersDark = new MediaQuery("prefers-color-scheme: dark"); diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index 20fe11c..53a8e67 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -33,23 +33,15 @@ } } - async function handleVersionSelect(event: Event) { - instance.selectedVersion = (event.target as HTMLSelectElement).value; - if (instance.selectedVersion === "" || instance.selectedVersion === null) { - return; - } else if (instance.selectedVersion) { - await instance.onVersionSelect((event.target as HTMLSelectElement).value); + function handleVersionSelect() { + if (instance.selectedVersion) { + instance.onVersionSelect(instance.selectedVersion); } } onMount(async () => { token.value = localStorage.getItem("token"); - if (token.value === null) { - await goto(resolve("/login")); - return; - } - await loadMinecraftVersions(); if (minecraftVersions.length > 0) { @@ -92,6 +84,7 @@