From: Muhammad Rizki <[email protected]>
To: Ammar Faizi <[email protected]>
Cc: Muhammad Rizki <[email protected]>,
Alviro Iskandar Setiawan <[email protected]>,
Dwiky Rizky Ananditya <[email protected]>,
GNU/Weeb Mailing List <[email protected]>
Subject: [PATCH v1 15/17] feat(routes): add login page
Date: Sun, 19 Jan 2025 08:11:32 +0700 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
this page includes login form and its page authentication handler.
Signed-off-by: Muhammad Rizki <[email protected]>
---
src/routes/+page.svelte | 124 +++++++++++++++++++++++++++++++++++++++-
src/routes/+page.ts | 17 ++++++
2 files changed, 139 insertions(+), 2 deletions(-)
create mode 100644 src/routes/+page.ts
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index cc88df0..46ef170 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,2 +1,122 @@
-<h1>Welcome to SvelteKit</h1>
-<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
+<script lang="ts">
+ import Loading from "$components/customs/loading.svelte";
+ import { Button } from "$components/ui/button";
+ import * as Card from "$components/ui/card";
+ import * as Form from "$components/ui/form";
+ import { Input } from "$components/ui/input";
+ import InputPassword from "$components/ui/input/input-password.svelte";
+ import { useAuth } from "$lib/hooks/auth.svelte";
+ import { useHttp } from "$lib/hooks/http.svelte";
+ import { loginSchema } from "$lib/schemas/login";
+ import type { LoginResponse, User } from "$typings";
+ import { superForm, setError, setMessage } from "sveltekit-superforms";
+ import { zod } from "sveltekit-superforms/adapters";
+
+ let { data } = $props();
+
+ const auth = useAuth();
+
+ const form = superForm(data.form, {
+ SPA: true,
+ validators: zod(loginSchema),
+
+ async onUpdate({ form }) {
+ const http = useHttp<LoginResponse, User>({
+ action: "login",
+ method: "POST",
+
+ payload: {
+ user: form.data.username_or_email,
+ pass: form.data.password
+ },
+
+ formatter(data, resp) {
+ data = resp?.data.res?.user_info!;
+ },
+
+ onComplete(resp) {
+ auth.save(resp.data.res!);
+ },
+
+ onError(_, errorMessage) {
+ setError(form, "username_or_email", "");
+ setError(form, "password", "");
+ setMessage(form, errorMessage);
+ }
+ });
+
+ await http.execute();
+ }
+ });
+
+ const isError = () => Boolean($errors.username_or_email && $errors.password);
+ const isValid = () => Boolean($formData.username_or_email && $formData.password);
+
+ const { form: formData, errors, message, submitting, constraints, enhance } = form;
+</script>
+
+<div class="mx-auto flex min-h-screen w-full items-center justify-center px-3 py-2">
+ <Card.Root class="w-full max-w-lg">
+ <form method="POST" use:enhance>
+ <Card.Header class="flex items-center justify-center space-y-1">
+ <Card.Title class="text-2xl">GNU/Weeb Mail Login</Card.Title>
+ <Card.Description>Proceed login to manager your email account</Card.Description>
+
+ {#if isError()}
+ <span class="text-sm font-medium text-destructive">
+ {$message}
+ </span>
+ {/if}
+ </Card.Header>
+
+ <Card.Content class="grid gap-4">
+ <Form.Field {form} name="username_or_email" class="grid gap-1">
+ <Form.Control>
+ {#snippet children({ props })}
+ <Form.Label>Username or Email</Form.Label>
+ <Input
+ {...props}
+ aria-invalid={$errors.username_or_email ? "true" : undefined}
+ bind:value={$formData.username_or_email}
+ placeholder="[email protected]"
+ disabled={$submitting}
+ {...$constraints.username_or_email}
+ />
+ <Form.FieldErrors />
+ {/snippet}
+ </Form.Control>
+ </Form.Field>
+
+ <Form.Field {form} name="password" class="grid gap-2">
+ <Form.Control>
+ {#snippet children({ props })}
+ <Form.Label>Password</Form.Label>
+ <InputPassword
+ {...props}
+ aria-invalid={$errors.password ? "true" : undefined}
+ bind:value={$formData.password}
+ placeholder="Enter password"
+ disabled={$submitting}
+ {...$constraints.password}
+ />
+ <Form.FieldErrors />
+ {/snippet}
+ </Form.Control>
+ </Form.Field>
+ </Card.Content>
+
+ <Card.Footer>
+ <Button
+ type="submit"
+ class="mt-3 flex w-full gap-x-2"
+ disabled={$submitting || !isValid() || isError()}
+ >
+ <span>Login</span>
+ {#if $submitting}
+ <Loading />
+ {/if}
+ </Button>
+ </Card.Footer>
+ </form>
+ </Card.Root>
+</div>
diff --git a/src/routes/+page.ts b/src/routes/+page.ts
new file mode 100644
index 0000000..99ac97a
--- /dev/null
+++ b/src/routes/+page.ts
@@ -0,0 +1,17 @@
+import { loginSchema } from "$lib/schemas/login";
+import { superValidate } from "sveltekit-superforms";
+import { zod } from "sveltekit-superforms/adapters";
+import type { PageLoad } from "./$types";
+import { useAuth } from "$lib/hooks/auth.svelte";
+import { redirect } from "@sveltejs/kit";
+
+export const load: PageLoad = async () => {
+ const auth = useAuth();
+
+ if (auth.isValid()) return redirect(307, "/home");
+
+ const data = { email: "", password: "" };
+ const form = await superValidate(data, zod(loginSchema));
+
+ return { form };
+};
--
Muhammad Rizki
next prev parent reply other threads:[~2025-01-19 1:12 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-19 1:11 [PATCH RESEND v1 00/17] Refactor GNU/Weeb Mail Site Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 01/17] feat: initial front-end Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 02/17] feat(routes): configure page layout options Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 03/17] feat(fonts): add Google fonts Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 04/17] feat(components): add shadcn-svelte components Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 05/17] feat(deps): add `axios` as HTTP client Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 06/17] feat(deps): add `svelte-copy` dependency Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 07/17] feat(constants): add navigations and mail-config constant Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 08/17] feat(components): add loading spinner component Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 09/17] feat(components): add header component Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 10/17] feat: initial hooks, schemas, typings for the login functions Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 11/17] feat(components): add app-sidebar component Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 12/17] feat(routes): create initial settings page Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 13/17] feat(routes): add home page Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 14/17] feat(routes): add main layout for the protected routes Muhammad Rizki
2025-01-19 1:11 ` Muhammad Rizki [this message]
2025-01-19 1:11 ` [PATCH v1 16/17] chore(.gitignore): add patch files ignore Muhammad Rizki
2025-01-19 1:11 ` [PATCH v1 17/17] chore: update README.md Muhammad Rizki
2025-01-19 19:53 ` [PATCH RESEND v1 00/17] Refactor GNU/Weeb Mail Site Ammar Faizi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox