clean up code

This commit is contained in:
Jesse Winton
2025-04-11 16:54:28 -04:00
parent 4a0e3ea8d2
commit a61b23366e
11 changed files with 138 additions and 92 deletions

View File

@@ -51,6 +51,7 @@
"@tailwindcss/postcss": "^4.1.2",
"@types/compression": "^1.7.5",
"@types/glob": "^8.1.0",
"@types/jsdom": "^21.1.7",
"@types/markdown-it": "^13.0.9",
"@types/morgan": "^1.9.9",
"analytics": "^0.8.16",

17
pnpm-lock.yaml generated
View File

@@ -78,6 +78,9 @@ importers:
'@types/glob':
specifier: ^8.1.0
version: 8.1.0
'@types/jsdom':
specifier: ^21.1.7
version: 21.1.7
'@types/markdown-it':
specifier: ^13.0.9
version: 13.0.9
@@ -1488,6 +1491,9 @@ packages:
'@types/http-errors@2.0.4':
resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
'@types/jsdom@21.1.7':
resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==}
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@@ -1542,6 +1548,9 @@ packages:
'@types/serve-static@1.15.7':
resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
'@types/tough-cookie@4.0.5':
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
'@typescript-eslint/eslint-plugin@8.26.1':
resolution: {integrity: sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -5230,6 +5239,12 @@ snapshots:
'@types/http-errors@2.0.4': {}
'@types/jsdom@21.1.7':
dependencies:
'@types/node': 22.13.10
'@types/tough-cookie': 4.0.5
parse5: 7.2.1
'@types/json-schema@7.0.15': {}
'@types/linkify-it@3.0.5': {}
@@ -5286,6 +5301,8 @@ snapshots:
'@types/node': 22.13.10
'@types/send': 0.17.4
'@types/tough-cookie@4.0.5': {}
'@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)':
dependencies:
'@eslint-community/regexpp': 4.12.1

View File

@@ -0,0 +1 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.750 2.914 C 13.517 2.971,13.319 3.079,13.067 3.285 C 12.947 3.383,11.791 4.525,10.497 5.823 C 7.967 8.360,8.038 8.279,7.918 8.749 C 7.847 9.023,7.846 10.546,7.916 10.876 C 8.045 11.485,8.515 11.955,9.124 12.084 C 9.454 12.154,10.977 12.153,11.251 12.082 C 11.724 11.961,11.628 12.046,14.286 9.387 C 15.793 7.880,16.802 6.845,16.874 6.733 C 17.208 6.214,17.216 5.562,16.893 5.058 C 16.714 4.778,15.221 3.285,14.940 3.106 C 14.603 2.890,14.144 2.816,13.750 2.914 M14.321 4.138 C 14.468 4.249,15.656 5.429,15.803 5.611 C 15.994 5.848,15.984 5.940,15.737 6.224 C 15.628 6.348,15.400 6.589,15.228 6.758 L 14.916 7.066 13.924 6.074 L 12.933 5.083 13.342 4.681 C 13.903 4.128,13.980 4.067,14.113 4.067 C 14.175 4.067,14.267 4.099,14.321 4.138 M4.733 4.438 C 4.093 4.525,3.540 5.078,3.435 5.733 C 3.388 6.028,3.387 14.966,3.434 15.267 C 3.536 15.920,4.077 16.460,4.733 16.565 C 5.028 16.612,13.966 16.613,14.267 16.566 C 14.920 16.464,15.460 15.923,15.565 15.267 C 15.586 15.138,15.600 14.352,15.600 13.324 C 15.600 11.492,15.598 11.463,15.440 11.289 C 15.174 10.995,14.666 11.062,14.472 11.417 C 14.423 11.505,14.415 11.730,14.400 13.341 L 14.383 15.165 14.274 15.274 L 14.165 15.383 9.500 15.383 L 4.835 15.383 4.726 15.274 L 4.617 15.165 4.617 10.500 L 4.617 5.835 4.726 5.726 L 4.835 5.617 6.742 5.600 C 8.591 5.584,8.654 5.581,8.767 5.515 C 9.173 5.276,9.156 4.699,8.736 4.477 L 8.590 4.400 6.770 4.404 C 5.769 4.406,4.852 4.422,4.733 4.438 M12.593 9.390 C 11.782 10.201,11.079 10.881,11.031 10.901 C 10.894 10.958,9.338 10.931,9.247 10.870 C 9.092 10.767,9.085 10.725,9.072 9.890 C 9.066 9.453,9.070 9.056,9.082 9.006 C 9.097 8.948,9.622 8.398,10.593 7.425 L 12.083 5.933 13.075 6.925 L 14.067 7.916 12.593 9.390 " stroke="none" fill-rule="evenodd" fill="black"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,28 @@
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.46377 5L5.6 5C5.03995 5 4.75992 5 4.54601 5.10899C4.35785 5.20487 4.20487 5.35785 4.10899 5.54601C4 5.75992 4 6.03995 4 6.6V14.4C4 14.9601 4 15.2401 4.10899 15.454C4.20487 15.6422 4.35785 15.7951 4.54601 15.891C4.75992 16 5.03995 16 5.6 16H13.4C13.9601 16 14.2401 16 14.454 15.891C14.6422 15.7951 14.7951 15.6422 14.891 15.454C15 15.2401 15 14.9601 15 14.4V11.6957"
stroke="currentColor"
stroke-width="1.2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12.99 4.18163C13.386 3.78562 13.584 3.58761 13.8123 3.51342C14.0132 3.44816 14.2295 3.44816 14.4304 3.51342C14.6587 3.58761 14.8567 3.78562 15.2527 4.18163L15.8184 4.74732C16.2144 5.14334 16.4124 5.34134 16.4866 5.56967C16.5519 5.77052 16.5519 5.98686 16.4866 6.18771C16.4124 6.41603 16.2144 6.61404 15.8184 7.01006L11.7615 11.0669C11.5886 11.2399 11.5021 11.3263 11.4012 11.3882C11.3117 11.443 11.2142 11.4834 11.1121 11.5079C10.9971 11.5355 10.8748 11.5355 10.6302 11.5355H10.0645C9.50443 11.5355 9.2244 11.5355 9.01049 11.4266C8.82233 11.3307 8.66935 11.1777 8.57348 10.9895C8.46448 10.7756 8.46448 10.4956 8.46448 9.93554V9.36986C8.46448 9.12527 8.46448 9.00297 8.49211 8.88788C8.51661 8.78585 8.55701 8.6883 8.61184 8.59883C8.67369 8.49791 8.76016 8.41144 8.93311 8.23849L12.99 4.18163Z"
stroke="currentColor"
stroke-width="1.2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12 5L15 8"
stroke="currentColor"
stroke-width="1.2"
stroke-linejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -5,7 +5,7 @@
type Props = SvelteHTMLElements['svg'] & {
class?: string;
name?: IconType;
name: IconType;
};
const {
@@ -14,7 +14,7 @@
height = 20,
width = 20,
class: className = '',
name = 'arrow-right',
name,
...rest
}: Props = $props();
</script>

View File

@@ -139,6 +139,14 @@
fill-rule="evenodd"
></path>
</symbol>
<symbol id="customize" stroke="currentColor" viewBox="0 0 20 20">
<path
d="M13.750 2.914 C 13.517 2.971,13.319 3.079,13.067 3.285 C 12.947 3.383,11.791 4.525,10.497 5.823 C 7.967 8.360,8.038 8.279,7.918 8.749 C 7.847 9.023,7.846 10.546,7.916 10.876 C 8.045 11.485,8.515 11.955,9.124 12.084 C 9.454 12.154,10.977 12.153,11.251 12.082 C 11.724 11.961,11.628 12.046,14.286 9.387 C 15.793 7.880,16.802 6.845,16.874 6.733 C 17.208 6.214,17.216 5.562,16.893 5.058 C 16.714 4.778,15.221 3.285,14.940 3.106 C 14.603 2.890,14.144 2.816,13.750 2.914 M14.321 4.138 C 14.468 4.249,15.656 5.429,15.803 5.611 C 15.994 5.848,15.984 5.940,15.737 6.224 C 15.628 6.348,15.400 6.589,15.228 6.758 L 14.916 7.066 13.924 6.074 L 12.933 5.083 13.342 4.681 C 13.903 4.128,13.980 4.067,14.113 4.067 C 14.175 4.067,14.267 4.099,14.321 4.138 M4.733 4.438 C 4.093 4.525,3.540 5.078,3.435 5.733 C 3.388 6.028,3.387 14.966,3.434 15.267 C 3.536 15.920,4.077 16.460,4.733 16.565 C 5.028 16.612,13.966 16.613,14.267 16.566 C 14.920 16.464,15.460 15.923,15.565 15.267 C 15.586 15.138,15.600 14.352,15.600 13.324 C 15.600 11.492,15.598 11.463,15.440 11.289 C 15.174 10.995,14.666 11.062,14.472 11.417 C 14.423 11.505,14.415 11.730,14.400 13.341 L 14.383 15.165 14.274 15.274 L 14.165 15.383 9.500 15.383 L 4.835 15.383 4.726 15.274 L 4.617 15.165 4.617 10.500 L 4.617 5.835 4.726 5.726 L 4.835 5.617 6.742 5.600 C 8.591 5.584,8.654 5.581,8.767 5.515 C 9.173 5.276,9.156 4.699,8.736 4.477 L 8.590 4.400 6.770 4.404 C 5.769 4.406,4.852 4.422,4.733 4.438 M12.593 9.390 C 11.782 10.201,11.079 10.881,11.031 10.901 C 10.894 10.958,9.338 10.931,9.247 10.870 C 9.092 10.767,9.085 10.725,9.072 9.890 C 9.066 9.453,9.070 9.056,9.082 9.006 C 9.097 8.948,9.622 8.398,10.593 7.425 L 12.083 5.933 13.075 6.925 L 14.067 7.916 12.593 9.390 "
stroke="none"
fill-rule="evenodd"
fill="currentColor"
></path>
</symbol>
<symbol id="daily-dev" stroke="currentColor" viewBox="0 0 40 40">
<path
d="M12.467 11.058 C 12.375 11.089,12.180 11.176,12.033 11.252 C 11.646 11.454,4.391 18.744,4.191 19.133 C 3.977 19.550,3.974 20.303,4.186 20.735 C 4.293 20.953,5.393 22.094,8.150 24.846 C 11.945 28.635,11.969 28.657,12.359 28.769 C 12.842 28.908,13.335 28.876,13.737 28.680 C 13.954 28.575,16.126 26.443,21.866 20.702 L 29.699 12.868 28.966 12.129 C 28.531 11.691,28.101 11.322,27.908 11.223 C 27.463 10.994,26.981 10.953,26.491 11.101 C 26.102 11.219,26.069 11.251,18.211 19.093 L 10.322 26.967 11.189 25.233 L 12.056 23.500 10.278 21.716 L 8.501 19.933 10.717 17.717 L 12.933 15.501 14.700 17.267 L 16.467 19.033 17.783 17.716 L 19.099 16.400 16.566 13.866 C 14.733 12.032,13.950 11.293,13.733 11.191 C 13.410 11.039,12.740 10.968,12.467 11.058 M28.844 14.711 L 27.989 16.422 29.761 18.195 L 31.533 19.967 28.532 22.967 C 26.392 25.105,25.489 26.053,25.385 26.266 C 25.191 26.665,25.188 27.313,25.379 27.739 C 25.681 28.413,26.326 28.829,27.067 28.829 C 27.884 28.829,27.776 28.919,31.907 24.780 C 36.005 20.674,35.947 20.743,35.953 19.967 C 35.959 19.197,35.961 19.199,32.715 15.950 C 31.094 14.327,29.752 13.000,29.733 13.000 C 29.714 13.000,29.314 13.770,28.844 14.711 "

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -16,6 +16,7 @@ export type IconType =
| 'close'
| 'command'
| 'copy'
| 'customize'
| 'daily-dev'
| 'dark'
| 'discord'

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import Spinner from '$lib/components/shared/spinner.svelte';
import VideoDialog from '$lib/components/shared/video-dialog.svelte';
import { Button, Icon } from '$lib/components/ui';
import { classNames } from '$lib/utils/classnames';
import { loginGithub } from '../(utils)/github';
import { initDates } from '../+page.svelte';
@@ -38,52 +39,26 @@
<nav class="mt-4 flex w-full flex-col items-center justify-center gap-4 md:flex-row">
{#if claimed}
<a href="/init/tickets/customize" class="web-button flex items-center gap-2">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.46377 5L5.6 5C5.03995 5 4.75992 5 4.54601 5.10899C4.35785 5.20487 4.20487 5.35785 4.10899 5.54601C4 5.75992 4 6.03995 4 6.6V14.4C4 14.9601 4 15.2401 4.10899 15.454C4.20487 15.6422 4.35785 15.7951 4.54601 15.891C4.75992 16 5.03995 16 5.6 16H13.4C13.9601 16 14.2401 16 14.454 15.891C14.6422 15.7951 14.7951 15.6422 14.891 15.454C15 15.2401 15 14.9601 15 14.4V11.6957"
stroke="currentColor"
stroke-width="1.2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12.99 4.18163C13.386 3.78562 13.584 3.58761 13.8123 3.51342C14.0132 3.44816 14.2295 3.44816 14.4304 3.51342C14.6587 3.58761 14.8567 3.78562 15.2527 4.18163L15.8184 4.74732C16.2144 5.14334 16.4124 5.34134 16.4866 5.56967C16.5519 5.77052 16.5519 5.98686 16.4866 6.18771C16.4124 6.41603 16.2144 6.61404 15.8184 7.01006L11.7615 11.0669C11.5886 11.2399 11.5021 11.3263 11.4012 11.3882C11.3117 11.443 11.2142 11.4834 11.1121 11.5079C10.9971 11.5355 10.8748 11.5355 10.6302 11.5355H10.0645C9.50443 11.5355 9.2244 11.5355 9.01049 11.4266C8.82233 11.3307 8.66935 11.1777 8.57348 10.9895C8.46448 10.7756 8.46448 10.4956 8.46448 9.93554V9.36986C8.46448 9.12527 8.46448 9.00297 8.49211 8.88788C8.51661 8.78585 8.55701 8.6883 8.61184 8.59883C8.67369 8.49791 8.76016 8.41144 8.93311 8.23849L12.99 4.18163Z"
stroke="currentColor"
stroke-width="1.2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12 5L15 8"
stroke="currentColor"
stroke-width="1.2"
stroke-linejoin="round"
/>
</svg>Customize your ticket</a
<Button href="/init/tickets/customize">
<Icon name="customize" /> Customize your ticket</Button
>
{:else}
<button
onclick={handleLogin}
class="web-button flex items-center gap-4"
disabled={claiming}
>
<Button onclick={handleLogin} disabled={claiming}>
{#if claiming}
<Spinner />
{:else}
<span class="web-icon-github text-primary"></span>
{/if}Claim your ticket</button
<Icon name="github" />
{/if}Claim your ticket</Button
>
{/if}
<a href="https://producthunt.com" class="web-button is-secondary">
<Button
href="https://producthunt.com"
variant="secondary"
target="_blank"
rel="noopener"
>
Follow on Product Hunt
</a>
</Button>
</nav>
</div>
</div>

View File

@@ -21,7 +21,8 @@
>
<div class="flex items-center justify-between px-1.5 pt-1 pb-2">
{#if link}
<span class="font-aeonik-fono tracking-loose text-micro text-primary pl-2 uppercase"
<span
class="font-aeonik-fono tracking-loose text-micro text-primary flex pl-2 uppercase"
>{@render link()}</span
>
{:else}

View File

@@ -31,7 +31,7 @@ export const load = async () => {
const updateSchema = zfd.formData({
name: zfd.text(),
title: zfd.text(),
sticker: zfd.text()
sticker: zfd.text().nullish()
});
export const actions = {

View File

@@ -3,7 +3,7 @@
</script>
<script lang="ts">
import { dequal } from 'dequal/lite';
import { isDeepEqual } from 'remeda';
import Sites from '../../(assets)/stickers/sites.webp';
import Flutter from '../../(assets)/stickers/flutter.webp';
@@ -15,31 +15,41 @@
import { enhance } from '$app/forms';
import { classNames } from '$lib/utils/classnames';
import TicketCard from '../(components)/ticket-card.svelte';
import { Icon } from '$lib/components/ui';
import { Button, Icon } from '$lib/components/ui';
let { data } = $props();
let originalName = $state(data.ticket?.name ?? '');
let name = $derived(originalName.split(' ')[0]);
let originalTitle = $state(data.ticket?.title ?? '');
let derivedTitle = $derived(originalTitle);
let originalSticker = $state(data.ticket.sticker);
let sticker = $derived(originalSticker);
let editing = $state(false);
let originalTicketData = $state({
name: data.ticket?.name ?? '',
title: data.ticket?.title ?? '',
sticker: data.ticket.sticker
});
let saving: boolean = $state(false);
let saved: boolean = $state(false);
let updatedTicketData = $derived({
name: originalTicketData.name.split(' ')[0],
title: originalTicketData.title,
sticker: originalTicketData.sticker
});
let modified = $derived(
!dequal(
{
name: originalName,
title: originalTitle,
sticker: originalSticker
},
{ name, derivedTitle, sticker }
)
);
let formState = $state({
editing: false,
saving: false,
saved: false
});
let isModified = $derived(!isDeepEqual(originalTicketData, updatedTicketData));
$effect(() => {
if (formState.saved) {
const timeout = setTimeout(() => {
formState.saved = false;
}, 2000);
return () => {
clearTimeout(timeout);
};
}
});
</script>
<svelte:head>
@@ -52,7 +62,7 @@
<Window class="container my-10">
{#snippet link()}
<a href="/init" class="group flex gap-1 uppercase">
<a href="/init" class="group flex items-center gap-2 uppercase">
<Icon name="chevron-left" class="transition-transform group-hover:-translate-x-0.5" />
Back</a
>
@@ -73,19 +83,13 @@
method="POST"
class="mt-4 flex flex-1 flex-col gap-4"
use:enhance={async () => {
saving = true;
formState.saving = true;
return async ({ result, update }) => {
if (result.type === 'success') {
originalName = name;
originalTitle = derivedTitle;
originalSticker = sticker;
saved = true;
saving = false;
const timeout = setTimeout(() => {
saved = false;
}, 3000);
originalTicketData = updatedTicketData;
formState.saved = true;
formState.saving = false;
}
update({ reset: false });
};
@@ -98,9 +102,9 @@
>First name</label
>
<input
bind:value={name}
onfocus={() => (editing = true)}
onblur={() => (editing = false)}
bind:value={originalTicketData.name}
onfocus={() => (formState.editing = true)}
onblur={() => (formState.editing = false)}
type="text"
name="name"
class="bg-smooth border-offset w-full appearance-none rounded-lg border p-2"
@@ -113,7 +117,7 @@
>Title</label
>
<input
bind:value={derivedTitle}
bind:value={originalTicketData.title}
type="text"
name="title"
class="bg-smooth border-offset w-full appearance-none rounded-lg border p-2"
@@ -131,7 +135,9 @@
<div
class={classNames(
'relative flex aspect-square w-full items-center justify-center rounded-[2px] border-black bg-black outline-2 outline-[var(--color-offset)] outline-dashed',
sticker === null ? 'outline-white' : 'outline-[var(--color-offset)]'
originalTicketData.sticker === null
? 'outline-white'
: 'outline-[var(--color-offset)]'
)}
>
<input
@@ -139,7 +145,7 @@
class="absolute inset-0 appearance-none border-none"
name="sticker"
value=""
onclick={() => (sticker = null)}
onclick={() => (originalTicketData.sticker = null)}
/>
<div
class="text-tertiary font-aeonik-fono tracking-loose text-micro bg-smooth flex size-[calc(100%_-_6px)] items-center justify-center rounded-[1px] p-1 uppercase"
@@ -152,7 +158,7 @@
<div
class={classNames(
'relative flex aspect-square w-full items-center justify-center rounded-sm bg-black outline-2 [outline-offset:-1px] transition outline-dashed',
sticker === i
originalTicketData.sticker === i
? 'outline-white'
: 'outline-[var(--color-offset)]'
)}
@@ -162,7 +168,7 @@
class="absolute inset-0 appearance-none border-none"
name="sticker"
value={i}
onclick={() => (sticker = i)}
onclick={() => (originalTicketData.sticker = i)}
/>
<div
class="bg-smooth flex size-[calc(100%_-_6px)] items-center justify-center rounded-[1px] p-1"
@@ -173,33 +179,41 @@
{/each}
</div>
</div>
<button
type="submit"
class="web-button is-secondary w-full!"
disabled={!modified || saving}
>
{#if saving}
<Button type="submit" class="w-full!" variant="secondary">
{#if formState.saving}
Saving
{:else if saved}
{:else if formState.saved}
Saved
{:else}
Save
{/if}
</button>
</Button>
</form>
</div>
<div
class="bg-smooth relative flex w-full flex-col items-center justify-center gap-8 rounded-xl p-4 outline-2 [outline-offset:-2px] outline-[var(--color-offset)] outline-dashed md:col-span-9 md:flex-row"
>
<div class="flex flex-col items-center gap-4 uppercase">
<TicketCard {...data.ticket} {name} title={derivedTitle} {editing} disableEffects />
<TicketCard
{...data.ticket}
name={originalTicketData.name}
title={originalTicketData.title}
editing={formState.editing}
disableEffects
/>
<span
class="font-aeonik-fono tracking-loose text-x-micro text-primary transition-opacity peer-hover:opacity-0"
>Front</span
>
</div>
<div class="flex flex-col items-center gap-4 uppercase">
<TicketCard {...data.ticket} {sticker} disableEffects flipped {stickerPack} />
<TicketCard
{...data.ticket}
sticker={updatedTicketData.sticker}
disableEffects
flipped
{stickerPack}
/>
<span
class="font-aeonik-fono tracking-loose text-x-micro text-primary transition duration-300 peer-hover:opacity-0 peer-hover:blur-sm"
>Back</span