cambio password

mail@pastecode.io avatar
unknown
typescript
a month ago
6.0 kB
9
Indexable
Never
import {
  Box,
  Button,
  Card,
  Container,
  createStyles,
  Group,
  LoadingOverlay,
  PasswordInput,
  Popover,
  Progress,
  Space,
  Title,
} from '@mantine/core'
import { useForm, zodResolver } from '@mantine/form'
import { showNotification } from '@mantine/notifications'
import axios, { AxiosError } from 'axios'
import PasswordRequirement from 'components/elements/Forms/Password'
import {
  getStrength,
  passwordRegex,
  requirements,
} from 'components/elements/Forms/Password/utils'
import { useSession } from 'next-auth/react'
import { useRouter } from 'next/router'
import { SessionWIthUsername } from 'pages/api/auth/[...nextauth]'
import { useState } from 'react'
import { Key } from 'tabler-icons-react'
import { z } from 'zod'
import axiosInstance, { PaxHubErrorResponse } from '../../../axios'

const useStyles = createStyles(theme => ({
  PageTitle: {
    color: theme.colors.blue[5],
    '&:hover': {
      color: theme.colors.blue[7],
    },
  },
  formCard: {
    width: 500,
    marginInline: 'auto',
    boxShadow: theme.shadows.sm,
  },
  formBox: {
    marginInline: 'auto',
  },
  sizedBox: {
    height: 50,
  },
}))

const schema = z
  .object({
    currentPassword: z.string().min(1, { message: 'Campo richiesto' }),
    newPassword: z
      .string()
      .min(2, { message: 'Campo richiesto' })
      .regex(passwordRegex, {
        message: 'La nuova password deve rispettare i criteri di sicurezza',
      }),
    confirmPassword: z.string().min(2, { message: 'Campo richiesto' }),
  })
  .refine(data => data.newPassword === data.confirmPassword, {
    message: 'Le password devono combaciare',
    path: ['confirmPassword'], // path of error
  })

const ChangePassword = () => {
  const { classes } = useStyles()
  const router = useRouter()
  const { data: session } = useSession()

  const [isSubmitting, setIsSubmitting] = useState(false)
  const [popoverOpened, setPopoverOpened] = useState(false)

  const form = useForm({
    schema: zodResolver(schema),
    initialValues: {
      currentPassword: '',
      newPassword: '',
      confirmPassword: '',
    },
  })

  const { onSubmit, getInputProps } = form

  const checks = requirements.map((requirement, index) => (
    <PasswordRequirement
      key={index}
      label={requirement.label}
      meets={requirement.re.test(getInputProps('newPassword').value)}
    />
  ))

  const strength = getStrength(getInputProps('newPassword').value)
  const color = strength === 100 ? 'teal' : strength > 50 ? 'yellow' : 'red'

  const handleSubmit = onSubmit(async (values: typeof form.values) => {
    try {
      setIsSubmitting(true)
      await axiosInstance.post('/admin/change-password', {
        ...values,
        userNameOrEmail: (session as SessionWIthUsername)?.user?.username,
      })
      showNotification({
        title: 'Successo!',
        message: 'Il cambio password è andato a buon fine',
      })
      router.push('/')
    } catch (err) {
      if (axios.isAxiosError(err)) {
        const error = err as AxiosError<PaxHubErrorResponse>
        showNotification({
          title: 'Errore',
          message:
            error.response?.data?.details?.[0] ??
            'Qualcosa è andato storto durante la creazione dello schema, riprova',
          color: 'red',
        })
      } else {
        showNotification({
          title: 'Errore',
          message:
            'Qualcosa è andato storto durante la creazione dello schema, riprova',
          color: 'red',
        })
      }
    } finally {
      setIsSubmitting(false)
    }
  })

  const handleCancel = () => router.push('/')

  return (
    <Container size="xl">
      <div className={classes.sizedBox}></div>
      <Card className={classes.formCard}>
        <LoadingOverlay visible={isSubmitting} />
        <Box className={classes.formBox}>
          <Title order={2} className={classes.PageTitle}>
            Cambia password
          </Title>
          <Space h="sm" />
          <form onSubmit={handleSubmit}>
            <PasswordInput
              label="Password corrente"
              placeholder="Inserisci la tua password attuale"
              autoComplete="current-password"
              {...form.getInputProps('currentPassword')}
            />
            <Space h="sm" />
            <Popover
              opened={popoverOpened}
              position="bottom"
              placement="start"
              withArrow
              styles={{ popover: { width: '100%' } }}
              trapFocus={false}
              transition="pop-top-left"
              onFocusCapture={() => setPopoverOpened(true)}
              onBlurCapture={() => setPopoverOpened(false)}
              target={
                <PasswordInput
                  label="Nuova password"
                  placeholder="Inserisci nuova password"
                  description="la nuova password deve includere lettere minuscole e maiuscole, almeno 1 numero, almeno 1 simbolo speciale"
                  autoComplete="new-password"
                  {...form.getInputProps('newPassword')}
                />
              }
            >
              <Progress
                color={color}
                value={strength}
                size={5}
                style={{ marginBottom: 10 }}
              />
              {checks}
            </Popover>
            <Space h="sm" />
            <PasswordInput
              label="Conferma nuova password"
              placeholder="conferma nuova password"
              autoComplete="new-password"
              {...form.getInputProps('confirmPassword')}
            />
            <Group position="right" mt="xl">
              <Button variant="subtle" onClick={handleCancel}>
                Annulla
              </Button>
              <Button type="submit" rightIcon={<Key size={14} />}>
                Cambia Password
              </Button>
            </Group>
          </form>
        </Box>
      </Card>
    </Container>
  )
}

export default ChangePassword
Leave a Comment