This commit is contained in:
Alex Holliday committed 2026-02-06 22:53:41 +00:00
1 parent 97e4b105a2
commit 2d84fae470
3 files changed
+143 -16

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
import { registerSchema, type RegisterFormData } from "@/Validation/register";
export const useRegisterForm = () => {
const defaults: RegisterFormData = {
firstName: "",
lastName: "",
email: "",
password: "",
confirm: "",
role: ["superadmin"],
};
return {
schema: registerSchema,
defaults,
};
};
+83 -16
View File
@@ -1,34 +1,101 @@
import { BaseAuthPage } from "@/Components/v2/design-elements";
import { Button, TextField } from "@/Components/v2/inputs";
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod/dist/zod.js";
import { useRegisterForm } from "@/Hooks/useRegisterForm";
import type { RegisterFormData } from "@/Validation/register";
import { useTranslation } from "react-i18next";
const RegisterPage = () => {
const { t } = useTranslation();
const { schema, defaults } = useRegisterForm();
const { control, handleSubmit } = useForm<RegisterFormData>({
resolver: zodResolver(schema),
defaultValues: defaults,
});
const onSubmit = (data: RegisterFormData) => {
console.log("Registration data:", data);
};
const onError = (errors: any) => {
console.log("Validation errors:", errors);
};
return (
<BaseAuthPage
component="form"
onSubmit={handleSubmit(onSubmit, onError)}
title={t("pages.auth.register.title")}
subtitle={t("pages.auth.register.subtitle")}
>
<TextField
fieldLabel={t("pages.auth.register.form.option.name.label")}
placeholder={t("pages.auth.register.form.option.name.placeholder")}
<Controller
name="firstName"
control={control}
render={({ field, fieldState }) => (
<TextField
{...field}
fieldLabel={t("pages.auth.register.form.option.name.label")}
placeholder={t("pages.auth.register.form.option.name.placeholder")}
error={!!fieldState.error}
helperText={fieldState.error?.message ?? ""}
/>
)}
/>
<TextField
fieldLabel={t("pages.auth.register.form.option.surname.label")}
placeholder={t("pages.auth.register.form.option.surname.placeholder")}
<Controller
name="lastName"
control={control}
render={({ field, fieldState }) => (
<TextField
{...field}
fieldLabel={t("pages.auth.register.form.option.surname.label")}
placeholder={t("pages.auth.register.form.option.surname.placeholder")}
error={!!fieldState.error}
helperText={fieldState.error?.message ?? ""}
/>
)}
/>
<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?.message ?? ""}
/>
)}
/>
<TextField
fieldLabel={t("pages.auth.common.form.option.password.label")}
placeholder={t("pages.auth.common.form.option.password.placeholder")}
<Controller
name="password"
control={control}
render={({ field, fieldState }) => (
<TextField
{...field}
type="password"
fieldLabel={t("pages.auth.common.form.option.password.label")}
placeholder={t("pages.auth.common.form.option.password.placeholder")}
error={!!fieldState.error}
helperText={fieldState.error?.message ?? ""}
/>
)}
/>
<TextField
fieldLabel={t("pages.auth.common.form.option.confirmPassword.label")}
placeholder={t("pages.auth.common.form.option.password.placeholder")}
<Controller
name="confirm"
control={control}
render={({ field, fieldState }) => (
<TextField
{...field}
type="password"
fieldLabel={t("pages.auth.common.form.option.confirmPassword.label")}
placeholder={t("pages.auth.common.form.option.password.placeholder")}
error={!!fieldState.error}
helperText={fieldState.error?.message ?? ""}
/>
)}
/>
<Button
variant="contained"
+43
View File
@@ -0,0 +1,43 @@
import { z } from "zod";
const namePattern = /^[\p{L}\p{M}''()\-\. ]+$/u;
const specialCharPattern = /[!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/]/;
export const registerSchema = z
.object({
firstName: z
.string()
.min(1, "First name is required")
.max(50, "First name must be 50 characters or less")
.regex(namePattern, "First name contains invalid characters")
.transform((val) => val.trim()),
lastName: z
.string()
.min(1, "Last name is required")
.max(50, "Last name must be 50 characters or less")
.regex(namePattern, "Last name contains invalid characters")
.transform((val) => val.trim()),
email: z
.email("Please enter a valid email address")
.min(1, "Email is required")
.transform((val) => val.toLowerCase().trim()),
password: z
.string()
.min(1, "Password is required")
.min(8, "Password must be at least 8 characters")
.refine((val) => /[A-Z]/.test(val), "Password must contain an uppercase letter")
.refine((val) => /[a-z]/.test(val), "Password must contain a lowercase letter")
.refine((val) => /\d/.test(val), "Password must contain a number")
.refine(
(val) => specialCharPattern.test(val),
"Password must contain a special character"
),
confirm: z.string().min(1, "Please confirm your password"),
role: z.array(z.string()).min(1, "Role is required"),
})
.refine((data) => data.password === data.confirm, {
message: "Passwords do not match",
path: ["confirm"],
});
export type RegisterFormData = z.infer<typeof registerSchema>;