validation
This commit is contained in:
1 parent
af4c9d8f91
commit
b6004241e7
8 files changed
+113
-10
No files matched your search
@@ -0,0 +1,13 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { passwordSchema, type PasswordFormData } from "@/Validation/password";
|
||||
|
||||
export const usePasswordForm = () => {
|
||||
return {
|
||||
resolver: zodResolver(passwordSchema),
|
||||
defaults: {
|
||||
currentPassword: "",
|
||||
newPassword: "",
|
||||
confirm: "",
|
||||
} as PasswordFormData,
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,47 @@
|
||||
import { Box } from "@mui/material";
|
||||
import { Stack } from "@mui/material";
|
||||
import { ConfigBox } from "@/Components/v2/design-elements";
|
||||
import { TextField } from "@/Components/v2/inputs";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTheme } from "@mui/material";
|
||||
|
||||
export const TabPassword = () => {
|
||||
return <Box>{/* TODO: Implement TabPassword */}</Box>;
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<ConfigBox
|
||||
title={t("pages.account.form.currentPassword.title")}
|
||||
subtitle={t("pages.account.form.currentPassword.description")}
|
||||
rightContent={
|
||||
<TextField
|
||||
type="password"
|
||||
fieldLabel={t("pages.account.form.currentPassword.option.label")}
|
||||
placeholder={t("pages.account.form.currentPassword.option.placeholder")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ConfigBox
|
||||
title={t("pages.account.form.newPassword.title")}
|
||||
subtitle={t("pages.account.form.newPassword.description")}
|
||||
rightContent={
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<TextField
|
||||
type="password"
|
||||
fieldLabel={t("pages.account.form.newPassword.option.newPassword.label")}
|
||||
placeholder={t(
|
||||
"pages.account.form.newPassword.option.newPassword.placeholder"
|
||||
)}
|
||||
/>
|
||||
<TextField
|
||||
type="password"
|
||||
fieldLabel={t("pages.account.form.newPassword.option.confirm.label")}
|
||||
placeholder={t("pages.account.form.newPassword.option.confirm.placeholder")}
|
||||
/>
|
||||
</Stack>
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Stack, Box } from "@mui/material";
|
||||
import { Stack } from "@mui/material";
|
||||
import { ConfigBox } from "@/Components/v2/design-elements";
|
||||
import { TextField, Button } from "@/Components/v2/inputs";
|
||||
import { ImageUpload } from "@/Components/v2/inputs";
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { z } from "zod";
|
||||
import { specialCharPattern } from "@/Validation/patterns";
|
||||
|
||||
export const passwordSchema = z
|
||||
.object({
|
||||
currentPassword: z.string().min(1, "Current password is required"),
|
||||
newPassword: z
|
||||
.string()
|
||||
.min(1, "New 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 new password"),
|
||||
})
|
||||
.refine((data) => data.newPassword === data.confirm, {
|
||||
message: "Passwords do not match",
|
||||
path: ["confirm"],
|
||||
});
|
||||
|
||||
export type PasswordFormData = z.infer<typeof passwordSchema>;
|
||||
@@ -0,0 +1,4 @@
|
||||
export const specialCharPattern = /[!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/]/;
|
||||
|
||||
// Unicode-aware name pattern (allows letters, marks, apostrophes, parentheses, hyphens, periods, spaces)
|
||||
export const namePattern = /^[\p{L}\p{M}''()\-\. ]+$/u;
|
||||
@@ -1,18 +1,17 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const NAME_PATTERN = /^[A-Za-z'-]+$/;
|
||||
import { namePattern } from "@/Validation/patterns";
|
||||
|
||||
export const profileSchema = z.object({
|
||||
firstName: z
|
||||
.string()
|
||||
.min(1, "First name is required")
|
||||
.max(50, "First name must be 50 characters or less")
|
||||
.regex(NAME_PATTERN, "First name can only contain letters, hyphens, and apostrophes"),
|
||||
.regex(namePattern, "First name contains invalid characters"),
|
||||
lastName: z
|
||||
.string()
|
||||
.min(1, "Last name is required")
|
||||
.max(50, "Last name must be 50 characters or less")
|
||||
.regex(NAME_PATTERN, "Last name can only contain letters, hyphens, and apostrophes"),
|
||||
.regex(namePattern, "Last name contains invalid characters"),
|
||||
profileImage: z.instanceof(File).optional().nullable(),
|
||||
deleteProfileImage: z.boolean().optional(),
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { z } from "zod";
|
||||
|
||||
const namePattern = /^[\p{L}\p{M}''()\-\. ]+$/u;
|
||||
const specialCharPattern = /[!?@#$%^&*()\-_=+[\]{};:'",.<>~`|\\/]/;
|
||||
import { specialCharPattern, namePattern } from "@/Validation/patterns";
|
||||
|
||||
export const registerSchema = z
|
||||
.object({
|
||||
|
||||
@@ -523,6 +523,28 @@
|
||||
"title": "Profile photo",
|
||||
"description": "Upload a profile picture"
|
||||
},
|
||||
"currentPassword": {
|
||||
"title": "Current password",
|
||||
"description": "Enter your current password to verify your identity",
|
||||
"option": {
|
||||
"label": "Current password",
|
||||
"placeholder": "Enter current password"
|
||||
}
|
||||
},
|
||||
"newPassword": {
|
||||
"title": "New password",
|
||||
"description": "Choose a strong password with at least 8 characters",
|
||||
"option": {
|
||||
"newPassword": {
|
||||
"label": "New password",
|
||||
"placeholder": "Enter new password"
|
||||
},
|
||||
"confirm": {
|
||||
"label": "Confirm password",
|
||||
"placeholder": "Confirm new password"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteAccount": {
|
||||
"title": "Delete account",
|
||||
"description": "This action is permanent and cannot be undone"
|
||||
|
||||
Reference in new issue
Block a user