import { Box, Button, Card, Flex, Group, PasswordInput, Popover, Progress, Text, } from '@mantine/core'; import { useForm, zodResolver } from '@mantine/form'; import { IconArrowLeft, IconArrowRight, IconCheck, IconDice, IconKey, IconX, } from '@tabler/icons-react'; import { useState } from 'react'; import { useTranslation } from 'next-i18next'; import { z } from 'zod'; import { api } from '~/utils/api'; import { passwordSchema } from '~/validations/user'; const requirements = [ { re: /[0-9]/, label: 'Includes number' }, { re: /[a-z]/, label: 'Includes lowercase letter' }, { re: /[A-Z]/, label: 'Includes uppercase letter' }, { re: /[$&+,:;=?@#|'<>.^*()%!-]/, label: 'Includes special symbol' }, ]; function getStrength(password: string) { let multiplier = password.length > 5 ? 0 : 1; requirements.forEach((requirement) => { if (!requirement.re.test(password)) { multiplier += 1; } }); return Math.max(100 - (100 / (requirements.length + 1)) * multiplier, 10); } interface CreateAccountSecurityStepProps { defaultPassword: string; nextStep: ({ password }: { password: string }) => void; prevStep: () => void; } export const CreateAccountSecurityStep = ({ defaultPassword, nextStep, prevStep, }: CreateAccountSecurityStepProps) => { const form = useForm({ initialValues: { password: defaultPassword, }, validateInputOnBlur: true, validateInputOnChange: true, validate: zodResolver(createAccountSecurityStepValidationSchema), }); const { mutateAsync, isLoading } = api.password.generate.useMutation(); const [popoverOpened, setPopoverOpened] = useState(false); const checks = requirements.map((requirement, index) => ( )); const { t } = useTranslation('user/create'); const strength = getStrength(form.values.password); const color = strength === 100 ? 'teal' : strength > 50 ? 'yellow' : 'red'; return (
setPopoverOpened(true)} onBlurCapture={() => setPopoverOpened(false)} > } style={{ flexGrow: 1, }} label={t('steps.security.password.label')} variant="filled" mb="md" withAsterisk {...form.getInputProps('password')} />
5} /> {checks}
); }; const PasswordRequirement = ({ meets, label }: { meets: boolean; label: string }) => { return ( {meets ? : } {label} ); }; export const createAccountSecurityStepValidationSchema = z.object({ password: passwordSchema, });