infoalloggi-monorepo/apps/infoalloggi/src/hooks/useStrongPassword.ts
Marco Pedone 9314026817 refactor: update zod imports to version 4 and adjust error handling
- Changed all zod imports from "zod" to "zod/v4" across multiple files.
- Updated error handling in forms to use new zod error configuration.
- Refactored custom error mapping to align with zod v4 changes.
- Adjusted password validation logic to utilize new zod features.
- Cleaned up unused locale error mapping code.
- Enhanced type definitions for async iterables in zod utility functions.
2025-08-07 14:50:40 +02:00

88 lines
2.4 KiB
TypeScript

import { useState } from "react";
import { z, type RefinementCtx } from "zod/v4";
import { useTranslation } from "~/providers/I18nProvider";
export const zStrongPassword = z.string().superRefine((password, ctx) => {
const test = [/.{8,}/, /[0-9]/, /[a-z]/, /[A-Z]/].every((regex) =>
regex.test(password),
);
if (!test) {
ctx.addIssue({
code: "custom",
message:
"La password deve contenere almeno 8 caratteri, un numero, una lettera minuscola e una maiuscola.",
});
}
});
export const useStrongPassword = () => {
const { t } = useTranslation();
const [isVisible, setIsVisible] = useState<boolean>(false);
const [strengthScore, setStrengthScore] = useState(0);
const checkStrength = (pass: string) => {
const requirements = [
{ regex: /.{8,}/, text: t.auth.signup.pw.lenght },
{ regex: /[0-9]/, text: t.auth.signup.pw.number },
{ regex: /[a-z]/, text: t.auth.signup.pw.lowercase },
{ regex: /[A-Z]/, text: t.auth.signup.pw.uppercase },
];
return requirements.map((req) => ({
met: req.regex.test(pass),
text: req.text,
}));
};
const getStrengthColor = (score: number) => {
if (score === 0) return "bg-border";
if (score <= 1) return "bg-red-500";
if (score <= 2) return "bg-orange-500";
if (score === 3) return "bg-amber-500";
return "bg-emerald-500";
};
const getStrengthTxt = (score: number) => {
if (score === 0) return "text-border";
if (score <= 1) return "text-red-500";
if (score <= 2) return "text-orange-500";
if (score === 3) return "text-amber-500";
return "text-emerald-500";
};
const toggleVisibility = () => setIsVisible((prevState) => !prevState);
const passwordRefine = ({
password,
refinementContext,
path,
}: {
password: string;
refinementContext: RefinementCtx;
path: string;
}) => {
const complexity = checkStrength(password);
if (complexity.filter((req) => req.met).length !== complexity.length) {
refinementContext.issues.push({
code: "custom",
message: complexity
.filter((req) => !req.met)
.map((req) => req.text)
.join("\n"),
path: [path],
input: "",
});
}
setStrengthScore(complexity.filter((req) => req.met).length);
};
return {
isVisible,
strengthScore,
getStrengthColor,
getStrengthTxt,
toggleVisibility,
passwordRefine,
};
};