Skip to content

Commit

Permalink
add form validation via zod
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Aug 8, 2024
1 parent 4e0f890 commit 554f667
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 18 deletions.
12 changes: 11 additions & 1 deletion kitsune-fe/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion kitsune-fe/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"typescript": "^5.5.4",
"unplugin-icons": "^0.19.1",
"vite": "^5.3.5",
"vitest": "^2.0.5"
"vitest": "^2.0.5",
"zod": "^3.23.8"
},
"type": "module"
}
39 changes: 23 additions & 16 deletions kitsune-fe/src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import Dialog from '$lib/components/Dialog.svelte';
import type { PageData } from './$houdini';
import IconThreeDotsLoading from '~icons/eos-icons/three-dots-loading?raw&width=2em&height=2em';
import { _registerSchema } from './+page';
const { data }: { data: PageData } = $props();
Expand All @@ -16,40 +17,44 @@
const register = new RegisterUserStore();
let registerButtonDisabled = $state(false);
let registerError = $state();
let registerErrors: string[] = $state([]);
let registerErrorDialogOpen = $state(false);
async function doRegister(event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement }) {
event.preventDefault();
registerButtonDisabled = true;
const formData = new FormData(event.currentTarget);
const [username, email, password, confirmPassword] = [
formData.get('username')!.toString(),
formData.get('email')!.toString(),
formData.get('password')!.toString(),
formData.get('confirm-password')!.toString()
];
if (password !== confirmPassword) {
registerError = 'Passwords do not match';
const validatedData = await _registerSchema.safeParseAsync(
Object.fromEntries(formData.entries())
);
if (!validatedData.success) {
const formattedErrors = validatedData.error.format(
(issue) => `${issue.path.join(', ')}: ${issue.message}`
);
registerErrors = Object.values(formattedErrors).flatMap((error) =>
'_errors' in error ? error._errors : error
);
registerErrorDialogOpen = true;
registerButtonDisabled = false;
return;
}
try {
const result = await register.mutate({ username, email, password });
const result = await register.mutate(validatedData.data);
if (result.errors) {
registerError = result.errors.map((error) => error.message).join(', ');
registerErrors = result.errors.map((error) => error.message);
registerErrorDialogOpen = true;
} else {
event.currentTarget.reset();
initiateLogin();
}
} catch (reason: unknown) {
if (reason instanceof Error) {
registerError = reason.message;
registerErrors = [reason.message];
}
registerErrorDialogOpen = true;
Expand All @@ -66,9 +71,11 @@
<Dialog isOpen={registerErrorDialogOpen}>
<h2>Registration failed!</h2>

<p>
{registerError}
</p>
<ol>
{#each registerErrors as error}
<li>{error}</li>
{/each}
</ol>

<button onclick={() => (registerErrorDialogOpen = false)}>Close</button>
</Dialog>
Expand Down
15 changes: 15 additions & 0 deletions kitsune-fe/src/routes/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { z } from 'zod';

const _registerSchema = z
.object({
username: z.string().min(1),
email: z.string().email(),
password: z.string().min(1),
'confirm-password': z.string().min(1)
})
.refine((data) => data.password === data['confirm-password'], {
message: 'Passwords do not match',
path: ['confirm-password']
});

export { _registerSchema };

0 comments on commit 554f667

Please sign in to comment.