list: prototype without nested params
This commit is contained in:
@@ -4,32 +4,44 @@
|
||||
import { SearchParamsSchema } from "./schema";
|
||||
import { ChipGroup } from "$lib/components/ui/chip-group";
|
||||
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();
|
||||
|
||||
const params = useSearchParams(SearchParamsSchema, {
|
||||
pushHistory: false,
|
||||
showDefaults: true,
|
||||
updateURL: false,
|
||||
});
|
||||
</script>
|
||||
|
||||
<h1 class="text-2xl font-semibold">List Search WIP</h1>
|
||||
|
||||
<form>
|
||||
<label for="list-kind">Kind</label>
|
||||
<!-- nested stuff won't work with useSearchParams -->
|
||||
<select id="list-kind" bind:value={params.list.kind}>
|
||||
<option value="mal">MAL</option>
|
||||
<option value="anilist">AniList</option>
|
||||
<option value="kitsu">Kitsu</option>
|
||||
</select>
|
||||
<label for="list-username">Username</label>
|
||||
<input id="list-username" bind:value={params.list.username} />
|
||||
<ChipGroup
|
||||
label="Status"
|
||||
items={AnimeListWatchStatus.options.map((v) => ({
|
||||
label: v.toUpperCase(),
|
||||
value: v,
|
||||
}))}
|
||||
bind:value={params.list.status}
|
||||
/>
|
||||
<form class="flex flex-wrap gap-2">
|
||||
<div class="flex flex-col gap-2">
|
||||
<Label for="list-kind">Kind</Label>
|
||||
<NativeSelect id="list-kind" bind:value={params.kind}>
|
||||
<NativeSelectOption value="mal">MAL</NativeSelectOption>
|
||||
<NativeSelectOption value="anilist">AniList</NativeSelectOption>
|
||||
<NativeSelectOption value="kitsu">Kitsu</NativeSelectOption>
|
||||
</NativeSelect>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<Label for="list-username">Username</Label>
|
||||
<Input id="list-username" bind:value={params.username} />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<Label for="list-status">Status</Label>
|
||||
<ChipGroup
|
||||
items={AnimeListWatchStatus.options.map((v) => ({
|
||||
label: v.toUpperCase(),
|
||||
value: v,
|
||||
}))}
|
||||
bind:value={params.status}
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit">Search</Button>
|
||||
</form>
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { AnimeList, AnimeListWatchStatus } from "$lib/utils/list";
|
||||
import { AnimeListKind, AnimeListWatchStatus } from "$lib/utils/list";
|
||||
import { z } from "zod";
|
||||
|
||||
const fieldSep = ":";
|
||||
const valueSep = ",";
|
||||
const valueSep = ".";
|
||||
|
||||
const listCodec = z.codec(z.string(), AnimeList, {
|
||||
decode: (s) => {
|
||||
const [kind, ...rest] = decodeURIComponent(s).split(fieldSep);
|
||||
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)}`),
|
||||
});
|
||||
const statusCodec = z.codec(z.string(), z.array(AnimeListWatchStatus), {
|
||||
decode: (s) => s ? decodeURIComponent(s).split(valueSep).map((s) => AnimeListWatchStatus.parse(s)) : [],
|
||||
encode: (v) => v.length ? encodeURIComponent(v.join(valueSep)) : "",
|
||||
})
|
||||
|
||||
export const SearchParamsSchema = z.object({
|
||||
list: listCodec.default({ kind: "mal", username: "", status: [] }),
|
||||
kind: AnimeListKind.default("mal"),
|
||||
username: z.string().optional().default(""),
|
||||
status: statusCodec.default([]),
|
||||
})
|
||||
|
||||
@@ -11,14 +11,14 @@ const songTypesCodec = z.codec(z.string(), z.array(AmqSongLinkType), {
|
||||
decode: (str) =>
|
||||
str
|
||||
? decodeURIComponent(str)
|
||||
.split(SEP)
|
||||
.map((s) => AmqSongLinkTypeMap[s as keyof typeof AmqSongLinkTypeMap])
|
||||
.split(SEP)
|
||||
.map((s) => AmqSongLinkTypeMap[s as keyof typeof AmqSongLinkTypeMap])
|
||||
: [],
|
||||
encode: (arr) =>
|
||||
arr
|
||||
? encodeURIComponent(
|
||||
arr.map((a) => AmqSongLinkTypeMapReverse[a]).join(SEP),
|
||||
)
|
||||
arr.map((a) => AmqSongLinkTypeMapReverse[a]).join(SEP),
|
||||
)
|
||||
: "",
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user