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/routes/archives/+page.svelte | 131 +++++++++++++++---------------
 1 file changed, 65 insertions(+), 66 deletions(-)

(limited to 'frontend/src/routes/archives/+page.svelte')

diff --git a/frontend/src/routes/archives/+page.svelte b/frontend/src/routes/archives/+page.svelte
index 545058a..3fc4ed4 100644
--- a/frontend/src/routes/archives/+page.svelte
+++ b/frontend/src/routes/archives/+page.svelte
@@ -3,10 +3,7 @@
 	import { archivesQuery } from '$gql/Queries';
 	import type { ArchiveFragment } from '$gql/graphql';
 	import { ArchiveSortLabel } from '$lib/Enums';
-	import { ArchiveFilterContext, initFilterContext } from '$lib/Filter';
-	import { initPaginationContext } from '$lib/Pagination';
-	import { initSelectionContext } from '$lib/Selection';
-	import { initSortContext } from '$lib/Sort';
+	import { ArchiveFilterContext } from '$lib/Filter.svelte';
 	import Card from '$lib/components/Card.svelte';
 	import Empty from '$lib/components/Empty.svelte';
 	import Guard from '$lib/components/Guard.svelte';
@@ -17,6 +14,7 @@
 	import Pagination from '$lib/pagination/Pagination.svelte';
 	import Pill from '$lib/pills/Pill.svelte';
 	import Selectable from '$lib/selection/Selectable.svelte';
+	import { initSelectionContext } from '$lib/selection/Selection.svelte';
 	import SelectionOverlay from '$lib/selection/SelectionOverlay.svelte';
 	import DeleteSelection from '$lib/toolbar/DeleteSelection.svelte';
 	import FilterOrganized from '$lib/toolbar/FilterOrganized.svelte';
@@ -29,90 +27,91 @@
 	import Toolbar from '$lib/toolbar/Toolbar.svelte';
 	import { getContextClient } from '@urql/svelte';
 	import { filesize } from 'filesize';
-	import type { PageData } from './$types';
+	import type { PageProps } from './$types';
 
-	let client = getContextClient();
+	let { data }: PageProps = $props();
+	let pagination = $derived(data.pagination);
+	let sort = $derived(data.sort);
 
-	export let data: PageData;
+	const client = getContextClient();
+	let result = $derived(archivesQuery(client, { ...data }));
+	let archives = $derived($result.data?.archives);
 
-	$: result = archivesQuery(client, {
-		pagination: data.pagination,
-		filter: data.filter,
-		sort: data.sort
+	let selection = initSelectionContext<ArchiveFragment>('Archive', (a) => a.name);
+	$effect(() => {
+		if (archives) {
+			selection.view = archives.edges;
+		}
 	});
 
-	$: archives = $result.data?.archives;
-
-	const selection = initSelectionContext<ArchiveFragment>('Archive', (a) => a.name);
-	$: if (archives) {
-		$selection.view = archives.edges;
-		$pagination.total = archives.count;
-	}
-
-	const pagination = initPaginationContext();
-	$: $pagination.update = data.pagination;
-
-	const filter = initFilterContext<ArchiveFilterContext>();
-	$: $filter = new ArchiveFilterContext(data.filter);
-
-	const sort = initSortContext(data.sort, ArchiveSortLabel);
-	$: $sort.update = data.sort;
-
-	function refresh() {
-		result.reexecute({ requestPolicy: 'network-only' });
-	}
+	let filter = $state(new ArchiveFilterContext(data.filter));
+	$effect(() => {
+		filter = new ArchiveFilterContext(data.filter);
+	});
 </script>
 
 <Head section="Archives" />
 
 <Column>
 	<Toolbar>
-		<SelectionControls slot="start">
-			<MarkSelection>
-				<MarkOrganized mutation={updateArchives} />
-			</MarkSelection>
-			<DeleteSelection
-				mutation={deleteArchives}
-				warning="Deleting an archive will also delete its archive file on disk as well as all comics that belong to it."
-			/>
-		</SelectionControls>
-		<svelte:fragment slot="center">
-			<Search name="Archives" bind:field={$filter.include.controls.path.contains} />
-			<FilterOrganized />
-			<SelectSort />
-			<SelectItems />
-		</svelte:fragment>
-		<RefreshButton slot="end" on:click={refresh} />
+		{#snippet start()}
+			<SelectionControls>
+				<MarkSelection>
+					<MarkOrganized mutation={updateArchives} />
+				</MarkSelection>
+				<DeleteSelection
+					mutation={deleteArchives}
+					warning="Deleting an archive will also delete its archive file on disk as well as all comics that belong to it."
+				/>
+			</SelectionControls>
+		{/snippet}
+		{#snippet center()}
+			<Search name="Archives" {filter} bind:field={filter.include.path.contains} />
+			<FilterOrganized {filter} />
+			<SelectSort {sort} labels={ArchiveSortLabel} />
+			<SelectItems {pagination} />
+		{/snippet}
+		{#snippet end()}
+			<RefreshButton onclick={() => result.reexecute({ requestPolicy: 'network-only' })} />
+		{/snippet}
 	</Toolbar>
 	{#if archives}
-		<Pagination />
+		<Pagination {pagination} total={archives.count} />
 		<main>
 			<Cards>
 				{#each archives.edges as { id, name, cover, size, pageCount }, index (id)}
-					<Selectable {index} {id} let:handle let:selected>
-						<Card
-							ellipsis={false}
-							href={id.toString()}
-							details={{ title: name, cover: cover }}
-							on:click={handle}
-						>
-							<SelectionOverlay position="left" {selected} slot="overlay" />
-							<div class="flex gap-1 text-xs">
-								<Pill name={`${pageCount} pages`}>
-									<span class="icon-[material-symbols--note] mr-0.5" slot="icon" />
-								</Pill>
-								<Pill name={filesize(size, { base: 2 })}>
-									<span class="icon-[material-symbols--hard-drive] mr-0.5" slot="icon" />
-								</Pill>
-							</div>
-						</Card>
+					<Selectable {index} {id}>
+						{#snippet children({ onclick, selected })}
+							<Card
+								ellipsis={false}
+								href={id.toString()}
+								details={{ title: name, cover }}
+								{onclick}
+							>
+								{#snippet overlay()}
+									<SelectionOverlay position="left" {selected} />
+								{/snippet}
+								<div class="flex gap-1 text-xs">
+									<Pill name={`${pageCount} pages`}>
+										{#snippet icon()}
+											<span class="icon-[material-symbols--note] mr-0.5"></span>
+										{/snippet}
+									</Pill>
+									<Pill name={filesize(size, { base: 2 })}>
+										{#snippet icon()}
+											<span class="icon-[material-symbols--hard-drive] mr-0.5"></span>
+										{/snippet}
+									</Pill>
+								</div>
+							</Card>
+						{/snippet}
 					</Selectable>
 				{:else}
 					<Empty />
 				{/each}
 			</Cards>
 		</main>
-		<Pagination />
+		<Pagination {pagination} total={archives.count} />
 	{:else}
 		<Guard {result} />
 	{/if}
-- 
cgit v1.2.3-2-gb3c3

