# Forms

## Form definition

```jsx
import React from 'react'
import * as yup from 'yup'
import { useTranslation } from 'next-i18next'
import { Grid, TextField, Button } from '@material-ui/core'

import { AlertStore } from 'stores/AlertStore'
import useForm, { translateError, customValidators } from 'common/form/useForm'

export type FormData = {
  email: string
}

const validationSchema: yup.SchemaOf<FormData> = yup.object().defined().shape({
  email: yup.string().email().required(),
})

const defaults: FormData = {
  email: '',
}

export type MyFormProps = { initialValues?: FormData }

export default function MyForm({ initialValues = defaults }: MyFormProps) {
  const { t } = useTranslation()

  const { formik } = useForm({
    initialValues,
    validationSchema,
    onSubmit: (values) => {
      console.log(values)
    },
  })

  return (
    <form onSubmit={formik.handleSubmit}>
      <Grid container spacing={3}>
        <Grid item xs={12}>
          <TextField
            type="text"
            fullWidth
            label={t('auth:fields.email')}
            name="email"
            size="small"
            variant="outlined"
            autoFocus
            error={Boolean(formik.errors.email)}
            helperText={translateError(formik.errors.email)}
            value={formik.values.email}
            onBlur={formik.handleBlur}
            onChange={formik.handleChange}
          />
        </Grid>
        <Grid item xs={12}>
          <Button fullWidth type="submit" color="primary" variant="contained">
            {t('auth:cta.login')}
          </Button>
        </Grid>
      </Grid>
    </form>
  )
}
```

## Form usage

```jsx
<MyForm />

<MyForm initailValues={{email: 'test@example.com'}} />
```

## Validation

### Default translations

Simple strings are mapped directly to their respective translation

```javascript
{
  "invalid": "Field is invalid",
  "required": "Required field"
}
```

```jsx
setLocale({
  mixed: {
    default: 'validation:invalid',
    required: 'validation:required',
  },
  string: {
    email: 'validation:email',
  },
})
```

### Default translations with interpolation

Complex translation keys are being evaluated upon translation

```javascript
{
  "field-too-short": "Field should be at least {{min}} symbols",
  "field-too-long": "Field should be maximum {{max}} symbols"
}
```

```jsx
setLocale({
  string: {
    min: ({ min }: { min: number }) => ({
      key: 'validation:field-too-short',
      values: { min },
    }),
    max: ({ max }: { max: number }) => ({
      key: 'validation:field-too-long',
      values: { max },
    }),
  },
})
```

#### Custom translations in validation schema

Commonly used translations with the same translation key

```javascript
yup.string().min(6 customValidators.passwordMin)
```

#### Inline translations in validation schema

Custom translations with keys defined right next to the form

```jsx
const validationSchema: yup.SchemaOf<FormData> = yup
  .object()
  .defined()
  .shape({
    password: yup.string().min(6, ({ min }) => ({
      key: 'validation:password-min',
      values: { min },
    })),
  })
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.podkrepi.bg/development/frontend/guidelines/forms.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
