From dc4db405d2991d3ec6a114f3b08d3fccd057d3ee Mon Sep 17 00:00:00 2001
From: Wolfgang Müller
Date: Thu, 13 Feb 2025 17:52:16 +0100
Subject: frontend: Migrate to Svelte 5

---
 frontend/src/lib/forms/ComicForm.svelte | 169 +++++++++++++++++---------------
 1 file changed, 92 insertions(+), 77 deletions(-)

(limited to 'frontend/src/lib/forms/ComicForm.svelte')

diff --git a/frontend/src/lib/forms/ComicForm.svelte b/frontend/src/lib/forms/ComicForm.svelte
index 74051c8..adc6a34 100644
--- a/frontend/src/lib/forms/ComicForm.svelte
+++ b/frontend/src/lib/forms/ComicForm.svelte
@@ -3,98 +3,113 @@
 	import { type OmitIdentifiers } from '$gql/Utils';
 	import type { FullComicFragment, UpdateComicInput } from '$gql/graphql';
 	import { categories, censorships, directions, languages, layouts, ratings } from '$lib/Enums';
-	import Labelled from '$lib/components/Labelled.svelte';
 	import LabelledBlock from '$lib/components/LabelledBlock.svelte';
 	import Select from '$lib/components/Select.svelte';
 	import { getContextClient } from '@urql/svelte';
-	import { createEventDispatcher } from 'svelte';
+	import { type Snippet } from 'svelte';
 
 	const client = getContextClient();
-	const dispatch = createEventDispatcher<{ submit: UpdateComicInput }>();
-
-	export let comic: OmitIdentifiers<FullComicFragment>;
-
-	$: tagsQuery = comicTagList(client);
-	$: artistsQuery = artistList(client);
-	$: charactersQuery = characterList(client);
-	$: circlesQuery = circleList(client);
-	$: worldsQuery = worldList(client);
-
-	$: tags = $tagsQuery.data?.comicTags.edges;
-	$: artists = $artistsQuery.data?.artists.edges;
-	$: characters = $charactersQuery.data?.characters.edges;
-	$: circles = $circlesQuery.data?.circles.edges;
-	$: worlds = $worldsQuery.data?.worlds.edges;
-
-	function submit() {
-		dispatch('submit', {
-			direction: comic.direction,
-			layout: comic.layout,
-			rating: comic.rating,
-			category: comic.category,
-			censorship: comic.censorship,
-			title: comic.title,
-			originalTitle: comic.originalTitle,
-			url: comic.url,
-			date: comic.date === '' ? null : comic.date,
-			language: comic.language,
-			tags: { ids: comic.tags.map((t) => t.id) },
-			artists: { ids: comic.artists.map((a) => a.id) },
-			characters: { ids: comic.characters.map((c) => c.id) },
-			circles: { ids: comic.circles.map((c) => c.id) },
-			worlds: { ids: comic.worlds.map((w) => w.id) }
+
+	interface Props {
+		input: OmitIdentifiers<FullComicFragment>;
+		submit: (input: UpdateComicInput) => void;
+		children?: Snippet;
+	}
+
+	let { input = $bindable(), submit, children }: Props = $props();
+
+	let tagsQuery = $derived(comicTagList(client));
+	let artistsQuery = $derived(artistList(client));
+	let charactersQuery = $derived(characterList(client));
+	let circlesQuery = $derived(circleList(client));
+	let worldsQuery = $derived(worldList(client));
+
+	let tags = $derived($tagsQuery.data?.comicTags.edges);
+	let artists = $derived($artistsQuery.data?.artists.edges);
+	let characters = $derived($charactersQuery.data?.characters.edges);
+	let circles = $derived($circlesQuery.data?.circles.edges);
+	let worlds = $derived($worldsQuery.data?.worlds.edges);
+
+	function onsubmit(event: SubmitEvent) {
+		event.preventDefault();
+
+		submit({
+			direction: input.direction,
+			layout: input.layout,
+			rating: input.rating,
+			category: input.category,
+			censorship: input.censorship,
+			title: input.title,
+			originalTitle: input.originalTitle,
+			url: input.url,
+			date: input.date === '' ? null : input.date,
+			language: input.language,
+			tags: { ids: input.tags.map((t) => t.id) },
+			artists: { ids: input.artists.map((a) => a.id) },
+			characters: { ids: input.characters.map((c) => c.id) },
+			circles: { ids: input.circles.map((c) => c.id) },
+			worlds: { ids: input.worlds.map((w) => w.id) }
 		});
 	}
 </script>
 
-<form on:submit|preventDefault={submit}>
+<form {onsubmit}>
 	<div class="grid-labels">
-		<Labelled label="Title" let:id>
-			<input required {id} bind:value={comic.title} title={comic.title} />
-		</Labelled>
-		<Labelled label="Original Title" let:id>
-			<input {id} bind:value={comic.originalTitle} title={comic.originalTitle} />
-		</Labelled>
-		<Labelled label="URL" let:id>
-			<input {id} bind:value={comic.url} />
-		</Labelled>
-		<Labelled label="Date" let:id>
-			<input {id} type="date" bind:value={comic.date} pattern={'d{4}-d{2}-d{2}'} />
-		</Labelled>
-		<Labelled label="Category" let:id>
-			<Select {id} options={categories} bind:value={comic.category} />
-		</Labelled>
-		<Labelled label="Rating" let:id>
-			<Select {id} options={ratings} bind:value={comic.rating} />
-		</Labelled>
-		<Labelled label="Censorship" let:id>
-			<Select {id} options={censorships} bind:value={comic.censorship} />
-		</Labelled>
-		<Labelled label="Language" let:id>
-			<Select {id} options={languages} bind:value={comic.language} />
-		</Labelled>
-		<Labelled label="Direction" let:id>
-			<Select {id} options={directions} bind:value={comic.direction} />
-		</Labelled>
-		<Labelled label="Layout" let:id>
-			<Select {id} options={layouts} bind:value={comic.layout} />
-		</Labelled>
+		<label class="self-center" for="title">Title</label>
+		<input required id="title" bind:value={input.title} title={input.title} />
+
+		<label class="self-center" for="original-title">Original Title</label>
+		<input id="original-title" bind:value={input.originalTitle} title={input.originalTitle} />
+
+		<label class="self-center" for="url">URL</label>
+		<input id="url" bind:value={input.url} />
+
+		<label class="self-center" for="date">Date</label>
+		<input id="date" type="date" bind:value={input.date} pattern={'d{4}-d{2}-d{2}'} />
+
+		<label class="self-center" for="category">Category</label>
+		<Select id="category" options={categories} bind:value={input.category} />
+
+		<label class="self-center" for="rating">Rating</label>
+		<Select id="rating" options={ratings} bind:value={input.rating} />
+
+		<label class="self-center" for="censorship">Censorship</label>
+		<Select id="censorship" options={censorships} bind:value={input.censorship} />
+
+		<label class="self-center" for="language">Language</label>
+		<Select id="language" options={languages} bind:value={input.language} />
+
+		<label class="self-center" for="direction">Direction</label>
+		<Select id="direction" options={directions} bind:value={input.direction} />
+
+		<label class="self-center" for="layout">Layout</label>
+		<Select id="layout" options={layouts} bind:value={input.layout} />
 	</div>
 
-	<LabelledBlock label="Artists" let:id>
-		<Select multi object {id} options={artists} bind:value={comic.artists} />
+	<LabelledBlock label="Artists">
+		{#snippet children({ id })}
+			<Select multi object {id} options={artists} bind:value={input.artists} />
+		{/snippet}
 	</LabelledBlock>
-	<LabelledBlock label="Circles" let:id>
-		<Select multi object {id} options={circles} bind:value={comic.circles} />
+	<LabelledBlock label="Circles">
+		{#snippet children({ id })}
+			<Select multi object {id} options={circles} bind:value={input.circles} />
+		{/snippet}
 	</LabelledBlock>
-	<LabelledBlock label="Characters" let:id>
-		<Select multi object {id} options={characters} bind:value={comic.characters} />
+	<LabelledBlock label="Characters">
+		{#snippet children({ id })}
+			<Select multi object {id} options={characters} bind:value={input.characters} />
+		{/snippet}
 	</LabelledBlock>
-	<LabelledBlock label="Worlds" let:id>
-		<Select multi object {id} options={worlds} bind:value={comic.worlds} />
+	<LabelledBlock label="Worlds">
+		{#snippet children({ id })}
+			<Select multi object {id} options={worlds} bind:value={input.worlds} />
+		{/snippet}
 	</LabelledBlock>
-	<LabelledBlock label="Tags" let:id>
-		<Select multi object {id} options={tags} bind:value={comic.tags} />
+	<LabelledBlock label="Tags">
+		{#snippet children({ id })}
+			<Select multi object {id} options={tags} bind:value={input.tags} />
+		{/snippet}
 	</LabelledBlock>
-	<slot />
+	{@render children?.()}
 </form>
-- 
cgit v1.2.3-2-gb3c3

