aboutsummaryrefslogtreecommitdiffstats
path: root/website/src/routes/welcome/+page.svelte
diff options
context:
space:
mode:
Diffstat (limited to 'website/src/routes/welcome/+page.svelte')
-rw-r--r--website/src/routes/welcome/+page.svelte219
1 files changed, 219 insertions, 0 deletions
diff --git a/website/src/routes/welcome/+page.svelte b/website/src/routes/welcome/+page.svelte
new file mode 100644
index 0000000..863b69f
--- /dev/null
+++ b/website/src/routes/welcome/+page.svelte
@@ -0,0 +1,219 @@
+<script lang="ts">
+ import { enhance } from '$app/forms';
+ import type { ActionData } from './$types';
+
+ type FormFailure = {
+ errors: { username?: string[]; bio?: string[] };
+ data: { username?: string; bio?: string };
+ };
+ const domain = 'sellershut.com';
+
+ let { form }: { form: ActionData } = $props();
+
+ const formError = $derived(form && 'errors' in form ? (form as FormFailure) : null);
+ const errors = $derived(formError?.errors);
+
+ let username = $state('');
+ let bio = $state('');
+ let avatarPreview = $state<string | null>(null);
+
+ let canSubmit = $derived(username.trim().length >= 3);
+
+ function handleFileChange(e: Event) {
+ const target = e.target as HTMLInputElement;
+ if (target.files && target.files[0]) {
+ const reader = new FileReader();
+ reader.onload = (e) => (avatarPreview = e.target?.result as string);
+ reader.readAsDataURL(target.files[0]);
+ }
+ }
+ $effect(() => {
+ if (formError?.data?.username) username = formError.data.username;
+ if (formError?.data?.bio) bio = formError.data.bio;
+ });
+</script>
+
+<form
+ method="POST"
+ use:enhance
+ enctype="multipart/form-data"
+ class="w-full max-w-md overflow-hidden rounded-3xl border border-rose-100 bg-white shadow-xl"
+>
+ <div class="relative h-32 bg-linear-to-r from-rose-400 to-rose-600">
+ <div class="absolute -bottom-12 left-1/2 -translate-x-1/2">
+ <div class="group relative cursor-pointer">
+ <div
+ class="h-24 w-24 overflow-hidden rounded-full border-4 border-white bg-rose-100 shadow-md"
+ >
+ {#if avatarPreview}
+ <img src={avatarPreview} alt="Preview" class="h-full w-full object-cover" />
+ {:else}
+ <div class="flex h-full w-full items-center justify-center text-rose-300">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ class="h-10 w-10"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke="currentColor"
+ >
+ <path
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
+ />
+ </svg>
+ </div>
+ {/if}
+ </div>
+
+ <div
+ class="absolute inset-0 flex items-center justify-center rounded-full bg-black/40 opacity-0 transition-opacity duration-200 group-hover:opacity-100"
+ >
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ class="h-6 w-6 text-white"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke="currentColor"
+ stroke-width="2"
+ >
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /><polyline
+ points="17 8 12 3 7 8"
+ /><line x1="12" y1="3" x2="12" y2="15" />
+ </svg>
+ </div>
+ <input
+ type="file"
+ name="avatar"
+ onchange={handleFileChange}
+ class="absolute inset-0 cursor-pointer opacity-0"
+ accept="image/*"
+ />
+ </div>
+ </div>
+ </div>
+
+ <div class="px-8 pt-16 pb-10 text-center">
+ <h1 class="text-2xl font-bold text-gray-800">Final Touches</h1>
+ <p class="mt-1 text-sm text-gray-500">Tell the world a bit about yourself.</p>
+
+ <div class="mt-8 space-y-5 text-left">
+ <div>
+ <label for="email" class="mb-1 ml-1 block text-sm font-semibold text-gray-700">
+ Account Email
+ </label>
+
+ <div
+ class="flex cursor-not-allowed items-center rounded-xl border border-gray-200 bg-gray-50 transition-colors"
+ >
+ <span class="pl-4 text-gray-400">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ class="h-5 w-5"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke="currentColor"
+ >
+ <path
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
+ />
+ </svg>
+ </span>
+
+ <input
+ id="email"
+ name="email"
+ type="email"
+ value="email@domain.com"
+ readonly
+ tabindex="-1"
+ class="flex-1 cursor-not-allowed border-none bg-transparent py-2.5 pr-4 pl-3 text-sm text-gray-500 outline-none focus:ring-0 md:text-base"
+ />
+
+ <span class="pr-4 text-gray-300">
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ class="h-4 w-4"
+ fill="none"
+ viewBox="0 0 24 24"
+ stroke="currentColor"
+ >
+ <path
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
+ />
+ </svg>
+ </span>
+ </div>
+ </div>
+ <div>
+ <label for="username" class="mb-1 ml-1 block text-sm font-semibold text-gray-700">
+ Username
+ </label>
+
+ <div
+ class="group flex items-center rounded-xl border border-gray-200 bg-white transition-all duration-200
+ focus-within:border-rose-400 focus-within:ring-4 focus-within:ring-rose-100
+ {errors?.username
+ ? 'border-red-500 focus-within:border-red-500 focus-within:ring-red-100'
+ : ''}"
+ >
+ <span class="pl-4 text-gray-400 select-none">@</span>
+
+ <input
+ id="username"
+ name="username"
+ type="text"
+ bind:value={username}
+ placeholder="username"
+ class="flex-1 border-none bg-transparent py-2.5 pr-2 pl-1 text-sm outline-none placeholder:text-gray-300 focus:ring-0 md:text-base"
+ />
+
+ <span
+ class="-ml-4 border-l border-gray-100 pr-4 pl-2 text-sm font-medium text-gray-400 select-none md:ml-2"
+ >
+ @{domain}
+ </span>
+ </div>
+
+ {#if errors?.username}
+ <p class="mt-1 ml-1 text-xs text-red-500">{errors.username[0]}</p>
+ {/if}
+ </div>
+ <div>
+ <label for="bio" class="mb-1 ml-1 block text-sm font-semibold text-gray-700"
+ >Bio</label
+ >
+ <textarea
+ id="bio"
+ name="bio"
+ bind:value={bio}
+ rows="3"
+ placeholder="I build cool things with Svelte..."
+ class="block w-full resize-none rounded-xl border border-gray-200 px-4
+ py-2.5 transition-all duration-200 outline-none
+ placeholder:text-gray-300 focus:border-rose-400 focus:ring-4 focus:ring-rose-100 focus:ring-offset-0
+ {errors?.bio ? 'border-red-500 focus:border-red-500 focus:ring-red-100' : ''}"
+ ></textarea>
+ {#if errors?.bio}
+ <p class="mt-1 ml-1 text-xs text-red-500">{errors.bio[0]}</p>
+ {/if}
+ </div>
+
+ <button
+ disabled={!canSubmit}
+ class="flex w-full justify-center rounded-md border border-transparent bg-rose-600 px-4 py-2 text-sm font-medium text-white shadow-sm transition-colors hover:bg-rose-700 focus:ring-2 focus:ring-rose-500 focus:ring-offset-2 focus:outline-none disabled:bg-rose-300"
+ >
+ Finish Setup
+ </button>
+
+ <p class="mt-4 text-center text-[10px] tracking-widest text-gray-400">sellershut.com</p>
+ </div>
+ </div>
+</form>