diff options
Diffstat (limited to 'apps/kit/src/routes/(main)/(public)')
| -rw-r--r-- | apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts | 11 | ||||
| -rw-r--r-- | apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.svelte | 121 |
2 files changed, 132 insertions, 0 deletions
diff --git a/apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts b/apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts new file mode 100644 index 0000000..389d04c --- /dev/null +++ b/apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.server.ts @@ -0,0 +1,11 @@ +import { is_guid } from '$lib/helpers'; +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ params }) => { + const resetRequestId = params.id ?? ""; + if (!is_guid(resetRequestId)) throw redirect(302, "/reset-password"); + return { + resetRequestId + }; +};
\ No newline at end of file diff --git a/apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.svelte b/apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.svelte new file mode 100644 index 0000000..7b46d2d --- /dev/null +++ b/apps/kit/src/routes/(main)/(public)/reset-password/[id]/+page.svelte @@ -0,0 +1,121 @@ +<script lang="ts"> + import { + check_forgot_password_request, + fulfill_forgot_password_request, + } from "$lib/api/user"; + import { onMount } from "svelte"; + import LL from "$lib/i18n/i18n-svelte"; + import { Alert, Input, Button } from "$lib/components"; + import type { PageServerData } from "./$types"; + import type { ErrorResult } from "$lib/models/ErrorResult"; + import { goto } from "$app/navigation"; + + export let data: PageServerData; + + const formData = { + newPassword: "", + }; + + $: showErrorAlert = + (errorData?.text.length ?? 0 + errorData?.title.length ?? 0) > 0 && + !showSuccessAlert; + + const errorData = { + text: "", + title: "", + } as ErrorResult; + + let finishedPreliminaryLoading = false; + let loading = false; + let showSuccessAlert = false; + let canSubmit = true; + + async function submitFormAsync() { + if (!canSubmit) return; + loading = true; + const request = await fulfill_forgot_password_request( + data.resetRequestId, + formData.newPassword + ); + if (request.ok) { + goto("/sign-in?m=1"); + } + + loading = false; + } + + onMount(async () => { + const isValidRequest = await check_forgot_password_request( + data.resetRequestId + ); + if (!isValidRequest.ok) { + errorData.text = isValidRequest.data?.text ?? $LL.tryAgainSoon(); + errorData.title = + isValidRequest.data?.title ?? $LL.unexpectedError(); + canSubmit = false; + } + if (isValidRequest.status === 404) goto("/reset-password"); + finishedPreliminaryLoading = true; + }); +</script> + +<div class="min-h-full flex flex-col justify-center py-12 sm:px-6 lg:px-8"> + {#if finishedPreliminaryLoading} + <div class="sm:mx-auto sm:w-full sm:max-w-md"> + <h2 + class="mt-6 text-center text-3xl tracking-tight font-bold text-gray-900" + > + {$LL.requestAPasswordReset()} + </h2> + <p class="mt-2 text-center text-sm text-gray-600"> + {$LL.or().toLowerCase()} + <a href="/sign-in" class="link"> + {$LL.signIntoYourAccount()} + </a> + </p> + </div> + + <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md"> + <div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10"> + <form + class="space-y-6" + on:submit|preventDefault={submitFormAsync} + > + <Alert + title={errorData.title} + message={errorData.text} + type="error" + visible={showErrorAlert} + /> + + <Alert + type="success" + title={$LL.success()} + message={$LL.requestSentMessage()} + rightLinkHref="/sign-in" + rightLinkText="Sign in" + visible={showSuccessAlert} + /> + + <Input + id="password" + name="password" + type="password" + autocomplete="new-password" + required + bind:value={formData.newPassword} + label={$LL.newPassword()} + /> + <Button + text={$LL.submit()} + type="submit" + {loading} + fullWidth + /> + </form> + </div> + </div> + {:else} + <p>Checking your request...</p> + {/if} +</div> |
