infoalloggi-monorepo/apps/infoalloggi/src/hooks/usePassword.ts

191 lines
4.7 KiB
TypeScript
Raw Normal View History

import { useState } from "react";
import { type RefinementCtx, z } 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.",
});
}
});
type PasswordManager = {
getStrengthColor: (score: number) => string;
getStrengthTxt: (score: number) => string;
isVisible: boolean;
passwordRefine: ({
password,
refinementContext,
path,
}: {
password: string;
refinementContext: RefinementCtx;
path: string;
}) => void;
strengthScore: number;
toggleVisibility: () => void;
maxStrength: number;
};
export const useStrongPassword = (): PasswordManager => {
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.lenght8 },
{ 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",
input: "",
message: complexity
.filter((req) => !req.met)
.map((req) => req.text)
.join("\n"),
path: [path],
});
}
setStrengthScore(complexity.filter((req) => req.met).length);
};
return {
getStrengthColor,
getStrengthTxt,
isVisible,
passwordRefine,
strengthScore,
toggleVisibility,
maxStrength: 4,
};
};
export const zMildPassword = z.string().superRefine((password, ctx) => {
const test = [/.{6,}/, /[a-z]/, /[A-Z]/].every((regex) =>
regex.test(password),
);
if (!test) {
ctx.addIssue({
code: "custom",
message:
"La password deve contenere almeno 6 caratteri, una lettera minuscola e una maiuscola.",
});
}
});
export const useMildPassword = (): PasswordManager => {
const { t } = useTranslation();
const [isVisible, setIsVisible] = useState<boolean>(false);
const [strengthScore, setStrengthScore] = useState(0);
const checkStrength = (pass: string) => {
const requirements = [
{ regex: /.{6,}/, text: t.auth.signup.pw.lenght6 },
{ 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-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-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",
input: "",
message: complexity
.filter((req) => !req.met)
.map((req) => req.text)
.join("\n"),
path: [path],
});
}
setStrengthScore(complexity.filter((req) => req.met).length);
};
return {
getStrengthColor,
getStrengthTxt,
isVisible,
passwordRefine,
strengthScore,
toggleVisibility,
maxStrength: 3,
};
};