aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes/(app)/login
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-12-07 15:10:24 -0800
committerAdam Soltys <[email protected]>2023-12-07 15:10:24 -0800
commit00e88944abb529d07e189f1181de8a4804f8ae9c (patch)
treeed161bcbf918b56b37d3c3417d6f4d5616f82ee8 /src/routes/(app)/login
parentae9106030759a88d0259a12b27a7cd0f2a422062 (diff)
downloadcoinos-ui-00e88944abb529d07e189f1181de8a4804f8ae9c.tar.gz
coinos-ui-00e88944abb529d07e189f1181de8a4804f8ae9c.zip
forgot password
Diffstat (limited to 'src/routes/(app)/login')
-rw-r--r--src/routes/(app)/login/+page.svelte175
1 files changed, 172 insertions, 3 deletions
diff --git a/src/routes/(app)/login/+page.svelte b/src/routes/(app)/login/+page.svelte
index 647ef03c..61eea586 100644
--- a/src/routes/(app)/login/+page.svelte
+++ b/src/routes/(app)/login/+page.svelte
@@ -1,7 +1,18 @@
<script>
- import RegisterOrLogin from "$comp/RegisterOrLogin.svelte";
import { onMount } from "svelte";
- import { pin } from "$lib/store";
+ import { applyAction, deserialize } from "$app/forms";
+ import { tick } from "svelte";
+ import { fly } from "svelte/transition";
+ import { enhance } from "$app/forms";
+ import Pin from "$comp/Pin.svelte";
+ import Icon from "$comp/Icon.svelte";
+ import Spinner from "$comp/Spinner.svelte";
+ import { focus, fail } from "$lib/utils";
+ import { password, pin, loginRedirect } from "$lib/store";
+ import { t } from "$lib/translations";
+ import { page } from "$app/stores";
+ import { generate } from "$lib/nostr";
+ import { invalidateAll } from "$app/navigation";
onMount(() => {
$pin = undefined;
@@ -10,6 +21,164 @@
});
export let form;
+
+ let token, formElement;
+ let code = [];
+ let redirect;
+
+ $password = undefined;
+
+ $: need2fa = form?.message === "2fa";
+ let cancel = () => (need2fa = false);
+ $: if (form?.message === "2fa" && form.token === token) token = "";
+
+ let username, email, btn;
+
+ $: update(form);
+ let update = (form) => form && ({ username, password: $password } = form);
+
+ $: token && token?.length === 6 && tick().then(() => btn.click());
+
+ let revealPassword = false;
+
+ let loading;
+ async function handleSubmit(e) {
+ loading = true;
+
+ let data = new FormData(this);
+ let user = Object.fromEntries(data);
+ await generate(user);
+
+ for (let k in user) {
+ data.set(k, user[k]);
+ }
+
+ const response = await fetch("/login", {
+ method: "POST",
+ body: data,
+ });
+
+ const result = deserialize(await response.text());
+
+ if (result.type === "success") {
+ await invalidateAll();
+ }
+
+ applyAction(result);
+ loading = false;
+ }
</script>
-<RegisterOrLogin pageID="signIn" bind:form />
+{#if need2fa}
+ <Pin bind:value={token} title="Enter 2FA Code" {cancel} notify={false} />
+{/if}
+
+<div class="pt-10">
+ <div class="w-[243px] mx-auto mb-10">
+ <a href="/">
+ <Icon icon="logo" />
+ </a>
+ </div>
+
+ <div class="flex justify-center items-center">
+ <div
+ class="shadow-xl rounded-3xl p-10 pb-12 space-y-5 w-full mx-5 md:mx-0 md:w-[400px]"
+ >
+ <h1 class="text-2xl font-bold text-center">{$t("login.signIn")}</h1>
+
+ {#if form?.error}
+ <div class="text-red-600 text-center" in:fly>
+ {form.error}
+ </div>
+ {/if}
+
+ <form
+ class="space-y-5"
+ on:submit|preventDefault={handleSubmit}
+ method="POST"
+ >
+ <input
+ type="hidden"
+ name="loginRedirect"
+ value={$loginRedirect || $page.url.searchParams.get("redirect")}
+ />
+ <input type="hidden" name="token" value={token} />
+
+ <div>
+ <label for="username" class="font-semibold"
+ >{$t("login.username")}</label
+ >
+ <input
+ name="username"
+ type="text"
+ required
+ class="bg-primary"
+ bind:value={username}
+ use:focus
+ autocapitalize="none"
+ />
+ </div>
+
+ <div class="relative">
+ <label for="password" class="block font-semibold"
+ >{$t("login.password")}</label
+ >
+ {#if revealPassword}
+ <input
+ name="password"
+ type="text"
+ required
+ class="bg-primary"
+ bind:value={$password}
+ autocapitalize="none"
+ />
+ {:else}
+ <input
+ name="password"
+ type="password"
+ required
+ class="bg-primary"
+ bind:value={$password}
+ autocapitalize="none"
+ />
+ {/if}
+ <button
+ type="button"
+ on:click={() => (revealPassword = !revealPassword)}
+ class="absolute right-5 top-10">
+ <Icon icon={revealPassword ? "eye" : "eye-off"} />
+ </button>
+ </div>
+
+ <div class="flex justify-end items-center">
+ <a
+ href="/forgot"
+ class="underline underline-offset-4 text-black text-sm"
+ >{$t("login.forgotUserOrPassword")}</a
+ >
+ </div>
+
+ <button
+ type="submit"
+ class="bg-black text-white w-full rounded-2xl p-4 font-semibold hover:opacity-80"
+ disabled={loading}
+ bind:this={btn}>
+ {#if loading}
+ <Spinner />
+ {:else}
+ {$t("login.signIn")}
+ {/if}
+ </button>
+ </form>
+
+ <p class="text-secondary text-center font-medium">
+ {$t("login.haveAccount")}
+ <a
+ href={"/register"}
+ class="block md:inline text-black underline underline-offset-4 hover:opacity-80">
+ {$t("login.register")}
+ </a>
+ </p>
+ </div>
+ </div>
+</div>