aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes/(static)
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-11-26 22:35:28 -0800
committerAdam Soltys <[email protected]>2024-11-26 22:35:28 -0800
commitf99bd15fabd6d7b361794f756a69d6f05a50701f (patch)
tree9bb1b14519b34c343ad3bcd001fbd4681a53e447 /src/routes/(static)
parentf4eb6547d0db5edd0137fdefe461433500515040 (diff)
downloadcoinos-ui-f99bd15fabd6d7b361794f756a69d6f05a50701f.tar.gz
coinos-ui-f99bd15fabd6d7b361794f756a69d6f05a50701f.zip
warnings
Diffstat (limited to 'src/routes/(static)')
-rw-r--r--src/routes/(static)/docs/+page.svelte37
-rw-r--r--src/routes/(static)/forgot/+page.server.ts14
-rw-r--r--src/routes/(static)/forgot/+page.svelte66
-rw-r--r--src/routes/(static)/login/+page.svelte38
-rw-r--r--src/routes/(static)/register/+page.svelte50
5 files changed, 113 insertions, 92 deletions
diff --git a/src/routes/(static)/docs/+page.svelte b/src/routes/(static)/docs/+page.svelte
index 80052805..f4e2ffb9 100644
--- a/src/routes/(static)/docs/+page.svelte
+++ b/src/routes/(static)/docs/+page.svelte
@@ -18,12 +18,17 @@
: `export token=<your auth token>`;
</script>
+{#snippet cp(something)}
+ <button type="button" class="ml-auto" onclick={() => copy(something)}>
+ <iconify-icon icon="ph:copy-bold" width="42"></iconify-icon>
+ </button>
+{/snippet}
+
<div class="space-y-8 lg:text-xl mt-20 pt-20 md:pt-0 w-full max-w-full">
<h1 class="text-4xl">Documentation</h1>
<p class="text-secondary">
- Coinos is free and open source software. The code is
- available at <a
+ Coinos is free and open source software. The code is available at <a
href="https://github.com/coinos"
class="text-secondary underline">github.com/coinos</a
>
@@ -31,19 +36,18 @@
<p class="text-secondary">
Coinos has a REST API that can be used to register accounts and make
- payments. The following examples show how you can call the API
- with <a href="https://curl.se/" class="text-secondary underline">curl</a>
+ payments. The following examples show how you can call the API with <a
+ href="https://curl.se/"
+ class="text-secondary underline">curl</a
+ >
</p>
<h2 class="text-2xl">API Base URL</h2>
- <div class="bg-primary text-primary-content rounded-lg p-4 flex gap-4 items-center">
+ <div
+ class="bg-primary text-primary-content rounded-lg p-4 flex gap-4 items-center"
+ >
<div>{api}</div>
- <iconify-icon
- icon="ph:copy-bold"
- onclick={() => copy(api)}
- width="42"
- class="ml-auto cursor-pointer"
- ></iconify-icon>
+ {@render cp(api)}
</div>
<h2 class="text-2xl">Auth Token</h2>
@@ -58,14 +62,11 @@
Save it in a variable called <b>$token</b> to run the examples.
</p>
- <div class="bg-primary text-primary-content rounded-lg p-4 flex gap-4 items-center">
+ <div
+ class="bg-primary text-primary-content rounded-lg p-4 flex gap-4 items-center"
+ >
<div class="w-full break-all">{tokenSample}</div>
- <iconify-icon
- icon="ph:copy-bold"
- onclick={() => copy(tokenSample)}
- width="42"
- class="ml-auto cursor-pointer"
- ></iconify-icon>
+ {@render cp(tokenSample)}
</div>
<h2 class="text-2xl">POST /register</h2>
diff --git a/src/routes/(static)/forgot/+page.server.ts b/src/routes/(static)/forgot/+page.server.ts
new file mode 100644
index 00000000..55169a5e
--- /dev/null
+++ b/src/routes/(static)/forgot/+page.server.ts
@@ -0,0 +1,14 @@
+import { fail } from "@sveltejs/kit";
+import { fd, post } from "$lib/utils";
+
+export const actions = {
+ default: async ({ request }) => {
+ try {
+ const { email } = await fd(request);
+ await post("/forgot", { email });
+ return { success: true };
+ } catch (e: any) {
+ return fail(400, { error: e.message });
+ }
+ },
+};
diff --git a/src/routes/(static)/forgot/+page.svelte b/src/routes/(static)/forgot/+page.svelte
new file mode 100644
index 00000000..45180543
--- /dev/null
+++ b/src/routes/(static)/forgot/+page.svelte
@@ -0,0 +1,66 @@
+<script>
+ import { focus } from "$lib/utils";
+ import { enhance } from "$app/forms";
+ import { t } from "$lib/translations";
+ import Icon from "$comp/Icon.svelte";
+ import Spinner from "$comp/Spinner.svelte";
+ import { fly } from "svelte/transition";
+
+ let { form } = $props();
+ let email = $state();
+ let loading;
+</script>
+
+<div
+ class="mx-auto md:shadow-xl rounded-3xl max-w-xl w-full md:w-[480px] md:p-8 mb-20 space-y-5"
+>
+ <h1 class="text-2xl font-bold text-center">{$t("login.reset")}</h1>
+
+ {#if form?.error}
+ <div class="text-red-600 text-center" in:fly>
+ {form.error}
+ </div>
+ {/if}
+
+ {#if form?.success}
+ <div class="text-secondary">
+ {$t("login.resetSent")}
+ </div>
+
+ <div class="flex w-full">
+ <a href="/login" class="btn">
+ {$t("login.continue")}
+ </a>
+ </div>
+ {:else}
+ <form class="space-y-5" method="POST" use:enhance>
+ <div>
+ <input
+ placeholder={$t("login.email")}
+ name="email"
+ type="text"
+ required
+ class="bg-primary"
+ bind:value={email}
+ use:focus
+ autocapitalize="none"
+ />
+ </div>
+
+ <div class="text-secondary">
+ {$t("login.resetDesc")}
+ <a href="mailto:[email protected]" class="font-bold"
+ >
+ </div>
+
+ <button type="submit" class="btn" disabled={loading}>
+ {#if loading}
+ <Spinner />
+ {:else}
+ {$t("login.submit")}
+ {/if}
+ </button>
+ </form>
+ {/if}
+</div>
diff --git a/src/routes/(static)/login/+page.svelte b/src/routes/(static)/login/+page.svelte
index 2b36dcfe..5caf48fb 100644
--- a/src/routes/(static)/login/+page.svelte
+++ b/src/routes/(static)/login/+page.svelte
@@ -8,6 +8,7 @@
import { fly } from "svelte/transition";
import { enhance } from "$app/forms";
import Pinpad from "$comp/Pinpad.svelte";
+ import PasswordInput from "$comp/PasswordInput.svelte";
import { focus, fail } from "$lib/utils";
import { password, pin, loginRedirect } from "$lib/store";
import { t } from "$lib/translations";
@@ -105,38 +106,7 @@
placeholder={$t("login.username")}
/>
- <label
- for="password"
- class="input flex items-center justify-center gap-2 w-full"
- >
- {#if revealPassword}
- <input
- class="clean"
- name="password"
- type="text"
- required
- bind:value={$password}
- autocapitalize="none"
- placeholder={$t("login.password")}
- />
- {:else}
- <input
- class="clean"
- name="password"
- type="password"
- required
- bind:value={$password}
- autocapitalize="none"
- placeholder={$t("login.password")}
- />
- {/if}
- <iconify-icon
- class="cursor-pointer ml-auto"
- onclick={() => (revealPassword = !revealPassword)}
- icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"}
- width="32"
- ></iconify-icon>
- </label>
+ <PasswordInput bind:value={$password} placeholder={$t("login.password")} />
<div class="flex justify-end items-center">
<a href="/forgot" class="underline underline-offset-4 text-secondary"
@@ -164,11 +134,13 @@
<div
class="fixed bg-base-100 bg-opacity-90 inset-0 h-full w-full z-50 cursor-default"
onclick={(e) => e.stopPropagation()}
+ role="dialog"
+ aria-labelledby="title"
>
<div
class="mx-auto p-5 border shadow-lg rounded-md bg-base-100 space-y-5 max-w-lg"
>
- <h1 class="text-center text-2xl font-semibold">2FA</h1>
+ <h1 id="title" class="text-center text-2xl font-semibold">2FA</h1>
<Pinpad bind:v={token} {cancel} />
<div class="w-full flex">
diff --git a/src/routes/(static)/register/+page.svelte b/src/routes/(static)/register/+page.svelte
index 8a2a5015..147c361e 100644
--- a/src/routes/(static)/register/+page.svelte
+++ b/src/routes/(static)/register/+page.svelte
@@ -9,6 +9,7 @@
import Pin from "$comp/Pin.svelte";
import Spinner from "$comp/Spinner.svelte";
+ import PasswordInput from "$comp/PasswordInput.svelte";
import { focus, fail } from "$lib/utils";
import { avatar, password, loginRedirect } from "$lib/store";
@@ -27,6 +28,7 @@
let username = $state();
let { index } = $state(data);
+ let revealPassword = $state(false);
let cleared;
let clear = () => {
@@ -40,6 +42,8 @@
let refresh = async (e) => {
e.preventDefault();
+ cleared = false;
+
username = uniqueNamesGenerator({
dictionaries: [animals, NumberDictionary.generate({ min: 10, max: 99 })],
length: 2,
@@ -73,8 +77,6 @@
let email,
btn = $state();
- let revealPassword = $state();
-
let loading = $state();
async function handleSubmit(e) {
e.preventDefault();
@@ -245,45 +247,11 @@
>
</label>
- <label
- for="password"
- class="input flex items-center justify-center gap-2 w-full"
- >
- {#if revealPassword}
- <input
- class="clean"
- name="password"
- type="text"
- required
- bind:value={$password}
- autocapitalize="none"
- placeholder={$t("login.password")}
- />
- {:else}
- <input
- class="clean"
- name="password"
- type="password"
- required
- bind:value={$password}
- autocapitalize="none"
- onfocus={clear}
- placeholder={$t("login.password")}
- />
- {/if}
- <button
- type="button"
- tabindex="-1"
- onclick={() => (revealPassword = !revealPassword)}
- class="contents"
- aria-label="Toggle"
- >
- <iconify-icon
- icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"}
- width="32"
- ></iconify-icon></button
- >
- </label>
+ <PasswordInput
+ bind:value={$password}
+ placeholder={$t("login.password")}
+ bind:show={revealPassword}
+ />
<button type="submit" class="btn" disabled={loading} bind:this={btn}>
{#if loading}