import {
  Meta,
  Story,
  Canvas,
  ArgsTable,
  Title,
  Subtitle,
  Controls,
} from '@storybook/addon-docs/blocks'
import { z } from 'zod'

<Meta title="Form/TanstackForm" />

<Title>Forms with Tanstack Forms</Title>
<Subtitle>Interactive forms with Tanstack Forms.</Subtitle>

## Basic Usage

The following example shows a simple form with a single field.

The submit button is outside the `<form />` tag and we use the `form` attribute in the button to link it back to the form.

```tsx
import React from 'react'
import { useForm } from '@tanstack/react-form'
import {
  Button,
  Field,
  FieldLabel,
  FieldHelper,
  FieldError,
  Input,
  Typography,
  toast,
} from '@chainlink/blocks'
import { z } from 'zod'

const validator = z.object({
  label: z.string().min(1),
})

function SimpleForm() {
  const form = useForm({
    defaultValues: {
      label: '',
    },
    onSubmit: async ({ value }) =>
      toast({
        title: 'Success!',
        description: 'Your action was successful.',
        variant: 'success',
      }),
    validators: {
      onSubmit: validator,
    },
  })

  return (
    <>
      <form
        id="add-organization-api-key-form"
        onSubmit={(e) => {
          e.preventDefault()
          e.stopPropagation()
          form.handleSubmit()
        }}
        className="grid max-w-screen-md gap-2"
      >
        <Typography variant="h5">Name your API</Typography>
        <form.Field name="label">
          {(field) => (
            <Field>
              <FieldLabel htmlFor={field.name}>Name</FieldLabel>
              <FieldHelper>
                The organization API is an HTTP trigger that is used across the
                entire organization for workflow triggers. It is not your
                personal login API, which is automatically generated and
                specific to you.
              </FieldHelper>
              <Input
                id={field.name}
                name={field.name}
                value={field.state.value}
                onBlur={field.handleBlur}
                onChange={(e) => field.handleChange(e.target.value)}
                className="!w-full"
                error={field.state.meta.errors.length > 0}
              />
              {field.state.meta.errors.length > 0 ? (
                <FieldError role="alert">
                  {field.state.meta.errors[0]}
                </FieldError>
              ) : null}
            </Field>
          )}
        </form.Field>
      </form>
      <form.Subscribe
        selector={(state) => [state.canSubmit, state.isSubmitting]}
      >
        {([canSubmit, isSubmitting]) => (
          <Button
            type="submit"
            disabled={!canSubmit}
            size="sm"
            form="add-organization-api-key-form"
          >
            {isSubmitting ? '...' : 'Submit'}
          </Button>
        )}
      </form.Subscribe>
    </>
  )
}
```

## Array Fields

The following example shows a form with an array field.

Array fields are forms where one field is an array of objects. Users can add and remove items from the array from the UI.

```tsx
import React from 'react'
import { useForm } from '@tanstack/react-form'
import {
  Button,
  Field,
  FieldError,
  FieldLabel,
  Input,
  Typography,
  toast,
} from '@chainlink/blocks'
import { z } from 'zod'

interface Member {
  name: string
  email: string
}

const defaultMembers: { members: Array<Member> } = {
  members: [{ name: '', email: '' }],
}

const validator = z.object({
  members: z.array(
    z.object({
      name: z.string().min(1),
      email: z.string().email(),
    }),
  ),
})

export function AddMemberForm() {
  const form = useForm({
    defaultValues: defaultMembers,
    onSubmit: async ({ value }) =>
      toast({
        title: 'Success!',
        description: 'Your action was successful.',
        variant: 'success',
      }),
    validators: {
      onChange: validator,
      onMount: validator,
    },
  })

  return (
    <>
      <form
        id="add-member-form"
        onSubmit={(e) => {
          e.preventDefault()
          e.stopPropagation()
          form.handleSubmit()
        }}
        className="grid max-w-screen-md gap-2"
      >
        <form.Field name="members" mode="array">
          {(field) => {
            return (
              <div>
                {field.state.value.map((_, i) => {
                  return (
                    <div
                      key={i}
                      className="grid grid-cols-[1fr_1fr_auto] items-end gap-4"
                    >
                      <form.Field name={`members[${i}].name`}>
                        {(subField) => {
                          return (
                            <Field>
                              <FieldLabel htmlFor={`members[${i}].name`}>
                                Name
                              </FieldLabel>
                              <Input
                                value={subField.state.value}
                                className="md:w-full! max-w-full"
                                onChange={(e) =>
                                  subField.handleChange(e.target.value)
                                }
                                style={{
                                  width: '100%',
                                }}
                                error={
                                  subField.state.meta.isTouched &&
                                  subField.state.meta.errors.length > 0
                                }
                              />
                              {subField.state.meta.errors.length > 0 ? (
                                <FieldError role="alert">
                                  {subField.state.meta.errors[0]}
                                </FieldError>
                              ) : null}
                            </Field>
                          )
                        }}
                      </form.Field>
                      <form.Field name={`members[${i}].email`}>
                        {(subField) => {
                          return (
                            <Field>
                              <FieldLabel htmlFor={`members[${i}].email`}>
                                Email
                              </FieldLabel>
                              <Input
                                value={subField.state.value}
                                className="md:w-full! max-w-full"
                                onChange={(e) =>
                                  subField.handleChange(e.target.value)
                                }
                                style={{
                                  width: '100%',
                                }}
                                error={
                                  subField.state.meta.isTouched &&
                                  subField.state.meta.errors.length > 0
                                }
                              />
                              {subField.state.meta.errors.length > 0 ? (
                                <FieldError role="alert">
                                  {subField.state.meta.errors[0]}
                                </FieldError>
                              ) : null}
                            </Field>
                          )
                        }}
                      </form.Field>
                      <Button onClick={() => field.removeValue(i)}>
                        Remove value
                      </Button>
                    </div>
                  )
                })}
                <Button
                  onClick={() => field.pushValue({ name: '', email: '' })}
                  type="button"
                  variant="secondary"
                  size="sm"
                  className="mt-4"
                >
                  Add person
                </Button>
              </div>
            )
          }}
        </form.Field>
      </form>
      <form.Subscribe
        selector={(state) => [state.canSubmit, state.isSubmitting]}
      >
        {([canSubmit, isSubmitting]) => (
          <Button
            type="submit"
            disabled={!canSubmit}
            size="sm"
            form="add-member-form"
          >
            {isSubmitting ? '...' : 'Submit'}
          </Button>
        )}
      </form.Subscribe>
    </>
  )
}
```
