recovery form, fix email service

This commit is contained in:
Alex Holliday committed 2026-02-06 22:14:42 +00:00
1 parent 16e8035299
commit 6a0f3426b3
5 files changed
+66 -7

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
import { recoverySchema } from "@/Validation/recovery";
export const useRecoveryForm = () => {
const defaults = {
email: "",
};
return {
schema: recoverySchema,
defaults,
};
};
+40 -4
View File
@@ -1,22 +1,58 @@
import { Button, TextField } from "@/Components/v2/inputs";
import { BaseAuthPage, TextLink } from "@/Components/v2/design-elements";
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod/dist/zod.js";
import { useRecoveryForm } from "@/Hooks/useRecoveryForm";
import type { RecoveryFormData } from "@/Validation/recovery";
import { usePost } from "@/Hooks/UseApi";
import { useTranslation } from "react-i18next";
const ForgotPasswordPage = () => {
const { t } = useTranslation();
const { post, loading } = usePost();
const { schema, defaults } = useRecoveryForm();
const { control, handleSubmit } = useForm<RecoveryFormData>({
resolver: zodResolver(schema),
defaultValues: defaults,
});
const onSubmit = async (data: RecoveryFormData) => {
if (loading) return;
const result = await post("/auth/recovery/request", data);
if (result?.success) {
// Navigate to Check email page
}
};
return (
<BaseAuthPage
component="form"
onSubmit={handleSubmit(onSubmit)}
title={t("pages.auth.forgotPassword.title")}
subtitle={t("pages.auth.forgotPassword.subtitle")}
>
<TextField
fieldLabel={t("pages.auth.common.form.option.email.label")}
placeholder={t("pages.auth.common.form.option.email.placeholder")}
<Controller
name="email"
control={control}
render={({ field, fieldState }) => (
<TextField
{...field}
fieldLabel={t("pages.auth.common.form.option.email.label")}
placeholder={t("pages.auth.common.form.option.email.placeholder")}
error={!!fieldState.error}
helperText={fieldState.error ? t(fieldState.error.message ?? "") : ""}
/>
)}
/>
<Button
variant="contained"
type="submit"
loading={loading}
>
{t("pages.auth.forgotPassword.submit")}
</Button>
@@ -24,7 +60,7 @@ const ForgotPasswordPage = () => {
alignSelf={"center"}
text={t("pages.auth.forgotPassword.links.login.text")}
linkText={t("pages.auth.forgotPassword.links.login.linkText")}
href={"/login"}
href="/login"
/>
</BaseAuthPage>
);
+11
View File
@@ -0,0 +1,11 @@
import { z } from "zod";
export const recoverySchema = z.object({
email: z
.string()
.min(1, "auth.common.inputs.email.errors.empty")
.email("auth.common.inputs.email.errors.invalid")
.transform((val) => val.toLowerCase().trim()),
});
export type RecoveryFormData = z.infer<typeof recoverySchema>;
+1 -1
View File
@@ -13,7 +13,7 @@ class SettingsRoutes {
initRoutes() {
this.router.get("/", this.settingsController.getAppSettings);
this.router.put("/", isAllowed(["admin", "superadmin"]), this.settingsController.updateAppSettings);
this.router.patch("/", isAllowed(["admin", "superadmin"]), this.settingsController.updateAppSettings);
this.router.post("/test-email", isAllowed(["admin", "superadmin"]), this.settingsController.sendTestEmail);
}
@@ -29,18 +29,18 @@ class EmailService {
this.mjml2html = mjml2html;
this.nodemailer = nodemailer;
this.logger = logger;
this.init();
this.templateLookup = {};
this.loadTemplate = () => {
return () => {};
};
this.init();
}
get serviceName() {
return EmailService.SERVICE_NAME;
}
init = async () => {
init = () => {
this.loadTemplate = (templateName) => {
try {
const templatePath = this.path.join(__dirname, `../../templates/${templateName}.mjml`);