mirror of
https://github.com/hay-kot/homebox.git
synced 2024-11-25 18:15:40 +00:00
request password reset form
This commit is contained in:
parent
ef06e4fbb2
commit
c83d178182
2 changed files with 72 additions and 8 deletions
|
@ -1,5 +1,11 @@
|
||||||
import { BaseAPI, route } from "./base";
|
import { BaseAPI, route } from "./base";
|
||||||
import type { APISummary, LoginForm, TokenResponse, UserRegistration } from "./types/data-contracts";
|
import type {
|
||||||
|
APISummary,
|
||||||
|
LoginForm,
|
||||||
|
PasswordResetRequest,
|
||||||
|
TokenResponse,
|
||||||
|
UserRegistration,
|
||||||
|
} from "./types/data-contracts";
|
||||||
|
|
||||||
export type StatusResult = {
|
export type StatusResult = {
|
||||||
health: boolean;
|
health: boolean;
|
||||||
|
@ -27,4 +33,11 @@ export class PublicApi extends BaseAPI {
|
||||||
public register(body: UserRegistration) {
|
public register(body: UserRegistration) {
|
||||||
return this.http.post<UserRegistration, TokenResponse>({ url: route("/users/register"), body });
|
return this.http.post<UserRegistration, TokenResponse>({ url: route("/users/register"), body });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public resetPasseord(email: string) {
|
||||||
|
return this.http.post<PasswordResetRequest, void>({
|
||||||
|
url: route("/users/request-password-reset"),
|
||||||
|
body: { email },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useRouteHash } from "@vueuse/router";
|
||||||
import MdiGithub from "~icons/mdi/github";
|
import MdiGithub from "~icons/mdi/github";
|
||||||
import MdiTwitter from "~icons/mdi/twitter";
|
import MdiTwitter from "~icons/mdi/twitter";
|
||||||
import MdiDiscord from "~icons/mdi/discord";
|
import MdiDiscord from "~icons/mdi/discord";
|
||||||
|
@ -9,6 +10,12 @@
|
||||||
import MdiArrowRight from "~icons/mdi/arrow-right";
|
import MdiArrowRight from "~icons/mdi/arrow-right";
|
||||||
import MdiLock from "~icons/mdi/lock";
|
import MdiLock from "~icons/mdi/lock";
|
||||||
|
|
||||||
|
enum PageForms {
|
||||||
|
Register = "register",
|
||||||
|
Login = "login",
|
||||||
|
ForgotPassword = "forgot-password",
|
||||||
|
}
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: "Homebox | Organize and Tag Your Stuff",
|
title: "Homebox | Organize and Tag Your Stuff",
|
||||||
});
|
});
|
||||||
|
@ -30,6 +37,9 @@
|
||||||
const api = usePublicApi();
|
const api = usePublicApi();
|
||||||
const toast = useNotifier();
|
const toast = useNotifier();
|
||||||
|
|
||||||
|
const pageForm = useRouteHash(PageForms.Login);
|
||||||
|
const pageFormStr = computed(() => (pageForm.value[0] === "#" ? pageForm.value.slice(1) : pageForm.value));
|
||||||
|
|
||||||
const { data: status } = useAsyncData(async () => {
|
const { data: status } = useAsyncData(async () => {
|
||||||
const { data } = await api.status();
|
const { data } = await api.status();
|
||||||
|
|
||||||
|
@ -92,12 +102,12 @@
|
||||||
toast.success("User registered");
|
toast.success("User registered");
|
||||||
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
registerForm.value = false;
|
pageForm.value = PageForms.Login;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (groupToken.value !== "") {
|
if (groupToken.value !== "") {
|
||||||
registerForm.value = true;
|
pageForm.value = PageForms.Register;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -120,7 +130,21 @@
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [registerForm, toggleLogin] = useToggle();
|
async function resetPassword() {
|
||||||
|
if (email.value === "") {
|
||||||
|
toast.error("Email is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resp = await api.resetPasseord(email.value);
|
||||||
|
if (resp.error) {
|
||||||
|
toast.error("Problem resetting password");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
toast.success("Password reset link sent to your email");
|
||||||
|
return await Promise.resolve();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -167,7 +191,7 @@
|
||||||
<div class="grid p-6 sm:place-items-center min-h-[50vh]">
|
<div class="grid p-6 sm:place-items-center min-h-[50vh]">
|
||||||
<div>
|
<div>
|
||||||
<Transition name="slide-fade">
|
<Transition name="slide-fade">
|
||||||
<form v-if="registerForm" @submit.prevent="registerUser">
|
<form v-if="pageFormStr === PageForms.Register" @submit.prevent="registerUser">
|
||||||
<div class="card w-max-[500px] md:w-[500px] bg-base-100 shadow-xl">
|
<div class="card w-max-[500px] md:w-[500px] bg-base-100 shadow-xl">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h2 class="card-title text-2xl align-center">
|
<h2 class="card-title text-2xl align-center">
|
||||||
|
@ -197,6 +221,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<form v-else-if="pageFormStr === PageForms.ForgotPassword" @submit.prevent="resetPassword">
|
||||||
|
<div class="card w-max-[500px] md:w-[500px] bg-base-100 shadow-xl">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-2xl align-center">
|
||||||
|
<MdiAccount class="mr-1 w-7 h-7" />
|
||||||
|
Reset Password
|
||||||
|
</h2>
|
||||||
|
<FormTextField v-model="email" label="Email" />
|
||||||
|
<p class="text-sm text-base-content/50">
|
||||||
|
If you have an account with us, we will send you a password reset link.
|
||||||
|
</p>
|
||||||
|
<div class="card-actions justify-end mt-4">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn btn-primary btn-block"
|
||||||
|
:class="loading ? 'loading' : ''"
|
||||||
|
:disabled="loading"
|
||||||
|
>
|
||||||
|
Reset Password
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<form v-else @submit.prevent="login">
|
<form v-else @submit.prevent="login">
|
||||||
<div class="card w-max-[500px] md:w-[500px] bg-base-100 shadow-xl">
|
<div class="card w-max-[500px] md:w-[500px] bg-base-100 shadow-xl">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -232,19 +280,22 @@
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="status && status.allowRegistration"
|
v-if="status && status.allowRegistration"
|
||||||
class="btn-primary btn-wide"
|
class="btn-primary btn-wide"
|
||||||
@click="() => toggleLogin()"
|
:to="pageFormStr === PageForms.Register ? `#${PageForms.Login}` : `#${PageForms.Register}`"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<MdiAccountPlus v-if="!registerForm" class="w-5 h-5 swap-off" />
|
<MdiAccountPlus v-if="pageFormStr === PageForms.Register" class="w-5 h-5 swap-off" />
|
||||||
<MdiLogin v-else class="w-5 h-5 swap-off" />
|
<MdiLogin v-else class="w-5 h-5 swap-off" />
|
||||||
<MdiArrowRight class="w-5 h-5 swap-on" />
|
<MdiArrowRight class="w-5 h-5 swap-on" />
|
||||||
</template>
|
</template>
|
||||||
{{ registerForm ? "Login" : "Register" }}
|
{{ pageFormStr === PageForms.Register ? "Login" : "Register" }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<p v-else class="text-base-content italic text-sm inline-flex items-center gap-2">
|
<p v-else class="text-base-content italic text-sm inline-flex items-center gap-2">
|
||||||
<MdiLock class="w-4 h-4 inline-block" />
|
<MdiLock class="w-4 h-4 inline-block" />
|
||||||
Registration Disabled
|
Registration Disabled
|
||||||
</p>
|
</p>
|
||||||
|
<NuxtLink :to="`#${PageForms.ForgotPassword}`">
|
||||||
|
<p class="text-xs text-base-content/50 mt-2">Forgot your password?</p>
|
||||||
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue