diff --git a/src/lib/components/inputs/anime-list-input/AnimeListInput.svelte b/src/lib/components/inputs/anime-list-input/AnimeListInput.svelte new file mode 100644 index 0000000..3f1a049 --- /dev/null +++ b/src/lib/components/inputs/anime-list-input/AnimeListInput.svelte @@ -0,0 +1,36 @@ + + +
+ + + MAL + AniList + Kitsu + +
+
+ + +
+
+ + ({ + label: v.toUpperCase(), + value: v, + }))} + bind:value={value.status} + /> +
diff --git a/src/lib/components/inputs/anime-list-input/index.ts b/src/lib/components/inputs/anime-list-input/index.ts new file mode 100644 index 0000000..b7e2ff3 --- /dev/null +++ b/src/lib/components/inputs/anime-list-input/index.ts @@ -0,0 +1,2 @@ +export { default as AnimeListInput } from "./AnimeListInput.svelte"; +export * from "./schema"; diff --git a/src/lib/components/inputs/anime-list-input/schema.ts b/src/lib/components/inputs/anime-list-input/schema.ts new file mode 100644 index 0000000..7a1fcff --- /dev/null +++ b/src/lib/components/inputs/anime-list-input/schema.ts @@ -0,0 +1,16 @@ +import { AnimeList, AnimeListWatchStatus } from "$lib/utils/list"; +import { z } from "zod"; + +const SEP_FIELD = ":"; +const SEP_VALUE = ","; + +export const AnimeListCodec = z.codec(z.string(), AnimeList, { + decode: (s) => { + const [kind, ...rest] = decodeURIComponent(s).split(SEP_FIELD); + const statusStr = rest.pop(); + const status = statusStr ? statusStr.split(SEP_VALUE).map((v) => AnimeListWatchStatus.parse(v)) : []; + const username = rest.join(""); + return AnimeList.parse({ kind, username, status }); + }, + encode: (list) => encodeURIComponent(`${list.kind}${SEP_FIELD}${list.username}${SEP_FIELD}${list.status.join(SEP_VALUE)}`), +}); diff --git a/src/lib/utils/list/index.ts b/src/lib/utils/list/index.ts index d784c53..d94d13a 100644 --- a/src/lib/utils/list/index.ts +++ b/src/lib/utils/list/index.ts @@ -21,7 +21,7 @@ export const AnimeListWatchStatus = z.enum({ export const AnimeList = z.object({ kind: AnimeListKind, username: z.string(), - status: z.array(AnimeListWatchStatus).default([]), + status: z.array(AnimeListWatchStatus), }); export function listExternalUrl(list: z.infer) { diff --git a/src/routes/list/+page.svelte b/src/routes/list/+page.svelte index d09f5e2..2f46741 100644 --- a/src/routes/list/+page.svelte +++ b/src/routes/list/+page.svelte @@ -2,46 +2,43 @@ import { useSearchParams } from "runed/kit"; import type { PageData } from "./$types"; 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"; + import { z } from "zod"; + import { + AnimeListCodec, + AnimeListInput, + } from "$lib/components/inputs/anime-list-input"; let { data }: { data: PageData } = $props(); const params = useSearchParams(SearchParamsSchema, { - showDefaults: true, - updateURL: false, + pushHistory: false, + }); + + let formState: z.infer = $state({ + kind: "mal", + username: "", + status: [], + }); + + // $inspect(formState); + + $effect(() => { + console.log("formState", formState); });

List Search WIP

-
-
- - - MAL - AniList - Kitsu - -
-
- - -
-
- - ({ - label: v.toUpperCase(), - value: v, - }))} - bind:value={params.status} - /> -
+ { + e.preventDefault(); + params.kind = formState.kind; + params.username = formState.username; + params.status = formState.status; + }} + class="flex flex-wrap items-end gap-2" +> + diff --git a/src/routes/list/schema.ts b/src/routes/list/schema.ts index df969b0..89ae69f 100644 --- a/src/routes/list/schema.ts +++ b/src/routes/list/schema.ts @@ -1,15 +1,8 @@ import { AnimeListKind, AnimeListWatchStatus } from "$lib/utils/list"; import { z } from "zod"; -const 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({ kind: AnimeListKind.default("mal"), - username: z.string().optional().default(""), - status: statusCodec.default([]), + username: z.string().default(""), + status: z.array(AnimeListWatchStatus).default([]), })