From fde50d21a6e683e40937c4d2937875f8b63cc541 Mon Sep 17 00:00:00 2001
From: bytedream <bytedream@protonmail.com>
Date: Sat, 28 Dec 2024 03:46:17 +0100
Subject: [PATCH] fuck that shit, revert

---
 .../PaginationTableBody.svelte                |  21 +--
 src/routes/admin/+layout.svelte               |   6 +-
 src/routes/admin/feedback/+page.svelte        | 118 +++++++------
 src/routes/admin/reports/+page.svelte         | 164 +++++++++---------
 src/routes/admin/users/+page.svelte           |  26 +--
 5 files changed, 159 insertions(+), 176 deletions(-)

diff --git a/src/lib/components/PaginationTable/PaginationTableBody.svelte b/src/lib/components/PaginationTable/PaginationTableBody.svelte
index 3422ea9..e6498d5 100644
--- a/src/lib/components/PaginationTable/PaginationTableBody.svelte
+++ b/src/lib/components/PaginationTable/PaginationTableBody.svelte
@@ -6,21 +6,6 @@
 	let bodyElem: HTMLTableSectionElement;
 	let intersectionElem: HTMLElement;
 
-	async function onUpdateProxy() {
-		let scrollElem: HTMLElement | null = bodyElem;
-		while (scrollElem && scrollElem.scrollHeight <= scrollElem.clientHeight) {
-			scrollElem = scrollElem.parentElement;
-		}
-
-		const scrollTop = scrollElem?.scrollTop ?? 0;
-
-		await onUpdate();
-
-		if (scrollElem) scrollElem.scrollTop = scrollTop;
-
-		await tick();
-	}
-
 	async function getIntersectionElement(): Promise<HTMLElement> {
 		if (!bodyElem.lastElementChild) {
 			await new Promise<void>((resolve) => {
@@ -36,7 +21,8 @@
 	}
 
 	onMount(async () => {
-		await onUpdateProxy();
+		await onUpdate();
+		await tick();
 
 		if (!bodyElem) return;
 
@@ -47,7 +33,8 @@
 
 				const rows = bodyElem.rows.length;
 
-				await onUpdateProxy();
+				await onUpdate();
+				await tick();
 
 				if (rows === bodyElem.rows.length) return;
 				observer.observe((intersectionElem = await getIntersectionElement()));
diff --git a/src/routes/admin/+layout.svelte b/src/routes/admin/+layout.svelte
index 3698d4b..4372931 100644
--- a/src/routes/admin/+layout.svelte
+++ b/src/routes/admin/+layout.svelte
@@ -82,7 +82,7 @@
 
 	let pageTitleSuffix = $derived(
 		tabs.find((t) => $page.url.pathname === t.path)?.name ??
-			($page.url.pathname === `${env.PUBLIC_BASE_PATH}/admin/login` ? 'Login' : null)
+		($page.url.pathname === `${env.PUBLIC_BASE_PATH}/admin/login` ? 'Login' : null)
 	);
 </script>
 
@@ -133,7 +133,7 @@
 	<div class="grid">
 		{#key $page.url.pathname}
 			<div
-				class="col-[1] row-[1] h-[calc(100vh-3rem)] w-full overflow-y-scroll overflow-x-hidden"
+				class="col-[1] row-[1] h-full w-full overflow-y-scroll overflow-x-hidden"
 				in:fly={{ x: transitionPrefix * window.innerWidth, duration: !transitionPrefix ? 0 : 100 }}
 				out:fly={{
 					x: transitionPrefix * -window.innerWidth,
@@ -145,7 +145,7 @@
 		{/key}
 	</div>
 {:else}
-	<div class="h-[calc(100vh-3rem)] w-full">
+	<div class="h-full w-full">
 		{@render children()}
 	</div>
 {/if}
diff --git a/src/routes/admin/feedback/+page.svelte b/src/routes/admin/feedback/+page.svelte
index 961ebe8..66f3818 100644
--- a/src/routes/admin/feedback/+page.svelte
+++ b/src/routes/admin/feedback/+page.svelte
@@ -66,67 +66,65 @@
 			onUpdate={() => fetchFeedback({ from: 0 }).then((r) => (feedbacks = r))}
 		/>
 		<hr class="divider my-1 mx-8 border-none" />
-		<div class="h-full overflow-scroll">
-			<table class="table table-fixed h-fit">
-				<thead>
-					<tr>
-						<th>Event</th>
-						<th>Titel</th>
-						<th>Nutzer</th>
-						<th>Datum</th>
-						<th>Inhalt</th>
-					</tr>
-				</thead>
-				<PaginationTableBody
-					onUpdate={async () =>
-						await fetchFeedback().then((feedback) => (feedbacks = [...feedbacks, ...feedback]))}
-				>
-					{#each feedbacks as feedback}
-						<tr
-							class="hover [&>*]:text-sm cursor-pointer"
-							class:bg-base-200={activeFeedback?.url_hash === feedback.url_hash}
-							onclick={async () => {
-								await goto(`${window.location.href.split('#')[0]}#${feedback.url_hash}`, {
-									replaceState: true
-								});
-								await openHashReport();
-							}}
+		<table class="table table-fixed h-fit">
+			<thead>
+			<tr>
+				<th>Event</th>
+				<th>Titel</th>
+				<th>Nutzer</th>
+				<th>Datum</th>
+				<th>Inhalt</th>
+			</tr>
+			</thead>
+			<PaginationTableBody
+				onUpdate={async () =>
+					await fetchFeedback().then((feedback) => (feedbacks = [...feedbacks, ...feedback]))}
+			>
+				{#each feedbacks as feedback}
+					<tr
+						class="hover [&>*]:text-sm cursor-pointer"
+						class:bg-base-200={activeFeedback?.url_hash === feedback.url_hash}
+						onclick={async () => {
+							await goto(`${window.location.href.split('#')[0]}#${feedback.url_hash}`, {
+								replaceState: true
+							});
+							await openHashReport();
+						}}
+					>
+						<td title={feedback.event}>{feedback.event}</td>
+						<td class="overflow-hidden overflow-ellipsis">{feedback.title}</td>
+						<td class="flex">
+							{feedback.user?.username || ''}
+							{#if feedback.user}
+								<button
+									class="pl-1"
+									title="Nach Ersteller filtern"
+									onclick={(e) => {
+										e.stopPropagation();
+										feedbackFilter.username = feedback.user.username;
+										fetchFeedback({ from: 0 }).then((r) => (feedbacks = r));
+									}}
+								>
+									<MagnifyingGlass size="14" />
+								</button>
+							{/if}
+						</td>
+						<td
+						>{new Intl.DateTimeFormat('de-DE', {
+							year: 'numeric',
+							month: '2-digit',
+							day: '2-digit',
+							hour: '2-digit',
+							minute: '2-digit'
+						}).format(new Date(feedback.updatedAt))} Uhr</td
 						>
-							<td title={feedback.event}>{feedback.event}</td>
-							<td class="overflow-hidden overflow-ellipsis">{feedback.title}</td>
-							<td class="flex">
-								{feedback.user?.username || ''}
-								{#if feedback.user}
-									<button
-										class="pl-1"
-										title="Nach Ersteller filtern"
-										onclick={(e) => {
-											e.stopPropagation();
-											feedbackFilter.username = feedback.user.username;
-											fetchFeedback({ from: 0 }).then((r) => (feedbacks = r));
-										}}
-									>
-										<MagnifyingGlass size="14" />
-									</button>
-								{/if}
-							</td>
-							<td
-								>{new Intl.DateTimeFormat('de-DE', {
-									year: 'numeric',
-									month: '2-digit',
-									day: '2-digit',
-									hour: '2-digit',
-									minute: '2-digit'
-								}).format(new Date(feedback.updatedAt))} Uhr</td
-							>
-							<td class="overflow-hidden overflow-ellipsis"
-								>{feedback.content}{feedback.content_stripped ? '...' : ''}</td
-							>
-						</tr>
-					{/each}
-				</PaginationTableBody>
-			</table>
-		</div>
+						<td class="overflow-hidden overflow-ellipsis"
+						>{feedback.content}{feedback.content_stripped ? '...' : ''}</td
+						>
+					</tr>
+				{/each}
+			</PaginationTableBody>
+		</table>
 	</div>
 	{#if activeFeedback}
 		<div
diff --git a/src/routes/admin/reports/+page.svelte b/src/routes/admin/reports/+page.svelte
index e6bbcf2..92a6d3c 100644
--- a/src/routes/admin/reports/+page.svelte
+++ b/src/routes/admin/reports/+page.svelte
@@ -115,97 +115,95 @@
 			</div>
 		</div>
 		<hr class="divider my-1 mx-8 border-none" />
-		<div class="h-full overflow-scroll">
-			<table class="table table-fixed h-fit">
-				<colgroup>
-					<col style="width: 20%" />
-					<col style="width: 15%" />
-					<col style="width: 15%" />
-					<col style="width: 20%" />
-					<col style="width: 15%" />
-					<col style="width: 15%" />
-				</colgroup>
-				<thead>
-					<tr>
-						<th>Grund</th>
-						<th>Ersteller</th>
-						<th>Reporteter User</th>
-						<th>Datum</th>
-						<th>Bearbeitungsstatus</th>
-						<th>Reportstatus</th>
-					</tr>
-				</thead>
-				<PaginationTableBody
-					onUpdate={async () =>
-						await fetchReports().then((res) => (reports = [...reports, ...res.reports]))}
-				>
-					{#each reports as report}
-						<tr
-							class="hover [&>*]:text-sm cursor-pointer"
-							class:bg-base-200={activeReport?.url_hash === report.url_hash}
-							onclick={() => {
-								goto(`${window.location.href.split('#')[0]}#${report.url_hash}`, {
-									replaceState: true
-								});
-								activeReport = $state.snapshot(report);
-								activeReport.originalStatus = report.status;
-							}}
-						>
-							<td title={report.subject}><div class="overflow-scroll">{report.subject}</div></td>
-							<td class="flex">
-								{report.reporter.username}
+		<table class="table table-fixed h-fit">
+			<colgroup>
+				<col style="width: 20%" />
+				<col style="width: 15%" />
+				<col style="width: 15%" />
+				<col style="width: 20%" />
+				<col style="width: 15%" />
+				<col style="width: 15%" />
+			</colgroup>
+			<thead>
+			<tr>
+				<th>Grund</th>
+				<th>Ersteller</th>
+				<th>Reporteter User</th>
+				<th>Datum</th>
+				<th>Bearbeitungsstatus</th>
+				<th>Reportstatus</th>
+			</tr>
+			</thead>
+			<PaginationTableBody
+				onUpdate={async () =>
+					await fetchReports().then((res) => (reports = [...reports, ...res.reports]))}
+			>
+				{#each reports as report}
+					<tr
+						class="hover [&>*]:text-sm cursor-pointer"
+						class:bg-base-200={activeReport?.url_hash === report.url_hash}
+						onclick={() => {
+							goto(`${window.location.href.split('#')[0]}#${report.url_hash}`, {
+								replaceState: true
+							});
+							activeReport = $state.snapshot(report);
+							activeReport.originalStatus = report.status;
+						}}
+					>
+						<td title={report.subject}><div class="overflow-scroll">{report.subject}</div></td>
+						<td class="flex">
+							{report.reporter.username}
+							<button
+								class="pl-1"
+								title="Nach Ersteller filtern"
+								onclick={(e) => {
+									e.stopPropagation();
+									reportFilter.reporter = report.reporter.username;
+									fetchReports({ from: 0 }).then((r) => (reports = r.reports));
+								}}
+							>
+								<MagnifyingGlass size="14" />
+							</button>
+						</td>
+						<td>
+							{report.reported?.username || ''}
+							{#if report.reported?.id}
 								<button
 									class="pl-1"
-									title="Nach Ersteller filtern"
+									title="Nach Reportetem Spieler filtern"
 									onclick={(e) => {
 										e.stopPropagation();
-										reportFilter.reporter = report.reporter.username;
+										reportFilter.reported = report.reported.username;
 										fetchReports({ from: 0 }).then((r) => (reports = r.reports));
 									}}
 								>
 									<MagnifyingGlass size="14" />
 								</button>
-							</td>
-							<td>
-								{report.reported?.username || ''}
-								{#if report.reported?.id}
-									<button
-										class="pl-1"
-										title="Nach Reportetem Spieler filtern"
-										onclick={(e) => {
-											e.stopPropagation();
-											reportFilter.reported = report.reported.username;
-											fetchReports({ from: 0 }).then((r) => (reports = r.reports));
-										}}
-									>
-										<MagnifyingGlass size="14" />
-									</button>
-								{/if}
-							</td>
-							<td
-								>{new Intl.DateTimeFormat('de-DE', {
-									year: 'numeric',
-									month: '2-digit',
-									day: '2-digit',
-									hour: '2-digit',
-									minute: '2-digit'
-								}).format(new Date(report.createdAt))} Uhr</td
-							>
-							<td>
-								{report.status === 'none'
-									? 'Unbearbeitet'
-									: report.status === 'review'
-										? 'In Bearbeitung'
-										: report.status === 'reviewed'
-											? 'Bearbeitet'
-											: ''}
-							</td>
-							<td>{report.draft ? 'Entwurf' : 'Erstellt'}</td>
-						</tr>
-					{/each}
-				</PaginationTableBody>
-			</table>
-		</div>
+							{/if}
+						</td>
+						<td
+						>{new Intl.DateTimeFormat('de-DE', {
+							year: 'numeric',
+							month: '2-digit',
+							day: '2-digit',
+							hour: '2-digit',
+							minute: '2-digit'
+						}).format(new Date(report.createdAt))} Uhr</td
+						>
+						<td>
+							{report.status === 'none'
+								? 'Unbearbeitet'
+								: report.status === 'review'
+									? 'In Bearbeitung'
+									: report.status === 'reviewed'
+										? 'Bearbeitet'
+										: ''}
+						</td>
+						<td>{report.draft ? 'Entwurf' : 'Erstellt'}</td>
+					</tr>
+				{/each}
+			</PaginationTableBody>
+		</table>
 	</div>
 	{#if activeReport}
 		<div
@@ -307,7 +305,7 @@
 					<option
 						value="none"
 						disabled={activeReport.auditor != null || activeReport.notice || activeReport.statement}
-						>Unbearbeitet</option
+					>Unbearbeitet</option
 					>
 					<option value="review">In Bearbeitung</option>
 					<option value="reviewed">Bearbeitet</option>
diff --git a/src/routes/admin/users/+page.svelte b/src/routes/admin/users/+page.svelte
index 67169a7..5c404f5 100644
--- a/src/routes/admin/users/+page.svelte
+++ b/src/routes/admin/users/+page.svelte
@@ -95,19 +95,19 @@
 	<div class="h-full overflow-scroll" bind:this={userTableContainerElement}>
 		<table class="table table-auto">
 			<thead>
-				<!-- prettier-ignore -->
-				<SortableTr>
-					<th></th>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'firstname', asc: e.asc}}}>Vorname</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'lastname', asc: e.asc}}}>Nachname</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'birthday', asc: e.asc}}}>Geburtstag</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'telephone', asc: e.asc}}}>Telefon</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'username', asc: e.asc}}}>Username</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'playertype', asc: e.asc}}}>Minecraft Edition</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'password', asc: e.asc}}}>Passwort</SortableTh>
-					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'uuid', asc: e.asc}}}>UUID</SortableTh>
-					<th></th>
-				</SortableTr>
+			<!-- prettier-ignore -->
+			<SortableTr class="[&>th]:bg-base-100 [&>th]:z-[1] [&>th]:sticky [&>th]:top-0">
+				<th></th>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'firstname', asc: e.asc}}}>Vorname</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'lastname', asc: e.asc}}}>Nachname</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'birthday', asc: e.asc}}}>Geburtstag</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'telephone', asc: e.asc}}}>Telefon</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'username', asc: e.asc}}}>Username</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'playertype', asc: e.asc}}}>Minecraft Edition</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'password', asc: e.asc}}}>Passwort</SortableTh>
+				<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'uuid', asc: e.asc}}}>UUID</SortableTh>
+				<th></th>
+			</SortableTr>
 			</thead>
 			<PaginationTableBody
 				onUpdate={async () => {