Fix profile update and toast works now.

This commit is contained in:
Bradley Shellnut 2024-02-27 22:49:21 -08:00
parent d9c1f55071
commit 3596a5dcd6
6 changed files with 73 additions and 71 deletions

View file

@ -57,7 +57,7 @@
"satori": "^0.10.13", "satori": "^0.10.13",
"satori-html": "^0.3.2", "satori-html": "^0.3.2",
"svelte": "^4.2.12", "svelte": "^4.2.12",
"svelte-check": "^3.6.4", "svelte-check": "^3.6.5",
"svelte-meta-tags": "^3.1.0", "svelte-meta-tags": "^3.1.0",
"svelte-preprocess": "^5.1.3", "svelte-preprocess": "^5.1.3",
"svelte-sequential-preprocessor": "^2.0.1", "svelte-sequential-preprocessor": "^2.0.1",
@ -85,7 +85,7 @@
"@lucia-auth/adapter-drizzle": "^1.0.2", "@lucia-auth/adapter-drizzle": "^1.0.2",
"@lucia-auth/adapter-prisma": "4.0.0", "@lucia-auth/adapter-prisma": "4.0.0",
"@lukeed/uuid": "^2.0.1", "@lukeed/uuid": "^2.0.1",
"@neondatabase/serverless": "^0.8.1", "@neondatabase/serverless": "^0.9.0",
"@paralleldrive/cuid2": "^2.2.2", "@paralleldrive/cuid2": "^2.2.2",
"@planetscale/database": "^1.16.0", "@planetscale/database": "^1.16.0",
"@prisma/client": "^5.9.1", "@prisma/client": "^5.9.1",
@ -93,7 +93,7 @@
"@sveltejs/adapter-vercel": "^5.1.0", "@sveltejs/adapter-vercel": "^5.1.0",
"@types/feather-icons": "^4.29.4", "@types/feather-icons": "^4.29.4",
"@vercel/og": "^0.5.20", "@vercel/og": "^0.5.20",
"bits-ui": "^0.18.3", "bits-ui": "^0.18.4",
"boardgamegeekclient": "^1.9.1", "boardgamegeekclient": "^1.9.1",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.0", "clsx": "^2.1.0",

View file

@ -24,8 +24,8 @@ dependencies:
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.0.1 version: 2.0.1
'@neondatabase/serverless': '@neondatabase/serverless':
specifier: ^0.8.1 specifier: ^0.9.0
version: 0.8.1 version: 0.9.0
'@paralleldrive/cuid2': '@paralleldrive/cuid2':
specifier: ^2.2.2 specifier: ^2.2.2
version: 2.2.2 version: 2.2.2
@ -48,8 +48,8 @@ dependencies:
specifier: ^0.5.20 specifier: ^0.5.20
version: 0.5.20 version: 0.5.20
bits-ui: bits-ui:
specifier: ^0.18.3 specifier: ^0.18.4
version: 0.18.3(svelte@4.2.12) version: 0.18.4(svelte@4.2.12)
boardgamegeekclient: boardgamegeekclient:
specifier: ^1.9.1 specifier: ^1.9.1
version: 1.9.1 version: 1.9.1
@ -64,7 +64,7 @@ dependencies:
version: 0.6.0 version: 0.6.0
drizzle-orm: drizzle-orm:
specifier: ^0.29.4 specifier: ^0.29.4
version: 0.29.4(@neondatabase/serverless@0.8.1)(@planetscale/database@1.16.0)(@types/pg@8.11.2)(mysql2@3.9.2)(pg@8.11.3)(postgres@3.4.3) version: 0.29.4(@neondatabase/serverless@0.9.0)(@planetscale/database@1.16.0)(@types/pg@8.11.2)(mysql2@3.9.2)(pg@8.11.3)(postgres@3.4.3)
feather-icons: feather-icons:
specifier: ^4.29.1 specifier: ^4.29.1
version: 4.29.1 version: 4.29.1
@ -227,8 +227,8 @@ devDependencies:
specifier: ^4.2.12 specifier: ^4.2.12
version: 4.2.12 version: 4.2.12
svelte-check: svelte-check:
specifier: ^3.6.4 specifier: ^3.6.5
version: 3.6.4(postcss-load-config@5.0.3)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12) version: 3.6.5(postcss-load-config@5.0.3)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12)
svelte-meta-tags: svelte-meta-tags:
specifier: ^3.1.0 specifier: ^3.1.0
version: 3.1.0(svelte@4.2.12)(typescript@5.3.3) version: 3.1.0(svelte@4.2.12)(typescript@5.3.3)
@ -1915,13 +1915,6 @@ packages:
'@jridgewell/resolve-uri': 3.1.1 '@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/sourcemap-codec': 1.4.15
/@jridgewell/trace-mapping@0.3.22:
resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==}
dependencies:
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@jridgewell/trace-mapping@0.3.23: /@jridgewell/trace-mapping@0.3.23:
resolution: {integrity: sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==} resolution: {integrity: sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==}
dependencies: dependencies:
@ -2033,8 +2026,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@neondatabase/serverless@0.8.1: /@neondatabase/serverless@0.9.0:
resolution: {integrity: sha512-nxZfTLbGqvDrw0W9WnQxzoPn4KC6SLjkvK4grdf6eWVMQSc24X+8udz9inZWOGu8f0O3wJAq586fCZ32r22lwg==} resolution: {integrity: sha512-mmJnUAzlzvxNSZuuhI6kgJjH+JgFdBMYUWxihtq/nj0Tjt+Y5UU3W+SvRFoucnd5NObYkuLYQzk+zV5DGFKGJg==}
dependencies: dependencies:
'@types/pg': 8.6.6 '@types/pg': 8.6.6
dev: false dev: false
@ -3793,8 +3786,8 @@ packages:
file-uri-to-path: 1.0.0 file-uri-to-path: 1.0.0
dev: false dev: false
/bits-ui@0.18.3(svelte@4.2.12): /bits-ui@0.18.4(svelte@4.2.12):
resolution: {integrity: sha512-kcEJWiOHlHv1R3EAmkVDdTnvucT3A5VL4h5ORkJjGUDrpCtPFoMO7jDF6P9XwpD3qVfIVQhN4OldPRNMXW9/RQ==} resolution: {integrity: sha512-Xw0DdjT21rJ1ICTy3CHXAKy6is3phXRqjpNwRZldC3A316thRCJn+viEtTifgh4kI+qCm5VutzBqsrimFd+CSA==}
peerDependencies: peerDependencies:
svelte: ^4.0.0 svelte: ^4.0.0
dependencies: dependencies:
@ -4302,7 +4295,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/drizzle-orm@0.29.4(@neondatabase/serverless@0.8.1)(@planetscale/database@1.16.0)(@types/pg@8.11.2)(mysql2@3.9.2)(pg@8.11.3)(postgres@3.4.3): /drizzle-orm@0.29.4(@neondatabase/serverless@0.9.0)(@planetscale/database@1.16.0)(@types/pg@8.11.2)(mysql2@3.9.2)(pg@8.11.3)(postgres@3.4.3):
resolution: {integrity: sha512-ZnSM8TAxFhzH7p1s3+w3pRE/eKaOeNkH9SKitm717pubDVVcV2I0BCDBPGKV+pe02+wMfw37ntlTcCyo2rA3IA==} resolution: {integrity: sha512-ZnSM8TAxFhzH7p1s3+w3pRE/eKaOeNkH9SKitm717pubDVVcV2I0BCDBPGKV+pe02+wMfw37ntlTcCyo2rA3IA==}
peerDependencies: peerDependencies:
'@aws-sdk/client-rds-data': '>=3' '@aws-sdk/client-rds-data': '>=3'
@ -4373,7 +4366,7 @@ packages:
sqlite3: sqlite3:
optional: true optional: true
dependencies: dependencies:
'@neondatabase/serverless': 0.8.1 '@neondatabase/serverless': 0.9.0
'@planetscale/database': 1.16.0 '@planetscale/database': 1.16.0
'@types/pg': 8.11.2 '@types/pg': 8.11.2
mysql2: 3.9.2 mysql2: 3.9.2
@ -7113,13 +7106,13 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
/svelte-check@3.6.4(postcss-load-config@5.0.3)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12): /svelte-check@3.6.5(postcss-load-config@5.0.3)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12):
resolution: {integrity: sha512-mY/dqucqm46p72M8yZmn81WPZx9mN6uuw8UVfR3ZKQeLxQg5HDGO3HHm5AZuWZPYNMLJ+TRMn+TeN53HfQ/vsw==} resolution: {integrity: sha512-5aLgoQEdadvp8ypvKQ2avhnQ+V9YPQQaWrTFlXFw5g/v8xIQBvo+X/WqxTyD+V/ItDqXg3+abUA53rdDHgUjCA==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0
dependencies: dependencies:
'@jridgewell/trace-mapping': 0.3.22 '@jridgewell/trace-mapping': 0.3.23
chokidar: 3.6.0 chokidar: 3.6.0
fast-glob: 3.3.2 fast-glob: 3.3.2
import-fresh: 3.3.0 import-fresh: 3.3.0

View file

@ -16,16 +16,22 @@ export const load: PageServerLoad = async (event) => {
const { user } = event.locals; const { user } = event.locals;
const dbUser = await db.query
.users
.findFirst({
where: eq(users.id, user.id)
});
const profileForm = await superValidate(zod(profileSchema), { const profileForm = await superValidate(zod(profileSchema), {
defaults: { defaults: {
firstName: user.firstName, firstName: dbUser?.first_name || '',
lastName: user.lastName, lastName: dbUser?.last_name || '',
username: user.username username: dbUser?.username || '',
} }
}); });
const emailForm = await superValidate(zod(changeEmailSchema), { const emailForm = await superValidate(zod(changeEmailSchema), {
defaults: { defaults: {
email: user.email email: dbUser?.email || '',
} }
}); });
@ -36,7 +42,7 @@ export const load: PageServerLoad = async (event) => {
}; };
export const actions: Actions = { export const actions: Actions = {
default: async (event) => { profileUpdate: async (event) => {
const form = await superValidate(event, zod(profileSchema)); const form = await superValidate(event, zod(profileSchema));
if (!form.valid) { if (!form.valid) {
@ -82,7 +88,7 @@ export const actions: Actions = {
} }
console.log('profile updated successfully'); console.log('profile updated successfully');
return message(form, 'Profile updated successfully.'); return message(form, { type: 'success', message: 'Profile updated successfully!' });
}, },
changeEmail: async (event) => { changeEmail: async (event) => {
const form = await superValidate(event, zod(changeEmailSchema)); const form = await superValidate(event, zod(changeEmailSchema));
@ -104,7 +110,7 @@ export const actions: Actions = {
}); });
if (existingUser && existingUser.id !== user.id) { if (existingUser && existingUser.id !== user.id) {
return setError(form, 'email', 'That email is already taken'); return setError(form, 'email', { type: 'error', message: 'That email is already taken' });
} }
await db await db
@ -127,5 +133,7 @@ export const actions: Actions = {
// receiveEmail: false // receiveEmail: false
// }); // });
} }
return message(form, { type: 'success', message: 'Email updated successfully!' });
} }
}; };

View file

@ -1,9 +1,11 @@
<script lang="ts"> <script lang="ts">
import { zodClient } from 'sveltekit-superforms/adapters'; import { zodClient } from 'sveltekit-superforms/adapters';
import { superForm } from 'sveltekit-superforms/client'; import { superForm } from 'sveltekit-superforms/client';
import * as flashModule from 'sveltekit-flash-message/client';
import { AlertTriangle, KeyRound } from 'lucide-svelte'; import { AlertTriangle, KeyRound } from 'lucide-svelte';
import { changeEmailSchema, profileSchema } from '$lib/validations/account'; import { changeEmailSchema, profileSchema } from '$lib/validations/account';
import * as Alert from "$lib/components/ui/alert"; import * as Alert from "$lib/components/ui/alert";
// import * as Form from '$lib/components/ui/form';
import { Label } from '$lib/components/ui/label'; import { Label } from '$lib/components/ui/label';
import { Input } from '$components/ui/input'; import { Input } from '$components/ui/input';
import { Button } from '$components/ui/button'; import { Button } from '$components/ui/button';
@ -13,7 +15,12 @@
const { form: profileForm, errors: profileErrors, enhance: profileEnhance } = superForm(data.profileForm, { const { form: profileForm, errors: profileErrors, enhance: profileEnhance } = superForm(data.profileForm, {
taintedMessage: null, taintedMessage: null,
validators: zodClient(profileSchema), validators: zodClient(profileSchema),
delayMs: 0 delayMs: 500,
multipleSubmits: 'prevent',
syncFlashMessage: true,
flashMessage: {
module: flashModule,
}
}); });
const { form: emailForm, errors: emailErrors, enhance: emailEnhance } = superForm(data.emailForm, { const { form: emailForm, errors: emailErrors, enhance: emailEnhance } = superForm(data.emailForm, {
@ -23,18 +30,9 @@
}); });
</script> </script>
<form method="POST" use:profileEnhance> <form method="POST" action="?/profileUpdate" use:profileEnhance>
<!--<SuperDebug data={$form} />-->
<h3>Your Profile</h3> <h3>Your Profile</h3>
<hr class="!border-t-2 mt-2 mb-6" /> <hr class="!border-t-2 mt-2 mb-6" />
{#if $message}
<aside class="alert variant-filled-success mt-6">
<!-- Message -->
<div class="alert-message">
<p>{$message}</p>
</div>
</aside>
{/if}
<div class="mt-6"> <div class="mt-6">
<Label for="username">Username</Label> <Label for="username">Username</Label>
<Input type="text" id="username" name="username" placeholder="Username" autocomplete="username" data-invalid={$profileErrors.username} bind:value={$profileForm.username} /> <Input type="text" id="username" name="username" placeholder="Username" autocomplete="username" data-invalid={$profileErrors.username} bind:value={$profileForm.username} />
@ -56,6 +54,7 @@
<small>{$profileErrors.lastName}</small> <small>{$profileErrors.lastName}</small>
{/if} {/if}
</div> </div>
<Button type="submit" class="w-full mt-3">Update Profile</Button>
</form> </form>
<form method="POST" action="?/changeEmail" use:emailEnhance> <form method="POST" action="?/changeEmail" use:emailEnhance>
<div class="grid gap-2 mt-6"> <div class="grid gap-2 mt-6">
@ -65,24 +64,17 @@
id="email" id="email"
name="email" name="email"
placeholder="Email Address" placeholder="Email Address"
autocorrect="off"
autocomplete="email"
data-invalid={$profileErrors.email}
bind:value={$profileForm.email}
/>
<!-- <Input
type="email"
autocapitalize="none" autocapitalize="none"
autocorrect="off" autocorrect="off"
autocomplete="username" autocomplete="email"
bind:value={$profileFormData.email} data-invalid={$emailErrors.email}
{...attrs} bind:value={$emailForm.email}
{...constraints} />
/> --> {#if $emailErrors.email}
{#if $profileErrors.email} <small>{$emailErrors.email}</small>
<small>{$profileErrors.email}</small>
{/if} {/if}
{#if !$profileForm.email} <Button type="submit" class="w-full">Update Email</Button>
{#if !$emailForm.email}
<Alert.Root variant="destructive"> <Alert.Root variant="destructive">
<AlertTriangle class="h-4 w-4" /> <AlertTriangle class="h-4 w-4" />
<Alert.Title>Heads up!</Alert.Title> <Alert.Title>Heads up!</Alert.Title>
@ -92,6 +84,7 @@
</Alert.Root> </Alert.Root>
{/if} {/if}
</div> </div>
</form>
<div class="mt-6"> <div class="mt-6">
<Button variant="link" class="text-secondary-foreground" href="/password/change"> <Button variant="link" class="text-secondary-foreground" href="/password/change">
<KeyRound class="mr-2 h-4 w-4" /> <KeyRound class="mr-2 h-4 w-4" />
@ -99,14 +92,6 @@
</Button> </Button>
</div> </div>
<div class="mt-6">
<Button type="submit" class="w-full">Update Profile</Button>
<!-- <button type="submit" class="btn variant-filled-primary w-full"
>{#if $delayed}<ConicGradient stops={conicStops} spin width="w-6" />{:else}Update Profile{/if}</button
> -->
</div>
</form>
<style lang="postcss"> <style lang="postcss">
form { form {
width: 20rem; width: 20rem;

View file

@ -3,7 +3,7 @@
import { superForm } from 'sveltekit-superforms/client'; import { superForm } from 'sveltekit-superforms/client';
import * as flashModule from 'sveltekit-flash-message/client'; import * as flashModule from 'sveltekit-flash-message/client';
import { AlertCircle } from "lucide-svelte"; import { AlertCircle } from "lucide-svelte";
import { signInSchema } from '$lib/validations/zod-schemas.js'; import { signInSchema } from '$lib/validations/auth';
import { Label } from '$components/ui/label'; import { Label } from '$components/ui/label';
import { Input } from '$components/ui/input'; import { Input } from '$components/ui/input';
import { Button } from '$components/ui/button'; import { Button } from '$components/ui/button';

View file

@ -29,9 +29,11 @@
...$page.data.metaTagsChild ...$page.data.metaTagsChild
} }
// const flash = getFlash(page, { const flash = getFlash(page, {
// clearAfterMs: 6000 clearOnNavigate: true,
// }); clearAfterMs: 3000,
clearArray: true
});
onMount(() => { onMount(() => {
// set the theme to the user's active theme // set the theme to the user's active theme
@ -39,6 +41,20 @@
document.querySelector('html')?.setAttribute('data-theme', $theme); document.querySelector('html')?.setAttribute('data-theme', $theme);
}); });
$: if ($flash) {
if ($flash.type === 'success') {
toast.success($flash.message);
} else {
toast.error($flash.message, {
duration: 5000
});
}
// Clearing the flash message could sometimes
// be required here to avoid double-toasting.
flash.set(undefined);
}
// flash.subscribe(($flash) => { // flash.subscribe(($flash) => {
// if (!$flash) return; // if (!$flash) return;