✨ Add password meter to onboarding
This commit is contained in:
24
src/components/Password/password-requirement.tsx
Normal file
24
src/components/Password/password-requirement.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Box, Text } from "@mantine/core";
|
||||
import { IconCheck, IconX } from "@tabler/icons-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { minPasswordLength } from "~/validations/user";
|
||||
|
||||
export const PasswordRequirement = ({ meets, label }: { meets: boolean; label: string }) => {
|
||||
const { t } = useTranslation('password-requirements');
|
||||
|
||||
return (
|
||||
<Text
|
||||
color={meets ? 'teal' : 'red'}
|
||||
sx={{ display: 'flex', alignItems: 'center' }}
|
||||
mt={7}
|
||||
size="sm"
|
||||
>
|
||||
{meets ? <IconCheck size="0.9rem" /> : <IconX size="0.9rem" />}{' '}
|
||||
<Box ml={10}>
|
||||
{t(`${label}`, {
|
||||
count: minPasswordLength,
|
||||
})}
|
||||
</Box>
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
39
src/components/Password/password-requirements.tsx
Normal file
39
src/components/Password/password-requirements.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Progress } from '@mantine/core';
|
||||
import { minPasswordLength } from '~/validations/user';
|
||||
|
||||
import { PasswordRequirement } from './password-requirement';
|
||||
|
||||
const requirements = [
|
||||
{ re: /[0-9]/, label: 'number' },
|
||||
{ re: /[a-z]/, label: 'lowercase' },
|
||||
{ re: /[A-Z]/, label: 'uppercase' },
|
||||
{ re: /[$&+,:;=?@#|'<>.^*()%!-]/, label: 'special' },
|
||||
];
|
||||
|
||||
function getStrength(password: string) {
|
||||
let multiplier = password.length >= minPasswordLength ? 0 : 1;
|
||||
|
||||
requirements.forEach((requirement) => {
|
||||
if (!requirement.re.test(password)) {
|
||||
multiplier += 1;
|
||||
}
|
||||
});
|
||||
|
||||
return Math.max(100 - (100 / (requirements.length + 1)) * multiplier, 10);
|
||||
}
|
||||
|
||||
export const PasswordRequirements = ({ value }: { value: string }) => {
|
||||
const checks = requirements.map((requirement, index) => (
|
||||
<PasswordRequirement key={index} label={requirement.label} meets={requirement.re.test(value)} />
|
||||
));
|
||||
|
||||
const strength = getStrength(value);
|
||||
const color = strength === 100 ? 'teal' : strength > 50 ? 'yellow' : 'red';
|
||||
return (
|
||||
<>
|
||||
<Progress color={color} value={strength} size={5} mb="xs" />
|
||||
<PasswordRequirement label="length" meets={value.length >= minPasswordLength} />
|
||||
{checks}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user