[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 binding-selector/graphql/types/BindingTranslations.graphql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
input BindingsInput {
  bindingId: String
  show: Boolean
  translatedLocales: [BindingsTranslationInput]
  externalRedirectData: ExternalRedirectDataInput
  customFlagData: CustomFlagDataInput
}

input BindingsTranslationInput {
  id: String
  label: String
  defaultLocale: String
  canonicalBaseAddress: String
  salesChannel: String
  hide: Boolean
}

input ExternalRedirectDataInput {
  redirectUrl: Boolean
  url: String
}

type BindingsTranslation {
  id: String
  label: String
  defaultLocale: String
  canonicalBaseAddress: String
  salesChannel: String
  hide: Boolean
}

type TranslatedInfoOutput {
  bindingId: String
  show: Boolean
  translatedLocales: [BindingsTranslation]
  externalRedirectData: ExternalRedirectData
  customFlagData: CustomFlagData
}

type ExternalRedirectData {
  redirectUrl: Boolean
  url: String
}

input CustomFlagDataInput {
  isCustom: Boolean
  url: String
}

type CustomFlagData {
  isCustom: Boolean
  url: String
}

```


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

[User] Show me the implementation of binding-selector/graphql/types/Item.graphql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
scalar InputValues

"""
ProductCategoriesObject is a Record<string, string>, in the following format:
{ '<categoryNumber>': '<categoryName>' }
"""
scalar ProductCategoriesObject

type Item {
  additionalInfo: ItemAdditionalInfo
  assemblyOptions: AssemblyOptionItem
  availability: String
  attachmentOfferings: [AttachmentOffering!]!
  attachments: [Attachment!]!
  bundleItems: [Item!]!
  detailUrl: String
  id: ID!
  imageUrls: ImageUrls
  listPrice: Float
  manualPrice: Float
  measurementUnit: String
  name: String @translatableV2
  offerings: [Offering!]!
  options: [AssemblyOptionType]
  parentAssemblyBinding: String
  parentItemIndex: Int
  price: Float
  productCategories: ProductCategoriesObject
  productCategoryIds: String
  """
  Id of the product. Can be null if included inside bundle items.
  """
  productId: String
  productRefId: String
  quantity: Float!
  refId: String
  """
  Product's seller. Can be null if included inside bundle items.
  """
  seller: String
  sellingPrice: Float
  sellingPriceWithAssemblies: Float
  skuName: String @translatableV2
  skuSpecifications: [SKUSpecification!]!
  uniqueId: String!
  unitMultiplier: Float
  priceTags: [PriceTag!]!
}

type ImageUrls {
  at1x: String!
  at2x: String!
  at3x: String!
}

type AssemblyOptionItem {
  added: [AddedOptionItem]!
  removed: [RemovedOptionItem]!
  parentPrice: Float
}

type RemovedOptionItem {
  initialQuantity: Int
  removedQuantity: Int
  name: String @translatableV2
}

type AddedOptionItem {
  item: Item
  compositionItem: CompositionItem
  normalizedQuantity: Int
  choiceType: String
  extraQuantity: Int
}

type CompositionItem {
  id: ID
  minQuantity: Int
  maxQuantity: Int
  initialQuantity: Int
  priceTable: String
  seller: String
}

type ItemAdditionalInfo {
  brandName: String @translatableV2
}

type SKUSpecification {
  fieldName: String @translatableV2
  fieldValues: [String]! @translatableV2
}

type AssemblyOptionType {
  assemblyId: String!
  id: ID
  quantity: Int
  seller: String
  inputValues: InputValues
  options: [AssemblyOptionType!]
}

type Offering {
  id: String!
  name: String! @translatableV2
  price: Int!
  type: String!
  attachmentOfferings: [AttachmentOffering!]!
}

scalar AttachmentSchema

type AttachmentOffering {
  name: String @translatableV2
  required: Boolean
  schema: AttachmentSchema
}

scalar AttachmentContent

type Attachment {
  name: String @translatableV2
  content: AttachmentContent
}

input ItemInput {
  id: Int
  index: Int
  quantity: Float
  seller: ID
  uniqueId: String
  inputValues: InputValues
  options: [AssemblyOptionInput]
}

input AssemblyOptionInput {
  assemblyId: String!
  id: ID
  quantity: Int
  seller: String
  inputValues: InputValues
  options: [AssemblyOptionInput!]
}

scalar OfferingInfo

input OfferingInput {
  itemIndex: Int!
  offeringId: String!
  offeringInfo: OfferingInfo
}

input BundleItemAttachmentInput {
  itemIndex: Int!
  bundleItemId: String!
  attachmentName: String!
  attachmentContent: AttachmentContent!
}

input ManualPriceInput {
  itemIndex: Int!
  price: Float!
}

type PriceTag {
  identifier: String
  isPercentual: Boolean
  name: String
  ratesAndBenefitsIdentifier: RatesAndBenefitsIdentifier
  rawValue: Float
  value: Int
}

type RatesAndBenefitsIdentifier {
  description: String
  featured: Boolean
  id: String
  matchedParameters: MatchedParameters
  name: String
}

scalar MatchedParameters

```


[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 binding-selector/node/clients/checkout.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { InstanceOptions, IOContext, RequestConfig } from '@vtex/api'
import { JanusClient } from '@vtex/api'
import type { OrderForm as CheckoutOrderForm } from 'vtex.checkout-graphql'

import { statusToError } from '../utils'

export class Checkout extends JanusClient {
  constructor(ctx: IOContext, options?: InstanceOptions) {
    super(ctx, {
      ...options,
      headers: {
        ...options?.headers,
        ...(ctx.storeUserAuthToken
          ? { VtexIdclientAutCookie: ctx.storeUserAuthToken }
          : null),
      },
    })
  }

  public getOrderForm = (orderFormId: string) => {
    return this.get<CheckoutOrderForm>(this.routes.getOrderForm(orderFormId), {
      metric: 'checkout-orderForm',
    })
  }

  public addItems = (
    orderFormId: string,
    items: CheckoutOrderForm['items'],
    salesChannel: string
  ) =>
    this.post<CheckoutOrderForm, { orderItems: CheckoutOrderForm['items'] }>(
      this.routes.addItems(orderFormId, salesChannel),
      {
        orderItems: items,
      },
      { metric: 'checkout-AddItem' }
    )

  protected get = <T>(url: string, config: RequestConfig = {}) => {
    try {
      return this.http.get<T>(url, config)
    } catch (e) {
      return (statusToError(e) as unknown) as CheckoutOrderForm
    }
  }

  protected post = async <T, D>(
    url: string,
    data?: D,
    config: RequestConfig = {}
  ) => {
    config.headers = {
      ...config.headers,
    }
    try {
      return this.http.post<T>(url, data, config)
    } catch (e) {
      return (statusToError(e) as unknown) as CheckoutOrderForm
    }
  }

  private get routes() {
    const base = '/api/checkout/pub'

    return {
      addItems: (orderFormId: string, salesChannel: string) =>
        `${base}/orderForm/${orderFormId}/items?sc=${salesChannel}`,
      getOrderForm: (orderFormId: string) => `${base}/orderForm/${orderFormId}`,
    }
  }
}

```


[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 binding-selector/node/clients/index.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { IOClients } from '@vtex/api'

import { Checkout } from './checkout'

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

```


[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 binding-selector/node/constants/index.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const CLOUDFRONT_VIEWER_COUNTRY = 'cloudfront-viewer-country'
export const VTEX_IO_VIEWER_COUNTRY = 'vtex-io-viewer-country'

```


[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 binding-selector/node/middlewares/viewerCountry.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { CLOUDFRONT_VIEWER_COUNTRY, VTEX_IO_VIEWER_COUNTRY } from '../constants'

export async function viewerCountry(ctx: Context) {
  const {
    request: { header },
  } = ctx

  const countryCode =
    header[CLOUDFRONT_VIEWER_COUNTRY] || header[VTEX_IO_VIEWER_COUNTRY] || null

  ctx.body = countryCode
}

```


[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 binding-selector/node/resolvers/Bindings.d.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface TranslatedInfo {
  id: string
  label: string
  canonicalBaseAddress: string
  defaultLocale: string
  hide: boolean
}

interface TranslatedBinding {
  bindingId: string
  show: boolean
  translatedLocales: [TranslatedInfo]
}

interface GetResponse {
  data: [TranslatedBinding]
}

interface GetSalesChannel {
  salesChannel: boolean
}

```


[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 binding-selector/node/resolvers/bindingInfo.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const bindingInfo = async (_: unknown, __: unknown, ctx: Context) => {
  const { clients } = ctx

  const { vbase } = clients

  try {
    const savedTranslations: GetResponse = await vbase.getJSON(
      'account.binding',
      'configs'
    )

    return savedTranslations.data
  } catch (e) {
    const { status } = e.response

    if (status === 404) {
      return []
    }

    throw e
  }
}

```


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

[User] Show me the implementation of binding-selector/node/resolvers/orderForm.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { OrderForm as CheckoutOrderForm } from 'vtex.checkout-graphql'

export const updateSalesChannel = async (
  _: unknown,
  args: {
    orderFormId: string
    salesChannel: string
    locale: string
  },
  ctx: Context
): Promise<CheckoutOrderForm> => {
  const { clients } = ctx
  const { orderFormId, salesChannel } = args
  const { checkout } = clients
  const orderForm = await checkout.getOrderForm(orderFormId)

  if (!orderForm.items.length) {
    return orderForm
  }

  return checkout.addItems(orderFormId, orderForm.items, salesChannel)
}

```


[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 binding-selector/node/resolvers/toggleSalesChannel.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const toggleSalesChannel = async (
  _: unknown,
  args: {
    salesChannel: boolean
  },
  ctx: Context
) => {
  const { clients } = ctx
  const { salesChannel } = args
  const { vbase } = clients

  await vbase.saveJSON('account.salesChannel', 'configs', {
    salesChannel,
  })

  return salesChannel
}

```


[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 binding-selector/node/resolvers/saveBindingInfo.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const saveBindingInfo = async (
  _: unknown,
  args: {
    data: [TranslatedBinding]
  },
  ctx: Context
) => {
  const { clients } = ctx
  const { data } = args
  const { vbase } = clients

  await vbase.saveJSON('account.binding', 'configs', {
    data,
  })

  return data
}

```


[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 binding-selector/node/resolvers/isSalesChannelUpdate.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const isSalesChannelUpdate = async (
  _: unknown,
  __: unknown,
  ctx: Context
) => {
  const { clients } = ctx
  const { vbase } = clients

  try {
    const salesChannelData: GetSalesChannel = await vbase.getJSON(
      'account.salesChannel',
      'configs'
    )

    return salesChannelData.salesChannel
  } catch (e) {
    const { status } = e.response

    if (status === 404) {
      return null
    }

    throw e
  }
}

```


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

[User] Show me the implementation of binding-selector/node/resolvers/index.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { bindingInfo } from './bindingInfo'
import { saveBindingInfo } from './saveBindingInfo'
import { updateSalesChannel } from './orderForm'
import { toggleSalesChannel } from './toggleSalesChannel'
import { isSalesChannelUpdate } from './isSalesChannelUpdate'

export const mutations = {
  updateSalesChannel,
  saveBindingInfo,
  toggleSalesChannel,
}

export const queries = {
  bindingInfo,
  isSalesChannelUpdate,
}

```


[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 binding-selector/react/typings/bindings.d.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Binding {
  id: string
  defaultLocale: string
  canonicalBaseAddress: string
  extraContext: {
    portal: {
      salesChannel: string
    }
  }
}

interface SalesChannelResponse {
  isSalesChannelUpdate: boolean
}

interface TenantInfoResponse {
  tenantInfo: {
    bindings: Binding[]
  }
}

interface BindingInfoResponse {
  bindingInfo: BindingsSaved[]
}

interface BindingTranslation {
  id: string
  label: string
  salesChannel: string
  defaultLocale: string
  canonicalBaseAddress: string
  hide: boolean
}

interface DataLocaleTypes {
  [key: string]: string
}

interface BindingsSaved {
  bindingId: string
  show: boolean
  translatedLocales: BindingTranslation[]
  externalRedirectData: ExternalRedirectData | null
  customFlagData: CustomFlagData | null
}

interface UpdateSalesChannelVariables {
  salesChannel: string
  orderFormId: string
}

interface AlternateHrefsVariables {
  id: string
  type: string
}

interface BindingsByBindingId {
  [bindingId: string]: TranslationsAndSettings[]
}

interface ExternalRedirectData {
  url: string
  redirectUrl: boolean
}

interface CustomFlagData {
  url: string
  isCustom: boolean
}

interface TranslationsAndSettings extends BindingTranslation {
  externalRedirectData: ExternalRedirectData | null
  customFlagData: CustomFlagData | null
}

interface ShowBindings {
  [key: string]: boolean
}

type FlagDisplay = 'text' | 'flag' | 'combined'

type SettingType = 'externalRedirectData' | 'customFlagData'

```


[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 binding-selector/react/typings/rewriter.d.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface QueryInternal {
  internal: {
    routes: [RoutesByBinding]
  }
}

interface RoutesByBinding {
  binding: string
  route: string
}

```


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

[User] Show me the implementation of binding-selector/react/typings/window.d.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface Window extends Window {
  __RUNTIME__: {
    segmentToken: string
  }
}

```


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

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

[Assistant]
Here's the implementation:

```typescript
declare module '*.gql' {
  import type { DocumentNode } from 'graphql'

  const value: DocumentNode
  export default value
}

```


[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 binding-selector/react/utils/index.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
/**
 * filterBingings function filters out the bindings that should not be displayed based on admin setting.
 * It returns an array with objects that have the binding Id's as keys and an array with the translations for that binding as values.
 */

const filterBindings = ({
  bindingInfo = [],
}: BindingInfoResponse): BindingsByBindingId[] => {
  const bindingsById = []

  const bindnigsToShow: Record<string, boolean> = {}

  const bindingExternalRedirect: Record<
    string,
    ExternalRedirectData | null
  > = {}

  const bindingCustomFlag: Record<string, CustomFlagData | null> = {}

  for (const binding of bindingInfo) {
    if (binding.show) {
      bindnigsToShow[binding.bindingId] = true
      bindingExternalRedirect[binding.bindingId] = binding.externalRedirectData
      bindingCustomFlag[binding.bindingId] = binding.customFlagData
    }
  }

  for (const binding of bindingInfo) {
    if (binding.show) {
      const bindingIdAndLabels = {
        [binding.bindingId]: binding.translatedLocales
          // filter out translations for bindings set to not show
          .filter(({ id }) => bindnigsToShow[id])
          // map over the left ones to add externalRedirect info
          .map((translation) => {
            const externalRedirectData = bindingExternalRedirect[translation.id]
            const customFlagData = bindingCustomFlag[translation.id]

            return {
              ...translation,
              externalRedirectData,
              customFlagData,
            }
          }),
      }

      bindingsById.push(bindingIdAndLabels)
    }
  }

  return bindingsById
}

/**
 * Based on a binding Id, this function returns the information for all bindings for the binding Id passed in, with the translated labels as its value
 */
const findBinding = ({
  filteredBindings,
  selectedBindingId,
}: {
  filteredBindings: BindingsByBindingId[]
  selectedBindingId: string
}) => {
  return filteredBindings.find(
    (binding) => Object.keys(binding)[0] === selectedBindingId
  )
}

/**
 * This function gets the translation for the current binding, returning the selected one and all information for the other binidngs
 */

const filterCurrentAndListBinding = ({
  bindingsById,
  selectedBindingId,
}: {
  bindingsById: BindingsByBindingId
  selectedBindingId: string
}) => {
  const currentList = bindingsById[selectedBindingId]
  const currentBinding = currentList.find(({ id }) => id === selectedBindingId)

  return { currentList, currentBinding }
}

export const getCurrentBindingAndList = ({
  bindingData,
  selectedBindingId,
}: {
  bindingData: BindingInfoResponse
  selectedBindingId: string
}) => {
  const filteredBindings = filterBindings(bindingData)
  const bindindFound = findBinding({
    filteredBindings,
    selectedBindingId,
  })

  if (bindindFound) {
    return filterCurrentAndListBinding({
      bindingsById: bindindFound,
      selectedBindingId,
    })
  }
}

export const removeBindingAdmin = (bindings: Binding[] = []): Binding[] => {
  return bindings.filter(
    (binding) => binding.canonicalBaseAddress.split('/')[1] !== 'admin'
  )
}

interface CreateQueryStringArgs {
  isMyVtex: boolean
  canonicalBaseAddress: string
  keepSalesChannel: boolean
  salesChannel?: string
}

const createQueryString = ({
  isMyVtex,
  canonicalBaseAddress,
  keepSalesChannel,
  salesChannel,
}: CreateQueryStringArgs): string => {
  const bindingAddressQueryString = `__bindingAddress=${canonicalBaseAddress}`

  // Add `sc` search string will force the session to be that salesChannel
  const salesChannelQueryString = keepSalesChannel ? `sc=${salesChannel}` : ''

  if (isMyVtex) {
    return keepSalesChannel
      ? `?${bindingAddressQueryString}&${salesChannelQueryString}`
      : `?${bindingAddressQueryString}`
  }

  return keepSalesChannel ? `?${salesChannelQueryString}` : ''
}

interface RedirectUrlArgs {
  canonicalBaseAddress: string
  hostname: Window['location']['hostname']
  protocol: Window['location']['protocol']
  path: string
  hash: string
  pageType: string
  keepSalesChannel?: boolean
  salesChannel?: string
}

export const isMyAccount = (pageType: string): boolean =>
  pageType === 'store.account'

export const createRedirectUrl = ({
  canonicalBaseAddress,
  hostname,
  protocol,
  path,
  hash,
  pageType,
  keepSalesChannel = false,
  salesChannel,
}: RedirectUrlArgs): string => {
  const isMyVtex = hostname.indexOf('myvtex') !== -1

  const myAccount = isMyAccount(pageType)

  const queryString = createQueryString({
    keepSalesChannel,
    salesChannel,
    canonicalBaseAddress,
    isMyVtex,
  })

  return `${protocol}//${
    isMyVtex ? hostname : canonicalBaseAddress.replace(/\/$/, '')
  }${!myAccount ? path : '/account'}${queryString}${hash}`
}

interface MatchRoute {
  currentBindingId: string
  routes: [RoutesByBinding] | []
}

export const getMatchRoute = ({
  currentBindingId,
  routes,
}: MatchRoute): string => {
  const { route } =
    routes.find(
      ({ binding }: { binding: string }) => binding === currentBindingId
    ) ?? {}

  return route ?? ''
}

export const transformUserRouteId = (id: string): string => {
  return id.replace('custom#', 'custom::')
}

export const setShowValues = (bindingList: BindingsSaved[]): ShowBindings => {
  return bindingList.reduce((acc, cur) => {
    return {
      ...acc,
      [cur.bindingId]: cur.show,
    }
  }, {})
}

export const hasAllTranslations = ({
  bindingsToShow,
  translatedBindings,
}: {
  bindingsToShow: string[]
  translatedBindings: BindingTranslation[]
}): boolean => {
  const labelMap = new Map<string, string>()
  const hideLabelMap = new Map<string, boolean>()

  for (const { id, label, hide } of translatedBindings) {
    labelMap.set(id, label)
    hideLabelMap.set(id, hide)
  }

  for (const bindingId of bindingsToShow) {
    if (
      !labelMap.has(bindingId) ||
      (!hideLabelMap.get(bindingId) && !labelMap.get(bindingId))
    ) {
      return false
    }
  }

  return true
}

export const createBindingsToLabel = (
  bindings: Binding[],
  currentTranslations: BindingTranslation[]
): Record<string, BindingTranslation> => {
  const translationsMap: Record<string, Partial<BindingTranslation>> = {}

  for (const translation of currentTranslations) {
    translationsMap[translation.id] = {
      id: translation.id,
      label: translation.label,
      hide: !!translation.hide,
    }
  }

  return bindings.reduce((map, binding) => {
    const staticInfo = {
      canonicalBaseAddress: binding.canonicalBaseAddress,
      salesChannel: String(binding.extraContext.portal.salesChannel),
      defaultLocale: binding.defaultLocale,
    }

    if (translationsMap[binding.id]) {
      return {
        ...map,
        [binding.id]: {
          ...translationsMap[binding.id],
          ...staticInfo,
        },
      }
    }

    return {
      ...map,
      [binding.id]: {
        id: binding.id,
        label: '',
        hide: false,
        ...staticInfo,
      },
    }
  }, {})
}

```


[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 binding-selector/react/components/BindingSelectorDropdown.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useRef, useEffect } from 'react'
import type { FC } from 'react'
import { useCssHandles } from 'vtex.css-handles'

import Spinner from './Spinner'
import LabelOption from './LabelsFlags'

interface Props {
  currentBinding: TranslationsAndSettings
  bindingInfo: TranslationsAndSettings[]
  onSelectBinding: (selectedBinding: TranslationsAndSettings) => void
  isLoading: boolean
  display: FlagDisplay
}

const CSS_HANDLES = [
  'list',
  'listElement',
  'container',
  'active',
  'relativeContainer',
  'button',
  'buttonText',
] as const

const BindingSelectorDropdown: FC<Props> = ({
  currentBinding,
  bindingInfo,
  onSelectBinding,
  isLoading,
  display,
}) => {
  const [open, setOpen] = useState<boolean>(false)
  const handles = useCssHandles(CSS_HANDLES)
  const relativeContainer = useRef<HTMLDivElement | null>(null)

  const handleOutsideClick = (e: MouseEvent) => {
    if (!relativeContainer.current?.contains(e.target as Node)) {
      setOpen(false)
    }
  }

  useEffect(() => {
    document.addEventListener('mousedown', handleOutsideClick)

    return () => {
      document.removeEventListener('mousedown', handleOutsideClick)
    }
  }, [])

  const handleClick = () => {
    setOpen(!open)
  }

  const handleSelection = (binding: TranslationsAndSettings) => {
    setOpen(false)
    onSelectBinding(binding)
  }

  return (
    <div
      className={`${handles.container} ${
        open ? handles.active : ''
      } flex items-center justify-center w3 relative`}
    >
      <div
        ref={relativeContainer}
        className={`${handles.relativeContainer} relative flex justify-center`}
      >
        {isLoading ? (
          <Spinner />
        ) : (
          <>
            <button
              type="button"
              onClick={handleClick}
              className={`${handles.button} link pa3 bg-transparent bn flex items-center pointer c-on-base`}
            >
              <span className={`${handles.buttonText}`}>
                <LabelOption
                  binding={currentBinding}
                  display={display}
                  flag={currentBinding.customFlagData}
                />
              </span>
            </button>
            <ul
              hidden={!open}
              className={`absolute z-9999 list top-1 ph0 mh0 mt5 bg-base ${handles.list}`}
            >
              {bindingInfo
                .filter((binding) => {
                  return binding.id !== currentBinding.id && !binding.hide
                })
                .map((binding) => (
                  // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
                  <li
                    key={binding.id}
                    className={`${handles.listElement} t-action--small pointer f5 pa3 hover-bg-muted-5 tc`}
                    onClick={() => {
                      handleSelection(binding)
                    }}
                    onKeyDown={() => {
                      handleSelection(binding)
                    }}
                    onMouseDown={(e) => e.preventDefault()}
                  >
                    <LabelOption
                      binding={binding}
                      display={display}
                      flag={binding.customFlagData}
                    />
                  </li>
                ))}
            </ul>
          </>
        )}
      </div>
    </div>
  )
}

export default BindingSelectorDropdown

```


[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 binding-selector/react/components/BindingSelectorSelect.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect } from 'react'
import { EXPERIMENTAL_Select as Select } from 'vtex.styleguide'

interface Props {
  bindingList: TranslationsAndSettings[]
  currentBinding: TranslationsAndSettings
  onSelectBinding: (selectedBinding: TranslationsAndSettings) => void
  isLoading: boolean
}

const BindingSelectorSelect = ({
  bindingList,
  currentBinding,
  onSelectBinding,
  isLoading,
}: Props) => {
  const [currentBindingId, setCurrentBindingId] = useState(currentBinding.id)

  useEffect(() => {
    setCurrentBindingId(currentBinding.id)
  }, [currentBinding.id])

  /* memoize it */
  const bindings = bindingList.map((binding) => {
    return { label: binding.label, value: binding.id }
  })

  /* Value of the select.
  value: PropTypes.oneOfType([OptionShape, OptionsShape]) */
  const selectedBinding = bindings.find(({ value }) => {
    return value === currentBindingId
  })

  const handleChange = (selectedBindingId: string) => {
    setCurrentBindingId(selectedBindingId)
    onSelectBinding(
      bindingList[bindingList.findIndex(({ id }) => id === selectedBindingId)]
    )
  }

  return (
    <Select
      size="small"
      options={bindings}
      value={[selectedBinding]}
      loading={isLoading}
      multi={false}
      clearable={false}
      searchable={false}
      onChange={(e: any) => {
        handleChange(e.value)
      }}
    />
  )
}

export default BindingSelectorSelect

```


[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 binding-selector/react/components/BindingSelectorList.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState } from 'react'
import type { FC } from 'react'
import { Button, ButtonGroup } from 'vtex.styleguide'
import { useCssHandles } from 'vtex.css-handles'

import LabelOption from './LabelsFlags'

const CSS_HANDLES = ['listContainer'] as const

interface Props {
  bindingList: TranslationsAndSettings[]
  onSelectBinding: (selectedBinding: TranslationsAndSettings) => void
  currentBinding: TranslationsAndSettings
  display: FlagDisplay
  isLoading: boolean
}

const BindingSelectorList: FC<Props> = ({
  bindingList,
  onSelectBinding,
  currentBinding,
  display,
  isLoading,
}) => {
  const [loading, setLoading] = useState(false)
  const handles = useCssHandles(CSS_HANDLES)

  const mappedBindings = bindingList
    .filter((binding) => {
      return !binding.hide
    })
    .map((binding) => {
      const flag = binding.customFlagData

      return (
        <Button
          key={binding.id}
          disabled={binding.id === currentBinding.id}
          isLoading={(loading && binding.id === currentBinding.id) || isLoading}
          onClick={() => {
            onSelectBinding(binding)
            setLoading(true)
          }}
        >
          <LabelOption binding={binding} display={display} flag={flag} />
        </Button>
      )
    })

  return (
    <div className={`${handles.listContainer}`}>
      <ButtonGroup buttons={mappedBindings} />
    </div>
  )
}

export default BindingSelectorList

```


[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 binding-selector/react/components/LabelsFlags.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { CountryFlag } from 'vtex.country-flags'

interface Props {
  binding: TranslationsAndSettings
  display: FlagDisplay
  flag: CustomFlagData | null
}

const LabelOption = ({ binding, display, flag }: Props) => {
  const locale = binding.defaultLocale.substring(3, 5).toUpperCase()

  const flagToDisplay = () =>
    flag?.isCustom && flag.url ? (
      <img
        src={flag.url}
        alt="A flag of the binding's locale"
        width="24"
        height="24"
        style={{ maxWidth: 24, maxHeight: 24 }}
      />
    ) : (
      <CountryFlag iso2={locale} />
    )

  if (display === 'flag') {
    return flagToDisplay()
  }

  if (display === 'combined') {
    return (
      <>
        {flagToDisplay()}
        <span className="ml3">{binding.label}</span>
      </>
    )
  }

  return <span>{binding.label}</span>
}

export default LabelOption

```


[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 binding-selector/react/components/Spinner.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { useCssHandles } from 'vtex.css-handles'
import { Spinner as VtexSpinner } from 'vtex.styleguide'

const CSS_HANDLES = ['loadingContainer'] as const

const Spinner = () => {
  const handles = useCssHandles(CSS_HANDLES)

  return (
    <div className={handles.loadingContainer}>
      <VtexSpinner color="currentColor" size={26} />
    </div>
  )
}

export default Spinner

```


[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 binding-selector/react/graphql/saveBindingInfo.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
#import './bindingInfoFragment.gql'

mutation saveBindingInfo($data: [BindingsInput]) {
  saveBindingInfo(data: $data) {
    ...BindingInfoFragment
  }
}

```


[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 binding-selector/react/graphql/toggleSalesChannel.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation toggleSalesChannel($salesChannel: Boolean) {
  toggleSalesChannel(salesChannel: $salesChannel)
}

```


[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 binding-selector/react/graphql/bindingInfo.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
#import './bindingInfoFragment.gql'

query bindingInfo {
  bindingInfo @context(provider: "vtex.binding-selector") {
    ...BindingInfoFragment
  }
}

```


[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 binding-selector/react/graphql/getOrderForm.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
query getOrderForm {
  orderForm @context(provider: "vtex.store-graphql") {
    salesChannel
    orderFormId
    items {
      id
    }
  }
}

```


[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 binding-selector/react/graphql/uploadFile.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UploadFile($file: Upload!) {
  uploadFile(file: $file) {
    fileUrl
  }
}

```


[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 binding-selector/react/graphql/updateSalesChannel.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation updateSalesChannel($orderFormId: ID, $salesChannel: String) {
  updateSalesChannel(orderFormId: $orderFormId, salesChannel: $salesChannel)
    @context(provider: "vtex.binding-selector") {
    orderFormId
    items {
      quantity
      uniqueId
    }
  }
}

```


[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 binding-selector/react/graphql/isSalesChannelUpdate.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
query isSalesChannelUpdate {
  isSalesChannelUpdate
}

```


[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 binding-selector/react/graphql/bindingInfoFragment.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
fragment BindingInfoFragment on TranslatedInfoOutput {
  bindingId
  show
  translatedLocales {
    id
    label
    defaultLocale
    canonicalBaseAddress
    salesChannel
    hide
  }
  externalRedirectData {
    url
    redirectUrl
  }
  customFlagData {
    isCustom
    url
  }
}

```


[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 binding-selector/react/graphql/getSalesChannel.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
query getSalesChannel {
  tenantInfo @context(provider: "vtex.tenant-graphql") {
    bindings {
      id
      defaultLocale
      extraContext
      canonicalBaseAddress
    }
  }
}

```


[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 binding-selector/react/graphql/alternateHrefs.gql from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```graphql
query alternateHrefs($id: String!, $type: String!) {
  internal @context(provider: "vtex.rewriter") {
    routes(locator: { id: $id, type: $type }) {
      binding
      route
    }
  }
}

```


[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 binding-selector/react/hooks/useBindings.ts from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useCallback, useEffect, useState } from 'react'
import { useRuntime } from 'vtex.render-runtime'
import { useQuery } from 'react-apollo'

import getBindingInfo from '../graphql/bindingInfo.gql'
import { getCurrentBindingAndList } from '../utils'

export const useBinding = () => {
  const [bindingList, setBindingList] = useState<TranslationsAndSettings[]>([])

  const [currentBinding, setCurrentBinding] = useState<TranslationsAndSettings>(
    {} as TranslationsAndSettings
  )

  const {
    data: bindingData,
    loading: loadingBindings,
    error: bindingsError,
  } = useQuery<BindingInfoResponse>(getBindingInfo, {
    ssr: false,
  })

  const { binding: runtimeBinding } = useRuntime()

  const setCurrentBindingInfo = useCallback(
    (selectedBindingId: string): void => {
      if (bindingData) {
        const bindingInfo = getCurrentBindingAndList({
          bindingData,
          selectedBindingId,
        })

        if (bindingInfo) {
          setBindingList(bindingInfo.currentList)
          setCurrentBinding(
            bindingInfo.currentBinding ?? ({} as TranslationsAndSettings)
          )
        }
      }
    },
    [bindingData]
  )

  /**
   * This effects uses sets the current binding user is on
   */
  useEffect(() => {
    if (bindingData && runtimeBinding?.id) {
      setCurrentBindingInfo(runtimeBinding.id)
    }
  }, [bindingData, runtimeBinding, setCurrentBindingInfo])

  return {
    data: {
      currentBinding,
      bindingList,
      bindingsError,
      loadingBindings,
    },
    actions: {
      setCurrentBindingInfo,
    },
  }
}

```


[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 binding-selector/react/components/admin/AdminBindingSection.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect } from 'react'
import type { FC, SyntheticEvent, FormEvent } from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
import {
  Toggle,
  Button,
  Divider,
  Collapsible,
  Input,
  Tooltip,
  IconExternalLink,
} from 'vtex.styleguide'
import { CountryFlag } from 'vtex.country-flags'

import CustomFlagSetting from './CustomFlagSetting'

export interface BindingSectionProps {
  modalControl: (modalOpen: boolean) => void
  modalOpen: boolean
  setChosenBinding: (binding: Binding) => void
  setShowBindings: (id: string) => void
  setAdvancedSettings: (
    bindingId: string,
    type: SettingType,
    extraData: ExternalRedirectData | CustomFlagData
  ) => Promise<void>
}

interface BindingSectionPropsLocal extends BindingSectionProps {
  i: number
  binding: Binding
  configSettings: BindingsSaved
  hasAllabels: boolean
}

const AdminBindingSection: FC<BindingSectionPropsLocal> = ({
  binding,
  modalControl,
  modalOpen,
  setChosenBinding,
  setShowBindings,
  setAdvancedSettings,
  configSettings,
  hasAllabels,
  i,
}) => {
  const [showAdvConfig, setShowAdvConfig] = useState(false)
  const [showRedirectUrl, setShowRedirectUrl] = useState(false)
  const [urlToRedirect, setUrlToRedirect] = useState('')
  const [edit, setEdit] = useState(false)
  const intl = useIntl()

  const flag = configSettings.customFlagData

  useEffect(() => {
    const { externalRedirectData } = configSettings

    if (externalRedirectData) {
      const { redirectUrl, url } = externalRedirectData

      if (redirectUrl) {
        setShowRedirectUrl(redirectUrl)
        setUrlToRedirect(url)
        setEdit(true)

        return
      }
    }

    setShowRedirectUrl(false)
    setUrlToRedirect('')
  }, [configSettings, showAdvConfig])

  const handleShowRedirectToggle = () => {
    setShowRedirectUrl(!showRedirectUrl)
    if (showRedirectUrl) {
      setAdvancedSettings(binding.id, 'externalRedirectData', {
        url: '',
        redirectUrl: false,
      })
    } else {
      setEdit(false)
    }
  }

  const handleChangeRedirectUrl = (event: SyntheticEvent) => {
    setUrlToRedirect((event.currentTarget as HTMLInputElement).value)
  }

  const handleFlagToggle = (active: boolean) => {
    /* We should always try to keep the original url */
    setAdvancedSettings(binding.id, 'customFlagData', {
      ...(flag?.url ? { url: flag.url } : { url: '' }),
      isCustom: active,
    })
  }

  const handleSubmitRedirect = (e: FormEvent) => {
    e.preventDefault()
    setAdvancedSettings(binding.id, 'externalRedirectData', {
      url: urlToRedirect,
      redirectUrl: showRedirectUrl,
    })
  }

  const handleSubmitFlag = async (inmutableUrl: string) => {
    await setAdvancedSettings(binding.id, 'customFlagData', {
      url: inmutableUrl,
      isCustom: true,
    })
  }

  const handleEditMode = (e: MouseEvent) => {
    e.preventDefault()
    setEdit(!edit)
  }

  return (
    <>
      <div className="mt6">
        <Divider orientation="horizontal" />
      </div>
      <section
        key={binding.id}
        className="flex items-center justify-between mb3"
      >
        <div className="flex items-center flex-basis-50">
          <span className="mr4">
            <Button disabled size="small">
              {flag?.isCustom && flag?.url ? (
                <img
                  src={flag.url}
                  alt="A flag of the binding's locale"
                  width="24"
                  height="24"
                  style={{ maxWidth: 24, maxHeight: 24 }}
                />
              ) : (
                <CountryFlag
                  iso2={binding.defaultLocale.substring(3, 5).toUpperCase()}
                />
              )}
            </Button>
          </span>
          <div className="flex flex-column mv5 flex-grow-1 flex-basis-33">
            <span className="b">
              <FormattedMessage
                id="admin/store"
                values={{
                  index: i + 1,
                  address: binding.canonicalBaseAddress,
                }}
              />
            </span>
            <span>
              <FormattedMessage
                id="admin/locale"
                values={{ locale: binding.defaultLocale }}
              />
            </span>
          </div>
        </div>

        <div className="flex items-center flex-basis-50 justify-end">
          {showRedirectUrl && (
            <div>
              <Tooltip
                label={
                  <FormattedMessage id="admin/redirect-url.tooltip-label" />
                }
              >
                <span className="c-on-base pointer">
                  <IconExternalLink />
                </span>
              </Tooltip>
            </div>
          )}

          <div className="flex-basis-50 tc">
            <Button
              disabled={!configSettings.show}
              onClick={() => {
                modalControl(!modalOpen)
                setChosenBinding(binding)
              }}
              size="small"
              variation="secondary"
            >
              <FormattedMessage id="admin/action" />
            </Button>
            {configSettings.show && !hasAllabels ? (
              <p className="absolute c-danger i-s">
                <FormattedMessage id="admin/missing-labels" />
              </p>
            ) : null}
          </div>

          <div className="flex flex-basis-25 justify-end">
            <Toggle
              checked={configSettings.show}
              semantic
              label={
                configSettings.show ? (
                  <FormattedMessage id="admin/hide-binding" />
                ) : (
                  <FormattedMessage id="admin/show-binding" />
                )
              }
              onChange={() => {
                setShowBindings(binding.id)
                if (!configSettings.show) {
                  setChosenBinding(binding)
                } else {
                  setChosenBinding({} as Binding)
                }
              }}
            />
          </div>
        </div>
      </section>
      <Collapsible
        header={
          <span className="c-action-primary hover-c-action-primary fw5">
            <FormattedMessage id="admin/advanced-settings" />
          </span>
        }
        isOpen={showAdvConfig}
        onClick={() => setShowAdvConfig(!showAdvConfig)}
      >
        <div className="mt7">
          <Toggle
            checked={showRedirectUrl}
            label={<FormattedMessage id="admin/set-external-url" />}
            onChange={handleShowRedirectToggle}
          />
          <form onSubmit={handleSubmitRedirect} className="mt4 flex">
            <div className="width-70">
              <Input
                value={urlToRedirect}
                disabled={!showRedirectUrl || edit}
                placeholder={intl.formatMessage({
                  id: 'admin/external-url-placeholder',
                })}
                onChange={handleChangeRedirectUrl}
                pattern="^https?:\/\/.+"
                helpText={<FormattedMessage id="admin/external-url-helper-text" />}
              />
            </div>
            <div className="ml5">
              {edit ? (
                <Button
                  type="button"
                  variation="secondary"
                  disabled={!urlToRedirect}
                  onClick={handleEditMode}
                >
                  <FormattedMessage id="admin/edit-url" />
                </Button>
              ) : (
                <Button type="submit" disabled={!urlToRedirect}>
                  <FormattedMessage id="admin/save-url" />
                </Button>
              )}
            </div>
          </form>
        </div>
        <div className="mt7">
          <CustomFlagSetting
            customFlag={Boolean(flag?.isCustom)}
            handleFlagToggle={handleFlagToggle}
            handleSubmitFlag={handleSubmitFlag}
          />
        </div>
      </Collapsible>
    </>
  )
}

export default AdminBindingSection

```


[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 binding-selector/react/components/admin/Selector.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { FC } from 'react'
import React, { useState, useEffect } from 'react'
import { useQuery, useMutation } from 'react-apollo'
import { FormattedMessage } from 'react-intl'
import { Toggle } from 'vtex.styleguide'

import Spinner from '../Spinner'
import FormDialog from './FormDialog'
import { removeBindingAdmin } from '../../utils'
import AdminBindingList from './AdminBindingList'
import bindingInfo from '../../graphql/bindingInfo.gql'
import saveBindingInfo from '../../graphql/saveBindingInfo.gql'
import getSalesChannel from '../../graphql/getSalesChannel.gql'
import toggleSalesChannel from '../../graphql/toggleSalesChannel.gql'
import isSalesChannelUpdate from '../../graphql/isSalesChannelUpdate.gql'

interface DataMutation {
  data: BindingsSaved[]
}

interface MutationResponse {
  saveBindingInfo: BindingsSaved[]
}

const Selector: FC = () => {
  const [updateSalesChannel, setUpdateSalesChannel] = useState<boolean>(false)
  const [modalOpen, setModalOpen] = useState<boolean>(false)
  const [chosenBinding, setChosenBinding] = useState<Binding>({} as Binding)
  const [fetchedData, setFetchedData] = useState<BindingsSaved[]>([])
  const { data: bindingData } = useQuery<TenantInfoResponse>(getSalesChannel, {
    ssr: false,
  })

  const [toggleSales] = useMutation<SalesChannelResponse>(toggleSalesChannel)

  const { data: translatedData, loading } = useQuery<BindingInfoResponse>(
    bindingInfo,
    {
      ssr: false,
    }
  )

  const [saveTranslatedInfo] = useMutation<MutationResponse, DataMutation>(
    saveBindingInfo
  )

  const { data: salesData } = useQuery<SalesChannelResponse>(
    isSalesChannelUpdate,
    {
      ssr: false,
    }
  )

  useEffect(() => {
    if (translatedData) {
      setFetchedData(translatedData?.bindingInfo ?? [])
    }
  }, [translatedData])

  useEffect(() => {
    if (salesData) {
      const salesChannelValue = salesData?.isSalesChannelUpdate ?? false

      setUpdateSalesChannel(salesChannelValue)
    }
  }, [salesData])

  const handleUpdateSalesChannel = () => {
    setUpdateSalesChannel(!updateSalesChannel)
    toggleSales({ variables: { salesChannel: !updateSalesChannel } })
  }

  const handleOnClose = () => setModalOpen(!modalOpen)

  const filteredBindings = removeBindingAdmin(bindingData?.tenantInfo.bindings)

  const handleShowBindings = async (bindingId: string) => {
    let bindingFound = false
    let currentToggleStatus = false
    const modifiedBindings = fetchedData.map((binding) => {
      if (binding.bindingId === bindingId) {
        bindingFound = true
        currentToggleStatus = binding.show
        const modifiedBinding = {
          ...binding,
          show: !binding.show,
        }

        return modifiedBinding
      }

      return binding
    })

    if (!currentToggleStatus) {
      setModalOpen(true)
    }

    const bindingsToSave = bindingFound
      ? modifiedBindings
      : [
          ...fetchedData,
          {
            bindingId,
            show: true,
            translatedLocales: [],
            externalRedirectData: null,
            customFlagData: null,
          },
        ]

    try {
      const savedData = await saveTranslatedInfo({
        variables: { data: bindingsToSave },
      })

      if (savedData.data) {
        setFetchedData(savedData.data.saveBindingInfo)
      }
    } catch (e) {
      console.error('error saving data', { e })
    }
  }

  const handleSetAdvancedSettings = async (
    bindingId: string,
    type: SettingType,
    extraData: ExternalRedirectData | CustomFlagData
  ): Promise<void> => {
    const transformedData = fetchedData.map((binding) => {
      if (binding.bindingId === bindingId) {
        return {
          ...binding,
          ...(extraData && { [type]: extraData }),
        }
      }

      return binding
    })

    await saveTranslatedInfo({ variables: { data: transformedData } })
    setFetchedData(transformedData)
  }

  const bindingsToShow = fetchedData
    .filter(({ show }) => show)
    .map(({ bindingId }) => bindingId)

  return (
    <div>
      <FormDialog
        open={modalOpen}
        handleOnClose={handleOnClose}
        chosenBinding={chosenBinding}
        bindings={filteredBindings ?? []}
        bindingInfoQueryData={fetchedData ?? []}
        setFetchedData={setFetchedData}
      />
      <Toggle
        checked={updateSalesChannel}
        label={<FormattedMessage id="admin/label" />}
        onChange={handleUpdateSalesChannel}
        helpText={<FormattedMessage id="admin/description" />}
      />
      {loading ? (
        <div className="w100 flex justify-center align-center pa7 ma7">
          <Spinner />
        </div>
      ) : (
        <AdminBindingList
          bindings={filteredBindings}
          modalControl={setModalOpen}
          modalOpen={modalOpen}
          setChosenBinding={setChosenBinding}
          setShowBindings={handleShowBindings}
          setAdvancedSettings={handleSetAdvancedSettings}
          configSettingsList={fetchedData}
          bindingsToShow={bindingsToShow}
        />
      )}
    </div>
  )
}

export default Selector

```


[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 binding-selector/react/components/admin/FormDialog.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { SyntheticEvent, FC } from 'react'
import React, { useState, useEffect } from 'react'
import { FormattedMessage } from 'react-intl'
import { Modal, Button } from 'vtex.styleguide'
import { useMutation } from 'react-apollo'

import saveBindingInfo from '../../graphql/saveBindingInfo.gql'
import {
  removeBindingAdmin,
  setShowValues,
  createBindingsToLabel,
} from '../../utils'
import AdminBindingLabelsList from './AdminBindingLabelsList'

interface FormDialogProps {
  open: boolean
  handleOnClose: () => void
  bindings: Binding[]
  chosenBinding: Binding
  bindingInfoQueryData: BindingsSaved[]
  setFetchedData: (binding: BindingsSaved[]) => void
}

interface DataMutation {
  data: BindingsSaved[]
}

const FormDialog: FC<FormDialogProps> = (props: FormDialogProps) => {
  const {
    open,
    handleOnClose,
    bindings,
    chosenBinding,
    bindingInfoQueryData,
    setFetchedData,
  } = props

  const [saveTranslatedInfo] = useMutation<BindingsSaved, DataMutation>(
    saveBindingInfo
  )

  const [translationsMap, setTranslationMap] = useState<
    Record<string, BindingTranslation>
  >({})

  const showBindings = setShowValues(bindingInfoQueryData)

  useEffect(() => {
    const bindingsToLabel = createBindingsToLabel(
      bindings,
      bindingInfoQueryData.find(
        (binding) => binding.bindingId === chosenBinding.id
      )?.translatedLocales ?? []
    )

    setTranslationMap(bindingsToLabel)
  }, [bindingInfoQueryData, bindings, chosenBinding.id])

  const handleChange = (event: SyntheticEvent) => {
    const { name, value } = event.target as HTMLInputElement

    setTranslationMap({
      ...translationsMap,
      [name]: {
        ...translationsMap[name],
        label: value,
      },
    })
  }

  const handleOnSave = () => {
    const transformedData = bindingInfoQueryData.map<BindingsSaved>(
      (binding) => {
        if (binding.bindingId === chosenBinding.id) {
          return {
            ...binding,
            translatedLocales: Object.values(translationsMap),
          }
        }

        return binding
      }
    )

    saveTranslatedInfo({ variables: { data: transformedData } })

    setFetchedData(transformedData)

    handleOnClose()
  }

  const bindingsToBeLabeled = removeBindingAdmin(bindings)

  const handleHideLabel = ({
    bindingId,
    status,
  }: {
    bindingId: string
    status: boolean
  }) => {
    setTranslationMap({
      ...translationsMap,
      [bindingId]: {
        ...translationsMap[bindingId],
        hide: status,
      },
    })
  }

  return (
    <Modal
      isOpen={open}
      title={<FormattedMessage id="admin/modal" />}
      onClose={handleOnClose}
      bottomBar={
        <div className="flex">
          <div className="pr4">
            <Button variation="tertiary" onClick={handleOnClose}>
              <FormattedMessage id="admin/cancel" />
            </Button>
          </div>
          <div>
            <Button onClick={handleOnSave}>
              <FormattedMessage id="admin/save" />
            </Button>
          </div>
        </div>
      }
    >
      <div className="pb6 pt3 flex w-100 flex-column justify-center items-center">
        <AdminBindingLabelsList
          bindings={bindingsToBeLabeled}
          activeBindings={showBindings}
          handleChange={handleChange}
          translationsMap={translationsMap}
          handleHideLabel={handleHideLabel}
        />
      </div>
    </Modal>
  )
}

export default FormDialog

```


[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 binding-selector/react/components/admin/AdminBindingLabelsList.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { SyntheticEvent } from 'react'
import React from 'react'

import FieldInput from './FieldInput'

const AdminBindingLabelsList = ({
  bindings = [],
  activeBindings,
  translationsMap,
  ...props
}: {
  bindings: Binding[]
  activeBindings: Record<string, boolean>
  translationsMap: Record<string, BindingTranslation>
  handleChange: (e: SyntheticEvent) => void
  handleHideLabel: ({
    bindingId,
    status,
  }: {
    bindingId: string
    status: boolean
  }) => void
}) => {
  return (
    <>
      {bindings.map((binding) => {
        return (
          <FieldInput
            key={binding.id}
            binding={binding}
            showValue={activeBindings[binding.id]}
            translationInfo={translationsMap[binding.id]}
            {...props}
          />
        )
      })}
    </>
  )
}

export default AdminBindingLabelsList

```


[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 binding-selector/react/components/admin/FieldInput.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { FC, SyntheticEvent } from 'react'
import React from 'react'
import { Input, Checkbox } from 'vtex.styleguide'
import { FormattedMessage } from 'react-intl'

interface FieldInputProps {
  binding: Binding
  handleChange: (e: SyntheticEvent) => void
  showValue: boolean
  translationInfo: BindingTranslation
  handleHideLabel: ({
    bindingId,
    status,
  }: {
    bindingId: string
    status: boolean
  }) => void
}

const FieldInput: FC<FieldInputProps> = (props: FieldInputProps) => {
  const {
    binding,
    handleChange,
    showValue,
    handleHideLabel,
    translationInfo,
  } = props

  return (
    <div className="flex items-center justify-center w-100">
      <div className="pa4 w-40">
        <label>
          {binding.canonicalBaseAddress} ({binding.defaultLocale})
        </label>
      </div>
      <div className="pa4 w-50 flex items-center">
        <Input
          disabled={!showValue || translationInfo.hide}
          required={showValue || !translationInfo.hide}
          name={binding.id}
          onChange={(e: SyntheticEvent) => handleChange(e)}
          value={translationInfo.label}
        />
        <div className="ml3 flex items-center">
          <Checkbox
            disabled={!showValue}
            id={`hide-label-${binding.id}`}
            checked={!!translationInfo.hide}
            onChange={() =>
              handleHideLabel({
                status: !translationInfo.hide,
                bindingId: binding.id,
              })
            }
          />
          <label htmlFor={`hide-label-${binding.id}`} className="ml3">
            <FormattedMessage id="admin/hide-label" />
          </label>
        </div>
      </div>
    </div>
  )
}

export default FieldInput

```


[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 binding-selector/react/components/admin/AdminBindingList.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import type { FC } from 'react'

import type { BindingSectionProps } from './AdminBindingSection'
import AdminBindingSection from './AdminBindingSection'
import { hasAllTranslations } from '../../utils'

interface BindingListProps extends BindingSectionProps {
  bindings: Binding[]
  configSettingsList: BindingsSaved[]
  bindingsToShow: string[]
}

const BindingList: FC<BindingListProps> = ({
  bindings,
  configSettingsList,
  bindingsToShow,
  ...props
}) => {
  return (
    <div>
      {bindings.map((binding, i) => {
        const configSettings =
          configSettingsList.find(
            ({ bindingId }) => bindingId === binding.id
          ) ?? ({} as BindingsSaved)

        const hasAllLabels = hasAllTranslations({
          bindingsToShow,
          translatedBindings: configSettings.translatedLocales ?? [],
        })

        return (
          <div key={binding.id}>
            <AdminBindingSection
              binding={binding}
              configSettings={configSettings}
              i={i}
              hasAllabels={hasAllLabels}
              {...props}
            />
          </div>
        )
      })}
    </div>
  )
}

export default BindingList

```


[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 binding-selector/react/components/admin/CustomFlagSetting.tsx from the binding-selector VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState } from 'react'
import type { FC } from 'react'
import { useMutation } from 'react-apollo'
import { FormattedMessage } from 'react-intl'
import {
  Toggle,
  ButtonWithIcon,
  IconEdit,
  Modal,
  Button,
  Dropzone,
  Alert,
} from 'vtex.styleguide'

import UPLOAD_MUTATION from '../../graphql/uploadFile.gql'

const edit = <IconEdit />

/* 512 KB */
const MAX_SIZE = 512000 as const

const RESET_ERROR = {
  error: false,
  size: 0,
  type: '',
}

interface IncomingFile {
  uploadFile: { fileUrl: string }
}

type Props = {
  customFlag: boolean
  handleFlagToggle: (active: boolean) => void
  handleSubmitFlag: (inmutableUrl: string) => Promise<void>
}

/**
 * Enables the advanced setting to upload a custom 'flag' as
 * an icon for the bindings.
 * @note Even when the user closes the modal when
 * uploading a file, it will still run on the background.
 * @param customFlag - controls weather the setting is
 * activated; a side effect of the display of the custom icon on
 * the binding summary
 * @param handleSubmitFlag - handler to update binding's settings
 */
const CustomFlagSetting: FC<Props> = ({
  customFlag = false,
  handleFlagToggle,
  handleSubmitFlag,
}) => {
  const [hasCustomFlag, toggleSetting] = useState(customFlag)
  const [isOpen, toggleModal] = useState(false)
  const [canUpload, setCanUpload] = useState(false)
  const [uploadingFile, setUploading] = useState(false)
  const [flag, prepareFile] = useState({})
  const [alert, handleAlert] = useState(RESET_ERROR)

  /**
   * Save file (returns file's immutable URL)
   * @see file-manager-graphql
   */
  const [saveFile] = useMutation<IncomingFile>(UPLOAD_MUTATION, {
    variables: { file: flag },
  })

  const handleToggle = () => {
    toggleSetting(!hasCustomFlag)
    handleFlagToggle(!hasCustomFlag)
  }

  const dropRejected = (file: File[]) => {
    setCanUpload(false)
    handleAlert({
      error: true,
      size: Math.floor(file[0].size / 1000),
      type: file[0].type,
    })
  }

  const dropAccepted = (file: File[]) => {
    setCanUpload(true)
    prepareFile(file[0])
  }
  /**
   * @todo: Add toast to display success or error for the user
   * Not only here, but for all other saving operations
   */

  const handleUpload = async () => {
    setUploading(true)

    try {
      const { data, errors } = await saveFile()

      if (errors) {
        throw new Error('Error saving custom flag')
      }

      const { fileUrl } = data?.uploadFile ?? {}

      if (fileUrl) {
        /* This will trigger a parent re-render */
        await handleSubmitFlag(fileUrl)
      }
    } catch (e) {
      console.error('Error saving data', { e })
    } finally {
      setUploading(false)
      toggleModal(false)
    }
  }

  return (
    <>
      <Toggle
        label={<FormattedMessage id="admin/custom-flag.toggle" />}
        checked={hasCustomFlag}
        onChange={() => handleToggle()}
        helpText={<FormattedMessage id="admin/custom-flag.helpText" />}
      />
      {hasCustomFlag && (
        <div className="mt4">
          <ButtonWithIcon
            onClick={() => toggleModal(!isOpen)}
            icon={edit}
            size="small"
          >
            {<FormattedMessage id="admin/custom-flag.cta" />}
          </ButtonWithIcon>
        </div>
      )}
      <Modal
        isOpen={isOpen}
        title={<FormattedMessage id="admin/custom-flag.modal-title" />}
        size="auto"
        onClose={() => {
          toggleModal(!isOpen)
        }}
        bottomBar={
          <Button onClick={() => handleUpload()} disabled={!canUpload}>
            <FormattedMessage id="admin/save" />
          </Button>
        }
      >
        <div className="mb4">
          {alert.error && (
            <div className="mb4">
              <Alert onClose={() => handleAlert(RESET_ERROR)} type="error">
                <FormattedMessage
                  id="admin/custom-flag.modal-error"
                  values={{
                    size: alert.size,
                    type: alert.type,
                  }}
                />
              </Alert>
            </div>
          )}
          <Dropzone
            accept="image/*"
            onDropRejected={dropRejected}
            onDropAccepted={dropAccepted}
            onFileReset={() => {
              setCanUpload(false)
            }}
            isLoading={uploadingFile}
            maxSize={MAX_SIZE}
          >
            <div className="pt7">
              <div id="modal-description">
                <span className="f4">
                  <FormattedMessage id="admin/custom-flag.modal-dropzone-title" />{' '}
                </span>
                <span className="f4 c-link" style={{ cursor: 'pointer' }}>
                  <FormattedMessage id="admin/custom-flag.modal-dropzone-cta" />
                </span>
                <p className="f6 c-muted-2 tc">
                  <FormattedMessage
                    id="admin/custom-flag.modal-dropzone-limit"
                    values={{
                      max_size: MAX_SIZE / 1000,
                    }}
                  />
                </p>
              </div>
            </div>
          </Dropzone>
        </div>
      </Modal>
    </>
  )
}

export default CustomFlagSetting

```


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

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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.newsletter-form.title": "Newsletter",
  "admin/editor.newsletter-input-email.title": "Campo de email",
  "admin/editor.newsletter-input-email.placeholderText.title": "Placeholder para campo de email",
  "admin/editor.newsletter-input-email.inputLabel.title": "Label para o campo de entrada de email",
  "admin/editor.newsletter-input-email.errorMessage.title": "Mensagem de erro",
  "admin/editor.newsletter-input-name.title": "Campo de nome",
  "admin/editor.newsletter-input-name.placeholderText.title": "Placeholder para campo de nome",
  "admin/editor.newsletter-input-name.inputLabel.title": "Label para o campo de entrada de nome",
  "admin/editor.newsletter-input-name.errorMessage.title": "Mensagem de erro",
  "admin/editor.newsletter-input-phone.title": "Campo de telefone",
  "admin/editor.newsletter-input-phone.placeholderText.title": "Placeholder para campo de telefone",
  "admin/editor.newsletter-input-phone.inputLabel.title": "Label para o campo de entrada de telefone",
  "admin/editor.newsletter-input-phone.errorMessage.title": "Mensagem de erro",
  "admin/editor.newsletter-checkbox-confirmation.title": "Confirmação",
  "admin/editor.newsletter-checkout-confirmation.checkboxLabel.title": "Label para a checkbox de confirmação",
  "admin/editor.newsletter-checkout-confirmation.firstLink.title": "Primeiro link a ser interpolado na label",
  "admin/editor.newsletter-checkout-confirmation.firstLink.url": "URL do primeiro link",
  "admin/editor.newsletter-checkout-confirmation.firstLink.text": "Texto do primeiro link",
  "admin/editor.newsletter-checkout-confirmation.secondLink.title": "Segundo link a ser interpolado na label",
  "admin/editor.newsletter-checkout-confirmation.secondLink.url": "URL do segundo link",
  "admin/editor.newsletter-checkout-confirmation.secondLink.text": "Texto do segundo link",
  "admin/editor.newsletter-submit.title": "Botão de submissão do formulário",
  "admin/editor.newsletter-submit.submitButtonLabel.title": "Texto do botão de submissão",
  "store/newsletter-input-email.placeholderText.default": "Endereço de email",
  "store/newsletter-input-email.errorMessage.default": "Email inválido",
  "store/newsletter-input-name.placeholderText.default": "Nome",
  "store/newsletter-input-name.errorMessage.default": "Nome inválido",
  "store/newsletter-input-phone.placeholderText.default": "Telefone",
  "store/newsletter-input-phone.errorMessage.default": "Telefone inválido",
  "store/newsletter-checkbox-confirmation.checkboxLabel.default": "Eu aceito receber essa newsletter.",
  "store/newsletter-submit.submitButtonLabel.default": "Inscrever-se",
  "store/newsletter-submit-success.default": "Obrigado!",
  "store/newsletter-submit-error.default": "Algo deu errado e não conseguimos efetuar seu cadastro."
}

```


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

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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.newsletter-form.title": "Newsletter",
  "admin/editor.newsletter-input-email.title": "Newsletter email input",
  "admin/editor.newsletter-input-email.placeholderText.title": "Email input placeholder",
  "admin/editor.newsletter-input-email.inputLabel.title": "Label for the email input",
  "admin/editor.newsletter-input-email.errorMessage.title": "\"Invalid email\" error message",
  "admin/editor.newsletter-input-name.title": "Newsletter name input",
  "admin/editor.newsletter-input-name.placeholderText.title": "Name input placeholder",
  "admin/editor.newsletter-input-name.inputLabel.title": "Label for the name input",
  "admin/editor.newsletter-input-name.errorMessage.title": "\"Invalid name\" error message",
  "admin/editor.newsletter-input-phone.title": "Newsletter phone input",
  "admin/editor.newsletter-input-phone.placeholderText.title": "Phone input placeholder",
  "admin/editor.newsletter-input-phone.inputLabel.title": "Label for the phone input",
  "admin/editor.newsletter-input-phone.errorMessage.title": "\"Invalid phone\" error message",
  "admin/editor.newsletter-checkbox-confirmation.title": "Newsletter confirmation",
  "admin/editor.newsletter-checkout-confirmation.checkboxLabel.title": "Label for the confirmation checkbox",
  "admin/editor.newsletter-checkout-confirmation.firstLink.title": "First link to be interpolated into the label",
  "admin/editor.newsletter-checkout-confirmation.firstLink.url": "First link url",
  "admin/editor.newsletter-checkout-confirmation.firstLink.text": "First link text",
  "admin/editor.newsletter-checkout-confirmation.secondLink.title": "Second link to be interpolated into the label",
  "admin/editor.newsletter-checkout-confirmation.secondLink.url": "Second link url",
  "admin/editor.newsletter-checkout-confirmation.secondLink.text": "Second link text",
  "admin/editor.newsletter-submit.title": "Newsletter form submit",
  "admin/editor.newsletter-submit.submitButtonLabel.title": "Label for the submit button",
  "store/newsletter-input-email.placeholderText.default": "Enter your email address",
  "store/newsletter-input-email.errorMessage.default": "Invalid email address",
  "store/newsletter-input-name.placeholderText.default": "Enter your name",
  "store/newsletter-input-name.errorMessage.default": "Invalid name",
  "store/newsletter-input-phone.placeholderText.default": "Enter your phone number",
  "store/newsletter-input-phone.errorMessage.default": "Invalid phone number",
  "store/newsletter-checkbox-confirmation.checkboxLabel.default": "I agree to received this newsletter.",
  "store/newsletter-submit.submitButtonLabel.default": "Subscribe",
  "store/newsletter-submit-success.default": "Thanks for subscribing!",
  "store/newsletter-submit-error.default": "Sorry, something went wrong."
}

```


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

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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.newsletter-form.title": "Newsletter",
  "admin/editor.newsletter-input-email.title": "Newsletter email input",
  "admin/editor.newsletter-input-email.placeholderText.title": "Email input placeholder",
  "admin/editor.newsletter-input-email.inputLabel.title": "Label for the email input",
  "admin/editor.newsletter-input-email.errorMessage.title": "\"Invalid email\" error message",
  "admin/editor.newsletter-input-name.title": "Newsletter name input",
  "admin/editor.newsletter-input-name.placeholderText.title": "Name input placeholder",
  "admin/editor.newsletter-input-name.inputLabel.title": "Label for the name input",
  "admin/editor.newsletter-input-name.errorMessage.title": "\"Invalid name\" error message",
  "admin/editor.newsletter-input-phone.title": "Newsletter phone input",
  "admin/editor.newsletter-input-phone.placeholderText.title": "Phone input placeholder",
  "admin/editor.newsletter-input-phone.inputLabel.title": "Label for the phone input",
  "admin/editor.newsletter-input-phone.errorMessage.title": "\"Invalid phone\" error message",
  "admin/editor.newsletter-checkbox-confirmation.title": "Newsletter confirmation",
  "admin/editor.newsletter-checkout-confirmation.checkboxLabel.title": "Label for the confirmation checkbox",
  "admin/editor.newsletter-checkout-confirmation.firstLink.title": "First link to be interpolated into the label",
  "admin/editor.newsletter-checkout-confirmation.firstLink.url": "First link url",
  "admin/editor.newsletter-checkout-confirmation.firstLink.text": "First link text",
  "admin/editor.newsletter-checkout-confirmation.secondLink.title": "Second link to be interpolated into the label",
  "admin/editor.newsletter-checkout-confirmation.secondLink.url": "Second link url",
  "admin/editor.newsletter-checkout-confirmation.secondLink.text": "Second link text",
  "admin/editor.newsletter-submit.title": "Newsletter form submit",
  "admin/editor.newsletter-submit.submitButtonLabel.title": "Label for the submit button",
  "store/newsletter-input-email.placeholderText.default": "Enter your email address",
  "store/newsletter-input-email.errorMessage.default": "Invalid email address",
  "store/newsletter-input-name.placeholderText.default": "Enter your name",
  "store/newsletter-input-name.errorMessage.default": "Invalid name",
  "store/newsletter-input-phone.placeholderText.default": "Enter your phone number",
  "store/newsletter-input-phone.errorMessage.default": "Invalid phone number",
  "store/newsletter-checkbox-confirmation.checkboxLabel.default": "I agree to received this newsletter.",
  "store/newsletter-submit.submitButtonLabel.default": "Subscribe",
  "store/newsletter-submit-success.default": "Thanks for subscribing!",
  "store/newsletter-submit-error.default": "Sorry, something went wrong."
}

```


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

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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.newsletter-form.title": "Newsletter",
  "admin/editor.newsletter-input-email.title": "Entrada de correo electrónico",
  "admin/editor.newsletter-input-email.placeholderText.title": "Marcador de posición de entrada de correo electrónico",
  "admin/editor.newsletter-input-email.inputLabel.title": "Etiqueta para la entrada de correo electrónico",
  "admin/editor.newsletter-input-email.errorMessage.title": "Mensaje de error \"Correo electrónico no válido\"",
  "admin/editor.newsletter-input-name.title": "Entrada del nombre",
  "admin/editor.newsletter-input-name.placeholderText.title": "Marcador de posición de entrada de nombre",
  "admin/editor.newsletter-input-name.inputLabel.title": "Etiqueta para la entrada del nombre",
  "admin/editor.newsletter-input-name.errorMessage.title": "Mensaje de error \"Nombre no válido\"",
  "admin/editor.newsletter-input-phone.title": "Entrada telefónica al boletín",
  "admin/editor.newsletter-input-phone.placeholderText.title": "Marcador de posición de entrada de teléfono",
  "admin/editor.newsletter-input-phone.inputLabel.title": "Etiqueta para la entrada del teléfono",
  "admin/editor.newsletter-input-phone.errorMessage.title": "Mensaje de error \"teléfono no válido\"",
  "admin/editor.newsletter-checkbox-confirmation.title": "Confirmación del boletín",
  "admin/editor.newsletter-checkout-confirmation.checkboxLabel.title": "Etiqueta para la casilla de verificación de confirmación",
  "admin/editor.newsletter-checkout-confirmation.firstLink.title": "Primer enlace que se interpolará en la etiqueta",
  "admin/editor.newsletter-checkout-confirmation.firstLink.url": "URL del primer enlace",
  "admin/editor.newsletter-checkout-confirmation.firstLink.text": "Texto del primer enlace",
  "admin/editor.newsletter-checkout-confirmation.secondLink.title": "Segundo enlace que se interpolará en la etiqueta",
  "admin/editor.newsletter-checkout-confirmation.secondLink.url": "URL del segundo enlace",
  "admin/editor.newsletter-checkout-confirmation.secondLink.text": "Texto del segundo enlace",
  "admin/editor.newsletter-submit.title": "Enviar formulario de boletín",
  "admin/editor.newsletter-submit.submitButtonLabel.title": "Etiqueta para el botón enviar",
  "store/newsletter-input-email.placeholderText.default": "Ingrese su dirección de correo electrónico",
  "store/newsletter-input-email.errorMessage.default": "Dirección de correo electrónico inválida",
  "store/newsletter-input-name.placeholderText.default": "Introduzca su nombre",
  "store/newsletter-input-name.errorMessage.default": "Nombre inválido",
  "store/newsletter-input-phone.placeholderText.default": "Ingrese su número telefónico",
  "store/newsletter-input-phone.errorMessage.default": "Numero de telefono invalido",
  "store/newsletter-checkbox-confirmation.checkboxLabel.default": "Acepto recibir este boletín.",
  "store/newsletter-submit.submitButtonLabel.default": "Suscribir",
  "store/newsletter-submit-success.default": "¡Gracias por suscribirte!",
  "store/newsletter-submit-error.default": "Perdón, algo salió mal."
}

```


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

[User] Show me the implementation of store-newsletter/docs/README.md from the store-newsletter VTEX app.

[Assistant]
Here's the implementation:

```markdown
📢 Use this project, [contribute](https://github.com/vtex-apps/store-newsletter) to it or open issues to help evolve it using [Store Discussion](https://github.com/vtex-apps/store-discussion).

# Store Newsletter

<!-- DOCS-IGNORE:start -->
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
<!-- DOCS-IGNORE:end -->

The Store Newsletter app provides a set of blocks that you can use to create a newsletter subscription form.

![newsletter-demo](https://user-images.githubusercontent.com/27777263/96277790-1c169b80-0fab-11eb-99cb-6b55ea7f5b7f.png)

## Configuration

1. Add `vtex.store-newsletter` to your app's dependencies in the `manifest.json` file:

```diff
 "dependencies": {
+  "vtex.store-newsletter": "1.x"
 }
```

Now, you are able to use all blocks exported by the `store-newsletter` app. Check out the full list below:

| Block name                         | Description                                                                                |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `newsletter-form`                  | ![mandatory](https://img.shields.io/badge/-Mandatory-red) Top level block that provides context to all its children. |
| `newsletter-input-email`           | ![mandatory](https://img.shields.io/badge/-Mandatory-red) Renders an email input in the newsletter form.             |
| `newsletter-input-name`            | Renders an name input in the newsletter form.                                                                        |
| `newsletter-input-phone`           | Renders an phone input in the newsletter form.                                                                       |
| `newsletter-checkbox-confirmation` | Renders a confirmation checkbox in the newsletter form.                                                              |
| `newsletter-hidden-field`          | Doesn't render anything, but enables hidden fields on the form to fetch custom data and save them in the store's [Master Data](https://help.vtex.com/en/tutorial/what-is-master-data--4otjBnR27u4WUIciQsmkAw) whenever a user subscribes to the newsletter. |
| `newsletter-submit`                | ![mandatory](https://img.shields.io/badge/-Mandatory-red) Renders a `Submit` button for the newsletter form.         |

2. In the desired store template, such as the `store.home`, add the `newsletter-form` block and its desired children:

```json
{
  "store.home": {
    "children": ["newsletter-form"]
  },

  "newsletter-form": {
    "children": [
      "newsletter-input-email",
      "newsletter-input-name",
      "newsletter-submit"
    ]
  }
}
```

### `newsletter-form` props

| Prop name      | Type               | Description                                                                                | Default value |
| -------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `ErrorState`   | `block`            | Block to be rendered if the submission of the form fails. If none is passed, a default error component will be rendered.                                                                                | `undefined`   |
| `SuccessState` | `block`            | Block to be rendered if form submission succeeds. If none is passed, a default success component will be rendered.                                                                                | `undefined`   |
| `LoadingState` | `block`            | Block to be rendered while the form submission is loading. If none is passed, the default behavior is for the submit button to show a spinner during this loading period.                                                                                | `undefined`   |
| `classes`      | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful if you're importing this block as a React component. | `undefined`   |

### `newsletter-input-email` props

| Prop name         | Type               | Description                                                                                | Default value                                                            |
| ----------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `placeholderText` | `string`           | Placeholder text for the email input.                                                                                | `Enter your email address` (translated according to the store's locale). |
| `inputLabel`      | `string`           | Label for the email input.                                                                                | `null`                                                                   |
| `errorMessage`    | `string`           | Error message to be shown if email is invalid.                                                                                | `Invalid email address` (translated according to the store's locale).    |
| `classes`         | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful if you're importing this block as a React component. | `undefined`                                                              |

### `newsletter-input-name` props

| Prop name         | Type               | Description                                                                                | Default value                                                   |
| ----------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `placeholderText` | `string`           | Placeholder text for name input.                                                                                | `Enter your name` (translated according to the store's locale). |
| `inputLabel`      | `string`           | Label for the name input.                                                                                | `null`                                                          |
| `errorMessage`    | `string`           | Error message to be shown if name input is empty.                                                                                | `Invalid name` (translated according to the store's locale).    |
| `classes`         | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful if you're importing this block as a React component. | `undefined`                                                     |

### `newsletter-input-phone` props

| Prop name         | Type               | Description                                                                                | Default value                                                    |
| ----------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `placeholderText` | `string`           | Placeholder text for phone input.                                                                                | `Enter your phone` (translated according to the store's locale). |
| `inputLabel`      | `string`           | Label for the phone input.                                                                                | `null`                                                           |
| `errorMessage`    | `string`           | Error message to be shown if phone input is empty.                                                                                | `Invalid phone` (translated according to the store's locale).    |
| `classes`         | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful if you're importing this block as a React component. | `undefined`                                                      |

### `newsletter-checkbox-confirmation` props

| Prop name       | Type     | Description                                                                                | Default value                                                                        |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| `checkboxLabel` | `string` | Label for the confirmation checkbox. This prop supports the [ICU Message Format](https://format-message.github.io/icu-message-format-for-translators/), exposing two variables for you to interpolate: `firstLink` and `secondLink`. | `I agree to received this newsletter.` (translated according to the store's locale). |
| `firstLabelLink`     | `Object` | Configures the `firstLink` variable to be interpolated by the text passed to `checkboxLabel`. checkbox.                                                                                | `undefined`.                                                                         |
| `secondLabelLink`    | `Object` | Configures the `secondLink` variable to be interpolated by the text passed to `checkboxLabel`. checkbox.                                                                                | `undefined`                                                                          |
| `classes`         | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful if you're importing this block as a React component.                                      | `undefined`           |

- `firstLabelLink` and `secondLabelLink` objects:

| Prop name | Type     | Description                 | Default value |
| --------- | -------- | --------------------------- | ------------- |
| `url`     | `string` | The link's URL.             | `undefined`   |
| `text`    | `string` | Text displayed on the link. | `undefined`   |

### `newsletter-hidden-field` props

| Prop name | Type     | Description                 | Default value |
| --------- | -------- | --------------------------- | ------------- |
| `dynamicFields` | `[enum]` | Desired hidden fields responsible for saving the user's custom data on [Master Data](https://help.vtex.com/en/tutorial/what-is-master-data--4otjBnR27u4WUIciQsmkAw) once the newsletter form is submitted. Notice that the name of the fields must be written in an array and represent which user data they save. Possible values are: `bindingUrl` and `bindingId`. *Caution*: To properly save the data, you must also [create the desired filters](https://help.vtex.com/en/tutorial/how-can-i-create-a-field-in-master-data--frequentlyAskedQuestions_1829) in the Master Data's `Client` entity.  | `undefined` |

### `newsletter-submit` props

| Prop name           | Type     | Description                          | Default value                                             |
| ------------------- | -------- | ------------------------------------ | --------------------------------------------------------- |
| `submitButtonLabel` | `string` | Text displayed on the submit button. | `Subscribe` (translated according to the store's locale). |
| `classes`         | `CustomCSSClasses` | Used to override default CSS handles. To better understand how this prop works, we recommend reading about it [here](https://github.com/vtex-apps/css-handles#usecustomclasses). Note that this is only useful if you're importing this block as a React component.                                      | `undefined`           |

## Customization

In order to apply CSS customizations in this and other blocks, follow the instructions given in the recipe on [Using CSS Handles for store customization](https://vtex.io/docs/recipes/style/using-css-handles-for-store-customization).

| CSS Handles                     |
| ------------------------------- |
| `confirmationCheckboxContainer` |
| `confirmationCheckboxLabel`     |
| `defaultErrorMessage`           |
| `defaultSuccessMessage`         |
| `emailInputContainer`           |
| `emailInputContainer--invalid`  |
| `emailInputLabel`               |
| `formSubmitContainer`           |
| `formSubmitContainer--invalid`  |
| `nameInputContainer`            |
| `nameInputContainer--invalid`   |
| `nameInputLabel`                |
| `newsletterForm`                |
| `phoneInputContainer`           |
| `phoneInputContainer--invalid`  |
| `phoneInputLabel`               |

<!-- DOCS-IGNORE:start -->

## Contributors ✨

Thanks goes to these wonderful people:

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tr>
    <td align="center"><a href="https://github.com/gutogama"><img src="https://avatars.githubusercontent.com/u/70643210?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Luiz Gama</b></sub></a><br /><a href="https://github.com/vtex-apps/store-newsletter/commits?author=gutogama" title="Code">💻</a></td>
  </tr>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!

<!-- DOCS-IGNORE:end -->

```