[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-sdk/src/components/RegisterForm/PaymentsForm.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable vtex/prefer-early-return */
/* eslint-disable prettier/prettier */
import React, { Fragment, useEffect, useState } from 'react'
import Payment from 'payment'
import { pathOr } from 'ramda'
import { useDispatch, useSelector } from 'react-redux'

import { useInputValue } from '../../hooks/useInputValue'
import { formatter, regularExpressions } from '../../utils'
import { Alert, Button, Input } from '../shared'
import vtexStyles from './vtex-styles.module.css'
import kuikpayStyles from './kuikpay-styles.module.css'
import genericStyles from './generic-styles.module.css'
import useFormatMessage from '../../i18n/useFormatMessage'
import { useValidateStyles } from '../../hooks/useValidateStyles'
import InputCard from './InputCard'
import { useUnits } from '../../hooks/useUnits'
import { useActionsDispatch } from '../../contexts/ActionsProviderV2'
import { InputCVCSF } from '../UserInfo/InputCVC'
import {
  useUserData,
  useUserDataDispatch,
} from '../../contexts/UserDataProvider'
import {
  clearNumber,
  formatExpiryDate,
  selectIdImgCard,
} from '../../utils/payments'
import type {
  DataPCIChange,
  DataPCIGetCardInfo,
  DataPCISuccess,
  PaymentForm,
  SelectValue,
} from '../../interfaces'
import {
  selectTheme,
  selectIsMobile,
  selectSettings,
} from '../../contexts/global-context/reducers/uiSettingsSlice'
import { selectItemData } from '../../contexts/global-context/reducers/cartSlice'
import { usePCIScript } from '../../hooks/usePCIScript'
import CouponContainer from '../Coupon/CouponContainer'
import {
  selectMainPayment,
  selectItems,
  setCardBin,
  setCardInfo,
  setPaymetId,
} from '../../contexts/global-context/reducers/orderFormDataSlice'
import type { InstallmentOptionsSimulation } from '../../interfaces/simulation'
import { useSelectValue } from '../../hooks/useSelectValue'
import { SelectDues } from '../UserInfo/SelectDues'
import { useFonts } from '../../hooks/useFonts'
import { selectTotalValue } from '../../contexts/global-context/reducers/simulationSlice'

const beforeOfChangeDocument = (val: string) => {
  return clearNumber(val)
}

const beforeOfChangeExpiryDate = (val: string) => {
  return formatExpiryDate(val)
}

const PaymentsForm = ({
  disabled,
  error,
  handlePayment,
  payments,
  selectedCard,
  setError,
  handledPaymentDisabled,
  setFranchiseImg,
}: PaymentForm) => {
  const dispatchUserData = useUserDataDispatch()
  const [secureFields, setSecureFields] = useState(null)
  const [isValidCard, setIsValidCard] = useState(null)
  const [IsValidFranchise, setIsValidFranchise] = useState(true)
  const [isValidCVC, setIsValidCVC] = useState(null)
  const [imgCard, setImgCard] = useState(null)
  const [lastDigits, setLastDigits] = useState(null)
  const [installments, setInstallments] = useState<
    InstallmentOptionsSimulation[]
  >([])

  const { selectedItem } = useSelector(selectItemData)
  const selectedPayment = useSelector(selectMainPayment)
  const items = useSelector(selectItems)

  const { paymentData, totalOfferings } = useUserData()
  const value = useSelector(selectTotalValue)

  const dispatchGlobal = useDispatch()

  const dispatchActions = useActionsDispatch()
  const { merchantID } = usePCIScript()
  const theme = useSelector(selectTheme)
  const { isLiteVersion } = useSelector(selectSettings)
  const isMobile = useSelector(selectIsMobile)
  const name = useInputValue('')
  const identification = useInputValue('', beforeOfChangeDocument)
  const expiryDate = useInputValue('', beforeOfChangeExpiryDate)
  const dues: SelectValue = useSelectValue(null)
  const units = useUnits(items)
  const globalStyles = useValidateStyles(true)
  const { fonts } = useFonts()

  const isDisabled = !(
    name.isValid &&
    identification.isValid &&
    dues.isValid &&
    expiryDate.isValid &&
    isValidCard &&
    isValidCVC
  )

  let styles = kuikpayStyles

  if (theme === 'vtex') {
    styles = vtexStyles
  } else if (theme === 'generic') {
    styles = genericStyles
  }

  const onBlurExpiryDate = () => {
    const { value: expiryValue, setIsValid } = expiryDate

    if (
      expiryValue === '' ||
      expiryValue.length < 5 ||
      !Payment?.fns?.validateCardExpiry(expiryValue)
    ) {
      setIsValid(false)
    } else {
      setIsValid(true)
    }
  }

  const onChangeExpiryDate = (
    e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    const { setIsValid, onChange } = expiryDate

    if (e.target.value === '') {
      setIsValid(false)
    } else {
      setIsValid(true)
    }

    if (Payment?.fns?.validateCardExpiry(e.target.value)) {
      expiryDate?.setIsValid(true)
    }

    onChange(e)
  }

  const onPaymentDisabled = () => {
    if (handledPaymentDisabled) handledPaymentDisabled()
    if (name.isValid === null) name.setIsValid(false)
    if (identification.isValid === null) identification.setIsValid(false)
    if (dues.isValid === null) dues.setIsValid(false)
    if (expiryDate.isValid === null) expiryDate.setIsValid(false)
    if (isValidCVC === null) setIsValidCVC(false)
    if (isValidCard === null) setIsValidCard(false)
  }

  const successCallback = (transactionId: string, franchise: string) => {
    setError(null)
    const paymentSystem =
      pathOr('', ['paymentId'], selectedPayment) ||
      pathOr('', ['paymentSystem'], selectedCard)

    const dataCard = {
      additionalData: [
        {
          key: 'transactionId',
          value: transactionId,
        },
        {
          key: 'installments',
          value: dues?.value?.value,
        },
        {
          key: 'paymentSystem',
          value: paymentSystem,
        },
      ],
      expirationDate: expiryDate.value,
      holderName: name.value,
      holderDocument: identification.value,
      gateway: 'noop',
      bin: paymentData.bin,
      paymentMethod: 'tc',
      franchise,
      number: lastDigits,
    }

    handlePayment(dataCard)
  }

  const onChangeSecureField = (sf: any) => {
    sf.on('change', (data: DataPCIChange) => {
      const { event, fields } = data

      if (event.field === 'cardNumber') {
        if (fields.cardNumber?.paymentMethod) {
          const { paymentMethod } = fields.cardNumber
          const dataPaymentMethod = selectIdImgCard(paymentMethod)

          const { installmentsOptions: installmentsOpt, id } =
            payments.paymentMethods.find(
              (item) =>
                item.name
                  .toLowerCase()
                  .includes(dataPaymentMethod?.nameComplete?.toLowerCase()) ||
                payments.paymentMethods.length === 1
            ) || null

          if (id !== selectedPayment.paymentId) {
            dispatchGlobal(setPaymetId(id))
          }

          if (
            installmentsOpt.length > 0 &&
            payments.paymentMethods.find(
              (p) =>
                p.isCustom ||
                p.name.toLowerCase() === dataPaymentMethod?.nameComplete
            )
          ) {
            setFranchiseImg(dataPaymentMethod?.name)
            setImgCard(dataPaymentMethod?.id)
            setIsValidFranchise(true)
            setInstallments(installmentsOpt || [])
          } else {
            setInstallments([])
            dues.reset()
            if (fields.cardNumber.length >= 2) {
              setIsValidFranchise(false)
              setIsValidCard(false)

              return
            }
          }
        } else {
          setInstallments([])
          dues.reset()
          setImgCard(null)
          setFranchiseImg(null)
        }

        if (
          event.type === 'blur' &&
          (fields.cardNumber.length === 0 || !fields.cardNumber.valid)
        ) {
          setIsValidCard(false)
        }

        if (fields.cardNumber.valid) {
          sf.getCardInfo()
          setIsValidCard(true)
        }
      }

      if (event.field === 'cvv') {
        if (
          event.type === 'blur' &&
          (fields.cvv.length === 0 || !fields.cvv.valid)
        ) {
          setIsValidCVC(false)
          if (isLiteVersion && isMobile) sf.setStyle('cvv', 'color: #bc4c47')
        }

        if (fields.cvv.valid) {
          setIsValidCVC(true)
        }
      }
    })
  }

  const placeholder = {
    cardNumber: useFormatMessage('store/checkoutless.card.cardNumber'),
    cvv: useFormatMessage('store/checkoutless.card.securityCodeCVV'),
  }

  useEffect(() => {
    const sf = new SecureFields()

    dispatchActions({
      type: 'SET_IS_LOADING_CVV_FIELD',
      args: true,
    })

    sf?.initTokenize(
      merchantID,
      {
        cardNumber: {
          placeholderElementId: `card-number-placeholder${
            selectedItem?.itemId || 'not-id'
          }`,
          inputType: 'tel',
        },
        cvv: {
          placeholderElementId: `cvv-placeholder`,
          inputType: 'tel',
        },
      },
      {
        '*': `font-family: ${fonts}`,
      }
    )

    const sfStyles = {
      colorPlaceholder: 'color: #919191',
      color: 'color: #011d1a',
      fontSize: 'font-size: 16px',
      fontFamily: `font-family: ${fonts}`,
      paddingLeft: '5px',
    }

    sf.on('ready', () => {
      dispatchActions({
        type: 'SET_IS_LOADING_CVV_FIELD',
        args: false,
      })

      sf.setPlaceholder('cardNumber', placeholder.cardNumber)
      sf.setPlaceholder('cvv', placeholder.cvv)
      sf.setStyle('cvv', sfStyles.fontSize)
      sf.setStyle('cardNumber', sfStyles.fontSize)
      sf.setStyle('cvv', sfStyles.color)
      sf.setStyle('cardNumber', sfStyles.color)
      sf.setStyle('cvv', sfStyles.fontFamily)
      sf.setStyle('cardNumber', sfStyles.fontFamily)
      sf.setStyle('cvv', sfStyles.paddingLeft)
      sf.setStyle('cardNumber', sfStyles.paddingLeft)
      sf.setStyle('cvv:focus', 'outline: 0')
      sf.setStyle('cardNumber:focus', 'outline: 0')
      sf.setStyle('cvv::placeholder', sfStyles.colorPlaceholder)
      sf.setStyle('cardNumber::placeholder', sfStyles.colorPlaceholder)
    })

    const cardContainer = document.getElementById(
      `card-number-container${selectedItem?.itemId || 'not-id'}`
    )

    const cvvContainer = document.getElementById(`cvv-container-inside`)

    const setFocus = (input: string) => sf.focus(input)

    cardContainer.addEventListener('click', () => setFocus('cardNumber'))
    cvvContainer.addEventListener('click', () => setFocus('cvv'))

    sf.on('error', (data: { error: string; action: string }) => {
      const { action } = data

      if (action === 'submit') {
        setError('store/checkoutless.register.card.numberError')
      }
    })

    onChangeSecureField(sf)

    setSecureFields(sf)
    // Solo se establece cuando una vez haya hecho submit
    // sf.on('validate', (data: any) => {
    //   console.log('data', data)
    // })

    return () => {
      sf?.destroy()
      cardContainer?.removeEventListener('click', () => setFocus('cardNumber'))
      cvvContainer?.removeEventListener('click', () => setFocus('cvv'))
    }
  }, [])

  useEffect(() => {
    if (secureFields) {
      secureFields.on('success', (data: DataPCISuccess) => {
        if (data.transactionId) {
          let franchise = data?.cardInfo?.brand?.toLowerCase()

          if (franchise?.includes('visa')) {
            franchise = 'visa'
          } else if (
            franchise?.includes('mci') ||
            franchise?.includes('mastercard')
          ) {
            franchise = 'master'
          } else if (franchise?.includes('diners')) {
            franchise = 'diner'
          } else if (franchise?.includes('american express')) {
            franchise = 'amex'
          }

          dispatchGlobal(setCardInfo({ franchise }))

          successCallback(data.transactionId, franchise)
        }
      })
    }
  }, [name, identification, expiryDate, dues, paymentData?.bin, lastDigits])

  useEffect(() => {
    if (secureFields) {
      onChangeSecureField(secureFields)

      secureFields.on('cardInfo', (data: DataPCIGetCardInfo) => {
        const dataDispatch: any = {
          type: 'SET_BIN',
          args: null,
        }

        if (data?.maskedCard) {
          dataDispatch.args = data?.maskedCard?.substr(0, 6)
          let limitDigits = 4

          if (data?.paymentMethod === 'AMX') {
            limitDigits = 3
          } else if (data?.paymentMethod === 'DIN') {
            limitDigits = 2
          }

          const number = data?.maskedCard?.substring(
            data?.maskedCard?.length,
            data?.maskedCard?.length - limitDigits
          )

          setLastDigits(number)
        }

        if (selectedPayment.bin !== dataDispatch.args) {
          dispatchGlobal(setCardBin(dataDispatch.args))
        }

        dispatchUserData(dataDispatch)
      })
    }
  }, [selectedPayment, secureFields])

  useEffect(() => {
    if (name.isValid && identification.isValid && expiryDate.isValid) {
      dispatchGlobal(
        setCardInfo({
          holderDocument: identification.value,
          holderName: name.value,
          expirationDate: expiryDate.value,
        })
      )
    }
  }, [name.value, identification.value, expiryDate.value])

  return (
    <Fragment>
      {error && (
        <Alert
          type="error"
          text="store/checkoutless.register.card.numberError"
        />
      )}
      <div className={globalStyles.gridFormTwoCols} data-more-left="true">
        <div>
          <InputCard
            theme={theme}
            isValid={isValidCard}
            imgCard={imgCard}
            itemId={selectedItem?.itemId || 'not-id'}
          />
          {!isValidCard && isValidCard !== null && (
            <p className={styles.labelError}>
              {IsValidFranchise
                ? useFormatMessage(
                    'store/checkoutless.register.card.numberError'
                  )
                : useFormatMessage(
                    'store/checkoutless.register.card.franchiseError'
                  )}
            </p>
          )}
        </div>
        <div>
          <InputCVCSF
            isValid={isValidCVC}
            className={`${styles.secureField__input} ${
              isValidCVC === false ? styles.secureFieldInvalidLite : null
            } ${isValidCVC === true ? styles.secureFieldValidLite : null} ${
              styles.secureFieldLite
            }`}
            itemId={selectedItem?.itemId || 'not-id'}
            showError={false}
          />
        </div>

        <div className={styles.marginBottom}>
          <Input
            placeholder="store/checkoutless.register.card.name"
            errorMessage="store/checkoutless.register.nameError"
            regularExpression={regularExpressions.name}
            name="name"
            maxLength={30}
            {...name}
          />
        </div>
        <div className={styles.marginBottom}>
          <Input
            type="tel"
            placeholder="store/checkoutless.register.card.expiryDate" // Cambiar a Fecha de vencimiento
            errorMessage="store/checkoutless.register.card.expiryDateError"
            blurFunction={onBlurExpiryDate}
            name="expiryDate"
            className={styles.expiryDate}
            {...expiryDate}
            onChange={onChangeExpiryDate}
          />
        </div>

        <div className={styles.marginBottom}>
          <Input
            placeholder="store/checkoutless.register.card.document"
            errorMessage="store/checkoutless.register.documentError"
            regularExpression={regularExpressions.document}
            name="identification"
            {...identification}
          />
        </div>
        <div className={`${styles.marginBottom}`}>
          <SelectDues dues={dues} installments={installments} />
        </div>
        <div data-col="two-col">
          <CouponContainer />
        </div>
      </div>

      <div
        className={`${globalStyles.buyButtonContainer} ${globalStyles.buyButtonContainerFixed}`}
      >
        <Button
          value={'store/checkoutless.register.pay'}
          onClick={() => secureFields?.submit()}
          onClickDisabled={onPaymentDisabled}
          customValue={`${formatter.format(value + totalOfferings)}`}
          disabled={isDisabled || disabled}
          units={units}
          id="kuikpay-purchase-button"
          isFixed={true}
          isPaymentButton={true}
        />
      </div>
    </Fragment>
  )
}

export default PaymentsForm

```


[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-sdk/src/components/RegisterForm/PaymentezForm.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect, Fragment } from 'react'
import { useSelector } from 'react-redux'
import { pathOr } from 'ramda'

import { useInputValue } from '../../hooks/useInputValue'
import { useUserData } from '../../contexts/UserDataProvider'
import type {
  DataPCIPGetCardInfo,
  DataPCIPSuccess,
  SelectValue,
} from '../../interfaces'
import { PaymentForm } from '../../interfaces'
import { formatter, regularExpressions } from '../../utils'
import { useValidateStyles } from '../../hooks/useValidateStyles'
import { Button, Input } from '../shared'
import kuikpayStyles from './kuikpay-styles.module.css'
import vtexStyles from './vtex-styles.module.css'
import { useActionsDispatch } from '../../contexts/ActionsProviderV2'
import { selectTheme } from '../../contexts/global-context/reducers/uiSettingsSlice'
import genericStyles from './generic-styles.module.css'
import {
  clearNumber,
  copyAttributes,
  formatExpiryDate,
  selectIdImgCard,
} from '../../utils/payments'
import { useUnits } from '../../hooks/useUnits'
import { useSelectValue } from '../../hooks/useSelectValue'
import { SelectDues } from '../UserInfo/SelectDues'
import CouponContainer from '../Coupon/CouponContainer'
import { selectProfile } from '../../contexts/global-context/reducers/orderFormDataSlice'

const beforeOfChangeDocument = (val: string) => {
  return clearNumber(val)
}

const beforeOfChangeExpiryDate = (val: string) => {
  return formatExpiryDate(val)
}

const PaymentezForm = ({
  handlePayment,
  setError,
  disabled,
  setFranchiseImg,
  selectedCard,
  handledPaymentDisabled,
  payments,
}: PaymentForm) => {
  const { value, items, paymentData, totalOfferings } = useUserData()

  const { email } = useSelector(selectProfile)

  const [IsValidFranchise, setIsValidFranchise] = useState(true)

  const [installments, setInstallments] = useState([])

  const dispatchActions = useActionsDispatch()

  const name = useInputValue('')
  const identification = useInputValue('', beforeOfChangeDocument)
  const cvv = useInputValue('')
  const expiryDate = useInputValue('', beforeOfChangeExpiryDate)
  const cardNumber = useInputValue('')
  const globalStyles = useValidateStyles(true)
  const theme = useSelector(selectTheme)
  const dues: SelectValue = useSelectValue(null)

  const units = useUnits(items)

  const styles = {
    kuikpay: kuikpayStyles,
    vtex: vtexStyles,
    generic: genericStyles,
  }[theme]

  const isDisabled = !(
    name.isValid &&
    identification.isValid &&
    dues.isValid &&
    expiryDate.isValid &&
    cardNumber.isValid &&
    cvv.isValid
  )

  const onBlurExpiryDate = () => {
    expiryDate.setIsValid(
      PaymentForm.isExpiryValid(
        PaymentForm.ctx.getExpiryMonth(),
        PaymentForm.ctx.getExpiryYear()
      )
    )
  }

  const onChangeExpiryDate = (
    e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    PaymentForm.ctx.expiryMonthYearInput.val(e.target.value.substring(0, 5))
    PaymentForm.ctx.expiryYearInput.val(e.target.value.substring(3, 5))
    PaymentForm.ctx.expiryMonthInput.val(PaymentForm.ctx.expiryMonth())

    if (PaymentForm.ctx.expiryMonthYearInput.val().length === 5) {
      expiryDate.setIsValid(
        PaymentForm.isExpiryValid(
          PaymentForm.ctx.getExpiryMonth(),
          PaymentForm.ctx.getExpiryYear()
        )
      )
    }

    expiryDate.onChange(e)
  }

  const onChangeCvv = (
    e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    PaymentForm.ctx.cvcInput.val(PaymentForm.numbersOnlyString(e.target.value))
    if (PaymentForm.ctx.cvcInput.val().length >= 3) {
      PaymentForm.ctx.cvcLenght = PaymentForm.ctx.cvcInput.val().length
      cvv.setIsValid(PaymentForm.ctx.isCvcValid())
    }

    cvv.onChange(e)
  }

  const onBlurCvv = () => {
    cvv.setIsValid(PaymentForm.ctx.isCvcValid())
  }

  const onKeyDownCardNumber = (
    e: React.KeyboardEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    PaymentForm.handleMaskedNumberInputKey(
      e,
      PaymentForm.ctx.creditCardNumberMask
    )
    PaymentForm.ctx.cardNumberInput.val($(e.target).val())
    cardNumber.setValue(PaymentForm.ctx.cardNumberInput.val())
  }

  const onBlurCardNumber = () => {
    cardNumber.setIsValid(PaymentForm.ctx.isCardNumberValid())
  }

  const refreshCardType = () => {
    const { setIsValid } = cardNumber

    const bin = PaymentForm.ctx.cardNumberInput
      .val()
      .replaceAll(' ', '')
      .substring(0, 6)

    if (bin.length >= 6 && !PaymentForm.ctx.cardType) {
      Payment.getBinInformation(
        bin,
        PaymentForm.ctx,
        (r: { brand_name: string; card_type: string; nip: string }) => {
          const paymentMethod = r.brand_name

          PaymentForm.ctx.cardType = r.card_type
          PaymentForm.ctx.nip = r.nip
          if (paymentMethod) {
            const dataPaymentMethod = selectIdImgCard(paymentMethod)

            const { installmentsOptions: installment } =
              payments.paymentMethods.find(
                (item) =>
                  item.name
                    .toLowerCase()
                    .includes(dataPaymentMethod?.nameComplete?.toLowerCase()) ||
                  payments.paymentMethods.length === 1
              ) || null

            if (
              installment &&
              installment.length > 0 &&
              payments.paymentMethods?.find(
                (p: { name: string }) =>
                  p.name.toLowerCase() === dataPaymentMethod?.nameComplete
              )
            ) {
              PaymentForm.ctx.numberBin = bin
              setFranchiseImg(dataPaymentMethod?.name)
              setIsValidFranchise(true)
              setInstallments(installment || [])
            } else {
              setInstallments([])
              dues.reset()
              setIsValidFranchise(false)
              setIsValid(false)
            }
          }

          return paymentMethod
        },
        () => {
          setIsValidFranchise(false)
        }
      )
    } else if (bin.length < 6) {
      PaymentForm.ctx.cardType = ''
      setInstallments([])
      dues.reset()
      setFranchiseImg(null)
    }
  }

  const onPasteCardNumber = (
    e: React.ClipboardEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    const data = e.clipboardData.getData('Text')

    PaymentForm.ctx.cardType = ''
    PaymentForm.ctx.cardNumberInput.val(PaymentForm.numbersOnlyString(data))
    refreshCardType()
    PaymentForm.ctx.refreshCreditCardNumberFormat()
    cardNumber.setValue(PaymentForm.ctx.cardNumberInput.val())
    e.preventDefault()
  }

  useEffect(() => {
    dispatchActions({
      type: 'SET_IS_LOADING_CVV_FIELD',
      args: true,
    })

    const base = `.payment`

    PaymentForm.ctx = $(base).PaymentForm('init').data('paymentform')

    const cvcNode = $(`${base} .custom-cvc`)
    const cardNode = $(`${base} .custom-card-number`)
    const expiryMonthNode = $(`${base} .custom-expiry-month`)
    const expiryYearNode = $(`${base} .custom-expiry-year`)
    const expiryMonthYearNode = $(`${base} .custom-expiry`)

    copyAttributes(`${base} .cvc`, cvcNode, [
      'class',
      'placeholder',
      'maxlength',
    ])
    copyAttributes(`${base} .card-number`, cardNode, ['class', 'placeholder'])
    copyAttributes(`${base} .expiry-year`, expiryYearNode, ['class'])
    copyAttributes(`${base} .expiry-month`, expiryMonthNode, ['class'])
    copyAttributes(`${base} .expiry`, expiryMonthYearNode, [
      'class',
      'placeholder',
    ])
    PaymentForm.ctx.cvcInput = cvcNode
    PaymentForm.ctx.cardNumberInput = cardNode
    PaymentForm.ctx.expiryYearInput = expiryYearNode
    PaymentForm.ctx.expiryMonthInput = expiryMonthNode
    PaymentForm.ctx.expiryMonthYearInput = expiryMonthYearNode

    $(`${base} .card-number-wrapper`).remove()
    $(`${base} .cvc-wrapper`).remove()
    $(`${base} .expiry-wrapper`).remove()

    dispatchActions({
      type: 'SET_IS_LOADING_CVV_FIELD',
      args: false,
    })
  }, [])

  const successCallback = (data: DataPCIPSuccess) => {
    setError(null)
    const { card } = data
    const type = PaymentForm.ctx.cardType.toLowerCase()
    const limitDigits = { [type]: 4, ax: 3, di: 2 }[type]
    const franchise = {
      [type]: type,
      vi: 'visa',
      mci: 'master',
      mc: 'master',
      di: 'diner',
      ax: 'amex',
    }[type]

    const number = card.number.substring(
      card.number.length,
      card.number.length - limitDigits
    )

    const paymentSystem =
      pathOr('', ['temporalPaymentSystem'], paymentData) ||
      pathOr('', ['paymentSystem'], selectedCard)

    const dataCard = {
      additionalData: [
        {
          key: 'installments',
          value: dues?.value?.value,
        },
        {
          key: 'paymentSystem',
          value: paymentSystem,
        },
      ],
      token: card.token,
      expirationDate: expiryDate.value,
      holderName: name.value,
      holderDocument: identification.value,
      gateway: 'noop',
      bin: card.bin,
      cvv: cvv.value,
      paymentMethod: 'tc',
      franchise,
      number,
    }

    handlePayment(dataCard)
  }

  const onPaymentDisabled = () => {
    if (handledPaymentDisabled) handledPaymentDisabled()
    if (name.isValid === null) name.setIsValid(false)
    if (identification.isValid === null) identification.setIsValid(false)
    if (dues.isValid === null) dues.setIsValid(false)
    if (expiryDate.isValid === null) expiryDate.setIsValid(false)
    if (cvv.isValid === null) cvv.setIsValid(false)
    if (cardNumber.isValid === null) cardNumber.setIsValid(false)
  }

  const handleClick = () => {
    const { card } = PaymentForm.ctx.getCard() as DataPCIPGetCardInfo

    try {
      card.holder_name = name.value
      Payment.addCard(
        email,
        email,
        { card },
        successCallback,
        (e: { error: { type: string } }) => {
          if (e.error.type.includes('Card already added')) {
            successCallback({
              card: {
                ...card,
                bin: PaymentForm.ctx.numberBin,
                expiry_month: card.expiry_month.toString(),
                expiry_year: card.expiry_year.toString(),
                token: e.error.type.split('Card already added: ')[1],
                message: e.error.type,
              },
            })
          } else {
            setError('store/checkoutless.register.creditCardError')
          }
        }
      )
    } catch {
      setError('store/checkoutless.register.creditCardError')
    }
  }

  return (
    <Fragment>
      <div
        className={`${globalStyles.gridFormTwoCols} ${'payment'}`}
        id="my-card"
        data-more-left="true"
      >
        <div className={styles.marginBottom}>
          <Input
            type="tel"
            placeholder="store/checkoutless.card.cardNumber"
            {...cardNumber}
            errorMessage={
              !IsValidFranchise && IsValidFranchise !== null
                ? 'store/checkoutless.register.card.franchiseError'
                : 'store/checkoutless.register.card.numberError'
            }
            className="custom-card-number"
            name="card-number"
            blurFunction={onBlurCardNumber}
            onKeyDown={onKeyDownCardNumber}
            onPaste={onPasteCardNumber}
            onCustomKeyUpEvent={refreshCardType}
          />
        </div>

        <div className={styles.marginBottom}>
          <Input
            type="tel"
            placeholder="store/checkoutless.card.cvv"
            errorMessage="store/checkoutless.card.invalidSecurityCodeError"
            {...cvv}
            className={`custom-cvc`}
            name="cvc"
            maxLength={4}
            onChange={onChangeCvv}
            blurFunction={onBlurCvv}
            showError={false}
          />
        </div>

        <div className={styles.marginBottom}>
          <Input
            placeholder="store/checkoutless.register.card.name"
            errorMessage="store/checkoutless.register.nameError"
            regularExpression={regularExpressions.name}
            name="name"
            maxLength={30}
            {...name}
          />
        </div>

        <div className={styles.marginBottom}>
          <Input
            type="tel"
            placeholder="store/checkoutless.register.card.expiryDate"
            errorMessage="store/checkoutless.register.card.expiryDateError"
            blurFunction={onBlurExpiryDate}
            name="expiry"
            className={`custom-expiry ${styles.expiryDate}`}
            {...expiryDate}
            onChange={onChangeExpiryDate}
          />
          <input className="custom-expiry-month" type="hidden"></input>
          <input className="custom-expiry-year" type="hidden"></input>
        </div>

        <div className={styles.marginBottom}>
          <Input
            placeholder="store/checkoutless.register.card.document"
            errorMessage="store/checkoutless.register.documentError"
            regularExpression={regularExpressions.document}
            name="identification"
            {...identification}
          />
        </div>

        <div className={`${styles.marginBottom}`}>
          <SelectDues dues={dues} installments={installments} />
        </div>
        <div data-col="two-col">
          <CouponContainer />
        </div>
      </div>
      <div
        className={`${globalStyles.buyButtonContainer} ${globalStyles.buyButtonContainerFixed}`}
      >
        <Button
          value={'store/checkoutless.register.pay'}
          onClick={handleClick}
          onClickDisabled={onPaymentDisabled}
          customValue={`${formatter.format(value + totalOfferings)}`}
          disabled={isDisabled || disabled}
          units={units}
          id="kuikpay-purchase-button"
          isFixed={false}
          isPaymentButton={true}
        />
      </div>
    </Fragment>
  )
}

export default PaymentezForm

```


[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-sdk/src/components/RegisterForm/MercadoPagoForm.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useEffect, useState } from 'react'
import { useIntl } from 'react-intl'
import { useSelector } from 'react-redux'

import constants from '../../utils/constants'
import { useUserData } from '../../contexts/UserDataProvider'
import type { PaymentForm } from '../../interfaces'
import { formatter } from '../../utils'
import { Button } from '../shared'
import vtexStyles from './vtex-styles.module.css'
import kuikpayStyles from './kuikpay-styles.module.css'
import genericStyles from './generic-styles.module.css'
import { useValidateStyles } from '../../hooks/useValidateStyles'
import { selectTheme } from '../../contexts/global-context/reducers/uiSettingsSlice'
// import globalVtexStyles from '../../vtex-styles.module.css'
// import globalKuikpayStyles from '../../kuikpay-styles.module.css'

interface Error {
  code: string
  message: string
}

const MercadoPagoForm = ({ handlePayment, loading, disabled }: PaymentForm) => {
  const intl = useIntl()
  const { value, clientProfileData, totalOfferings } = useUserData()
  const theme = useSelector(selectTheme)
  const [errors, setErrors] = useState([])
  const [messages, setMessages] = useState<any>({})
  const mp = new MercadoPago(constants.mercadoPagoPublicKey)
  const global = useValidateStyles()

  let styles = kuikpayStyles

  if (theme === 'vtex') {
    styles = vtexStyles
  } else if (theme === 'generic') {
    styles = genericStyles
  }

  const loadCardForm = () => {
    const cardForm = mp.cardForm({
      amount: value.toString(),
      autoMount: true,
      form: {
        id: 'form-checkout',
        cardholderName: {
          id: 'form-checkout__cardholderName',
          placeholder: intl.formatMessage({
            id: 'store/checkoutless.register.creditCardName',
          }),
        },
        cardNumber: {
          id: 'form-checkout__cardNumber',
          placeholder: intl.formatMessage({
            id: 'store/checkoutless.register.creditCardNumber',
          }),
        },
        cardExpirationMonth: {
          id: 'form-checkout__cardExpirationMonth',
          placeholder: 'MM',
        },
        cardExpirationYear: {
          id: 'form-checkout__cardExpirationYear',
          placeholder: 'YY',
        },
        securityCode: {
          id: 'form-checkout__securityCode',
          placeholder: 'CVC',
        },
        installments: {
          id: 'form-checkout__installments',
          placeholder: 'Cuotas',
        },
        identificationType: {
          id: 'form-checkout__identificationType',
          placeholder: 'Tipo de documento',
        },
        identificationNumber: {
          id: 'form-checkout__identificationNumber',
          placeholder: 'Número de documento',
        },
        issuer: {
          id: 'form-checkout__issuer',
          placeholder: 'Banco emisor',
        },
      },
      callbacks: {
        onFormMounted: (error: string) => {
          if (error) return console.warn('Form Mounted handling error: ', error)
        },
        onCardTokenReceived: (error: any) => {
          if (error) return setErrors(error)
        },
        onSubmit: (event: any) => {
          event.preventDefault()

          setErrors([])

          const {
            paymentMethodId,
            // issuerId,
            // cardholderEmail: email,
            // amount,
            token,
            // installments,
            // identificationNumber,
            // identificationType,
          } = cardForm.getCardFormData()

          handlePayment({
            token,
            number: '1',
            gateway: 'Mercadopago',
            franchise: paymentMethodId,
            paymentMethod: 'tc',
          })
        },
      },
    })
  }

  useEffect(() => {
    setTimeout(() => {
      loadCardForm()
    }, 1000)
  }, [])

  useEffect(() => {
    if (!errors.length) {
      setMessages({})

      return
    }

    const formErrors = {}

    errors.forEach((error: Error) => {
      formErrors[error.code] = error.message
    })

    setMessages(formErrors)
  }, [errors])

  return (
    <form id="form-checkout" className="payment-form">
      <div>
        <input
          type="text"
          name="cardNumber"
          id="form-checkout__cardNumber"
          maxLength={16}
        />
        {messages[205] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.cardNumberError',
            })}
          </p>
        )}

        {messages.E301 && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.invalidCardNumberError',
            })}
          </p>
        )}
      </div>

      <div className={styles.formGroup}>
        <div className={styles.inputGroup}>
          <input
            type="text"
            name="cardExpirationMonth"
            id="form-checkout__cardExpirationMonth"
            maxLength={2}
          />
          {messages[208] && (
            <p className={global.labelError}>
              {intl.formatMessage({
                id: 'store/checkoutless.card.cardExpirationMonthError',
              })}
            </p>
          )}
          {messages[325] && (
            <p className={global.labelError}>
              {intl.formatMessage({
                id: 'store/checkoutless.card.invalidCardExpirationMonthError',
              })}
            </p>
          )}
        </div>
        <div className={styles.inputGroup}>
          <input
            type="text"
            name="cardExpirationYear"
            id="form-checkout__cardExpirationYear"
            maxLength={2}
          />
          {messages[209] && (
            <p className={global.labelError}>
              {intl.formatMessage({
                id: 'store/checkoutless.card.cardExpirationYearError',
              })}
            </p>
          )}
          {messages[326] && (
            <p className={global.labelError}>
              {intl.formatMessage({
                id: 'store/checkoutless.card.invalidCardExpirationYearError',
              })}
            </p>
          )}
        </div>
      </div>

      <div>
        <input
          type="text"
          name="cardholderName"
          id="form-checkout__cardholderName"
        />
        {messages[221] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.cardholderNameError',
            })}
          </p>
        )}
        {messages[316] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.invalidcardholderNameError',
            })}
          </p>
        )}
      </div>

      <div>
        <input
          type="text"
          name="securityCode"
          id="form-checkout__securityCode"
          maxLength={4}
        />
        {messages[224] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.securityCodeError',
            })}
          </p>
        )}
        {messages.E302 && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.invalidSecurityCodeError',
            })}
          </p>
        )}
      </div>

      <div style={{ display: 'none' }}>
        <select name="issuer" id="form-checkout__issuer"></select>
        {messages[220] && (
          <p className={global.labelError}>
            {intl.formatMessage({ id: 'store/checkoutless.card.issuerError' })}
          </p>
        )}
      </div>

      <div style={{ display: 'none' }}>
        <select
          name="identificationType"
          id="form-checkout__identificationType"
        ></select>
        {messages[212] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.identificationTypeError',
            })}
          </p>
        )}
        {messages[322] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.invalidIdentificationTypeError',
            })}
          </p>
        )}
      </div>

      <div style={{ display: 'none' }}>
        <input
          type="text"
          name="identificationNumber"
          id="form-checkout__identificationNumber"
          defaultValue={clientProfileData.document}
        />
        {messages[214] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.identificationNumberError',
            })}
          </p>
        )}
        {messages[324] && (
          <p className={global.labelError}>
            {intl.formatMessage({
              id: 'store/checkoutless.card.invalidIdentificationNumberError',
            })}
          </p>
        )}
      </div>
      <select name="installments" id="form-checkout__installments"></select>
      <div>
        <Button
          value={
            loading
              ? 'store/checkoutless.register.processingPayment'
              : 'store/checkoutless.register.pay'
          }
          disabled={disabled}
          customValue={`${formatter.format(value + totalOfferings)}`}
          type="submit"
          id="form-checkout__submit"
          isPaymentButton={true}
        />
      </div>
    </form>
  )
}

export default MercadoPagoForm

```


[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-sdk/src/components/RegisterForm/vtex-styles.module.css from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```css
.container {
  width: 100%;
}

.containerDocument {
  display: flex;
  justify-content: space-between;
}

.containerDocumentType {
  width: 39%;
}

.containerDocumentNumber {
  width: 59%;
}

.containerTrigger {
  width: 100%;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.containerInfo {
  display: flex;
  align-items: center;
}

.containerText.containerText {
  margin-left: 10px;
  margin-right: 22px;
}

.containerData {
  padding: 0px 32px;
  margin-bottom: 8px;
}

.radioHide {
  position: absolute;
  opacity: 0;
  cursor: pointer;
  height: 0;
  width: 0;
}

.checkmark {
  position: absolute;
  top: 0;
  left: 0;
  height: 17px;
  width: 17px;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 50%;
  box-sizing: border-box;
}

.paymentLabelContainer {
  display: block;
  position: relative;
  padding-left: 25px;
  margin: 8px;
  cursor: pointer;
  font-size: 22px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.paymentLabelContainer label {
  cursor: pointer;
}

/* When the radio button is checked, add a blue background */
.checkmarkChecked {
  background-color: #fff;
  border: 1px solid #f71963;
}

/* Create the indicator (the dot/circle - hidden when not checked) */
.checkmarkNoChecked::after {
  content: '';
  position: absolute;
  display: none;
}

/* Show the indicator (dot/circle) when checked */
.checkmarkChecked::after {
  display: block;
}

/* Style the indicator (dot/circle) */
.checkmarkContainer {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background-color: #f71963;
}

.paymentLabel {
  font-size: 16px;
}

.paymentMethodContainer {
  padding: 8px 0;
}

.paymentMethodPromissory {
  margin: 0px 15px;
  width: 90%;
  padding: 35px;
  box-shadow: 0px 3px 6px #00000029;
  margin-bottom: 15px;
}

.formGroup {
  display: flex;
  justify-content: space-between;
}

.inputGroup {
  width: 48%;
}

.labelError {
  color: #cb4242;
}

.containerLocation {
  display: flex;
  align-items: center;
  cursor: pointer;
}

.cityContainer {
  margin-top: 15px;
}

.cityContainer div {
  z-index: 101;
}

.marginTop {
  margin-top: 12px;
}

.habeasDataLink.habeasDataLink {
  text-decoration: underline;
}

.radioButtonContainer {
  display: flex;
  justify-content: space-around;
}

.cardsImgContainer {
  margin-left: 35px;
  margin-bottom: 10px;
}

.cardsImgContainer img {
  margin-right: 10px;
  height: 25px;
}

.logisticsContainer {
  border-top: 1px solid #e0e2e7;
  padding-top: 12px;
}

.textUnderline {
  text-decoration: underline;
}

.locationContainer {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.locationContainer p {
  font-weight: 600;
  font-size: 26px;
  text-align: center;
  margin-bottom: 8px;
}

.containerDuesExpiry {
  display: flex;
}

.containerDuesExpiry .dues {
  margin-right: 9px;
  background-color: white;
}

.containerDuesExpiry .expiryDate {
  width: 99% !important;
}

.secureField__input {
  display: inline-block;
  width: 100%;
  line-height: 1.3;
  cursor: text;
  height: 46px;
  border-radius: 8px;
  margin-bottom: 8px;
  padding: 0 17.3px;
  border: 1px solid #c4c5ca;
  color: white;
  background-color: #fff;
}

.secureFieldInvalid {
  border: 1px solid #bc4c47;
}

.secureFieldValid {
  border: 1px solid #4b816b;
}

.secureField__inputContainer {
  position: relative;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}

.secureField__actions {
  position: absolute;
  top: 0;
  left: 0;
  display: -ms-flexbox;
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  width: 100%;
  height: 100%;
  padding-right: 16px;
  padding-left: 16px;
  pointer-events: none;
  -ms-flex-pack: end;
  -webkit-box-pack: end;
  -webkit-justify-content: flex-end;
  justify-content: flex-end;
  align-items: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -webkit-box-align: center;
}

.secureField__action {
  position: relative;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  width: 40px;
  height: 100%;
  padding: 12px 0 10px;
  pointer-events: auto;
  cursor: pointer;
  transition: color 200ms ease;
  align-items: center;
  -webkit-justify-content: center;
  -ms-flex-flow: row nowrap;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-transition: color 200ms ease;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -webkit-flex-flow: row nowrap;
  justify-content: center;
  flex-flow: row nowrap;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -webkit-box-align: center;
}

.secureField__action.secureField__actionCardIcon {
  width: 40px;
  height: 100%;
  padding: 0;
  pointer-events: none;
}

.secureField__actionCardWrap {
  position: relative;
  width: 100%;
  height: 100%;
}

.secureField__cardIcon {
  position: absolute;
  top: 43%;
  right: 0;
  display: block;
  max-width: 100%;
  transform: translate3d(0, -50%, 0);
  -webkit-transform: translate3d(0, -50%, 0);
}

.labelError.labelError {
  color: #cb4242;
  margin-top: -7px;
  margin-bottom: 10px;
  font-size: 14px;
}

.paymentCardContainer {
  margin-bottom: 10px;
}

.paymentPromissoryContainer {
  margin-bottom: 10px;
}

.paymentLabelContainer .paymentCustomCreditLabel {
  font-size: 14px !important;
  color: #284859;
  line-height: 24px;
  margin: 12px 0px;
  border-radius: 8px;
  box-shadow: 0px 3px 6px #0000000f;
  padding: 5px 28px;
  margin-bottom: 15px;
  cursor: initial;
}

.paymentLabelContainer .paymentCustomCreditLabel b {
  color: #1b998b;
}

.paymentCustomCreditLabelInfo {
}

.paymentCustomerCreditContainer {
}

.cursorPointer {
  cursor: pointer;
}

.display {
  display: none;
}

.marginLeft.marginLeft {
  margin-left: 5px;
}

.marginBottom {
  margin-bottom: 12px;
}

.loadingContainer {
  position: relative;
  height: 150px;
  display: flex;
  justify-content: center;
}

@media (min-width: 992px) {
  .buyButtonContainer {
    position: fixed;
    padding: 14px;
    margin-top: 14px;
    box-shadow: inset 0px 3px 6px #0000000f;
    width: 30%;
    right: 0;
    bottom: 0;
    background: #ffffff 0% 0% no-repeat padding-box;
    z-index: 100;
  }
}

@media (min-width: 992px) {
  .container {
    margin-bottom: 35%;
  }
}

.summary {
  margin-bottom: 22%;
}

@media screen and (max-width: 792px) {
  .paymentMethodLiteContainer {
    padding-bottom: 70px;
  }
}

```


[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-sdk/src/components/RegisterForm/RegisterFormContainer.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import RegisterForm from './RegisterForm'
import useRegisterForm from './useRegisterForm'

const RegisterFormContainer = () => {
  const registerFormProps = useRegisterForm()

  return <RegisterForm {...registerFormProps} />
}

export default RegisterFormContainer

```


[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-sdk/src/components/RegisterForm/PaymentForm.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Fragment, useEffect, useMemo, useState } from 'react'
import { useMutation } from '@apollo/client'
import { useIntl } from 'react-intl'
import { useDispatch, useSelector } from 'react-redux'

import { BuyCompletedEvent, SelectedMethodPaymentEvent } from '../../events'
import { CREATE_ORDER } from '../../graphql/mutations'
import { CreditCard, MyOrder } from '../Icons'
import { Events } from '../../interfaces'
import { PaymentProvider } from '../../contexts/PaymentContext'
import { PaymentsList } from '../Payments/Models/payments'
import { useActionsDispatch } from '../../contexts/ActionsProviderV2'
import { useCustomerCredit } from '../../hooks/useCustomerCredit'
import { useEcommerce } from '../../hooks/useEcommerce'
import { useUnits } from '../../hooks/useUnits'
import {
  selectLoadingOrder,
  setErrorOrder,
  setLoadingOrder,
  setNextSection,
  setStep,
} from '../../contexts/global-context/reducers/checkoutFormSlice'
import {
  selectSettings,
  selectTheme,
} from '../../contexts/global-context/reducers/uiSettingsSlice'
import {
  useUserData,
  useUserDataDispatch,
} from '../../contexts/UserDataProvider'
import constants from '../../utils/constants'
import InfoItem from '../shared/InfoItem'
import LoadingProcessOrder from '../UserInfo/LoadingProcessOrder/LoadingProcessOrderContainer'
import Payments from '../Payments'
import Title from '../shared/Title'
import type { BundleItem, BundleIteminput, Item } from '../../interfaces'
import genericStyles from './generic-styles.module.css'
import globalStyles from '../../myCheckout-styles.module.css'
import kuikpayStyles from './kuikpay-styles.module.css'
import vtexStyles from './vtex-styles.module.css'
import {
  selectAddressStore,
  selectDeliveryAddress,
  selectItems,
  selectLogisticsInfo,
  selectOrderForm,
  selectPickUpPointAddress,
  selectProfile,
} from '../../contexts/global-context/reducers/orderFormDataSlice'
import { Alert } from '../shared'
import { useFetchIpAddress } from '../../hooks/useFetchIpAddress'
import { selectTotalValue } from '../../contexts/global-context/reducers/simulationSlice'

interface Props {
  gateway?: string
  handleGetDocumentsClient?: (email: string) => void
}

const PaymentForm = ({ gateway, handleGetDocumentsClient }: Props) => {
  const { marketingData, customData, totalOfferings, totalizers } =
    useUserData()

  const value = useSelector(selectTotalValue)
  const { hasGoogleAnalytics } = useSelector(selectSettings)
  const { ipAddress } = useFetchIpAddress()

  const theme = useSelector(selectTheme)
  const items = useSelector(selectItems)
  const { email } = useSelector(selectProfile)
  const addressAlternative = useSelector(selectPickUpPointAddress)
  const selectedAddress = useSelector(selectDeliveryAddress)
  const addressStore = useSelector(selectAddressStore)
  const { shipping } = useSelector(selectOrderForm)

  const intl = useIntl()
  const [paymentMethod, setPaymentMethod] = useState<string>(
    PaymentsList.CreditCard
  )

  const [paymentSystem, setPaymentSystem] = useState<string>('')
  const [error, setError] = useState(null)
  const [disabled, setDisabled] = useState(true)
  const [franchiseImg, setFranchiseImg] = useState(null)
  const [showAlert, setShowAlert] = useState(false)

  const { canPayWithCredit, onSimulationCredit, onChangePaymet } =
    useCustomerCredit()

  const logisticsInfo = useSelector(selectLogisticsInfo)
  const dispatchGlobal = useDispatch()
  const { handleEcommerce } = useEcommerce()
  const dispatchActions = useActionsDispatch()
  const dispatchUserData = useUserDataDispatch()
  let styles = kuikpayStyles

  const loadingOrder = useSelector(selectLoadingOrder)

  if (theme === 'vtex') {
    styles = vtexStyles
  } else if (theme === 'generic') {
    styles = genericStyles
  }

  const units = useUnits(items)

  const [createOrder] = useMutation(CREATE_ORDER, {
    onCompleted: (data) => {
      const url =
        data.createOrder?.transaction?.RedirectResponseCollection?.[0]
          ?.redirectUrl

      if (
        handleGetDocumentsClient &&
        handleGetDocumentsClient instanceof Function
      ) {
        handleGetDocumentsClient(email || '')
      }

      const products = items?.map((item: Item) => {
        const categories = Object.values(item.productCategories)

        return {
          sku: item.id,
          quantity: item.quantity,
          price: item.sellingPrice || item?.price,
          category: categories?.[0] || 'unnkown',
          subcategory: categories?.[1] || 'unnkown',
        }
      })

      handleEcommerce(Events.checkout, { products })

      dispatchGlobal(setStep(constants.lastStep))

      dispatchGlobal(setErrorOrder(false))
      dispatchUserData({
        type: 'SET_CHANGE_INFO',
        args: {
          isEdit: false,
          isNewInfo: false,
          userLocation: false,
          isChangeEmail: false,
        },
      })
      dispatchGlobal(setLoadingOrder(false))

      if (url) {
        dispatchActions({
          type: 'SET_REDIRECT_URL',
          args: url,
        })
      } else {
        BuyCompletedEvent({
          items,
          transactionId: data.createOrder?.id,
          totalizers,
          value,
          hasGoogleAnalytics,
        })
      }
    },
    onError: (err) => {
      console.error(`error`, err)
      dispatchGlobal(setLoadingOrder(false))
      dispatchGlobal(setErrorOrder(true))

      setTimeout(() => {
        dispatchGlobal(setErrorOrder(false))
      }, 3000)
    },
  })

  useEffect(() => {
    const itemsAvailability = items.filter(
      (item: Item) => item.availability !== 'available'
    )

    if (itemsAvailability.length === 0 && items.length) {
      setDisabled(false)
    } else {
      setDisabled(true)
    }
  }, [items])

  useEffect(() => {
    const payment = sessionStorage.getItem('force-payment')

    setPaymentMethod(payment || PaymentsList.CreditCard)

    SelectedMethodPaymentEvent({ option: paymentMethod, hasGoogleAnalytics })

    return () => {
      setPaymentMethod(PaymentsList.CreditCard)
    }
  }, [])

  useEffect(() => {
    if (paymentMethod === 'bnpl') {
      onSimulationCredit()
    }

    onChangePaymet()

    SelectedMethodPaymentEvent({ option: paymentMethod, change: true })
  }, [paymentMethod])

  const handleClick = (cardData: any) => {
    setError(null)
    dispatchGlobal(setLoadingOrder(true))
    dispatchGlobal(setErrorOrder(null))

    const bundleItems: BundleIteminput[] = []
    const gifts: any[] = []

    items.forEach((item: Item) =>
      item.bundleItems.forEach((bundleItem: BundleItem) =>
        bundleItems.push({
          id: bundleItem.id,
          parentItemId: item.id,
        })
      )
    )

    const orderItems = items?.map((item: Item) => {
      if (item.isGift) {
        gifts.push({
          id: item.id,
          seller: item.seller,
          quantity: item.quantity,
        })
      }

      return {
        id: item.id,
        seller: item.seller,
        quantity: item.quantity,
      }
    })

    const data: any = {
      items: orderItems,
      gifts,
      payment: cardData || {
        paymentMethod,
        gateway: 'promissory',
      },
      profile: {
        email,
      },
      shipping: {
        addressId: selectedAddress?.id,
        logisticsInfo: logisticsInfo?.map((logisticsInfoItem) => ({
          itemIndex: logisticsInfoItem?.itemIndex,
          selectedDeliveryChannel: logisticsInfoItem?.selectedDeliveryChannel,
          selectedSla: logisticsInfoItem?.selectedSla,
          ...(logisticsInfoItem?.deliveryWindow &&
          logisticsInfoItem?.deliveryWindow?.startDateUtc &&
          logisticsInfoItem?.deliveryWindow?.endDateUtc
            ? {
                deliveryWindow: {
                  startDateUtc: logisticsInfoItem?.deliveryWindow?.startDateUtc,
                  endDateUtc: logisticsInfoItem?.deliveryWindow?.endDateUtc,
                },
              }
            : {}),
        })),
      },
      account: {
        storePreferences: {
          currencyCode: constants.currencyCode,
          countryCode: constants.countryCode,
          salesChannel: constants.salesChannel,
        },
      },
      channel: 'kuikpay',
      customData: customData || null,
      offerings: bundleItems,
      marketingData: marketingData?.coupon ? marketingData : null,
    }

    if (!data.marketingData) delete data.marketingData

    if (
      (addressAlternative &&
        addressAlternative?.addressDeliveryType !== 'delivery' &&
        (!selectedAddress || !selectedAddress?.id)) ||
      (addressAlternative &&
        selectedAddress &&
        !logisticsInfo?.some(
          (item) => item.selectedDeliveryChannel === 'delivery'
        ))
    ) {
      delete data?.shipping?.addressId
    }

    if (
      addressAlternative &&
      addressAlternative?.addressDeliveryType !== 'delivery'
    ) {
      data.shipping.externalAddress = {
        addressId: addressAlternative?.id || '',
        postalCode: addressAlternative?.postalCode,
        country: addressAlternative?.country,
        state: addressAlternative?.state,
        city: addressAlternative?.city,
        street: addressAlternative?.street,
        number: addressAlternative?.number,
        geoCoordinates: addressAlternative?.geoCoordinates,
        neighborhood: addressAlternative?.neighborhood || '',
        addressType: addressAlternative?.addressDeliveryType,
        receiverName: addressAlternative?.receiverName?.trim() || '',
        reference: addressAlternative?.reference || '',
      }
    } else if (addressStore) {
      const { availableAddresses } = shipping

      if (
        availableAddresses.find((address) => address.id === addressStore.id)
      ) {
        return
      }

      data.shipping.externalAddress = {
        addressId: addressStore?.id || '',
        postalCode: addressStore?.postalCode,
        country: addressStore?.country,
        state: addressStore?.state,
        city: addressStore?.city,
        street: addressStore?.street,
        number: addressStore?.number || 0,
        geoCoordinates: addressStore?.geoCoordinates,
        neighborhood: addressStore?.neighborhood || '',
        addressType: addressStore?.addressDeliveryType,
        receiverName: addressStore?.receiverName?.trim() || '',
        reference: addressStore?.reference || '',
      }
    }

    data.ip = ipAddress

    createOrder({
      variables: {
        orderArgs: data,
      },
    })
  }

  const handledClickDisabled = () => setShowAlert(true)

  useEffect(() => {
    if (loadingOrder) {
      setDisabled(true)
    } else {
      setDisabled(false)
    }
  }, [loadingOrder])

  const onSelectedPayment = (type: string, paymentSystemArgs: string) => {
    setPaymentMethod(type)
    setPaymentSystem(paymentSystemArgs)
  }

  const context = useMemo(
    () => ({
      canPayWithCredit,
      disabled,
      error,
      franchiseImg,
      gateway,
      global: globalStyles,
      intl,
      loadingOrder,
      paymentMethod,
      paymentSystem,
      styles,
      value,
      handleClick,
      handledClickDisabled,
      onSelectedPayment,
      setError,
      setFranchiseImg,
    }),
    [
      canPayWithCredit,
      disabled,
      error,
      franchiseImg,
      gateway,
      loadingOrder,
      paymentMethod,
      paymentSystem,
      selectedAddress,
      value,
    ]
  )

  return (
    <PaymentProvider value={context}>
      <Fragment>
        {loadingOrder ? (
          <Fragment>
            loading
            <LoadingProcessOrder />
          </Fragment>
        ) : (
          <div style={{ display: loadingOrder ? 'none' : '' }}>
            <Alert
              enableAutoClose={true}
              isOpen={showAlert}
              text="store/checkoutless.register.card.enterAllFields"
              type="warning"
              handleClickClose={() => setShowAlert(false)}
            />
            <Title>
              <Title.Item title="store/checkoutless.register.payment">
                <CreditCard fill={globalStyles.iconPrimary} />
              </Title.Item>

              <InfoItem
                className={globalStyles.inMobileFlex}
                firstAction={() => dispatchGlobal(setNextSection('summary'))}
              >
                <InfoItem.Icon>
                  <MyOrder
                    fill={globalStyles.iconAlternative}
                    height={24}
                    width={24}
                  />
                </InfoItem.Icon>
                <InfoItem.Content text="store/checkoutless.summary.myOrder" />
              </InfoItem>
            </Title>
            <Payments units={units} totalOfferings={totalOfferings} />
          </div>
        )}
      </Fragment>
    </PaymentProvider>
  )
}

export default PaymentForm

```


[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-sdk/src/components/RegisterForm/InputCard.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import vtexStyles from './vtex-styles.module.css'
import kuikpayStyles from './kuikpay-styles.module.css'
import genericStyles from './generic-styles.module.css'

interface InputCardProps {
  theme: string
  isValid: boolean | null
  imgCard?: string | null
  itemId: string
}

const InputCard = (props: InputCardProps) => {
  const {
    theme,
    isValid,
    itemId,
    // imgCard
  } = props

  let styles = kuikpayStyles

  if (theme === 'vtex') {
    styles = vtexStyles
  } else if (theme === 'generic') {
    styles = genericStyles
  }

  return (
    <div
      id={`card-number-container${itemId}`}
      className={styles.secureField__inputContainer}
    >
      <div
        id={`card-number-placeholder${itemId}`}
        className={`${styles.secureField__input} ${
          isValid === false ? styles.secureFieldInvalidLite : null
        } ${isValid === true ? styles.secureFieldValidLite : null} ${
          styles.secureFieldLite
        }`}
      ></div>
    </div>
  )
}

export default InputCard

```


[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-sdk/src/components/RegisterForm/useRegisterForm.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'

import { useActions } from '../../contexts/ActionsProviderV2'
import {
  selectSettings,
  setIsFullscreen,
} from '../../contexts/global-context/reducers/uiSettingsSlice'
import { useCreateAddressExternal } from '../../hooks/useCreateAddressExternal'
import { usePCIScript } from '../../hooks/usePCIScript'
import { useScript } from '../../hooks/useScript'
import {
  selectLoadingOrder,
  selectUserRegistrationSections,
} from '../../contexts/global-context/reducers/checkoutFormSlice'
import constants from '../../utils/constants'
import {
  selectAddressStore,
  selectHasAddress,
  selectIsProfileComplete,
  selectItems,
  selectProfile,
} from '../../contexts/global-context/reducers/orderFormDataSlice'
import {
  selectSimulationLogistics,
  selectSimulationStatus,
} from '../../contexts/global-context/reducers/simulationSlice'

const useRegisterForm = () => {
  const dispatchGlobal = useDispatch()
  const { handleGetDocumentsClient } = useActions()
  const loadingOrder = useSelector(selectLoadingOrder)
  const userRegistrationSections = useSelector(selectUserRegistrationSections)
  const simulationStatus = useSelector(selectSimulationStatus)
  const profile = useSelector(selectProfile)
  const profileComplete = useSelector(selectIsProfileComplete)
  const addressAlternative = useSelector(selectAddressStore)
  const items = useSelector(selectItems)
  const logisticsInfo = useSelector(selectSimulationLogistics)
  const hasAddress = useSelector(selectHasAddress)

  const { PCI_PROXY_SCRIPT } = usePCIScript()

  const { additionalData } = useSelector(selectSettings)

  const { sandbox } = useActions()
  const [isPickupPoint, setIsPickupPoint] = useState(false)

  const [steps, setSteps] = useState({
    profile: false,
    shipping: false,
    logistic: false,
    payment: false,
  })

  const [loadPaymentForm, setLoadPaymentForm] = useState(false)

  const { createAddressExternal, successAddressAlter, setSuccessAddressAlter } =
    useCreateAddressExternal()

  const gateway = localStorage.getItem('gateway')

  const isLogisticPickupPoint =
    logisticsInfo?.length > 0 &&
    logisticsInfo[0].selectedDeliveryChannel === 'pickup-in-point'

  const isAddressResidential =
    addressAlternative?.addressDeliveryType === 'delivery'

  const isAddressPickupPoint =
    addressAlternative?.addressDeliveryType === 'pickup'

  const showEditButtonAddress =
    !addressAlternative ||
    isAddressResidential ||
    (isAddressPickupPoint &&
      isLogisticPickupPoint &&
      logisticsInfo?.some(
        (item) => item.selectedDeliveryChannel === 'delivery'
      ))

  const validateAddressPickup = isAddressPickupPoint && isLogisticPickupPoint

  const validateTriggerPayment = isAddressPickupPoint
    ? !validateAddressPickup
    : !hasAddress

  useEffect(() => {
    setSteps({
      profile: userRegistrationSections === 1,
      shipping: isPickupPoint ? false : userRegistrationSections === 2,
      logistic: isPickupPoint
        ? userRegistrationSections === 2
        : userRegistrationSections === 3,
      payment: isPickupPoint
        ? userRegistrationSections >= 3
        : userRegistrationSections >= 4,
    })
  }, [userRegistrationSections, isPickupPoint])

  useEffect(() => {
    if (
      addressAlternative &&
      addressAlternative?.addressDeliveryType === 'pickup' &&
      logisticsInfo?.length > 0 &&
      !logisticsInfo?.find(
        (item) => item.selectedDeliveryChannel === 'delivery'
      ) &&
      profileComplete
    ) {
      if (steps.shipping) {
        setIsPickupPoint(true)
        setSteps({
          profile: false,
          shipping: false,
          logistic: true,
          payment: false,
        })
      }

      setSuccessAddressAlter(true)
      setTimeout(() => {
        setSuccessAddressAlter(false)
      }, 3000)
    }
  }, [logisticsInfo, profileComplete, addressAlternative, steps])

  useEffect(() => {
    const addressAlter = addressAlternative

    if (
      addressAlter &&
      addressAlter?.addressDeliveryType === 'delivery' &&
      (addressAlter?.id !== '' || addressAlter?.id) &&
      profileComplete
    ) {
      let dataForCreate: any = {
        addressId: addressAlter?.id,
        profileId: profile.id,
      }

      if (
        !addressAlter?.city?.includes('*') ||
        !addressAlter?.postalCode?.includes('*')
      ) {
        dataForCreate = {
          ...dataForCreate,
          country: addressAlter?.country,
          state: addressAlter?.state,
          city: addressAlter?.city,
          street: addressAlter?.street,
          number: addressAlter?.number,
          postalCode: addressAlter?.postalCode,
          receiverName: addressAlter?.receiverName || '',
          geoCoordinates: addressAlter?.geoCoordinates,
          neighborhood: addressAlter?.neighborhood || '',
          reference: addressAlter?.reference,
        }
      }

      createAddressExternal({
        variables: { args: dataForCreate },
      })
    }
  }, [profileComplete])

  useEffect(() => {
    dispatchGlobal(setIsFullscreen(true))

    return () => {
      dispatchGlobal(setIsFullscreen(false))
    }
  }, [])

  useEffect(() => {
    // TODO: eliminar PCI al terminar la transición
    if (additionalData?.paymentez === 'true') {
      if (gateway === 'noop' || gateway === null || gateway === 'creditpay') {
        if (!(window as any).PaymentezLoad) {
          useScript(
            constants.JQUERY_SCRIPT[0],
            constants.JQUERY_SCRIPT[1]
          ).then(() => {
            useScript(
              constants.PAYMENTEZ_SCRIPT[0],
              constants.PAYMENTEZ_SCRIPT[1]
            ).then(() => {
              // eslint-disable-next-line prettier/prettier
              ;(window as any).PaymentezLoad = true
              Payment.init(
                ...constants.PAYMENTEZ_CREDENTIALS[sandbox ? 'stg' : 'prod']
              )
              setLoadPaymentForm(true)
            })
          })
        }

        if ((window as any).PaymentezLoad && !loadPaymentForm) {
          setLoadPaymentForm(true)
        }
      }
    } else if (
      gateway === 'noop' ||
      gateway === null ||
      gateway === 'creditpay'
    ) {
      if (!(window as any).SecureFieldsLoad) {
        useScript(PCI_PROXY_SCRIPT[0], PCI_PROXY_SCRIPT[1])
          .then(() => {
            ;(window as any).SecureFieldsLoad = true
            setLoadPaymentForm(true)
          })
          .catch((err) => {
            console.error('ERROR', err)
            setLoadPaymentForm(true)
          })
      }

      if ((window as any).SecureFieldsLoad && !loadPaymentForm) {
        setLoadPaymentForm(true)
      }
    }
  }, [])

  useEffect(() => {
    dispatchGlobal(setIsFullscreen(!loadingOrder))
  }, [loadingOrder])

  useEffect(() => {
    dispatchGlobal(setIsFullscreen(items.length > 0))
  }, [items])

  return {
    gateway,
    isPickupPoint,
    items,
    loadingOrder,
    loadPaymentForm,
    showEditButtonAddress,
    steps,
    successAddressAlter,
    validateTriggerPayment,
    handleGetDocumentsClient,
    setSteps,
    profile,
    logisticsInfo,
    simulationStatus,
  }
}

export default useRegisterForm

```


[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-sdk/src/components/RegisterForm/Form.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
// TODO: Este cambio es temporal, se debe eliminar payments form, luego de la transicion a paymentez
import React from 'react'

import PaymentsForm from './PaymentsForm'
import PaymentezForm from './PaymentezForm'

const Form = (props: any) => {
  if (props.id === 'noop') {
    if (props.gateway === 'paymentez') {
      return <PaymentezForm {...props} />
    }

    return <PaymentsForm {...props} />
  }

  return null
}

export default Form

```


[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-sdk/src/components/ViewValidate/index.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { useSelector } from 'react-redux'

import Addresses from '../UserInfo/Addresses/AddressesContainer'
import PaymentMethods from '../UserInfo/PaymentMethods'
import { getCookie } from '../../utils/index'
import ProfileForm from '../RegisterForm/Profile/ProfileFormContainer'
import Packages from '../LogisticsInfo/Packages/PackagesContainer'
import { selectSection } from '../../contexts/global-context/reducers/checkoutFormSlice'
import Cart from '../UserInfo/Cart'
import AccessKeyFormContainer from '../AccessKeyForm/AccessKeyFormContainer'
import RegisterFormContainer from '../RegisterForm/RegisterFormContainer'

const ViewValidate = () => {
  const section = useSelector(selectSection)
  const sessionCookie = getCookie('x-checkoutless-auth')
  const persistedData = JSON.parse(localStorage.getItem('checkoutless_data'))
  const authorizedUser = persistedData
    ? persistedData.email === persistedData.authorizedEmail
    : false

  // TODO: Revisar esta logica, no se deberia confiar en una autenticación sobre localStorage
  if (
    section !== 'logisticsInfo' &&
    section !== 'summary' &&
    (!sessionCookie || !authorizedUser)
  ) {
    return <AccessKeyFormContainer />
  }

  switch (section) {
    case 'clientProfileData':
      return <ProfileForm />

    case 'shippingData':
      return <Addresses />

    case 'paymentData':
      return <PaymentMethods />

    case 'logisticsInfo':
      return <Packages />

    case 'registerFormProfile':
      return <RegisterFormContainer />

    case 'registerFormShipping':
      return <RegisterFormContainer />

    case 'summary':
      return <Cart />

    default: {
      return null
    }
  }
}

export default ViewValidate

```


[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-sdk/src/components/Payments/index.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Fragment, useMemo } from 'react'
import { pathOr } from 'ramda'
import { useDispatch, useSelector } from 'react-redux'

import { Button, Loader } from '../shared'
import { selectSettings } from '../../contexts/global-context/reducers/uiSettingsSlice'
import { usePayment } from '../../contexts/PaymentContext'
import {
  selectPaymentDataSection,
  selectUserRegistrationSections,
  setNextUserRegistrationSections,
  setPaymentDataSection,
} from '../../contexts/global-context/reducers/checkoutFormSlice'
import CreditCart from './Components/CreditCart'
import CustomPayment from './Components/CustomPayment'
import Orion from './Components/Orion'
import PaymentOption from './Components/PaymentOption'
import { setPaymetId } from '../../contexts/global-context/reducers/orderFormDataSlice'
import { selectGroupAvailablePaymentMethods } from '../../contexts/global-context/reducers/simulationSlice'
import { useActions } from '../../contexts/ActionsProviderV2'

interface PaymentsRenderProps {
  units: number
  paymentInfo?: any
  totalOfferings: number
}

const PaymentsRender = ({ units, totalOfferings }: PaymentsRenderProps) => {
  const dispatchGlobal = useDispatch()
  const userRegistrationSections = useSelector(selectUserRegistrationSections)

  const { styles, paymentMethod: SelectPayment, paymentSystem } = usePayment()

  const { showPaymentMethods } = useActions()
  const paymentDataSection = useSelector(selectPaymentDataSection)

  const availablePaymentMethods = useSelector(
    selectGroupAvailablePaymentMethods
  )?.filter((availablePayment) => {
    const paymentId = availablePayment?.paymentMethods[0]?.id
    const foundPayment = showPaymentMethods?.find(
      (test) => test?.id === paymentId
    )

    return foundPayment?.id ? foundPayment?.show : true
  })

  const settings = useSelector(selectSettings)

  const orion = useMemo(() => pathOr(false, ['orion'], settings), [settings])

  return (
    <Fragment>
      <div className={styles.paymentMethodContainer} style={{ padding: 0 }}>
        {availablePaymentMethods.map((payment, index) => {
          if (payment.isCreditCard) {
            return (
              <PaymentOption
                key={payment.groupName}
                payments={payment}
                selected={SelectPayment === payment.groupName}
                paymentDataSection={paymentDataSection}
              >
                <CreditCart
                  key={`credit-payment-${index}`}
                  payments={payment}
                />
              </PaymentOption>
            )
          }

          return (
            <PaymentOption
              key={payment.groupName}
              payments={payment}
              selected={SelectPayment === payment.groupName}
              paymentDataSection={paymentDataSection}
            >
              <CustomPayment
                key={`custom-payment-${index}`}
                payments={payment}
                units={units}
                totalOfferings={totalOfferings}
              />
            </PaymentOption>
          )
        })}
        {orion && (
          <PaymentOption
            selected={
              paymentDataSection === 'details' && SelectPayment === 'creditpay'
            }
            paymentDataSection={paymentDataSection}
            payments={null}
            orion
          >
            <Orion units={units} totalOfferings={totalOfferings} />
          </PaymentOption>
        )}
        <PaymentOption
          customLabel="store/checkoutless.userInfo.otherPaymentMethod"
          payments={{ groupName: 'otherPayments' }}
          selected={SelectPayment === 'otherPayments'}
          paymentDataSection={paymentDataSection}
        >
          <Loader text="store/checkoutless.loading.almostThere" />
        </PaymentOption>
        {paymentDataSection === 'list' && (
          <Button
            value={'store/checkoutless.next'}
            disabled={!SelectPayment}
            onClick={() => {
              if (SelectPayment === 'otherPayments') {
                setTimeout(
                  () => window.open('/checkout/#/profile', '_blank'),
                  1500
                )
              }

              dispatchGlobal(setPaymetId(paymentSystem))

              if (userRegistrationSections >= 3) {
                dispatchGlobal(setNextUserRegistrationSections())
              } else {
                dispatchGlobal(setPaymentDataSection('details'))
              }
            }}
          />
        )}
      </div>
    </Fragment>
  )
}

export default PaymentsRender

```


[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-sdk/src/components/BuyButton/BuyButton.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'

import { Button } from '../shared'
import { formatter } from '../../utils'
import globalStyles from '../../myCheckout-styles.module.css'
import { setShowingBuyButton } from '../../contexts/global-context/reducers/uiSettingsSlice'

interface Props {
  canBuy: boolean
  className?: string
  classNameContainer?: string
  disabled: boolean
  forceDisabled: boolean
  loadingOrder: boolean
  isSimulationReady: boolean
  secondary?: boolean
  totalOfferings: number
  units: number
  value: number
  onClickDisabled?: () => void
  preHandleClick: () => void
}

export const BuyButton = ({
  canBuy,
  className,
  classNameContainer,
  disabled,
  forceDisabled,
  loadingOrder,
  isSimulationReady,
  secondary,
  totalOfferings,
  units,
  value,
  onClickDisabled,
  preHandleClick,
}: Props) => {
  const dispatchGlobal = useDispatch()

  useEffect(() => {
    dispatchGlobal(setShowingBuyButton(true))

    return () => {
      dispatchGlobal(setShowingBuyButton(false))
    }
  }, [])

  return (
    <div className={`${globalStyles.buyButtonContainer} ${classNameContainer}`}>
      <Button
        value={
          !isSimulationReady
            ? 'Calculando'
            : loadingOrder
            ? 'store/checkoutless.register.processingPayment'
            : 'store/checkoutless.register.pay'
        }
        onClick={preHandleClick}
        disabled={disabled || canBuy !== true || forceDisabled}
        customValue={`${formatter.format(value + totalOfferings)}`}
        units={units}
        className={className}
        secondary={secondary}
        onClickDisabled={onClickDisabled}
      />
    </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-sdk/src/components/BuyButton/index.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import { BuyButton } from './BuyButton'
import { useBuyButton } from './useBuyButton'

interface Props {
  canBuy?: boolean
  className?: string
  classNameContainer?: string
  cvv?: string
  dues?: string
  forceDisabled?: boolean
  handleSubmit?: any
  secondary?: boolean
  onClickDisabled?: () => void
}

const BuyButtonContainer = ({
  canBuy = true,
  className,
  classNameContainer,
  cvv,
  dues,
  forceDisabled = false,
  handleSubmit,
  secondary = false,
  onClickDisabled,
}: Props) => {
  const buyButton = useBuyButton(
    canBuy,
    className,
    classNameContainer,
    cvv,
    dues,
    forceDisabled,
    handleSubmit,
    secondary
  )

  return <BuyButton {...buyButton} onClickDisabled={onClickDisabled} />
}

export default BuyButtonContainer

```


[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-sdk/src/components/BuyButton/styles.module.css from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```css
.habeasDataLink.habeasDataLink {
  text-decoration: underline;
}

.buyButtonContainer {
  position: sticky;
  bottom: 0px;
  width: 100%;
  background-color: #fff;
  z-index: 2;
}

@media (min-width: 992px) {
  .buyButtonContainer {
    position: fixed;
    padding: 14px;
    margin-top: 14px;
    box-shadow: inset 0px 3px 6px #0000000f;
    width: 30%;
    right: 0;
    background: #ffffff 0% 0% no-repeat padding-box;
    z-index: 100;
  }
}

```


[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-sdk/src/components/BuyButton/useBuyButton.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable max-params */
import { useDispatch, useSelector } from 'react-redux'
import { useMutation } from '@apollo/client'
import { useEffect, useState } from 'react'

import {
  selectLoadingOrder,
  setErrorOrder,
  setLoadingOrder,
  setStep,
} from '../../contexts/global-context/reducers/checkoutFormSlice'
import { selectSettings } from '../../contexts/global-context/reducers/uiSettingsSlice'
import { useUserData } from '../../contexts/UserDataProvider'
import type { BundleItem, BundleIteminput, Item } from '../../interfaces'
import { Events } from '../../interfaces'
import constants from '../../utils/constants'
import { CREATE_ORDER } from '../../graphql/mutations'
import { useEcommerce } from '../../hooks/useEcommerce'
import { useActionsDispatch } from '../../contexts/ActionsProviderV2'
import { useUnits } from '../../hooks/useUnits'
import { useCustomerCredit } from '../../hooks/useCustomerCredit'
import { BuyCompletedEvent } from '../../events'
import { useFetchIpAddress } from '../../hooks/useFetchIpAddress'
import {
  selectAddressStore,
  selectDeliveryAddress,
  selectItems,
  selectLogisticsInfo,
  selectMainPayment,
  selectOrderForm,
  selectPickUpPointAddress,
  selectProfile,
} from '../../contexts/global-context/reducers/orderFormDataSlice'
import {
  selectSimulationStatus,
  selectTotalValue,
} from '../../contexts/global-context/reducers/simulationSlice'

export const useBuyButton = (
  canBuy: boolean,
  className: string,
  classNameContainer: string,
  cvv: string,
  dues: string,
  forceDisabled: boolean,
  handleSubmit: any,
  secondary: boolean
) => {
  const CONSTANTS = {
    delivery: 'delivery',
    creditCard: 'tc',
    store: 'store',
    promissory: 'promissory',
  }

  const [disabled, setDisabled] = useState(true)
  const { ipAddress } = useFetchIpAddress()

  const { hasGoogleAnalytics } = useSelector(selectSettings)
  const loadingOrder = useSelector(selectLoadingOrder)
  const dispatchGlobal = useDispatch()
  const { customData, marketingData, totalizers, totalOfferings } =
    useUserData()

  const value = useSelector(selectTotalValue)

  const { email, habeasData } = useSelector(selectProfile)
  const items = useSelector(selectItems)
  const addressAlternative = useSelector(selectPickUpPointAddress)
  const selectedAddress = useSelector(selectDeliveryAddress)
  const selectedPaymentMethod = useSelector(selectMainPayment)
  const simulationStatus = useSelector(selectSimulationStatus)

  const logisticsInfo = useSelector(selectLogisticsInfo)
  const { handleEcommerce } = useEcommerce()
  const dispatchActions = useActionsDispatch()
  const units = useUnits(items)
  const { onSimulationCredit } = useCustomerCredit()
  const addressStore = useSelector(selectAddressStore)
  const { shipping: shippingOrderForm } = useSelector(selectOrderForm)

  const [createOrder] = useMutation(CREATE_ORDER, {
    onCompleted: (data) => {
      const url =
        data.createOrder?.transaction?.RedirectResponseCollection?.[0]
          ?.redirectUrl

      dispatchGlobal(setStep(constants.lastStep))
      dispatchGlobal(setLoadingOrder(false))
      dispatchGlobal(setErrorOrder(null))

      const products = items?.map((item: Item) => {
        const categories = Object.values(item.productCategories)

        return {
          sku: item.id,
          quantity: item.quantity,
          price: item.sellingPrice || item?.price,
          category: categories?.[0] || 'unnkown',
          subcategory: categories?.[1] || 'unnkown',
        }
      })

      handleEcommerce(Events.checkout, { products })

      if (url) {
        dispatchActions({
          type: 'SET_REDIRECT_URL',
          args: url,
        })
      } else {
        BuyCompletedEvent({
          items,
          transactionId: data.createOrder?.id,
          totalizers,
          value,
          hasGoogleAnalytics,
        })
      }
    },
    onError: (error) => {
      console.error(`error`, error)
      dispatchGlobal(setErrorOrder(true))

      setTimeout(() => {
        dispatchGlobal(setErrorOrder(false))
      }, 3000)
      setDisabled(false)
      dispatchGlobal(setLoadingOrder(false))
      dispatchGlobal(setErrorOrder(error))
    },
  })

  const handleClick = (transactionId?: string) => {
    dispatchGlobal(setLoadingOrder(true))
    dispatchGlobal(setErrorOrder(null))

    const bundleItems: BundleIteminput[] = []
    const gifts: any[] = []

    items.forEach((item: Item) =>
      item.bundleItems.forEach((bundleItem: BundleItem) =>
        bundleItems.push({
          id: bundleItem.id,
          parentItemId: item.id,
        })
      )
    )

    const orderItems = items?.map((item: Item) => {
      if (item.isGift) {
        gifts.push({
          id: item.id,
          seller: item.seller,
          quantity: item.quantity,
        })
      }

      return {
        id: item.id,
        seller: item.seller,
        quantity: item.quantity,
      }
    })

    // deberia haber solo un Gateway que seria VTEX

    const gateway =
      selectedPaymentMethod?.paymentMethod === 'BNPL'
        ? 'creditpay'
        : selectedPaymentMethod?.paymentMethod === CONSTANTS.promissory
        ? CONSTANTS.promissory
        : selectedPaymentMethod?.paymentMethod === CONSTANTS.creditCard
        ? 'noop'
        : 'custom'

    const paymentMethod = selectedPaymentMethod?.cardId
      ? CONSTANTS.creditCard
      : selectedPaymentMethod?.paymentMethod

    const additionalData =
      selectedPaymentMethod?.origin === CONSTANTS.store &&
      selectedPaymentMethod?.paymentMethod === CONSTANTS.creditCard
        ? [{ key: 'accountId', value: selectedPaymentMethod?.cardId }]
        : []

    const franchise =
      selectedPaymentMethod?.origin === CONSTANTS.store &&
      selectedPaymentMethod?.paymentMethod === CONSTANTS.creditCard
        ? selectedPaymentMethod?.franchise
        : null

    const data: any = {
      items: orderItems,
      gifts,
      payment: {
        additionalData,
        ...(selectedPaymentMethod?.paymentMethod === CONSTANTS.creditCard && {
          cardId:
            selectedPaymentMethod?.paymentMethod === CONSTANTS.creditCard &&
            selectedPaymentMethod?.origin !== CONSTANTS.store
              ? selectedPaymentMethod?.cardId
              : null,
        }),
        paymentMethod,
        gateway, // 'paymentez'
        ...(franchise && {
          franchise,
        }),
      },
      profile: {
        email,
        habeasData,
      },
      shipping: {
        addressId: selectedAddress?.id,
        logisticsInfo: logisticsInfo?.map((logisticsInfoItem) => ({
          itemIndex: logisticsInfoItem?.itemIndex,
          selectedDeliveryChannel: logisticsInfoItem?.selectedDeliveryChannel,
          selectedSla: logisticsInfoItem?.selectedSla,
          ...(logisticsInfoItem?.deliveryWindow &&
          logisticsInfoItem?.deliveryWindow?.startDateUtc &&
          logisticsInfoItem?.deliveryWindow?.endDateUtc
            ? {
                deliveryWindow: {
                  startDateUtc: logisticsInfoItem?.deliveryWindow?.startDateUtc,
                  endDateUtc: logisticsInfoItem?.deliveryWindow?.endDateUtc,
                },
              }
            : {}),
        })),
      },
      account: {
        storePreferences: {
          currencyCode: constants.currencyCode,
          countryCode: constants.countryCode,
          salesChannel: constants.salesChannel,
        },
      },
      channel: 'kuikpay',
      customData: customData || null,
      offerings: bundleItems,
      marketingData: marketingData?.coupon ? marketingData : null,
    }

    if (selectedPaymentMethod?.paymentMethod === CONSTANTS.creditCard) {
      if (dues !== '') {
        data.payment.additionalData.push({
          key: 'installments',
          value: dues,
        })
      }

      if (cvv) {
        data.payment.cvv = cvv
      }

      if (transactionId) {
        data.payment.additionalData.push({
          key: 'transactionId',
          value: transactionId,
        })
      }
    }

    if (selectedPaymentMethod?.paymentId) {
      data.payment.additionalData.push({
        key: 'paymentSystem',
        value: selectedPaymentMethod?.paymentId,
      })
    }

    if (!data.marketingData) delete data.marketingData

    if (
      (addressAlternative &&
        addressAlternative?.addressDeliveryType !== CONSTANTS.delivery &&
        (!selectedAddress || !selectedAddress?.id)) ||
      (addressAlternative &&
        selectedAddress &&
        !logisticsInfo?.some(
          (item) => item.selectedDeliveryChannel === CONSTANTS.delivery
        ))
    ) {
      delete data?.shipping?.addressId
    }

    if (
      addressAlternative &&
      addressAlternative?.addressDeliveryType !== CONSTANTS.delivery
    ) {
      data.shipping.externalAddress = {
        addressId: addressAlternative?.id || '',
        postalCode: addressAlternative?.postalCode,
        country: addressAlternative?.country,
        state: addressAlternative?.state,
        city: addressAlternative?.city,
        street: addressAlternative?.street,
        number: addressAlternative?.number,
        geoCoordinates: addressAlternative?.geoCoordinates,
        neighborhood: addressAlternative?.neighborhood || '',
        addressType: addressAlternative?.addressDeliveryType,
        receiverName: addressAlternative?.receiverName?.trim() || '',
        reference: addressAlternative?.reference || '',
      }
    } else if (addressStore) {
      const { availableAddresses } = shippingOrderForm

      if (
        availableAddresses.find((address) => address.id === addressStore.id)
      ) {
        return
      }

      data.shipping.externalAddress = {
        addressId: addressStore?.id || '',
        postalCode: addressStore?.postalCode,
        country: addressStore?.country,
        state: addressStore?.state,
        city: addressStore?.city,
        street: addressStore?.street,
        number: addressStore?.number || 0,
        geoCoordinates: addressStore?.geoCoordinates,
        neighborhood: addressStore?.neighborhood || '',
        addressType: addressStore?.addressDeliveryType,
        receiverName: addressStore?.receiverName?.trim() || '',
        reference: addressStore?.reference || '',
      }
    }

    data.ip = ipAddress

    createOrder({
      variables: {
        orderArgs: data,
      },
    })
  }

  /**
   * Validation before sending data
   */
  const preHandleClick = () => {
    handleSubmit && handleSubmit instanceof Function
    if (handleSubmit && handleSubmit instanceof Function) {
      handleSubmit(handleClick)
    } else {
      handleClick()
    }
  }

  useEffect(() => {
    const itemsAvailability = items.filter(
      (item: Item) => item.availability !== 'available'
    )

    if (itemsAvailability.length === 0 && items.length) {
      setDisabled(false)
    } else {
      setDisabled(true)
    }
  }, [items])

  useEffect(() => {
    if (selectedPaymentMethod?.paymentMethod === 'BNPL' && totalizers.length) {
      const isShipping = !!totalizers.find((e) => e.id === 'Shipping')

      isShipping && onSimulationCredit()
    }
  }, [selectedPaymentMethod, value, totalizers])

  useEffect(() => {
    if (loadingOrder) {
      setDisabled(true)
    } else {
      setDisabled(false)
    }
  }, [loadingOrder])

  return {
    canBuy,
    className,
    classNameContainer,
    disabled,
    forceDisabled,
    loadingOrder,
    secondary,
    totalOfferings,
    units,
    value,
    preHandleClick,
    isSimulationReady: !(
      simulationStatus === 'preloading' || simulationStatus === 'idle'
    ),
  }
}

```


[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-sdk/src/components/Portal/index.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

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

import styles from '../../myCheckout-styles.module.css'

interface Props {
  children: JSX.Element | JSX.Element[]
}

const Portal: (props: Props) => React.ReactPortal = ({ children }: Props) => {
  const handleClick = (e: any) => {
    e.stopPropagation()
  }

  const target = window?.document?.body

  return ReactDOM.createPortal(
    <div className={styles.Checkoutless} onClick={handleClick}>
      {children}
    </div>,
    target
  )
}

export default Portal

```


[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-sdk/src/components/QuotaInformative/QuotaInformativeContainer.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import type { ProductItem } from '../../interfaces'
import useQuotaInformative from './useQuotaInformative'
import QuotaInformative from './QuotaInformative'

interface QuotaInformativeProps {
  selectedItem: ProductItem | null
}

const QuotaInformativeContainer = ({ selectedItem }: QuotaInformativeProps) => {
  const quotaInformativeProps = useQuotaInformative(selectedItem)

  return <QuotaInformative {...quotaInformativeProps} />
}

export default QuotaInformativeContainer

```


[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-sdk/src/components/QuotaInformative/useQuotaInformative.tsx from the mycheckout-sdk VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useCallback, useMemo, useState } from 'react'
import { pathOr } from 'ramda'

import type { ProductItem } from '../../interfaces'

interface Quota {
  quotas: number
  value: number
}

const useQuotaInformative = (selectedItem: ProductItem | null) => {
  const [open, setOpen] = useState(false)

  const priceProduct = useMemo(
    () => pathOr(0, ['sellers', 0, 'commertialOffer', 'Price'], selectedItem),
    [selectedItem]
  )

  const onCalculateQuota = useCallback(
    (quantity: number, price: number) => {
      return {
        quotas: quantity,
        value: price / quantity,
      }
    },
    [priceProduct]
  )

  const quota = useMemo<Quota>(() => {
    if (priceProduct < 100000) {
      return onCalculateQuota(3, priceProduct)
    }

    if (priceProduct > 100001 && priceProduct < 1000000) {
      return onCalculateQuota(6, priceProduct)
    }

    return onCalculateQuota(9, priceProduct)
  }, [priceProduct])

  const handleModal = () => setOpen(!open)

  return {
    handleModal,
    open,
    quota,
  }
}

export default useQuotaInformative

```