list: prototype without nested params

This commit is contained in:
2026-02-13 00:32:47 -08:00
parent 21d62f8c6f
commit a144baba2b
3 changed files with 44 additions and 36 deletions

View File

@@ -4,32 +4,44 @@
import { SearchParamsSchema } from "./schema"; import { SearchParamsSchema } from "./schema";
import { ChipGroup } from "$lib/components/ui/chip-group"; import { ChipGroup } from "$lib/components/ui/chip-group";
import { AnimeListWatchStatus } from "$lib/utils/list"; import { AnimeListWatchStatus } from "$lib/utils/list";
import NativeSelect from "$lib/components/ui/native-select/native-select.svelte";
import NativeSelectOption from "$lib/components/ui/native-select/native-select-option.svelte";
import Input from "$lib/components/ui/input/input.svelte";
import { Label } from "$lib/components/ui/label";
import { Button } from "$lib/components/ui/button";
let { data }: { data: PageData } = $props(); let { data }: { data: PageData } = $props();
const params = useSearchParams(SearchParamsSchema, { const params = useSearchParams(SearchParamsSchema, {
pushHistory: false, showDefaults: true,
updateURL: false,
}); });
</script> </script>
<h1 class="text-2xl font-semibold">List Search WIP</h1> <h1 class="text-2xl font-semibold">List Search WIP</h1>
<form> <form class="flex flex-wrap gap-2">
<label for="list-kind">Kind</label> <div class="flex flex-col gap-2">
<!-- nested stuff won't work with useSearchParams --> <Label for="list-kind">Kind</Label>
<select id="list-kind" bind:value={params.list.kind}> <NativeSelect id="list-kind" bind:value={params.kind}>
<option value="mal">MAL</option> <NativeSelectOption value="mal">MAL</NativeSelectOption>
<option value="anilist">AniList</option> <NativeSelectOption value="anilist">AniList</NativeSelectOption>
<option value="kitsu">Kitsu</option> <NativeSelectOption value="kitsu">Kitsu</NativeSelectOption>
</select> </NativeSelect>
<label for="list-username">Username</label> </div>
<input id="list-username" bind:value={params.list.username} /> <div class="flex flex-col gap-2">
<ChipGroup <Label for="list-username">Username</Label>
label="Status" <Input id="list-username" bind:value={params.username} />
items={AnimeListWatchStatus.options.map((v) => ({ </div>
label: v.toUpperCase(), <div class="flex flex-col gap-2">
value: v, <Label for="list-status">Status</Label>
}))} <ChipGroup
bind:value={params.list.status} items={AnimeListWatchStatus.options.map((v) => ({
/> label: v.toUpperCase(),
value: v,
}))}
bind:value={params.status}
/>
</div>
<Button type="submit">Search</Button>
</form> </form>

View File

@@ -1,19 +1,15 @@
import { AnimeList, AnimeListWatchStatus } from "$lib/utils/list"; import { AnimeListKind, AnimeListWatchStatus } from "$lib/utils/list";
import { z } from "zod"; import { z } from "zod";
const fieldSep = ":"; const valueSep = ".";
const valueSep = ",";
const listCodec = z.codec(z.string(), AnimeList, { const statusCodec = z.codec(z.string(), z.array(AnimeListWatchStatus), {
decode: (s) => { decode: (s) => s ? decodeURIComponent(s).split(valueSep).map((s) => AnimeListWatchStatus.parse(s)) : [],
const [kind, ...rest] = decodeURIComponent(s).split(fieldSep); encode: (v) => v.length ? encodeURIComponent(v.join(valueSep)) : "",
const status = rest.pop()?.split(valueSep).map((v) => AnimeListWatchStatus.parse(v)) ?? []; })
const username = rest.join("");
return AnimeList.parse({ kind, username, status });
},
encode: (list) => encodeURIComponent(`${list.kind}${fieldSep}${list.username}${fieldSep}${list.status?.join(valueSep)}`),
});
export const SearchParamsSchema = z.object({ export const SearchParamsSchema = z.object({
list: listCodec.default({ kind: "mal", username: "", status: [] }), kind: AnimeListKind.default("mal"),
username: z.string().optional().default(""),
status: statusCodec.default([]),
}) })

View File

@@ -11,14 +11,14 @@ const songTypesCodec = z.codec(z.string(), z.array(AmqSongLinkType), {
decode: (str) => decode: (str) =>
str str
? decodeURIComponent(str) ? decodeURIComponent(str)
.split(SEP) .split(SEP)
.map((s) => AmqSongLinkTypeMap[s as keyof typeof AmqSongLinkTypeMap]) .map((s) => AmqSongLinkTypeMap[s as keyof typeof AmqSongLinkTypeMap])
: [], : [],
encode: (arr) => encode: (arr) =>
arr arr
? encodeURIComponent( ? encodeURIComponent(
arr.map((a) => AmqSongLinkTypeMapReverse[a]).join(SEP), arr.map((a) => AmqSongLinkTypeMapReverse[a]).join(SEP),
) )
: "", : "",
}); });