[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/Newsletter.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { ComponentType, PropsWithChildren, FormEvent } from 'react'
import { FormattedMessage } from 'react-intl'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'
import { usePixel } from 'vtex.pixel-manager'
import type { PixelEventTypes } from 'vtex.pixel-manager'

import {
  NewsletterContextProvider,
  useNewsletterDispatch,
  useNewsletterState,
  MutationArguments,
  State,
} from './components/NewsletterContext'
import {
  validateEmail,
  validatePhoneNumber,
  validateUserName,
} from './modules/formValidators'

export const CSS_HANDLES = [
  'newsletterForm',
  'defaultSuccessMessage',
  'defaultErrorMessage',
] as const

interface Props {
  ErrorState?: ComponentType
  SuccessState?: ComponentType<{
    subscribedUserData?: {
      email: State['email']
      name: State['name']
      phone: State['phone']
    }
  }>
  LoadingState?: ComponentType
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
  customEventId?: string
}

interface CustomField {
  name: string
  value: string | null | undefined
}

function generateMutationVariables({
  email,
  name,
  phone,
  customFields,
}: {
  email: string
  name: string | undefined | null
  phone: string | undefined | null
  customFields: CustomField[] | null
}) {
  const variables: MutationArguments = { email, fields: {} }

  if (name) {
    variables.fields.name = name
  }

  if (phone) {
    variables.fields.phone = phone
  }

  if (customFields) {
    customFields.forEach((customField) => {
      variables.fields[customField.name] = customField.value
    })
  }

  return variables
}

function Newsletter(props: PropsWithChildren<Props>) {
  const {
    ErrorState,
    SuccessState,
    LoadingState,
    classes,
    children,
    customEventId,
  } = props

  const {
    email,
    name,
    phone,
    submission,
    subscribe,
    customFields,
  } = useNewsletterState()

  const dispatch = useNewsletterDispatch()
  const { push } = usePixel()
  const { handles } = useCssHandles(CSS_HANDLES, { classes })

  if (submission.loading && LoadingState) {
    return <LoadingState />
  }

  if (submission.error) {
    return ErrorState ? (
      <ErrorState />
    ) : (
      <p className={handles.defaultErrorMessage}>
        <FormattedMessage id="store/newsletter-submit-error.default" />
      </p>
    )
  }

  if (submission.data?.subscribeNewsletter) {
    return SuccessState ? (
      <SuccessState subscribedUserData={{ email, name, phone }} />
    ) : (
      <p className={handles.defaultSuccessMessage}>
        <FormattedMessage id="store/newsletter-submit-success.default" />
      </p>
    )
  }

  function validateFormInputs() {
    const isEmailValid = validateEmail(email)

    // name === null is valid because it means there is no name input in the
    // newsletter form.
    const isNameValid = name === null || validateUserName(name)

    // phone === null is valid because it means there is no phone input in the
    // newsletter form.
    const isPhoneValid = phone === null || validatePhoneNumber(phone)

    dispatch({
      type: 'SET_INVALID_EMAIL',
      value: !isEmailValid,
    })

    dispatch({
      type: 'SET_INVALID_NAME',
      value: !isNameValid,
    })

    dispatch({
      type: 'SET_INVALID_PHONE',
      value: !isPhoneValid,
    })

    return isNameValid && isPhoneValid && isEmailValid
  }

  function handleSubmit(e: FormEvent) {
    e.preventDefault()

    const areUserInputsValid = validateFormInputs()

    if (!areUserInputsValid) {
      return
    }

    const pixelData = {
      name,
      email,
      phone,
    }

    const pixelEvent: PixelEventTypes.PixelData = customEventId
      ? {
          id: customEventId,
          event: 'newsletterSubscription',
          data: pixelData,
        }
      : {
          event: 'newsletterSubscription',
          data: pixelData,
        }

    push(pixelEvent)

    const mutationVariables = generateMutationVariables({
      email,
      name,
      phone,
      customFields,
    })

    // The '.catch' here is to prevent 'unhandled promise rejection'.
    // Proper error handling for this is implemented by NewsletterContext
    // using the variables returned by the 'useMutation' call it performs.
    subscribe({ variables: mutationVariables }).catch(() => {})
  }

  return (
    <form className={handles.newsletterForm} onSubmit={handleSubmit}>
      {children}
    </form>
  )
}

function WrappedNewsletter(props: PropsWithChildren<Props>) {
  return (
    <NewsletterContextProvider>
      <Newsletter {...props}>{props.children}</Newsletter>
    </NewsletterContextProvider>
  )
}

WrappedNewsletter.schema = {
  title: 'admin/editor.newsletter-form.title',
}

export default WrappedNewsletter

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/FormNameInput.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { ChangeEvent, useEffect } from 'react'
import { useIntl } from 'react-intl'
import { Input } from 'vtex.styleguide'
import { formatIOMessage } from 'vtex.native-types'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

import {
  useNewsletterDispatch,
  useNewsletterState,
} from './components/NewsletterContext'

const CSS_HANDLES = ['nameInputContainer'] as const

interface Props {
  placeholderText?: string
  inputLabel?: string
  errorMessage?: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

function FormNameInput(props: Props) {
  const {
    placeholderText = 'store/newsletter-input-name.placeholderText.default',
    errorMessage = 'store/newsletter-input-name.errorMessage.default',
    inputLabel,
    classes,
  } = props

  const { invalidName } = useNewsletterState()
  const dispatch = useNewsletterDispatch()
  const { withModifiers } = useCssHandles(CSS_HANDLES, { classes })
  const intl = useIntl()

  // Initialize `name` context value to signal that there is a FormNameInput
  // being rendered inside the newsletter form.
  useEffect(() => dispatch({ type: 'UPDATE_NAME', value: '' }), [dispatch])

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    dispatch({ type: 'UPDATE_NAME', value: e.target.value.trim() })
  }

  return (
    <div
      className={`${withModifiers(
        'nameInputContainer',
        invalidName ? 'invalid' : ''
      )}`}
    >
      <Input
        id="newsletter-input-name"
        name="newsletter"
        onChange={handleChange}
        label={formatIOMessage({ id: inputLabel, intl })}
        errorMessage={
          invalidName ? formatIOMessage({ id: errorMessage, intl }) : null
        }
        placeholder={formatIOMessage({ id: placeholderText, intl })}
      />
    </div>
  )
}

FormNameInput.schema = {
  title: 'admin/editor.newsletter-input-name.title',
}

export default FormNameInput

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/FormSubmit.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'
import { IOMessage } from 'vtex.native-types'
import { Button } from 'vtex.styleguide'

import { useNewsletterState } from './components/NewsletterContext'

const CSS_HANDLES = ['formSubmitContainer'] as const

interface Props {
  submitButtonLabel?: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

function FormSubmit(props: Props) {
  const {
    submitButtonLabel = 'store/newsletter-submit.submitButtonLabel.default',
    classes,
  } = props

  const {
    submission,
    invalidEmail,
    invalidName,
    invalidPhone,
  } = useNewsletterState()

  const formHasInvalidFields = invalidEmail || invalidName || invalidPhone

  const { withModifiers } = useCssHandles(CSS_HANDLES, { classes })

  return (
    <div
      className={`${withModifiers(
        'formSubmitContainer',
        formHasInvalidFields ? 'invalid' : ''
      )}`}
    >
      <Button type="submit" isLoading={submission.loading}>
        <IOMessage id={submitButtonLabel} />
      </Button>
    </div>
  )
}

FormSubmit.schema = {
  title: 'admin/editor.newsletter-submit.title',
}

export default FormSubmit

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/FormConfirmationCheckbox.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { ChangeEvent, useEffect } from 'react'
import { Checkbox } from 'vtex.styleguide'
import { IOMessage } from 'vtex.native-types'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

import {
  useNewsletterDispatch,
  useNewsletterState,
} from './components/NewsletterContext'

const CSS_HANDLES = [
  'confirmationCheckboxContainer',
  'confirmationCheckboxLabel',
  'labelLink',
] as const

interface Props {
  checkboxLabel?: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
  firstLabelLink?: {
    url: string
    text: string
  }
  secondLabelLink?: {
    url: string
    text: string
  }
}

function FormConfirmationCheckbox(props: Props) {
  const {
    checkboxLabel = 'store/newsletter-checkbox-confirmation.checkboxLabel.default',
    firstLabelLink,
    secondLabelLink,
    classes,
  } = props

  const dispatch = useNewsletterDispatch()
  const { confirmation } = useNewsletterState()

  const { handles, withModifiers } = useCssHandles(CSS_HANDLES, { classes })

  // Initialize `confirmation` context value to signal that there is a
  // FormConfirmationCheckbox being rendered inside the newsletter form.
  useEffect(() => dispatch({ type: 'UPDATE_CONFIRMATION', value: false }), [
    dispatch,
  ])

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    dispatch({ type: 'UPDATE_CONFIRMATION', value: e.target.checked })
  }

  return (
    <div className={handles.confirmationCheckboxContainer}>
      <Checkbox
        id="newsletter-checkbox-confirmation"
        name="newsletter-confirmation"
        label={
          <IOMessage
            id={checkboxLabel}
            values={{
              firstLink: (
                <a
                  className={withModifiers('labelLink', 'first')}
                  href={firstLabelLink?.url}
                >
                  {firstLabelLink?.text}
                </a>
              ),
              secondLink: (
                <a
                  className={withModifiers('labelLink', 'second')}
                  href={secondLabelLink?.url}
                >
                  {secondLabelLink?.text}
                </a>
              ),
            }}
          />
        }
        onChange={handleChange}
        checked={confirmation}
        required
      />
    </div>
  )
}

FormConfirmationCheckbox.schema = {
  title: 'admin/editor.newsletter-checkbox-confirmation.title',
}

export default FormConfirmationCheckbox

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/FormHiddenField.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useEffect } from 'react'
import { useRuntime } from 'vtex.render-runtime'

import { useNewsletterDispatch } from './components/NewsletterContext'

type DynamicField = 'bindingUrl' | 'bindingId'

interface Props {
  dynamicFields: DynamicField[]
}

interface ResolvedCustomField {
  name: string
  value: string | undefined | null
}

function FormHiddenField({ dynamicFields = [] }: Props) {
  const dispatch = useNewsletterDispatch()
  const runtime = useRuntime()

  const resolvedCustomFields = dynamicFields.map((field) => {
    const resolvedCustomField: ResolvedCustomField = {
      name: field,
      value: null,
    }

    if (field === 'bindingUrl') {
      resolvedCustomField.value = runtime.binding?.canonicalBaseAddress ?? null
    }

    if (field === 'bindingId') {
      resolvedCustomField.value = runtime.binding?.id ?? null
    }

    return resolvedCustomField
  })

  useEffect(() => {
    dispatch({
      type: 'SET_CUSTOM_VALUES',
      value: resolvedCustomFields,
    })
  }, [resolvedCustomFields, dispatch])

  return null
}

export default FormHiddenField

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/FormPhoneInput.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { ChangeEvent, useEffect } from 'react'
import { useIntl } from 'react-intl'
import { Input } from 'vtex.styleguide'
import { formatIOMessage } from 'vtex.native-types'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

import {
  useNewsletterDispatch,
  useNewsletterState,
} from './components/NewsletterContext'

const CSS_HANDLES = ['phoneInputContainer'] as const

interface Props {
  placeholderText?: string
  inputLabel?: string
  errorMessage?: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

function FormPhoneInput(props: Props) {
  const {
    placeholderText = 'store/newsletter-input-phone.placeholderText.default',
    errorMessage = 'store/newsletter-input-phone.errorMessage.default',
    inputLabel,
    classes,
  } = props

  const { invalidPhone } = useNewsletterState()
  const dispatch = useNewsletterDispatch()
  const { withModifiers } = useCssHandles(CSS_HANDLES, { classes })
  const intl = useIntl()

  // Initialize `phone` context value to signal that there is a FormPhoneInput
  // being rendered inside the newsletter form.
  useEffect(() => dispatch({ type: 'UPDATE_PHONE', value: '' }), [dispatch])

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    dispatch({ type: 'UPDATE_PHONE', value: e.target.value.trim() })
  }

  return (
    <div
      className={`${withModifiers(
        'phoneInputContainer',
        invalidPhone ? 'invalid' : ''
      )}`}
    >
      <Input
        id="newsletter-input-phone"
        name="newsletter"
        type="tel"
        label={formatIOMessage({ id: inputLabel, intl })}
        onChange={handleChange}
        errorMessage={
          invalidPhone ? formatIOMessage({ id: errorMessage, intl }) : null
        }
        placeholder={formatIOMessage({ id: placeholderText, intl })}
      />
    </div>
  )
}

FormPhoneInput.schema = {
  title: 'admin/editor.newsletter-input-phone.title',
}

export default FormPhoneInput

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/FormEmailInput.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { ChangeEvent } from 'react'
import { useIntl } from 'react-intl'
import { Input } from 'vtex.styleguide'
import { formatIOMessage } from 'vtex.native-types'
import { useCssHandles, CssHandlesTypes } from 'vtex.css-handles'

import {
  useNewsletterDispatch,
  useNewsletterState,
} from './components/NewsletterContext'

const CSS_HANDLES = ['emailInputContainer'] as const

interface Props {
  placeholderText?: string
  inputLabel?: string
  errorMessage?: string
  classes?: CssHandlesTypes.CustomClasses<typeof CSS_HANDLES>
}

function FormEmailInput(props: Props) {
  const {
    placeholderText = 'store/newsletter-input-email.placeholderText.default',
    errorMessage = 'store/newsletter-input-email.errorMessage.default',
    inputLabel,
    classes,
  } = props

  const { invalidEmail } = useNewsletterState()
  const dispatch = useNewsletterDispatch()
  const { withModifiers } = useCssHandles(CSS_HANDLES, { classes })
  const intl = useIntl()

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    dispatch({ type: 'UPDATE_EMAIL', value: e.target.value.trim() })
  }

  return (
    <div
      className={`${withModifiers(
        'emailInputContainer',
        invalidEmail ? 'invalid' : ''
      )}`}
    >
      <Input
        id="newsletter-input-email"
        type="email"
        name="newsletter"
        label={formatIOMessage({ id: inputLabel, intl })}
        onChange={handleChange}
        errorMessage={
          invalidEmail ? formatIOMessage({ id: errorMessage, intl }) : null
        }
        placeholder={formatIOMessage({ id: placeholderText, intl })}
      />
    </div>
  )
}

FormEmailInput.schema = {
  title: 'admin/editor.newsletter-input-email.title',
}

export default FormEmailInput

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/package.json from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "store-newsletter",
  "version": "1.3.0",
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "apollo-client": "^2.6.8",
    "react": "^16.12.0",
    "react-apollo": "^3.1.3",
    "react-dom": "^16.12.0",
    "react-intl": "^3.12.0"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/jest": "^25.1.4",
    "@types/node": "^13.9.8",
    "@types/react": "^16.9.31",
    "@vtex/test-tools": "^3.3.2",
    "@vtex/tsconfig": "^0.4.4",
    "apollo-cache-inmemory": "^1.6.5",
    "graphql": "^14.6.0",
    "typescript": "3.9.7",
    "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@1.0.0/public/@types/vtex.css-handles",
    "vtex.native-types": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.native-types@0.7.5/public/@types/vtex.native-types",
    "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.7.0/public/@types/vtex.pixel-manager",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.128.2/public/@types/vtex.render-runtime",
    "vtex.store-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-graphql@2.139.0/public/@types/vtex.store-graphql",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.136.2/public/@types/vtex.styleguide"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/store/contentSchemas.json from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "definitions": {
    "EmailInput": {
      "properties": {
        "placeholderText": {
          "title": "admin/editor.newsletter-input-email.placeholderText.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "inputLabel": {
          "title": "admin/editor.newsletter-input-email.inputLabel.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "errorMessage": {
          "title": "admin/editor.newsletter-input-email.errorMessage.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        }
      }
    },

    "NameInput": {
      "properties": {
        "placeholderText": {
          "title": "admin/editor.newsletter-input-name.placeholderText.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "inputLabel": {
          "title": "admin/editor.newsletter-input-name.inputLabel.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "errorMessage": {
          "title": "admin/editor.newsletter-input-name.errorMessage.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        }
      }
    },

    "PhoneInput": {
      "properties": {
        "placeholderText": {
          "title": "admin/editor.newsletter-input-phone.placeholderText.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "inputLabel": {
          "title": "admin/editor.newsletter-input-phone.inputLabel.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "errorMessage": {
          "title": "admin/editor.newsletter-input-phone.errorMessage.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        }
      }
    },

    "ConfirmationCheckbox": {
      "properties": {
        "checkboxLabel": {
          "title": "admin/editor.newsletter-checkout-confirmation.checkboxLabel.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        },
        "firstLink": {
          "title": "admin/editor.newsletter-checkout-confirmation.firstLink.title",
          "properties": {
            "url": {
              "title": "admin/editor.newsletter-checkout-confirmation.firstLink.url",
              "$ref": "app:vtex.native-types#/definitions/url"
            },
            "text": {
              "title": "admin/editor.newsletter-checkout-confirmation.firstLink.text",
              "$ref": "app:vtex.native-types#/definitions/text"
            }
          }
        },
        "secondLink": {
          "title": "admin/editor.newsletter-checkout-confirmation.secondLink.title",
          "properties": {
            "url": {
              "title": "admin/editor.newsletter-checkout-confirmation.secondLink.url",
              "$ref": "app:vtex.native-types#/definitions/url"
            },
            "text": {
              "title": "admin/editor.newsletter-checkout-confirmation.secondLink.text",
              "$ref": "app:vtex.native-types#/definitions/text"
            }
          }
        }
      }
    },

    "NewsletterSubmit": {
      "properties": {
        "submitButtonLabel": {
          "title": "admin/editor.newsletter-submit.submitButtonLabel.title",
          "$ref": "app:vtex.native-types#/definitions/text"
        }
      }
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/store/interfaces.json from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "newsletter-form": {
    "component": "Newsletter",
    "composition": "children"
  },
  "newsletter-hidden-field": {
    "component": "FormHiddenField"
  },
  "newsletter-input-email": {
    "component": "FormEmailInput",
    "content": {
      "$ref": "app:vtex.store-newsletter#/definitions/EmailInput"
    }
  },
  "newsletter-input-name": {
    "component": "FormNameInput",
    "content": {
      "$ref": "app:vtex.store-newsletter#/definitions/NameInput"
    }
  },
  "newsletter-input-phone": {
    "component": "FormPhoneInput",
    "content": {
      "$ref": "app:vtex.store-newsletter#/definitions/PhoneInput"
    }
  },
  "newsletter-checkbox-confirmation": {
    "component": "FormConfirmationCheckbox",
    "content": {
      "$ref": "app:vtex.store-newsletter#/definitions/ConfirmationCheckbox"
    }
  },
  "newsletter-submit": {
    "component": "FormSubmit",
    "content": {
      "$ref": "app:vtex.store-newsletter#/definitions/NewsletterSubmit"
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/typings/graphql.d.ts from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module '*.gql' {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const graphql: any
  export default graphql
}

declare module '*.graphql' {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const graphql: any
  export default graphql
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/typings/vtex.styleguide.d.ts from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module 'vtex.styleguide' {
  export const Button: any
  export const Input: any
  export const Checkbox: any
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/components/NewsletterContext.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { ApolloError } from 'apollo-client'
import React, {
  createContext,
  useReducer,
  useContext,
  PropsWithChildren,
  useEffect,
} from 'react'
import { MutationFunction, useMutation } from 'react-apollo'

import subscribeNewsletterMutation from '../graphql/subscribeNewsletter.gql'

interface SubmissionState {
  error: undefined | ApolloError
  data: { subscribeNewsletter: boolean } | undefined
  loading: boolean
}

export interface MutationArguments {
  email: string
  fields: {
    name?: string
    phone?: string
    bindingUrl?: string
    bindingId?: string
    [key: string]: string | undefined | null
  }
}

interface CustomField {
  name: string
  value: string | undefined | null
}

export interface State {
  email: string
  name: string | null
  phone: string | null
  customFields: CustomField[] | null
  confirmation: boolean | null
  invalidEmail: boolean
  invalidName: boolean
  invalidPhone: boolean
  submission: SubmissionState
  subscribe: MutationFunction<
    { subscribeNewsletter: boolean },
    MutationArguments
  >
}

interface UpdateEmailAction {
  type: 'UPDATE_EMAIL'
  value: State['email']
}

interface UpdateNameAction {
  type: 'UPDATE_NAME'
  value: State['name']
}

interface UpdatePhoneAction {
  type: 'UPDATE_PHONE'
  value: State['phone']
}

interface UpdateConfirmationAction {
  type: 'UPDATE_CONFIRMATION'
  value: State['confirmation']
}

interface SetInvalidEmailAction {
  type: 'SET_INVALID_EMAIL'
  value: State['invalidEmail']
}

interface SetInvalidNameAction {
  type: 'SET_INVALID_NAME'
  value: State['invalidName']
}

interface SetInvalidPhoneAction {
  type: 'SET_INVALID_PHONE'
  value: State['invalidPhone']
}

interface SetCustomValuesAction {
  type: 'SET_CUSTOM_VALUES'
  value: State['customFields']
}

interface SetMutationValues {
  type: 'SET_MUTATION_VALUES'
  value: SubmissionState
}

type Action =
  | UpdateEmailAction
  | UpdateNameAction
  | UpdatePhoneAction
  | UpdateConfirmationAction
  | SetInvalidEmailAction
  | SetMutationValues
  | SetInvalidNameAction
  | SetInvalidPhoneAction
  | SetCustomValuesAction
type Dispatch = (action: Action) => void

const NewsletterStateContext = createContext<State | undefined>(undefined)
const NewsletterDispatchContext = createContext<Dispatch | undefined>(undefined)

function newsletterContextReducer(state: State, action: Action): State {
  switch (action.type) {
    case 'UPDATE_EMAIL':
      return {
        ...state,
        email: action.value,
      }

    case 'UPDATE_NAME':
      return {
        ...state,
        name: action.value,
      }

    case 'UPDATE_PHONE':
      return {
        ...state,
        phone: action.value,
      }

    case 'UPDATE_CONFIRMATION':
      return {
        ...state,
        confirmation: action.value,
      }

    case 'SET_INVALID_EMAIL':
      return {
        ...state,
        invalidEmail: action.value,
      }

    case 'SET_INVALID_NAME':
      return {
        ...state,
        invalidName: action.value,
      }

    case 'SET_INVALID_PHONE':
      return {
        ...state,
        invalidPhone: action.value,
      }

    case 'SET_MUTATION_VALUES': {
      return {
        ...state,
        submission: action.value,
      }
    }

    case 'SET_CUSTOM_VALUES': {
      return {
        ...state,
        customFields: action.value,
      }
    }

    default:
      return state
  }
}

function NewsletterContextProvider(props: PropsWithChildren<{}>) {
  const [subscribeToNewsletter, { data, loading, error }] = useMutation<
    { subscribeNewsletter: boolean },
    MutationArguments
  >(subscribeNewsletterMutation)

  const [state, dispatch] = useReducer(newsletterContextReducer, {
    email: '',
    name: null,
    phone: null,
    customFields: null,
    confirmation: null,
    invalidEmail: false,
    invalidName: false,
    invalidPhone: false,
    subscribe: subscribeToNewsletter,
    submission: {
      data,
      loading,
      error,
    },
  })

  // Update mutation variables in State
  useEffect(() => {
    dispatch({
      type: 'SET_MUTATION_VALUES',
      value: { loading, error, data },
    })
  }, [error, loading, data])

  return (
    <NewsletterStateContext.Provider value={state}>
      <NewsletterDispatchContext.Provider value={dispatch}>
        {props.children}
      </NewsletterDispatchContext.Provider>
    </NewsletterStateContext.Provider>
  )
}

function useNewsletterState() {
  const context = useContext(NewsletterStateContext)

  if (context === undefined) {
    throw new Error(
      'useNewsletterState must be used within a NewsletterContextProvider'
    )
  }

  return context
}

function useNewsletterDispatch() {
  const context = useContext(NewsletterDispatchContext)

  if (context === undefined) {
    throw new Error(
      'useNewsletterDispatch must be used within a NewsletterContextProvider'
    )
  }

  return context
}

export { NewsletterContextProvider, useNewsletterDispatch, useNewsletterState }

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/__tests__/index.test.tsx from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { render, fireEvent, waitFor } from '@vtex/test-tools/react'
import { usePixel } from 'vtex.pixel-manager'

import Newsletter from '../Newsletter'
import FormEmailInput from '../FormEmailInput'
import FormNameInput from '../FormNameInput'
import FormPhoneInput from '../FormPhoneInput'
import FormSubmit from '../FormSubmit'
import subscribeNewsletter from '../graphql/subscribeNewsletter.gql'

const mockedUsePixel = usePixel as jest.Mock<ReturnType<typeof usePixel>>

beforeEach(() => {
  mockedUsePixel().push.mockReset()
})

const EMAIL_PLACEHOLDER_MESSAGE_ID =
  'store/newsletter-input-email.placeholderText.default'

const NAME_PLACEHOLDER_MESSAGE_ID =
  'store/newsletter-input-name.placeholderText.default'

const PHONE_PLACEHOLDER_MESSAGE_ID =
  'store/newsletter-input-phone.placeholderText.default'

describe('Basic rendering', () => {
  it('should render complete newsletter subscribe form', () => {
    const { getByPlaceholderText, getByText } = render(
      <Newsletter>
        <FormNameInput />
        <FormEmailInput />
        <FormSubmit />
      </Newsletter>
    )

    // newsletter-input-email block
    expect(getByPlaceholderText(EMAIL_PLACEHOLDER_MESSAGE_ID)).toBeTruthy()

    // newsletter-input-name block
    expect(getByPlaceholderText(NAME_PLACEHOLDER_MESSAGE_ID)).toBeTruthy()

    // newsletter-submit block
    expect(getByText('Subscribe')).toBeTruthy()
  })
})

describe('Form validation', () => {
  it('should show error message if email is not a valid one', () => {
    const { getByPlaceholderText, getByText } = render(
      <Newsletter>
        <FormEmailInput />
        <FormSubmit />
      </Newsletter>
    )

    const mockedInput = getByPlaceholderText(EMAIL_PLACEHOLDER_MESSAGE_ID)

    const submit = getByText('Subscribe')

    const wrongEmail = 'foobar'

    fireEvent.change(mockedInput, { target: { value: wrongEmail } })
    fireEvent.click(submit)

    expect(mockedInput).toHaveAttribute('data-errormessage')
  })

  it('should show error message if name is empty', () => {
    const { getByPlaceholderText, getByText } = render(
      <Newsletter>
        <FormNameInput />
        <FormSubmit />
      </Newsletter>
    )

    const mockedInput = getByPlaceholderText(NAME_PLACEHOLDER_MESSAGE_ID)

    const submit = getByText('Subscribe')

    fireEvent.click(submit)

    expect(mockedInput).toHaveAttribute('data-errormessage')
  })
})

describe('Reacting to mutation results', () => {
  it('should show success message if everything went well', async () => {
    const validEmail = 'foobar@vtex.com'
    const validPhone = '+5511123456789'
    const validName = 'Ted'

    const mocks = [
      {
        request: {
          query: subscribeNewsletter,
          variables: {
            email: validEmail,
            fields: { name: validName, phone: validPhone },
          },
        },
        result: {
          data: {
            subscribeNewsletter: {},
          },
        },
      },
    ]

    const { getByPlaceholderText, getByText } = render(
      <Newsletter>
        <FormEmailInput />
        <FormNameInput />
        <FormPhoneInput />
        <FormSubmit />
      </Newsletter>,
      {
        graphql: { mocks, addTypename: false },
      }
    )

    const mockedEmailInput = getByPlaceholderText(EMAIL_PLACEHOLDER_MESSAGE_ID)
    const mockedNameInput = getByPlaceholderText(NAME_PLACEHOLDER_MESSAGE_ID)
    const mockedPhoneInput = getByPlaceholderText(PHONE_PLACEHOLDER_MESSAGE_ID)

    const submit = getByText('Subscribe')

    fireEvent.change(mockedEmailInput, { target: { value: validEmail } })
    fireEvent.change(mockedNameInput, { target: { value: validName } })
    fireEvent.change(mockedPhoneInput, { target: { value: validPhone } })

    fireEvent.click(submit)

    const thanks = await waitFor(() => getByText('Thanks for subscribing!'))

    expect(mockedUsePixel().push).toHaveBeenCalledWith({
      event: 'newsletterSubscription',
      data: { email: validEmail, name: validName, phone: validPhone },
    })

    expect(thanks).toBeTruthy()
  })

  it('should show error message if something went wrong', async () => {
    const validEmail = 'foobar@vtex.com'
    const validName = 'Ted'

    const mocks = [
      {
        request: {
          query: subscribeNewsletter,
          variables: { email: validEmail, name: validName },
        },
        error: new Error('Something went wrong'),
      },
    ]

    const { getByPlaceholderText, getByText } = render(
      <Newsletter>
        <FormEmailInput />
        <FormNameInput />
        <FormSubmit />
      </Newsletter>,
      {
        graphql: { mocks, addTypename: false },
      }
    )

    const mockedEmailInput = getByPlaceholderText(EMAIL_PLACEHOLDER_MESSAGE_ID)
    const mockedNameInput = getByPlaceholderText(NAME_PLACEHOLDER_MESSAGE_ID)

    const submit = getByText('Subscribe')

    fireEvent.change(mockedEmailInput, { target: { value: validEmail } })
    fireEvent.change(mockedNameInput, { target: { value: validName } })

    fireEvent.click(submit)

    const sorry = await waitFor(() => getByText('Sorry, something went wrong.'))

    expect(sorry).toBeTruthy()
  })
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/graphql/subscribeNewsletter.gql from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation subscribeNewsletter($email: String, $fields: NewsletterFieldsInput)
  @context(provider: "vtex.store-graphql") {
  subscribeNewsletter(email: $email, fields: $fields)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of store-newsletter/react/modules/formValidators.ts from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```typescript
// https://regex101.com/r/926sxf/1
// If you change the regex, don't forget to go to the link above, update it there and save.
const EMAIL_REGEX = /^[A-z0-9"+_-]+(?:\.[A-z0-9+_-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/

// https://regex101.com/r/5dVM9R/1
// If you change the regex, don't forget to go to the link above, update it there and save.
const PHONE_REGEX = /([0-9]|\(|\)|\+| |-)+/

export function validateEmail(email: string) {
  return EMAIL_REGEX.test(email)
}

export function validatePhoneNumber(phone: string) {
  return PHONE_REGEX.test(phone)
}

export function validateUserName(name: string) {
  return name.length > 0
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/index.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { infiniteScroll } from './InfinityScroll'
import { pagination } from './Pagination'

const render = (seeMore: string) => {
  switch (seeMore) {
    case 'pagination': {
      pagination()
      break
    }

    case 'infinite': {
      infiniteScroll()
      break
    }

    default: {
      infiniteScroll()
    }
  }
}

render('infinite')

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/Pagination.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import ReactDOM from 'react-dom'

import Button from './QuickpayButton'
import Wrapper from './KuikpayWrapper'
import { search } from './services'
import { formatItems, useRender } from './utils'

export const pagination = () => {
  const { elements, item, wrapper, items } = useRender()

  if (!wrapper) return

  ReactDOM.render(<Wrapper />, wrapper)

  if (elements.length) {
    const searchQuery = items
      .map((parameter: string) => `fq=skuId:${parameter}&`)
      .join('')

    search(searchQuery, 0, 49).then((products) => {
      const sortedProducts: any = []

      items.forEach((itemId: string) => {
        products.forEach((product: any) => {
          product.items.forEach((sku: any) => {
            if (sku.itemId === itemId) sortedProducts.push(product)
          })
        })
      })

      sortedProducts.forEach((product: any, index: number) => {
        const { selectedItem, itemsFormatted, variations } = formatItems(
          product,
          items[index]
        )

        if (selectedItem) {
          const itemInfo = {
            id: selectedItem.itemId,
            seller: selectedItem.sellers[0].sellerId,
          }

          ReactDOM.render(
            <Button
              key={selectedItem.itemId}
              itemInfo={itemInfo}
              product={{ ...product, items: itemsFormatted }}
              selectedItem={{ ...selectedItem, variations }}
            />,
            elements[index]
          )
        }
      })
    })
  }

  if (item) {
    ReactDOM.render(<Button />, item)
  }
}

const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.addedNodes.length) {
      pagination()
    }
  })
})

const list = document.getElementsByClassName('prateleira')[0]

if (list) {
  observer.observe(list, {
    childList: true,
  })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/KuikpayQuotaInformation.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { KuikpayQuotaInformative } from 'kuikpay-sdk'
import type { ProductItem } from 'kuikpay-sdk/dist/interfaces'

import { CONSTANTS } from './utils'

const LANGUAGE = 'es'
const THEME = 'kuikpay'
const windowInfo: any = window
const { vtxctx } = windowInfo
const RUNTIME = {
  account: vtxctx.url.split('.')[0],
  workspace: CONSTANTS.workspace,
  platform: CONSTANTS.platform,
}

interface Props {
  selectedItem?: ProductItem
}

export const KuikpayQuotaInformation = ({ selectedItem }: Props) => {
  return (
    <div>
      <KuikpayQuotaInformative
        language={LANGUAGE}
        theme={THEME}
        selectedItem={selectedItem}
        runtime={RUNTIME}
      />
    </div>
  )
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/QuickpayButton.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect } from 'react'
import { Kuikpay } from 'kuikpay-sdk'
import 'kuikpay-sdk/dist/index.css'
import type {
  ItemToAdd,
  Product,
  ProductItem,
} from 'kuikpay-sdk/dist/interfaces'

import type { ItemInfo } from './interfaces'
import { CONSTANTS } from './utils'

interface Props {
  itemInfo?: ItemInfo
  product?: Product
  selectedItem?: ProductItem
  onClickBehavior?: 'ensure-sku-selection'
}

const windowInfo: any = window
const { vtexjs, vtxctx } = windowInfo

const Button = (props: Props) => {
  const {
    itemInfo,
    product,
    selectedItem: mainSelectedItem,
    onClickBehavior = 'ensure-sku-selection',
  } = props

  const [selectedItem, setSelectedItem] = useState(mainSelectedItem)
  const [skuInfo, setSkuInfo] = useState(
    windowInfo.skuJson_0
      ? {
          id: windowInfo.skuJson_0.skus[0]?.sku,
          quantity: 1,
          seller: windowInfo.skuJson_0.skus[0]?.sellerId,
        }
      : {
          id: itemInfo?.id,
          quantity: 1,
          seller: itemInfo?.seller,
        }
  )

  const [visible, setVisible] = useState(true)

  const changeSkuId = (skuId: string) => {
    setSkuInfo((prevState) => ({
      ...prevState,
      id: skuId,
    }))
  }

  useEffect(() => {
    if (!windowInfo.skuJson_0) return

    // This detects new sku selection from PDP
    $(window).on('vtex.sku.selected', (evt, productId, sku) => {
      changeSkuId(sku.sku)
      setVisible(sku.available)
    })

    return () => {
      $(window).off('vtex.sku.selected', (evt, productId, sku) => {
        changeSkuId(sku.sku)
      })
    }
  }, [])

  // useEffect(() => {
  // 	vtexjs.checkout.getOrderForm().done(orderForm => {
  // 		setOrderForm(orderForm)
  // 	});

  useEffect(() => {
    if (!selectedItem) return
    changeSkuId(selectedItem?.itemId)
  }, [selectedItem])

  // const handleOrderFormUpdated = (_: any, orderFormData: any) => {
  //   setOrderForm(orderFormData)
  // }

  // useEffect(() => {
  //   $(window).on('orderFormUpdated.vtex', handleOrderFormUpdated)

  //   return () => {
  //     $(window).off('orderFormUpdated.vtex', handleOrderFormUpdated)
  //   }
  // }, [])

  const handleAddToCart = (item: ItemToAdd) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.addToCart([item])
    })
  }

  // Item to add to cart
  const itemToAdd = skuInfo
    ? {
        id: skuInfo.id,
        quantity: 1,
        seller: skuInfo.seller,
      }
    : null

  // Function to update order form selected address
  // const handleUpdateSelectedAddress = (address: any) => {
  //   vtexjs.checkout.getOrderForm().then(function () {
  //     return vtexjs.checkout.sendAttachment('shippingData', {
  //       address,
  //       clearAddressIfPostalCodeNotFound: false,
  //     })
  //   })
  // }

  const itemsLength = product?.items?.length ?? 0
  const multipleAvailableSKUs = itemsLength > 1

  const handleSelectedItem = (item: ProductItem) => {
    setSelectedItem(item)
  }

  const runtime = {
    account: vtxctx.url.split('.')[0],
    workspace: CONSTANTS.workspace,
    platform: CONSTANTS.platform,
  }

  return (
    <Kuikpay
      addToCart={handleAddToCart}
      itemToAdd={itemToAdd}
      isVisible={visible}
      // validateItems={validateItems}
      // customData={customData}
      // config={config}
      // validateBeforeOfAdd={validateBeforeOfAdd}
      multipleAvailableSKUs={multipleAvailableSKUs}
      onClickBehavior={onClickBehavior}
      product={product}
      selectedItem={selectedItem}
      handleSelectedItem={handleSelectedItem}
      runtime={runtime}
      sandbox={false}
    />
  )
}

export default Button

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/KuikpayWrapper.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useEffect, useState } from 'react'
import { KuikpayWrapper } from 'kuikpay-sdk'
import type {
  Item,
  ItemToAdd,
  ItemToRemove,
  OfferingInput,
  Totalizer,
} from 'kuikpay-sdk/dist/interfaces'

import { cartSimulation } from './services'
import type { Profile } from './interfaces'
import { CONSTANTS } from './utils'

const LANGUAGE = 'es'
const THEME = 'kuikpay'
const windowInfo: any = window
const { vtexjs, jsnomeLoja } = windowInfo
const RUNTIME = {
  account: jsnomeLoja,
  workspace: CONSTANTS.workspace,
  platform: CONSTANTS.platform,
}

const Kuikpaywrapper = () => {
  const [order, setOrder] = useState(null)
  const [orderForm, setOrderForm] = useState<any>({})

  const listendCheckout = (_: any, orderFormData: any) => {
    setOrderForm(orderFormData)
  }

  useEffect(() => {
    $(window).on('orderFormUpdated.vtex', listendCheckout)

    return () => {
      $(window).off('orderFormUpdated.vtex', listendCheckout)
    }
  }, [])

  useEffect(() => {
    const formattedOrderForm = {
      clientProfileData: {
        email: orderForm.clientProfileData?.email,
      },
      shippingData: {
        selectedAddress: {
          addressId: orderForm.selectedAddress?.addressId || '',
          addressType: orderForm.selectedAddress?.addressType || '',
          city: orderForm.selectedAddress?.city || '',
          complement: orderForm.selectedAddress?.complement || '',
          country: orderForm.selectedAddress?.country || '',
          geoCoordinates: orderForm.selectedAddress?.geoCoordinates || '',
          isDisposable: orderForm.selectedAddress?.isDisposable || '',
          neighborhood: orderForm.selectedAddress?.neighborhood || '',
          number: orderForm.selectedAddress?.number || '',
          postalCode: orderForm.selectedAddress?.postalCode || '',
          receiverName: orderForm.selectedAddress?.receiverName || '',
          reference: orderForm.selectedAddress?.reference || '',
          state: orderForm.selectedAddress?.state || '',
          street: orderForm.selectedAddress?.street || '',
          completed: false || '',
        },
      },
      items: orderForm?.items?.map((item: Item, index: number) => ({
        ...item,
        sellingPrice: item.sellingPrice / 100,
        price: item.price / 100,
        listPrice: item?.listPrice / 100,
        index,
      })),
      totalizers: orderForm.totalizers,
      value: orderForm.value / 100,
      messages: orderForm.messages?.couponMessages
        ? orderForm.messages?.couponMessages
        : orderForm.messages,
      marketingData: {
        coupon: orderForm.marketingData?.coupon,
      },
    }

    setOrder(formattedOrderForm)
  }, [orderForm])

  const handleInsertCoupon = (text: string) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.addDiscountCoupon(text)
    })
  }

  const handleAddItemOffering = ({ offeringId, itemIndex }: OfferingInput) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.addOffering(offeringId, itemIndex)
    })
  }

  const handleRemoveItemOffering = ({
    offeringId,
    itemIndex,
  }: OfferingInput) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.removeOffering(offeringId, itemIndex)
    })
  }

  const handleUpdateOrderFormProfile = (profile: Profile) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.sendAttachment('clientProfileData', profile)
    })
  }

  const handleUpdateItems = (items: ItemToRemove[]) => {
    const itemsInfo = items.map((item: ItemToRemove) => {
      return { index: item.index, quantity: item.quantity }
    })

    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.updateItems(itemsInfo, null, false)
    })
  }

  const handleClearItems = (_items: ItemToRemove[]) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.removeAllItems()
    })
  }

  const handleAddToCart = (item: ItemToAdd) => {
    vtexjs.checkout.getOrderForm().then(() => {
      return vtexjs.checkout.addToCart([item])
    })
  }

  const clearOrderFormProfile = async () => {
    const clientProfileData = orderForm?.clientProfileData

    if (clientProfileData) {
      const changeToAnonymousUserURL =
        await vtexjs.checkout.getChangeToAnonymousUserURL()

      fetch(changeToAnonymousUserURL, {
        method: 'GET',
        redirect: 'follow',
      }).then(() => {
        vtexjs.checkout.getOrderForm().then((e: any) => {
          listendCheckout('', e)
        })
      })
    }
  }

  return (
    <KuikpayWrapper
      updateSelectedAddress={() => {}}
      cartSimulation={cartSimulation}
      language={LANGUAGE}
      theme={THEME}
      runtime={RUNTIME}
      insertCoupon={handleInsertCoupon}
      addItemOffering={handleAddItemOffering}
      removeItemOffering={handleRemoveItemOffering}
      updateOrderFormProfile={handleUpdateOrderFormProfile}
      updateItems={handleUpdateItems}
      clearData={handleClearItems}
      orderForm={order}
      addToCart={handleAddToCart}
      sandbox={false}
      clearOrderFormProfile={clearOrderFormProfile}
    />
  )
}

export default Kuikpaywrapper

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/InfinityScroll.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import ReactDOM from 'react-dom'

import Button from './QuickpayButton'
import { renderWrapper } from './Wrapper'
import { search } from './services'
import { formatItems, useRender } from './utils'

const container = document.currentScript.getAttribute('container')

renderWrapper()

export const infiniteScroll = () => {
  const { elements, item, items, undockedElements } = useRender()

  if (elements.length) {
    const intervalItems: any = []
    const interval = 50

    for (let i = 0; i < items.length; i += interval) {
      const intervalItem = items.slice(i, i + interval)

      intervalItems.push(intervalItem)
    }

    const searchQueries = intervalItems.map((intervalItem: string[]) => {
      return intervalItem
        .map((parameter: string) => `fq=skuId:${parameter}&`)
        .join('')
    })

    searchQueries.forEach(async (searchQuery: string) => {
      const products = await search(searchQuery, 0, 49)

      const sortedProducts: any = []

      intervalItems.forEach((intervalItem: any) => {
        intervalItem.forEach((itemId: string) => {
          products.forEach((product: any) => {
            product.items.forEach((sku: any) => {
              if (sku.itemId === itemId) sortedProducts.push(product)
            })
          })
        })
      })

      sortedProducts.forEach((product: any, index: number) => {
        const { selectedItem, itemsFormatted, variations } = formatItems(
          product,
          items[index]
        )

        if (selectedItem) {
          const itemInfo = {
            id: selectedItem.itemId,
            seller: selectedItem.sellers[0].sellerId,
          }

          ReactDOM.render(
            <Button
              key={selectedItem.itemId}
              itemInfo={itemInfo}
              product={{ ...product, items: itemsFormatted }}
              selectedItem={{ ...selectedItem, variations }}
            />,
            elements[index]
          )
        }

        elements[index].className = 'kuikpay-rendered'
      })
    })
  }

  if (item) {
    ReactDOM.render(<Button />, item)
  }

  if (undockedElements) {
    undockedElements.forEach((undockedElement: any) =>
      ReactDOM.render(<Button />, undockedElement)
    )
  }
}

const observer = new MutationObserver((mutations) => {
  if (mutations.length) {
    infiniteScroll()
  }
})

// const list = document.getElementsByClassName('showcases__grid')[1]
const list = document.getElementsByClassName(container)[0]

if (list) {
  observer.observe(list, {
    childList: true,
    subtree: true,
  })
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/Wrapper.tsx from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import ReactDOM from 'react-dom'

import Wrapper from './KuikpayWrapper'
import { useRender } from './utils'

export const renderWrapper = () => {
  const { wrapper } = useRender()

  if (!wrapper) return
  ReactDOM.render(<Wrapper />, wrapper)
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/utils/index.ts from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const CONSTANTS = {
  workspace: 'master',
  platform: 'vtex-cms',
}

export const useRender = () => {
  const elements = Array.from(document.getElementsByClassName('kuikpay'))
  const undockedElements = Array.from(
    document.getElementsByClassName('kuikpay-undocked')
  )

  const item = document.getElementById('kuikpay')
  const wrapper = document.getElementById('kuikpayWrapper')
  const items = elements.map((e) => e.id.split('-')[1])

  return {
    elements,
    item,
    wrapper,
    items,
    undockedElements,
  }
}

export const formatItems = (product: any, itemId: any) => {
  const selectedItem = product.items.find(
    (itemInfo: any) => itemInfo.itemId === itemId
  )

  const itemsFormatted = product?.items?.map((sku: any) => {
    const variations = sku?.variations?.map((variation: any) => {
      return {
        name: variation,
        values: sku[variation],
      }
    })

    return {
      ...sku,
      variations,
    }
  })

  const variations = selectedItem?.variations?.map((variation: any) => {
    return {
      name: variation,
      values: selectedItem[variation],
    }
  })

  return {
    selectedItem,
    itemsFormatted,
    variations,
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/services/index.ts from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { CartSimulation } from 'kuikpay-sdk/dist/interfaces'

export const search = async (query: string, from = 0, to = 12) => {
  const myHeaders = new Headers()

  myHeaders.append('Accept', 'application/json')
  myHeaders.append('Content-Type', 'application/json')

  const requestOptions = {
    method: 'GET',
    headers: myHeaders,
    redirect: 'follow' as const,
  }

  const response = await fetch(
    `/api/catalog_system/pub/products/search/?${query}_from=${from}&_to=${to}`,
    requestOptions
  )

  return response.json()
}

export const cartSimulation = async (body: CartSimulation) => {
  const myHeaders = new Headers()

  myHeaders.append('Accept', 'application/json')
  myHeaders.append('Content-Type', 'application/json')

  const raw = JSON.stringify(body)

  const requestOptions = {
    method: 'POST',
    headers: myHeaders,
    body: raw,
    redirect: 'follow' as const,
  }

  const response = await fetch(
    '/api/checkout/pub/orderforms/simulation',
    requestOptions
  )

  return response
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of mycheckout-portal-cms/src/interfaces/index.ts from the mycheckout-portal-cms VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface ItemInfo {
  id: string
  seller: string
}

export interface Profile {
  email?: string
  firstName?: string
  lastName?: string
  document?: string
  phone?: string
  documentType?: string
  isCorporate?: boolean
  corporateName?: string
  tradeName?: string
  corporateDocument?: string
  stateInscription?: string
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/docs/README.md from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```markdown
# File Manager GraphQL

A GraphQL service for managing files in VTEX applications. This service provides a simple interface for uploading, retrieving, and deleting files with support for image resizing.

This API is a GraphQL abstraction of the [vtex.file-manager@0.x](https://github.com/vtex/file-manager) app, providing a unified interface for file management.
Usage

## Features

- File uploads with automatic UUID-based naming
- File retrieval with optional image resizing
- File URL generation for direct access
- File deletion
- Authentication requirements for sensitive operations
- Support for different storage buckets

## Usage
To use this API, declare it in your manifest.json file:

```JSON
"dependencies": {
  "file-manager-graphql": "0.x"
}
```

## Queries

### getFileUrl
Returns the immutable URL of a file.

| Arguments | Type | Description |
| --- | --- | --- |
| path | [String](#string) | File path |
| bucket | [String](#string) |  Bucket name |

### getFile

| Arguments | Type | Description |
| --- | --- | --- |
| path | [String](#string) | File path |
| bucket | [String](#string) |  Bucket name |
| width | [Int](#int) |  Image width |
| height | [Int](#int) |  Image height |
| aspect | [Boolean](#boolean) |  Maintain image aspect ratio |

### settings
Returns the API settings.

## Mutations

### uploadFile
Saves a file and returns its immutable URL.

| Arguments | Type | Description |
| --- | --- | --- |
| file | [File](#file) | File to be uploaded |
| bucket | [String](#string) |  Bucket name |

### deleteFile
Deletes a file from a bucket.

| Arguments | Type | Description |
| --- | --- | --- |
| path | [String](#string) | File path |
| bucket | [String](#string) |  Bucket name |

## Types

### File

| Field | Type | Description |
| --- | --- | --- |
| fileUrl | [String](#string) | File URL |
| mimetype | [String](#string) |  File MIME type |
| encoding | [String](#string) |  File encoding |

### Settings

| Field | Type | Description |
| --- | --- | --- |
| maxFileSizeMB | [Int](#int) | Maximum allowed file size (in MB) |

### Examples

Getting a file URL

```graphql
query {
  getFileUrl(path: "path/to/file", bucket: "images") {
    fileUrl
  }
}
```

Getting a file

```graphql
query {
  getFile(path: "path/to/file", width: 100, height: 100, bucket: "images") {
    file
  }
}
```

Uploading a file

```graphql

mutation {
  uploadFile(file: ..., bucket: "images") {
    fileUrl
  }
}
```

## Scalars

### Boolean

The `Boolean` scalar type represents `true` or `false`.

### Int

The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.

### String

The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

## Security

This service implements authentication directives to ensure that sensitive operations like file uploads and deletions are properly authorized.

## License

This project is licensed under the terms specified in the `package.json` file.
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/graphql/schema.graphql from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```graphql
type File {
  fileUrl: String!
  mimetype: String!
  encoding: String!
}

type Settings {
  maxFileSizeMB: Int
}

type Mutation {
  """Save file (returns file's immutable URL)"""
  uploadFile(file: Upload!, bucket: String = "images"): File @requiresAuth
  """Delete file from bucket"""
  deleteFile(path: String!, bucket: String = "images"): Boolean! @requiresAuth
}

type Query {
  """Get file’s immutable URL"""
  getFileUrl(path: String!, bucket: String = "images"): String
  """Get file"""
  getFile(path: String!, width: Int = 1, height: Int = 2, aspect: Boolean = false, bucket: String = "images"): String
  """Settings"""
  settings: Settings
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/FileManager.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext } from '@vtex/api'
import { ExternalClient } from '@vtex/api'

import { FileNotFound } from './exceptions/fileNotFound'
import { InternalServerError } from './exceptions/internalServerError'

const appId = process.env.VTEX_APP_ID
const [runningAppName] = appId ? appId.split('@') : ['']

const FORWARD_FIELDS = ['status', 'statusText', 'data', 'stack', 'stackTrace']

const pickForwardFields = (object: any) =>
  ({ ...Object.fromEntries(FORWARD_FIELDS.map(field => [field, object[field]])) })

const routes = {
  Assets: () => `/assets/${runningAppName}`,
  FileUpload: (bucket: string, path: string) =>
    `${routes.Assets()}/save/${bucket}/${path}`,
  FileUrl: (bucket: string, path: string) =>
    `${routes.Assets()}/route/${bucket}/${path}`,
  FileDelete: (bucket: string, path: string) =>
    `${routes.Assets()}/delete/${bucket}/${path}`,
  File: (
    path: string,
    width: number,
    height: number,
    aspect: boolean,
    bucket: string
  ) =>
    `${routes.Assets()}/${bucket}/${path}?width=${width}&height=${height}&aspect=${aspect}`,
}

export default class FileManager extends ExternalClient {

  constructor(protected context: IOContext, options?: InstanceOptions) {
    super(
      `http://app.io.vtex.com/vtex.file-manager/v0/${context.account}/${context.workspace}`,
      context,
      {
        ...(options ?? {}),
        headers: {
          ...(options?.headers ?? {}),
          'VtexIdclientAutCookie': context.authToken,
          'Content-Type': 'application/json',
          'X-Vtex-Use-Https': 'true',
        },
      }
    )
  }

  public getFile = async ({
    path,
    width,
    height,
    aspect,
    bucket,
  }: {
    path: string
    width: number
    height: number
    aspect: boolean
    bucket: string
  }) => {
    try {
      return await this.http.get(
        routes.File(path, width, height, aspect, bucket)
      )
    } catch (e) {
      if (e.statusCode === 404 || e.response?.status === 404) {
        throw new FileNotFound(pickForwardFields(e.response))
      } else {
        throw e
      }
    }
  }

  getFileUrl = async (path: string, bucket: string) => {
    try {
      const fileUrl = routes.FileUrl(bucket, path)
      const file = await this.http.get(fileUrl)
      return file
    } catch (e) {
      if (e.statusCode === 404 || e.response?.status === 404) {
        throw new FileNotFound(pickForwardFields(e.response))
      } else {
        throw e
      }
    }
  }

  saveFile = async (file: IncomingFile, stream: any, bucket: string) => {
    try {
      const { filename, encoding, mimetype } = file
      const headers = {
        'Content-Type': mimetype,
        'Content-Encoding': encoding,
      }

      return await this.http.put(routes.FileUpload(bucket, filename), stream, {
        headers,
        metric: 'file-manager-save-file',
      })
    } catch (e) {
      const status = e.statusCode || e.response?.status || 500
      const extensions = pickForwardFields(e.response)

      throw new InternalServerError(extensions, 'Fail to save file', status)
    }
  }

  deleteFile = async (path: string, bucket: string) => {
    try {
      return await this.http.delete(routes.FileDelete(bucket, path), {
        metric: 'file-manager-delete-file',
      })
    } catch (e) {
      if (e.statusCode === 404 || e.response?.status === 404) {
        throw new FileNotFound(pickForwardFields(e.response))
      } else {
        throw e
      }
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/service.json from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "stack": "nodejs",
  "memory": 128,
  "ttl": 60,
  "timeout": 60,
  "minReplicas": 4,
  "maxReplicas": 10,
  "runtimeArgs": ["--max_old_space_size=400"]
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/typings.d.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare global {
  interface IncomingFile {
    filename: string
    mimetype: string
    encoding: string
  }
}

export {}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/package.json from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "vtex.file-manager-graphql",
  "description": "GraphQL resolvers. Any required dependencies should be defined in this file.",
  "version": "0.7.6",
  "dependencies": {
    "@vtex/api": "^7.0.0",
    "apollo-upload-server": "^5.0.0",
    "dompurify": "^3.2.6",
    "jsdom": "21",
    "ramda": "^0.25.0",
    "uuid": "^8.2.0"
  },
  "resolutions": {
    "@types/express": "4.16.0",
    "@types/express-serve-static-core": "4.16.0"
  },
  "devDependencies": {
    "@types/jest": "^24.0.24",
    "@types/jsdom": "^21.1.7",
    "@types/node": "^20.0.0",
    "@types/uuid": "^10.0.0",
    "tslint": "^5.14.0",
    "tslint-config-vtex": "^2.1.0",
    "typescript": "5.5.3",
    "vtex.file-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.file-manager@0.11.0/public/_types/react"
  },
  "scripts": {
    "lint": "tsc --noEmit && tslint -c tslint.json './**/*.ts'"
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/index.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ParamsContext, RecorderState } from '@vtex/api'
import { Service } from '@vtex/api'

import { resolvers } from './resolvers'
import type { Clients } from './clients'
import { clients } from './clients'
import { Authorization } from './directives/auth'

export default new Service<Clients, RecorderState, ParamsContext>({
  clients,
  graphql: {
    resolvers,
    schemaDirectives: {
      requiresAuth: Authorization,
    },
  },
})

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/directives/auth.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { defaultFieldResolver, GraphQLField } from 'graphql'
import { SchemaDirectiveVisitor } from 'graphql-tools'

import { ALLOW_LIST } from '../config/allowList'

export const authFromCookie = async (ctx: any, operationName: string) => {
  const {
    clients: { sphinx, vtexID },
    vtex: { authToken },
  } = ctx

  const vtexIdToken =
    ctx.cookies.get('VtexIdclientAutCookie') ??
    ctx.request.header.vtexidclientautcookie ??
    ctx.cookies.get('VtexIdclientAutCookie_' + ctx.vtex.account)

  if (!vtexIdToken) {
    return 'User must be logged to access this resource'
  }

  const { user: email } = (await vtexID.getIdUser(vtexIdToken, authToken)) || {
    user: '',
  }

  if (!email) {
    return 'Could not find user specified by token.'
  }

  if (operationName === 'deleteFile') {
    // Only admin users can delete files
    const isAdminUser = await sphinx.isAdmin(email)

    if (!isAdminUser) {
      return 'User is not admin and can not access resource.'
    }
  }

  return true
}

export class Authorization extends SchemaDirectiveVisitor {
  public visitFieldDefinition(field: GraphQLField<any, any>) {
    const { resolve = defaultFieldResolver } = field

    // eslint-disable-next-line max-params
    field.resolve = async (root, args, ctx, info) => {
      const operationName = info.fieldName
      let isAllowed = false

      if (operationName === 'uploadFile') {
        const isInAllowList = ALLOW_LIST.includes(ctx.vtex.account)

        if (isInAllowList) {
          isAllowed = true
        }
      }

      if (!isAllowed) {
        const cookieAllowsAccess = await authFromCookie(ctx, operationName)

        if (cookieAllowsAccess !== true) {
          throw new Error(cookieAllowsAccess)
        }
      }

      return resolve(root, args, ctx, info)
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/clients/index.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ClientsConfig } from '@vtex/api'
import { Sphinx, IOClients } from '@vtex/api'

import { VtexID } from './id'

const DEFAULT_CLIENT_TIMEOUT = 2 * 60000

export class Clients extends IOClients {
  public get vtexID() {
    return this.getOrSet('vtexID', VtexID)
  }

  public get sphinx() {
    return this.getOrSet('sphinx', Sphinx)
  }
}

export const clients: ClientsConfig<Clients> = {
  implementation: Clients,
  options: {
    default: {
      retries: 1,
      timeout: DEFAULT_CLIENT_TIMEOUT,
    },
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/clients/id.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { ExternalClient, InstanceOptions, IOContext } from '@vtex/api'

const userAgent = process.env.VTEX_APP_ID!

export class VtexID extends ExternalClient {
  public constructor(context: IOContext, options?: InstanceOptions) {
    super('http://vtexid.vtex.com.br/api/vtexid', context, options)
  }

  public getIdUser = (token: string, authToken: string) =>
    this.http.get(`pub/authenticated/user`, {
      headers: {
        Accept: 'application/json',
        Authorization: authToken,
        'Content-Type': 'application/json',
        'User-Agent': userAgent,
        'X-VTEX-Proxy-To': 'https://vtexid.vtex.com.br',
        'X-Vtex-Use-Https': true,
      },
      metric: 'vtexid-authtoken',
      params: {
        authToken: token,
      },
    })
}
```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/config/allowList.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const ALLOW_LIST = [
  'storecomponents',
  'adidasuy',
  'amakha',
  'ambientegourmetb2b',
  'americanas',
  'amoedo',
  'animalcare',
  'animalsveterinaria',
  'arcaplanetqa',
  'arraisjoalheria',
  'artwalk',
  'asicsar',
  'aureliusarg',
  'authogar',
  'batistellaar',
  'b2bextratosdaterra',
  'b2cdistraves',
  'b2ctrendy',
  'bellapiel',
  'bemol',
  'bosico',
  'bremenar',
  'caffarenacl',
  'calcadosbibi',
  'calimaxmx',
  'calzadobucaramanga',
  'canadiennecl',
  'carrefourar',
  'carsaperupoc',
  'casatema',
  'cellarvinhos',
  'cemacogt',
  'ceramicaitalia',
  'chedrauimx',
  'ciatoy',
  'cnutresa',
  'cocinailko',
  'coffeemarleycl',
  'cograb2b',
  'colchonesfantasiacol',
  'columbiaar',
  'corona',
  'cutis',
  'cynthiapamplona',
  'dallabernardina',
  'damasco',
  'dartelcl',
  'dbebesec',
  'delupo',
  'diafer',
  'discoargentina',
  'distrollermx',
  'drogasmil',
  'electroluxb2bcc',
  'elbalconar',
  'exitocol',
  'extrafarmav2',
  'farmaonline',
  'farmaciaindiana',
  'farmaciasklyns',
  'farmaciasdelpueblo',
  'farmaciauniversalpe',
  'filaar',
  'fstudio',
  'furzaiarg',
  'geant',
  'gersamex',
  'ginebra',
  'gruposoares',
  'hacebco',
  'hering',
  'hopelingerie',
  'hospinet',
  'hrojoyas',
  'imegab2c',
  'inpostfresh',
  'irmaossoares',
  'isesacl',
  'jorgebischoff',
  'jorlan',
  'jumbocolombiaio',
  'jwpepper',
  'keralty',
  'keybiscaynear',
  'kidsmadehereperu',
  'kiplingco',
  'kiplingmexico',
  'krosscl',
  'lamarinamx',
  'lasirena',
  'ledstudiocl',
  'levisarg',
  'levisuy',
  'librerialerner',
  'lojaobramax',
  'lojaspompeia',
  'lojaspeedo',
  'lojasrede',
  'lojavivara',
  'lojahr',
  'lotodelsur',
  'loucossantos',
  'lunettes',
  'magazzinoar',
  'magherar',
  'marshallmoffat',
  'mateuarg',
  'mcxhoreca',
  'medipielsa',
  'melimeloparis',
  'micco',
  'mkchile',
  'monumentalar',
  'mpower',
  'multicenter',
  'multitop',
  'muralsyourway',
  'murataar',
  'negrarosaloja',
  'nespressouy',
  'newiwcstore',
  'novaikesaki',
  'nuevaamericanapy',
  'officemax',
  'pandoraar',
  'panamericanaeditorial',
  'paguemenos',
  'paulette',
  'pcbox',
  'pedidosfarma',
  'pentruanimalero',
  'pepeganga',
  'pilatos21',
  'pillin',
  'pinataar',
  'plataformaamtres',
  'privilege',
  'puntodeportivoar',
  'ramasamx',
  'realplaza',
  'reebokpe',
  'renawarecolombia',
  'renawareperu',
  'roddos',
  'rocamadour',
  'rosario',
  'rsconnect',
  'safetystoremx',
  'sallybeautymx',
  'samsungar',
  'samsclub',
  'scandinavianar',
  'sbslibreria',
  'sedinternationalb2b',
  'servicomglobalar',
  'simanguatemala',
  'simannicor',
  'sjdigital',
  'sportingio',
  'springstep',
  'stanleypm',
  'startar',
  'tekielar',
  'tennis',
  'tfcz36',
  'tfcqf0',
  'tfcvgc',
  'tfcr83',
  'thinkpinkperub2b',
  'timesquare',
  'tommyperu',
  'tommycostarica',
  'tonypapelerias',
  'tosel',
  'totouy',
  'tottoecuador',
  'tpvcl',
  'tuaar',
  'tuachlb2b',
  't55018',
  't06512',
  'underarmourcl',
  'unidrogas',
  'vansuy',
  'vitrioenhancedpartnerbr',
  'wokerio',
  'xuss',
  'yagmourio',
  'yuhmak',
]

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/exceptions/fileNotFound.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
export class FileNotFound extends Error {
  constructor(
    public extensions: any,
    public message = 'File Not Found',
    public statusCode = 404
  ) {
    super(message)
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/exceptions/internalServerError.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
export class InternalServerError extends Error {
  constructor(
    public extensions: any,
    public message = 'Internal Server Error',
    public statusCode = 500
  ) {
    super(message)
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of file-manager-graphql/node/resolvers/index.ts from the file-manager-graphql VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { v4 as uuidv4 } from 'uuid'
import { JSDOM } from 'jsdom'
import createDOMPurify from 'dompurify'
// eslint-disable-next-line prettier/prettier
import type { ServiceContext } from '@vtex/api'

import FileManager from '../FileManager'
import { Readable } from 'stream'

type FileManagerArgs = {
  path: string
  width: number
  height: number
  aspect: boolean
  bucket: string
}

type UploadFileArgs = {
  file: Promise<any>
  bucket: string
}

const isValidFileFormat = (extension: string, mimetype: string) => {

  if (!extension || !mimetype) {
    return false
  }

  // Normalize extension to lowercase
  const normalizedExtension = extension.toLowerCase()

  // Define allowed file types with their corresponding MIME types
  const allowedFileTypes = {
  png: 'image/png',
  jpg: 'image/jpeg',
  jpeg: 'image/jpeg',
  gif: 'image/gif',
  webp: 'image/webp',
  svg: 'image/svg+xml',
  pdf: 'application/pdf',
  doc: 'application/msword',
  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  xls: 'application/vnd.ms-excel',
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  txt: 'text/plain',
}

  if(!(extension in allowedFileTypes)) {
    return false
  }

  return normalizedExtension in allowedFileTypes && allowedFileTypes[normalizedExtension as keyof typeof allowedFileTypes] === mimetype
}

const sanitizeSvgFile = async (loadedFile: any) => {
    const fileBuffer = await loadedFile.createReadStream().toArray()
    const fileString = Buffer.concat(fileBuffer).toString('utf8')

    const {window} = new JSDOM('')
    const DOMPurify = createDOMPurify(window)

    const cleanSvgString = DOMPurify.sanitize(fileString, {
      USE_PROFILES: { svg: true },
    })

    return {
      isSafe: typeof cleanSvgString === 'string' &&
      cleanSvgString.trim().length > 0 &&
      cleanSvgString.includes('<svg'),
      sanitizedContent: cleanSvgString,
    }
}

export const resolvers = {
  Query: {
    getFile: async (_: unknown, args: FileManagerArgs, ctx: ServiceContext) => {
      const fileManager = new FileManager(ctx.vtex)
      const { path, width, height, aspect, bucket } = args

      const file = await fileManager.getFile({path, width, height, aspect, bucket})

      return file
    },
    getFileUrl: async (_: unknown, args: FileManagerArgs, ctx: ServiceContext) => {
      const fileManager = new FileManager(ctx.vtex)
      const { path, bucket } = args

      const file = await fileManager.getFileUrl(path, bucket)

      return file
    },
    settings: async () => ({
      maxFileSizeMB: 4,
    }),
  },
  Mutation: {
    uploadFile: async (_: unknown, args: UploadFileArgs, ctx: ServiceContext) => {
      const fileManager = new FileManager(ctx.vtex)
      const { file, bucket } = args
      let loadedFile = await file
      const {filename: name, mimetype, encoding } = loadedFile
      const [extension] = name?.split('.')?.reverse()

      if (!isValidFileFormat(extension, mimetype)) {
        throw new Error('Invalid file format')
      }

      // Validate SVG files separately
      // SVG files require additional validation to prevent XSS attacks
      // and other security issues, so we check if the file is SVG
      // and sanitize it if necessary.

      if (mimetype === 'image/svg+xml') {
        const {isSafe, sanitizedContent} = await sanitizeSvgFile(loadedFile)
          if (!isSafe) {
            throw new Error('Forced attempt to upload unsafe SVG file with no valid content')
          }

        const sanitizedBuffer = Buffer.from(sanitizedContent, 'utf8')

        loadedFile.createReadStream = () => Readable.from(sanitizedBuffer)
      }

      const filename = `${uuidv4()}.${extension}`
      const stream = loadedFile.createReadStream()

      const incomingFile = { filename, mimetype, encoding }

      return {
        encoding,
        mimetype,
        fileUrl: await fileManager.saveFile(incomingFile, stream, bucket),
      }
    },
    deleteFile: async (_: unknown, args: FileManagerArgs, ctx: ServiceContext) => {
      const fileManager = new FileManager(ctx.vtex)
      const { path, bucket } = args

      await fileManager.deleteFile(path, bucket)

      return true
    },
  },
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of io-landing/messages/pt.json from the io-landing VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "io.page-title": "VTEX IO",
  "io.navbar.learn": "Learn",
  "io.navbar.feature-list": "Our Components",
  "io.navbar.keepup": "Keep Up",
  "io.navbar.build": "Build with IO",
  "io.navbar.faq": "FAQ",
  "io.hero.globalbrands": "Build for global brands.",
  "io.hero.resources": "With right resources at hand, you will help expand the possibilities of businesses around the world.",
  "io.hero.cta": "Build stores with IO",
  "io.hero.partners": "Learn about our Partner Program",
  "io.cards.first.title": "Get Started with IO",
  "io.cards.first.text": "Learn the basics and start building apps, extensions and integrations.",
  "io.cards.second.title": "IO Master Class",
  "io.cards.second.text": "Watch videos and take a deep dive into all things IO: tools, tips, and possibilities.",
  "io.cards.third.title": "Explore our Components",
  "io.cards.third.text": "Explore the components we've developed and explore our available and upcoming features.",
  "io.cards.fourth.title": "Frequently Asked Questions",
  "io.cards.fourth.text": "Find the answers you are looking for.",
  "io.product.deliver": "Deliver more, deliver better",
  "io.product.scale": "Tailor-made meets scale.",
  "io.product.cloud": "With a cloud environment and an integrated commerce-drive toolset, it's a lot easier for retailers and developers to scale solutions for specific needs.",
  "io.howitworks.appstore": "App Store",
  "io.howitworks.appstore.scale": "Solutions that scale",
  "io.howitworks.appstore.solutions": "Make your business-driven solutions available to 2.500+ stores in 25 countries through our exclusive distribution channel.",
  "io.howitworks.abtesting": "A/B Testing",
  "io.howitworks.abtesting.decisions": "Informed business decisions",
  "io.howitworks.abtesting.tests": "Perform tests on every aspect of your business to learn what works best. Use the isolated Test Workspaces to iterate faster, increase sales, and raise conversion rates.",
  "io.howitworks.storeframework": "Store Framework",
  "io.howitworks.storeframework.build": "Build faster, grow better",
  "io.howitworks.storeframework.develop": "Reduce loading time, improve usability, and make the best of SEO. Developing scalable components with a comprehensive, easy-to-use toolset, you can build stores faster than ever.",
  "io.evolution.focus": "Focus on what matters",
  "io.evolution.evolution": "Seamless evolution.",
  "io.evolution.perspective": "VTEX IO delivers a new paradigm for cloud software development that’s heavily integrated into the environment where your code will actually run. This shift in perspective unlocks new capabilities that were impossible on the traditional, local development model.",
  "io.evolution.vtexio": "VTEX IO",
  "io.evolution.vtexio.description": "It's our serverless development platform, designed to help you create scalable, production-ready web applications – and never have to worry about any infrastructure complexity again.",
  "io.features.title": "Powerful tools to power-up your solutions.",
  "io.features.title.small": "Make the most out of your work",
  "io.features.cloud": "Works on the cloud",
  "io.features.cloud.description": "It's the end of the mismatch between local and production environments. No code runs on your computer: The source gets synced to the cloud, where it is built and deployed in real-time.",
  "io.features.setupless": "Setupless",
  "io.features.setupless.description": "No need to oldfashioned developer environment setup anymore. All you need to start building apps is a lightweight console application and a developer account.",
  "io.features.workspaces": "Workspaces",
  "io.features.workspaces.description": "Instantaneous app deploy and rollback with a single command. Manage different versions of your apps and test new features in isolation, with the peace of mind you need to experiment and evolve to quickly.",
  "io.features.serverless": "Serverless",
  "io.features.serverless.description": "Our infrastructure is designed to scale your code according to traffic. CDN distribution and the SmartCacheⓇ system guarantees high performance and low latency.",
  "io.startbuilding.title": "Start building the future of commerce.",
  "io.startbuilding.text": "Build apps with cutting-edge technology, meet the needs of world-class brands and expand the possibilities of retail.",
  "io.startbuilding.cta": "BECOME A PARTNER",
  "io.footer.vtex": "Accelerating Commerce Transformation.",
  "io.footer.pricing": "Pricing",
  "io.footer.company": "Company",
  "io.footer.company.carrers": "Carrers",
  "io.footer.company.partnersAWS": "Partners AWS",
  "io.footer.company.dmca": "DMCA Policy",
  "io.footer.company.blog": "Blog",
  "io.footer.resources": "Resources",
  "io.footer.resources.devdocs": "Development Docs",
  "io.footer.resources.support": "Support",
  "io.footer.resources.announcements": "Announcements",
  "io.footer.resources.releases": "Releases",
  "io.footer.resources.status": "Status",
  "io.footer.resources.health": "Health Check",
  "io.footer.resources.vtexio": "VTEX IO",
  "io.footer.partners": "Partners",
  "io.footer.partners.vtex": "VTEX Partners",
  "io.footer.partners.find": "Find a partner",
  "io.footer.partners.program": "Partner Program",
  "io.footer.partners.appstore": "VTEX App Store",
  "io.faq.page-title": "FAQ - VTEX IO",
  "io.faq.basic-concepts.vtex-vtexio.summary": "What's the difference between VTEX and VTEX IO?",
  "io.faq.basic-concepts.vtex-vtexio.ans": "",
  "io.faq.migrate.why-v1-no-more.summary": "Why was v1 discontinued?",
  "io.faq.migrate.why-v1-no-more.ans": "",
  "io.faq.migrate.why-migrate.summary": "Why should I upgrade to v2?",
  "io.faq.migrate.why-migrate.ans": "You should upgrade so that you have access to the full power and capabilities of VTEX IO and Store Framework, the latest and greatest VTEX has to offer. Also, stay up to date with every new feature we develop in a seamless way, just as described at https://vtex.io .",
  "io.faq.migrate.advantages-v2.summary": "What are the advantages of using Store v2?",
  "io.faq.migrate.advantages-v2.ans": "",
  "io.faq.migrate.unavailable-features.summary": "Are there functionalities that were available in v1 but not in v2?",
  "io.faq.migrate.unavailable-features.ans": "For a full feature comparison between our new CMS and our old one, you can check out https://vtex.io/store-features .",
  "io.faq.migrate.how-to.summary": "How can I get started with migrating to v2?",
  "io.faq.migrate.how-to.ans": "Currently there is not an automated process to migrate a store from v1 to v2. Basically the front-end needs to be rebuilt using our Store Framework.",
  "io.faq.create-store.components.summary": "What components already exist?",
  "io.faq.create-store.components.ans": "Quite a few! And new ones are coming. You can check out a list at https://vtex.io/store-features#store-component-apps .",
  "io.faq.create-store.components-functionality.summary": "Will I be able to implement functionalities I need using the components already provided by VTEX or should I build my own?",
  "io.faq.create-store.components-functionality.ans": "We strongly recommend everyone to use the components already provided by VTEX, as they already offer a certain degree of customization and are fully supported by the Store Framework team. If you want some new feature that we do not support yet, please check our contributing guidelines so that you can maybe add this feature to our components and make it available to everyone (open-source rules!). ",
  "io.faq.create-store.unsupported.summary": "What is not supported by Store v2?",
  "io.faq.create-store.unsupported.ans": "We don't fully support (for now) exclusive features for: marketplaces, B2B, delivery and grocery. For the time being we will not be making any modification to our components so that they support those specific use cases.",
  "io.faq.create-store.supported.summary": "What is supported by Store v2?",
  "io.faq.create-store.supported.ans": "We support all common features for basic stores that sell items which don't require a great degree of personalization, such as: fashion, home appliances, cosmedics and sporting goods.",
  "io.faq.create-store.to-PR-or-not-to-PR.summary": "How do I know if I should create a new app or send a PR to make an existing app better?",
  "io.faq.create-store.to-PR-or-not-to-PR.ans": "We always encourage everyone to contribute to the development of all components we build, that's why they are all open-source! Check out our contributing guidelines for a better guide on how to send that PR or discuss a new feature you want to implement, they live at: https://github.com/vtex-apps/awesome-io .",
  "io.faq.create-store.component-docs.summary": "Where can I find documentation on which props (or blocks) can be passed to each block?",
  "io.faq.create-store.component-docs.ans": "Each block is exported by a component built by the Store Framework team, and their documentation lives in each one of their GitHub repositories. You can check out our list of available components and the links to each repository at https://vtex.io/store-features#store-component-apps .",
  "io.faq.extend-store-framework.summary": "How can I extend the provided functionalities from Store Framework?",
  "io.faq.extend-store-framework.ans": "Due to a recent change in the way VTEX is handling extensibility with VTEX IO, in order to garantee quality support to every client by VTEX support team, agencies that do not have enterprise accounts will have limited access to extensibility features and can only publish and install apps into their VTEX accounts, but not create apps extending features provided by Store Framework.",
  "io.faq.create-front-end-app.already-exists.summary": "How do I know if an app I want to create already exists?",
  "io.faq.create-front-end-app.already-exists.ans": "",
  "io.faq.create-front-end-app.getting-started.summary": "How can I get started developing front-end apps?",
  "io.faq.create-front-end-app.getting-started.ans": "",
  "io.faq.create-front-end-app.how-to-whitelist.summary": "What is the criteria I need to meet in order to get into the whitelist?",
  "io.faq.create-front-end-app.how-to-whitelist.ans": "",
  "io.faq.create-back-end-app.permission.summary": "Can I develop Node + GraphQL apps?",
  "io.faq.create-back-end-app.permission.ans": "The use of Node and GraphQL will only be allowed to enterprise accounts that want to create new features that support their store development."
}

```