chore: clear the mechanical lint and type findings
Dead imports and locals removed, each blocks keyed, `any` narrowed to unknown. Two context setters kept their calls and lost only the unused binding; the settings redirect no longer awaits a parent whose data it discards. A leading underscore now marks a binding that only holds a position.
This commit is contained in:
@@ -28,7 +28,18 @@ export default defineConfig(
|
|||||||
rules: {
|
rules: {
|
||||||
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
|
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
|
||||||
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
|
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
|
||||||
'no-undef': 'off'
|
'no-undef': 'off',
|
||||||
|
// A leading underscore marks a binding that exists to hold a position — a callback
|
||||||
|
// parameter the signature requires, or the discarded half of a destructure.
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
argsIgnorePattern: '^_',
|
||||||
|
varsIgnorePattern: '^_',
|
||||||
|
caughtErrorsIgnorePattern: '^_',
|
||||||
|
destructuredArrayIgnorePattern: '^_'
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { BACKEND_API_URL } from '$lib/server/config';
|
|||||||
import { invalid, redirect } from '@sveltejs/kit';
|
import { invalid, redirect } from '@sveltejs/kit';
|
||||||
|
|
||||||
export const login = form(loginSchema, async (data, issue) => {
|
export const login = form(loginSchema, async (data, issue) => {
|
||||||
const { cookies, locals } = getRequestEvent();
|
const { cookies } = getRequestEvent();
|
||||||
|
|
||||||
// Create URL-encoded form data
|
// Create URL-encoded form data
|
||||||
const formData = new URLSearchParams();
|
const formData = new URLSearchParams();
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ export const createLibrary = form(libraryCreateSchema, async (data) => {
|
|||||||
return await response.json();
|
return await response.json();
|
||||||
});
|
});
|
||||||
|
|
||||||
export const deleteLibrary = query('unchecked', async (data) => {
|
export const deleteLibrary = query('unchecked', async (_data) => {
|
||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
import { Checkbox } from '$lib/components/ui/checkbox/index.js';
|
import { Checkbox } from '$lib/components/ui/checkbox/index.js';
|
||||||
import { Button } from '$lib/components/ui/button/index.js';
|
import { Button } from '$lib/components/ui/button/index.js';
|
||||||
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
||||||
import { getBookSelectionState } from '$lib/state/bookSelection.svelte';
|
|
||||||
import { getBookOperationsState } from '$lib/state/bookOperations.svelte';
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
open = $bindable(),
|
open = $bindable(),
|
||||||
@@ -16,9 +14,6 @@
|
|||||||
deleteFn: (deleteFiles: boolean) => void | Promise<void>;
|
deleteFn: (deleteFiles: boolean) => void | Promise<void>;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
const selectedState = getBookSelectionState();
|
|
||||||
const bookOps = getBookOperationsState();
|
|
||||||
|
|
||||||
let deleteFiles = $state(false);
|
let deleteFiles = $state(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="name">Device name</Field.Label>
|
<Field.Label for="name">Device name</Field.Label>
|
||||||
<Input {...createDevice.fields.name.as('text')} placeholder="e.g. Kindle Paperwhite" />
|
<Input {...createDevice.fields.name.as('text')} placeholder="e.g. Kindle Paperwhite" />
|
||||||
{#each createDevice.fields.name.issues() ?? [] as issue}
|
{#each createDevice.fields.name.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
|
|||||||
@@ -128,7 +128,7 @@
|
|||||||
<Field.Field class="col-span-full">
|
<Field.Field class="col-span-full">
|
||||||
<Field.Label for="title">Title</Field.Label>
|
<Field.Label for="title">Title</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.title.as('text')} />
|
<Input {...updateBookMetadata.fields.title.as('text')} />
|
||||||
{#each updateBookMetadata.fields.title.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.title.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="subtitle">Subtitle</Field.Label>
|
<Field.Label for="subtitle">Subtitle</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.subtitle.as('text')} />
|
<Input {...updateBookMetadata.fields.subtitle.as('text')} />
|
||||||
{#each updateBookMetadata.fields.subtitle.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.subtitle.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="edition">Edition</Field.Label>
|
<Field.Label for="edition">Edition</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.edition.as('number')} />
|
<Input {...updateBookMetadata.fields.edition.as('number')} />
|
||||||
{#each updateBookMetadata.fields.edition.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.edition.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="series">Series</Field.Label>
|
<Field.Label for="series">Series</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.series.as('text')} />
|
<Input {...updateBookMetadata.fields.series.as('text')} />
|
||||||
{#each updateBookMetadata.fields.series.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.series.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="series_position">No.</Field.Label>
|
<Field.Label for="series_position">No.</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.series_position.as('text')} />
|
<Input {...updateBookMetadata.fields.series_position.as('text')} />
|
||||||
{#each updateBookMetadata.fields.series_position.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.series_position.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -169,7 +169,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="language">Language</Field.Label>
|
<Field.Label for="language">Language</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.language.as('text')} />
|
<Input {...updateBookMetadata.fields.language.as('text')} />
|
||||||
{#each updateBookMetadata.fields.language.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.language.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -185,10 +185,10 @@
|
|||||||
placeholder="Add an author"
|
placeholder="Add an author"
|
||||||
class="min-h-10 p-2 text-sm"
|
class="min-h-10 p-2 text-sm"
|
||||||
/>
|
/>
|
||||||
{#each authors as author}
|
{#each authors as author, i (i)}
|
||||||
<input class="hidden" {...updateBookMetadata.fields.authors.as('checkbox', author)} />
|
<input class="hidden" {...updateBookMetadata.fields.authors.as('checkbox', author)} />
|
||||||
{/each}
|
{/each}
|
||||||
{#each updateBookMetadata.fields.authors.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.authors.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -201,10 +201,10 @@
|
|||||||
placeholder="Add a tag"
|
placeholder="Add a tag"
|
||||||
class="min-h-10 p-2 text-sm"
|
class="min-h-10 p-2 text-sm"
|
||||||
/>
|
/>
|
||||||
{#each tags as tag}
|
{#each tags as tag, i (i)}
|
||||||
<input class="hidden" {...updateBookMetadata.fields.tags.as('checkbox', tag)} />
|
<input class="hidden" {...updateBookMetadata.fields.tags.as('checkbox', tag)} />
|
||||||
{/each}
|
{/each}
|
||||||
{#each updateBookMetadata.fields.tags.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.tags.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="publisher">Publisher</Field.Label>
|
<Field.Label for="publisher">Publisher</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.publisher.as('text')} />
|
<Input {...updateBookMetadata.fields.publisher.as('text')} />
|
||||||
{#each updateBookMetadata.fields.publisher.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.publisher.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="published_date">Published</Field.Label>
|
<Field.Label for="published_date">Published</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.published_date.as('date')} />
|
<Input {...updateBookMetadata.fields.published_date.as('date')} />
|
||||||
{#each updateBookMetadata.fields.published_date.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.published_date.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="pages">Pages</Field.Label>
|
<Field.Label for="pages">Pages</Field.Label>
|
||||||
<Input {...updateBookMetadata.fields.pages.as('number')} />
|
<Input {...updateBookMetadata.fields.pages.as('number')} />
|
||||||
{#each updateBookMetadata.fields.pages.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.pages.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -240,7 +240,7 @@
|
|||||||
<Field.Field class="col-span-full">
|
<Field.Field class="col-span-full">
|
||||||
<Field.Label for="identifiers">Identifiers</Field.Label>
|
<Field.Label for="identifiers">Identifiers</Field.Label>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
{#each identifierKeys as _, idx}
|
{#each identifierKeys as _, idx (idx)}
|
||||||
<div class="grid grid-cols-[1fr_1.6fr_auto] gap-2">
|
<div class="grid grid-cols-[1fr_1.6fr_auto] gap-2">
|
||||||
<Input bind:value={identifierKeys[idx]} placeholder="ISBN, DOI…" />
|
<Input bind:value={identifierKeys[idx]} placeholder="ISBN, DOI…" />
|
||||||
<Input bind:value={identifierValues[idx]} placeholder="Value" />
|
<Input bind:value={identifierValues[idx]} placeholder="Value" />
|
||||||
@@ -271,7 +271,7 @@
|
|||||||
<Field.Field class="col-span-full">
|
<Field.Field class="col-span-full">
|
||||||
<Field.Label for="description" class="sr-only">Description</Field.Label>
|
<Field.Label for="description" class="sr-only">Description</Field.Label>
|
||||||
<Textarea {...updateBookMetadata.fields.description.as('text')} rows={6} />
|
<Textarea {...updateBookMetadata.fields.description.as('text')} rows={6} />
|
||||||
{#each updateBookMetadata.fields.description.issues() ?? [] as issue}
|
{#each updateBookMetadata.fields.description.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="name">Library name</Field.Label>
|
<Field.Label for="name">Library name</Field.Label>
|
||||||
<Input {...createLibrary.fields.name.as('text')} />
|
<Input {...createLibrary.fields.name.as('text')} />
|
||||||
{#each createLibrary.fields.name.issues() ?? [] as issue}
|
{#each createLibrary.fields.name.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="description">Description</Field.Label>
|
<Field.Label for="description">Description</Field.Label>
|
||||||
<Textarea {...createLibrary.fields.description.as('text')} />
|
<Textarea {...createLibrary.fields.description.as('text')} />
|
||||||
{#each createLibrary.fields.description.issues() ?? [] as issue}
|
{#each createLibrary.fields.description.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="root_path">Root Path</Field.Label>
|
<Field.Label for="root_path">Root Path</Field.Label>
|
||||||
<Input {...createLibrary.fields.root_path.as('text')} />
|
<Input {...createLibrary.fields.root_path.as('text')} />
|
||||||
{#each createLibrary.fields.root_path.issues() ?? [] as issue}
|
{#each createLibrary.fields.root_path.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
<Field.Description class="text-xs">
|
<Field.Description class="text-xs">
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="path_template">Path Template</Field.Label>
|
<Field.Label for="path_template">Path Template</Field.Label>
|
||||||
<Input {...createLibrary.fields.path_template.as('text')} />
|
<Input {...createLibrary.fields.path_template.as('text')} />
|
||||||
{#each createLibrary.fields.path_template.issues() ?? [] as issue}
|
{#each createLibrary.fields.path_template.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
<Field.Description class="text-xs">
|
<Field.Description class="text-xs">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="email">Email</Field.Label>
|
<Field.Label for="email">Email</Field.Label>
|
||||||
<Input {...login.fields.email.as('email')} />
|
<Input {...login.fields.email.as('email')} />
|
||||||
{#each login.fields.email.issues() ?? [] as issue}
|
{#each login.fields.email.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="password">Password</Field.Label>
|
<Field.Label for="password">Password</Field.Label>
|
||||||
<Input {...login.fields.password.as('password')} />
|
<Input {...login.fields.password.as('password')} />
|
||||||
{#each login.fields.password.issues() ?? [] as issue}
|
{#each login.fields.password.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="email">Email</Field.Label>
|
<Field.Label for="email">Email</Field.Label>
|
||||||
<Input {...signup.fields.email.as('email')} />
|
<Input {...signup.fields.email.as('email')} />
|
||||||
{#each signup.fields.email.issues() ?? [] as issue}
|
{#each signup.fields.email.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="password">Password</Field.Label>
|
<Field.Label for="password">Password</Field.Label>
|
||||||
<Input {...signup.fields.password.as('password')} />
|
<Input {...signup.fields.password.as('password')} />
|
||||||
{#each signup.fields.password.issues() ?? [] as issue}
|
{#each signup.fields.password.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<Field.Field>
|
<Field.Field>
|
||||||
<Field.Label for="confirmPassword">Confirm Password</Field.Label>
|
<Field.Label for="confirmPassword">Confirm Password</Field.Label>
|
||||||
<Input {...signup.fields.confirmPassword.as('password')} />
|
<Input {...signup.fields.confirmPassword.as('password')} />
|
||||||
{#each signup.fields.confirmPassword.issues() ?? [] as issue}
|
{#each signup.fields.confirmPassword.issues() ?? [] as issue, i (i)}
|
||||||
<Field.Error>{issue.message}</Field.Error>
|
<Field.Error>{issue.message}</Field.Error>
|
||||||
{/each}
|
{/each}
|
||||||
</Field.Field>
|
</Field.Field>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
||||||
import { useSidebar } from '$lib/components/ui/sidebar/index.js';
|
import { useSidebar } from '$lib/components/ui/sidebar/index.js';
|
||||||
import { Badge } from '$lib/components/ui/badge/index.js';
|
import { Badge } from '$lib/components/ui/badge/index.js';
|
||||||
import { getLibraryState, LibraryState } from '$lib/state/library.svelte';
|
import { getLibraryState } from '$lib/state/library.svelte';
|
||||||
import { LIBRARY_ICONS } from '$lib/components/ui/icon-picker/index.js';
|
import { LIBRARY_ICONS } from '$lib/components/ui/icon-picker/index.js';
|
||||||
import ChevronsUpDownIcon from '@lucide/svelte/icons/chevrons-up-down';
|
import ChevronsUpDownIcon from '@lucide/svelte/icons/chevrons-up-down';
|
||||||
import PlusIcon from '@lucide/svelte/icons/plus';
|
import PlusIcon from '@lucide/svelte/icons/plus';
|
||||||
|
|||||||
@@ -53,9 +53,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClick(e: any) {
|
function handleClick(e: Event & { currentTarget: HTMLElement }) {
|
||||||
open = true;
|
open = true;
|
||||||
e.target.blur();
|
e.currentTarget.blur();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Command.List class="max-h-[600px]">
|
<Command.List class="max-h-[600px]">
|
||||||
{#if searchResult?.items.length > 0}
|
{#if (searchResult?.items?.length ?? 0) > 0}
|
||||||
<Command.Group heading="Books">
|
<Command.Group heading="Books">
|
||||||
{#each searchResult?.items as book (book.id)}
|
{#each searchResult?.items as book (book.id)}
|
||||||
<Command.Item
|
<Command.Item
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
{#if book.authors.length > 0}
|
{#if book.authors.length > 0}
|
||||||
<span class="line-clamp-1 w-full text-sm text-muted-foreground">
|
<span class="line-clamp-1 w-full text-sm text-muted-foreground">
|
||||||
by
|
by
|
||||||
{#each book.authors as author}
|
{#each book.authors as author (author.id)}
|
||||||
<a
|
<a
|
||||||
href="{resolve('/(root)/(library)/library/[libraryId]/view', {
|
href="{resolve('/(root)/(library)/library/[libraryId]/view', {
|
||||||
libraryId: String(libraryState.activeLibrary!.id)
|
libraryId: String(libraryState.activeLibrary!.id)
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="mt-1 ml-[-1.5] flex">
|
<div class="mt-1 ml-[-1.5] flex">
|
||||||
{#each book.tags as tag}
|
{#each book.tags as tag (tag.id)}
|
||||||
<Badge class="scale-75">{tag.name}</Badge>
|
<Badge class="scale-75">{tag.name}</Badge>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import type { Book } from '$lib/schema';
|
import type { Book } from '$lib/schema';
|
||||||
import BookThumbnail from './book-thumbnail.svelte';
|
import BookThumbnail from './book-thumbnail.svelte';
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
import { getBookSelectionState } from '$lib/state/bookSelection.svelte';
|
import { getBookSelectionState } from '$lib/state/bookSelection.svelte';
|
||||||
import { getBookOperationsState } from '$lib/state/bookOperations.svelte';
|
import { getBookOperationsState } from '$lib/state/bookOperations.svelte';
|
||||||
import { getLibraryState } from '$lib/state/library.svelte';
|
import { getLibraryState } from '$lib/state/library.svelte';
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
let { src, fallback = '/images/default_cover.jpg', class: className = '' } = $props();
|
let { src, fallback = '/images/default_cover.jpg', class: className = '' } = $props();
|
||||||
|
|
||||||
async function handleError(e) {
|
/** @param {Event} e */
|
||||||
e.target.src = fallback;
|
function handleError(e) {
|
||||||
|
const img = /** @type {HTMLImageElement} */ (e.currentTarget);
|
||||||
|
img.src = fallback;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
import { resolve } from '$app/paths';
|
import { resolve } from '$app/paths';
|
||||||
import * as Table from '$lib/components/ui/table/index';
|
import * as Table from '$lib/components/ui/table/index';
|
||||||
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index';
|
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index';
|
||||||
import * as Tooltip from '$lib/components/ui/tooltip/index';
|
|
||||||
import { Checkbox } from '$lib/components/ui/checkbox/index';
|
import { Checkbox } from '$lib/components/ui/checkbox/index';
|
||||||
import { Badge } from '$lib/components/ui/badge/index';
|
import { Badge } from '$lib/components/ui/badge/index';
|
||||||
import { buttonVariants } from '$lib/components/ui/button/index.js';
|
import { buttonVariants } from '$lib/components/ui/button/index.js';
|
||||||
|
|||||||
@@ -2,12 +2,11 @@
|
|||||||
import { resolve } from '$app/paths';
|
import { resolve } from '$app/paths';
|
||||||
import BookImage from './book-image.svelte';
|
import BookImage from './book-image.svelte';
|
||||||
import GeneratedCover from './generated-cover.svelte';
|
import GeneratedCover from './generated-cover.svelte';
|
||||||
import { Progress } from '$lib/components/ui/progress/index';
|
|
||||||
import { getLibraryState } from '$lib/state/library.svelte';
|
import { getLibraryState } from '$lib/state/library.svelte';
|
||||||
import { getBookSelectionState } from '$lib/state/bookSelection.svelte';
|
import { getBookSelectionState } from '$lib/state/bookSelection.svelte';
|
||||||
import type { Book } from '$lib/schema';
|
import type { Book } from '$lib/schema';
|
||||||
|
|
||||||
let { book, class: className = '', ...rest }: { book: Book; class?: string } = $props();
|
let { book, class: className = '' }: { book: Book; class?: string } = $props();
|
||||||
|
|
||||||
const selectionState = getBookSelectionState();
|
const selectionState = getBookSelectionState();
|
||||||
const libraryState = getLibraryState();
|
const libraryState = getLibraryState();
|
||||||
@@ -78,7 +77,7 @@
|
|||||||
|
|
||||||
<!-- Authors list -->
|
<!-- Authors list -->
|
||||||
<p class="line-clamp-1 w-full text-xs text-muted-foreground">
|
<p class="line-clamp-1 w-full text-xs text-muted-foreground">
|
||||||
{#each book.authors as author}
|
{#each book.authors as author (author.id)}
|
||||||
<a
|
<a
|
||||||
href="{resolve('/(root)/(library)/library/[libraryId]/view', {
|
href="{resolve('/(root)/(library)/library/[libraryId]/view', {
|
||||||
libraryId: String(libraryState.activeLibrary?.id ?? '')
|
libraryId: String(libraryState.activeLibrary?.id ?? '')
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<Collapsible.Content class="h-full max-h-128 overflow-y-auto">
|
<Collapsible.Content class="h-full max-h-128 overflow-y-auto">
|
||||||
<Sidebar.GroupContent>
|
<Sidebar.GroupContent>
|
||||||
<Sidebar.Menu>
|
<Sidebar.Menu>
|
||||||
{#each filter.items as item, index (item.id)}
|
{#each filter.items as item (item.id)}
|
||||||
<Sidebar.MenuItem
|
<Sidebar.MenuItem
|
||||||
onclick={() => bookCollection.toggleFilter(filter.value, item.id.toString())}
|
onclick={() => bookCollection.toggleFilter(filter.value, item.id.toString())}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Content class="w-40">
|
<DropdownMenu.Content class="w-40">
|
||||||
<DropdownMenu.Group>
|
<DropdownMenu.Group>
|
||||||
{#each bookCollection.sortOptions as sortProp}
|
{#each bookCollection.sortOptions as sortProp (sortProp.value)}
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
onSelect={() => bookCollection.updateSort(sortProp.value)}
|
onSelect={() => bookCollection.updateSort(sortProp.value)}
|
||||||
class={bookCollection.orderBy === sortProp.value ? 'bg-muted' : ''}
|
class={bookCollection.orderBy === sortProp.value ? 'bg-muted' : ''}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ const emailSchema = z
|
|||||||
.email('Please enter a valid email address')
|
.email('Please enter a valid email address')
|
||||||
.max(255, 'Email address cannot exceed 255 characters');
|
.max(255, 'Email address cannot exceed 255 characters');
|
||||||
|
|
||||||
const usernameSchema = z.string().min(1, 'Email is required');
|
|
||||||
|
|
||||||
const basePasswordSchema = z.string().min(1, 'Password is required');
|
const basePasswordSchema = z.string().min(1, 'Password is required');
|
||||||
|
|
||||||
const strongPasswordSchema = z.string().min(8, 'Password must be at least 8 characters');
|
const strongPasswordSchema = z.string().min(8, 'Password must be at least 8 characters');
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import type { components } from './openapi/schema';
|
import type { components } from './openapi/schema';
|
||||||
import { commonQuerySchema, stringArrayCoerce, stringCoerce } from './common';
|
import { commonQuerySchema, stringArrayCoerce } from './common';
|
||||||
|
|
||||||
export type Author = components['schemas']['AuthorRead'];
|
export type Author = components['schemas']['AuthorRead'];
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const identifiersSchema = z
|
|||||||
.transform((str, ctx) => {
|
.transform((str, ctx) => {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(str);
|
return JSON.parse(str);
|
||||||
} catch (e) {
|
} catch {
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
code: 'custom',
|
code: 'custom',
|
||||||
message: 'Must be a valid JSON string'
|
message: 'Must be a valid JSON string'
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import type { components } from './openapi/schema';
|
import type { components } from './openapi/schema';
|
||||||
import { commonQuerySchema, stringArrayCoerce } from './common';
|
import { commonQuerySchema, stringArrayCoerce } from './common';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import type { components } from './openapi/schema';
|
import type { components } from './openapi/schema';
|
||||||
import { commonQuerySchema, stringArrayCoerce } from './common';
|
import { commonQuerySchema, stringArrayCoerce } from './common';
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class ApiClient {
|
|||||||
return this.request(endpoint);
|
return this.request(endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
async post(endpoint: string, data: any): Promise<Response> {
|
async post(endpoint: string, data: unknown): Promise<Response> {
|
||||||
return this.request(endpoint, {
|
return this.request(endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -48,7 +48,7 @@ export class ApiClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async put(endpoint: string, data: any): Promise<Response> {
|
async put(endpoint: string, data: unknown): Promise<Response> {
|
||||||
return this.request(endpoint, {
|
return this.request(endpoint, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -71,7 +71,7 @@ export class ApiClient {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patch(endpoint: string, data: any): Promise<Response> {
|
async patch(endpoint: string, data: unknown): Promise<Response> {
|
||||||
return this.request(endpoint, {
|
return this.request(endpoint, {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getContext, setContext } from 'svelte';
|
import { getContext, setContext } from 'svelte';
|
||||||
import { goto, pushState, replaceState } from '$app/navigation';
|
import { goto, replaceState } from '$app/navigation';
|
||||||
import type { Book, DynamicFilterData, FilterOption, PaginatedResponse } from '$lib/schema';
|
import type { Book, DynamicFilterData, FilterOption, PaginatedResponse } from '$lib/schema';
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { BookOperationsState } from './bookOperations.svelte';
|
import { BookOperationsState } from './bookOperations.svelte';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class BookOperationsState {
|
|||||||
// Delete dialog related state
|
// Delete dialog related state
|
||||||
deleteDialogOpen = $state(false);
|
deleteDialogOpen = $state(false);
|
||||||
deleteDialogTitle = $state('Delete books?');
|
deleteDialogTitle = $state('Delete books?');
|
||||||
deleteFn = $state((deleteFiles: boolean) => {});
|
deleteFn = $state((_deleteFiles: boolean) => {});
|
||||||
|
|
||||||
// Edit dialog related state
|
// Edit dialog related state
|
||||||
editDialogOpen = $state(false);
|
editDialogOpen = $state(false);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { goto, invalidate } from '$app/navigation';
|
import { invalidate } from '$app/navigation';
|
||||||
import { addBooksToShelf, createBookshelf, listBookshelves, removeBooksFromShelf } from '$lib/api';
|
import { addBooksToShelf, createBookshelf, listBookshelves, removeBooksFromShelf } from '$lib/api';
|
||||||
import type { Book, Bookshelf } from '$lib/schema';
|
import type { Book, Bookshelf } from '$lib/schema';
|
||||||
import { getContext, setContext } from 'svelte';
|
import { getContext, setContext } from 'svelte';
|
||||||
@@ -22,7 +22,7 @@ export class BookshelfState {
|
|||||||
|
|
||||||
async fetchBookshelves(libraryId: string) {
|
async fetchBookshelves(libraryId: string) {
|
||||||
try {
|
try {
|
||||||
let paginatedBookshelves = await listBookshelves({
|
const paginatedBookshelves = await listBookshelves({
|
||||||
libraries: [libraryId]
|
libraries: [libraryId]
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export class BookshelfState {
|
|||||||
|
|
||||||
async addBookshelf(name: string, libraryId?: string | number, booksToAdd?: string[] | number[]) {
|
async addBookshelf(name: string, libraryId?: string | number, booksToAdd?: string[] | number[]) {
|
||||||
try {
|
try {
|
||||||
let bookshelf = await createBookshelf({
|
const bookshelf = await createBookshelf({
|
||||||
title: name,
|
title: name,
|
||||||
library_id: libraryId,
|
library_id: libraryId,
|
||||||
book_ids: booksToAdd
|
book_ids: booksToAdd
|
||||||
@@ -133,7 +133,7 @@ export class BookshelfState {
|
|||||||
decrementBy++;
|
decrementBy++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { ...shelf, total: shelf.total - decrementBy };
|
return { ...shelf, total: (shelf.total ?? 0) - decrementBy };
|
||||||
}
|
}
|
||||||
return shelf;
|
return shelf;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { resolve } from '$app/paths';
|
import { resolve } from '$app/paths';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { goto, invalidate } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { deleteLibrary } from '$lib/api';
|
import { deleteLibrary } from '$lib/api';
|
||||||
import type { Library } from '$lib/schema';
|
import type { Library } from '$lib/schema';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import BookDelete from '$lib/components/forms/book-delete.svelte';
|
import BookDelete from '$lib/components/forms/book-delete.svelte';
|
||||||
import { BookEdit } from '$lib/components/forms/edit-book';
|
import { BookEdit } from '$lib/components/forms/edit-book';
|
||||||
import { getBookOperationsState, setBookOperationsState } from '$lib/state/bookOperations.svelte';
|
import { getBookOperationsState } from '$lib/state/bookOperations.svelte';
|
||||||
import { getLibraryState } from '$lib/state/library.svelte';
|
import { getLibraryState } from '$lib/state/library.svelte';
|
||||||
import { setBookSelectionState } from '$lib/state/bookSelection.svelte';
|
import { setBookSelectionState } from '$lib/state/bookSelection.svelte';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
|
|||||||
@@ -28,22 +28,16 @@
|
|||||||
import { getBookOperationsState } from '$lib/state/bookOperations.svelte.js';
|
import { getBookOperationsState } from '$lib/state/bookOperations.svelte.js';
|
||||||
import { getBookshelfState } from '$lib/state/bookshelf.svelte.js';
|
import { getBookshelfState } from '$lib/state/bookshelf.svelte.js';
|
||||||
import { getLibraryState } from '$lib/state/library.svelte.js';
|
import { getLibraryState } from '$lib/state/library.svelte.js';
|
||||||
import { Progress } from '$lib/components/ui/progress/index.js';
|
|
||||||
import * as Accordion from '$lib/components/ui/accordion/index.js';
|
import * as Accordion from '$lib/components/ui/accordion/index.js';
|
||||||
import * as Table from '$lib/components/ui/table/index.js';
|
import * as Table from '$lib/components/ui/table/index.js';
|
||||||
import * as AlertDialog from '$lib/components/ui/alert-dialog/index.js';
|
import * as AlertDialog from '$lib/components/ui/alert-dialog/index.js';
|
||||||
import ShelfCreateDialog from '$lib/components/forms/shelf-create-dialog.svelte';
|
import ShelfCreateDialog from '$lib/components/forms/shelf-create-dialog.svelte';
|
||||||
import { untrack } from 'svelte';
|
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
|
||||||
// Seeded once, then kept in sync by the effect below — untrack says so
|
// Follows the loaded book, and stays assignable so an edit can update it locally
|
||||||
// explicitly rather than capturing the initial value and warning about it.
|
// until the next navigation supplies a fresh one.
|
||||||
let book = $state(untrack(() => data.book));
|
let book = $derived(data.book);
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
book = data.book;
|
|
||||||
});
|
|
||||||
|
|
||||||
const bookOps = getBookOperationsState();
|
const bookOps = getBookOperationsState();
|
||||||
const libraryState = getLibraryState();
|
const libraryState = getLibraryState();
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { listBookshelves } from '$lib/api';
|
|
||||||
import AppSidebar from '$lib/components/layout/app-sidebar.svelte';
|
import AppSidebar from '$lib/components/layout/app-sidebar.svelte';
|
||||||
import SiteHeader from '$lib/components/layout/site-header.svelte';
|
import SiteHeader from '$lib/components/layout/site-header.svelte';
|
||||||
import UploadTray from '$lib/components/layout/upload-tray.svelte';
|
import UploadTray from '$lib/components/layout/upload-tray.svelte';
|
||||||
import { Loading } from '$lib/components/ui/command';
|
|
||||||
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
||||||
import type { Library, PaginatedResponse } from '$lib/schema';
|
import type { Library, PaginatedResponse } from '$lib/schema';
|
||||||
import { setBookOperationsState } from '$lib/state/bookOperations.svelte';
|
import { setBookOperationsState } from '$lib/state/bookOperations.svelte';
|
||||||
@@ -28,8 +26,8 @@
|
|||||||
// init. `untrack` says that explicitly, instead of silently capturing the
|
// init. `untrack` says that explicitly, instead of silently capturing the
|
||||||
// initial value and warning about it.
|
// initial value and warning about it.
|
||||||
const libraryState = setLibraryState(untrack(() => data.libraries.items));
|
const libraryState = setLibraryState(untrack(() => data.libraries.items));
|
||||||
const bookshelfState = setBookshelfState();
|
setBookshelfState();
|
||||||
const bookOps = setBookOperationsState(libraryState.activeLibrary!.id);
|
setBookOperationsState(libraryState.activeLibrary!.id);
|
||||||
const theme = setThemeState(untrack(() => data.theme));
|
const theme = setThemeState(untrack(() => data.theme));
|
||||||
|
|
||||||
// Set here rather than beside the upload dialog so a running import survives
|
// Set here rather than beside the upload dialog so a running import survives
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
of libraries; the row above it is overflow-hidden, so without this a
|
of libraries; the row above it is overflow-hidden, so without this a
|
||||||
long list is clipped rather than reachable. -->
|
long list is clipped rather than reachable. -->
|
||||||
<nav class="flex w-48 shrink-0 flex-col gap-1 overflow-y-auto">
|
<nav class="flex w-48 shrink-0 flex-col gap-1 overflow-y-auto">
|
||||||
{#each items as item}
|
{#each items as item (item.routeId)}
|
||||||
<a
|
<a
|
||||||
href={resolve(item.routeId)}
|
href={resolve(item.routeId)}
|
||||||
class="rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-muted {page
|
class="rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-muted {page
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function load({ parent }) {
|
export async function load() {
|
||||||
const { libraries } = await parent();
|
|
||||||
|
|
||||||
// Immediately redirect to the account settings
|
// Immediately redirect to the account settings
|
||||||
redirect(303, `/settings/account`);
|
redirect(303, `/settings/account`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@
|
|||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{#each data.devices as device}
|
{#each data.devices as device (device.id)}
|
||||||
{@const isVisible = visibleApiKeys.has(String(device.id))}
|
{@const isVisible = visibleApiKeys.has(String(device.id))}
|
||||||
<Table.Row class="h-14">
|
<Table.Row class="h-14">
|
||||||
<Table.Cell class="pl-4 font-medium">
|
<Table.Cell class="pl-4 font-medium">
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
</Table.Row>
|
</Table.Row>
|
||||||
</Table.Header>
|
</Table.Header>
|
||||||
<Table.Body>
|
<Table.Body>
|
||||||
{#each libraryState.libraries as library}
|
{#each libraryState.libraries as library (library.id)}
|
||||||
<Table.Row class="h-14">
|
<Table.Row class="h-14">
|
||||||
<Table.Cell class="w-16 pl-4 text-center text-lg font-semibold"
|
<Table.Cell class="w-16 pl-4 text-center text-lg font-semibold"
|
||||||
>{library.name[0]}</Table.Cell
|
>{library.name[0]}</Table.Cell
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ export const DELETE: RequestHandler = async ({ params, locals, fetch, request, u
|
|||||||
const headers = prepareRequest(locals, request);
|
const headers = prepareRequest(locals, request);
|
||||||
|
|
||||||
// DELETE may or may not have a body
|
// DELETE may or may not have a body
|
||||||
let options: RequestInit = {
|
const options: RequestInit = {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers
|
headers
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { replaceState } from '$app/navigation';
|
|
||||||
import LoginForm from '$lib/components/forms/login-form.svelte';
|
import LoginForm from '$lib/components/forms/login-form.svelte';
|
||||||
import SignupForm from '$lib/components/forms/signup-form.svelte';
|
import SignupForm from '$lib/components/forms/signup-form.svelte';
|
||||||
import * as Tabs from '$lib/components/ui/tabs/index.js';
|
import * as Tabs from '$lib/components/ui/tabs/index.js';
|
||||||
import { redirect } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
let tabValue = $state('login');
|
let tabValue = $state('login');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user