[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 supply-lots/react/components/Provider/Warehouse.tsx from the supply-lots VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable vtex/prefer-early-return */
/* eslint-disable func-names */
import type { FC, SyntheticEvent } from 'react'
import React, { useEffect, useMemo, useState } from 'react'
import { useMutation, useQuery } from 'react-apollo'
import * as yup from 'yup'
import {
  IconDelete,
  IconEdit,
  Tag,
  Tooltip,
  Button,
  IconInfo,
} from 'vtex.styleguide'
import { injectIntl, useIntl } from 'react-intl'

import WarehouseContext from '../Context/WarehouseContext'
import getSkuAndWarehouseNames from '../../queries/getSkuAndWarehouseNames.gql'
import listSupplyLots from '../../queries/listSupplyLots.gql'
import setSupplyLot from '../../queries/setSupplyLot.gql'
import deleteSupplyLot from '../../queries/deleteSupplyLot.gql'
import transferSupplyLot from '../../queries/transferSupplyLot.gql'
import IconTransfer from '../../icons/IconsTransfer'
import { provider } from '../../utils/definedMessages'

const initialSku = {
  id: '',
  name: '',
}

const initialWarehouse = {
  id: '',
  name: '',
}

const schemaYup = yup.object().shape({
  dateOfSupplyUtc: yup.date().required(),
  keepSellingAfterExpiration: yup.boolean().required(),
  totalQuantity: yup.number().required().positive().integer(),
})

const WarehouseProvider: FC = (props) => {
  // Definições
  const intl = useIntl()
  const [warehouse, setWarehouse] = useState<Warehouse>(initialWarehouse)
  const [sku, setSku] = useState<Sku>(initialSku)
  const [date, setDate] = useState<Date>()
  const [keep, setKeep] = useState<boolean>()
  const [items, setItems] = useState<number>()
  const [modal, setModal] = useState(0)
  const [modalDelete, setDelete] = useState(false)
  const [modalTransfer, setTransfer] = useState(false)
  const [text, setText] = useState('')
  const [id, setId] = useState('')
  const [sortedByValue, setSortedBy] = useState('index')
  const [sortOrderValue, setSortOrder] = useState('index')
  const [limit, setLimit] = useState(false)
  const [orderedItems, setOrderedItems] = useState<any[]>()

  const { data: dataListSupplyLots, refetch } = useQuery(listSupplyLots, {
    variables: { skuId: sku.id, warehouseId: warehouse.id },
  })

  const { data: dataNames } = useQuery(getSkuAndWarehouseNames, {
    variables: { skuId: sku.id, warehouseId: warehouse.id },
  })

  const [setSupplyLotValue] = useMutation(setSupplyLot)
  const [deleteSupplyLotValue] = useMutation(deleteSupplyLot)
  const [transferSupplyLotValue] = useMutation(transferSupplyLot)

  useEffect(() => {
    const url = window.location.href
    let values = url.split('?')

    if (values[1] !== undefined) {
      values = values[1].split('&')
      const idSku = values[0].split('=')
      const idWarehouse = values[1].split('=')

      updateSku({ id: idSku[1] })
      updateWarehouse({ id: idWarehouse[1] })
    }
  }, [])

  useMemo(() => {
    if (dataNames) {
      updateSku({ name: dataNames?.getSkuAndWarehouseNames[0] })
      updateWarehouse({ name: dataNames?.getSkuAndWarehouseNames[1] })
    }
  }, [dataNames])

  function updateSku(object: Sku) {
    setSku({ ...sku, ...object })
  }

  function updateWarehouse(object: Warehouse) {
    setWarehouse({ ...warehouse, ...object })
  }

  function updateItems(object: number) {
    setItems(object)
  }

  // Funções da tabela
  async function validation() {
    const object = {
      dateOfSupplyUtc: date,
      keepSellingAfterExpiration: keep,
      totalQuantity: items,
    }

    const retorno = await schemaYup.validate(object).catch(function (err) {
      err.name
      err.errors

      if (err.errors[0] === 'totalQuantity must be a positive number') {
        setText(intl.formatMessage(provider.textNoticeNumber))
      } else {
        setText(intl.formatMessage(provider.textNotice))
      }

      return false
    })

    return retorno
  }

  async function addSupplyLot() {
    const valid = await validation()

    if (valid) {
      setModal(0)
      setText('')
      let dateValue = '0000-00-00'

      if (date !== undefined) dateValue = date?.toISOString()
      const supplyLotData: SupplyLotInput = {
        dateOfSupplyUtc: dateValue,
        keepSellingAfterExpiration: keep ?? false,
        skuId: sku.id ? sku.id : '',
        warehouseId: warehouse.id ? warehouse.id : '',
        totalQuantity: items ?? 0,
      }

      await setSupplyLotValue({ variables: { supplyLotData } })

      refetch()
    }
  }

  function newSupplyLot() {
    setModal(1)
    setDate(undefined)
    setKeep(undefined)
    setItems(undefined)
  }

  async function editSupplyLot() {
    const valid = await validation()

    if (valid) {
      setModal(0)
      setText('')

      let dateValue = '0000-00-00'

      if (date !== undefined) dateValue = date?.toISOString()
      const supplyLotData: SupplyLotInput = {
        dateOfSupplyUtc: dateValue,
        keepSellingAfterExpiration: keep ?? false,
        skuId: sku.id ? sku.id : '',
        warehouseId: warehouse.id ? warehouse.id : '',
        totalQuantity: items ?? 0,
        supplyLotId: id || '',
      }

      await setSupplyLotValue({ variables: { supplyLotData } })

      refetch()
    }
  }

  async function clickEdit(index: number, supplyLotId: string) {
    setModal(2)
    const dateValue = new Date(
      dataListSupplyLots?.listSupplyLots[index]?.dateOfSupplyUtc
    )

    setDate(dateValue)
    setItems(dataListSupplyLots?.listSupplyLots[index]?.totalQuantity)
    setKeep(
      dataListSupplyLots?.listSupplyLots[index]?.keepSellingAfterExpiration
    )

    setId(supplyLotId)
  }

  async function deleteSupplyLots() {
    setDelete(false)
    await deleteSupplyLotValue({
      variables: { skuId: sku.id, warehouseId: warehouse.id, supplyLotId: id },
    })

    refetch()
  }

  function clickDelete(supplyLotId: string) {
    setDelete(true)
    setId(supplyLotId)
  }

  async function transferSupplyLots() {
    setTransfer(false)
    await transferSupplyLotValue({
      variables: { skuId: sku.id, warehouseId: warehouse.id, supplyLotId: id },
    })

    refetch()
  }

  function clickTransfer(supplyLotId: string) {
    setTransfer(true)
    setId(supplyLotId)
  }

  const listSupplyLotsValues = useMemo(() => {
    const tableValues: any[] = []

    if (
      dataListSupplyLots?.listSupplyLots.length === 8 &&
      !limit &&
      modal === 1
    ) {
      setLimit(true)
    } else if (limit) {
      setLimit(false)
    }

    // eslint-disable-next-line array-callback-return
    dataListSupplyLots?.listSupplyLots.map(function (
      values: {
        supplyLotId: string
        dateOfSupplyUtc: string
        totalQuantity: number
        keepSellingAfterExpiration: boolean
        reservedQuantity: number
        availableQuantity: number
      },
      indexOf: number
    ) {
      const value = {
        index: indexOf + 1,
        date: new Date(values.dateOfSupplyUtc).toLocaleDateString(),
        total: values.totalQuantity,
        reserved: values.reservedQuantity,
        available: values.availableQuantity,
        keepSelling: values.keepSellingAfterExpiration
          ? intl.formatMessage(provider.yes)
          : intl.formatMessage(provider.no),
        color: colorLabel(
          values.keepSellingAfterExpiration,
          values.dateOfSupplyUtc
        ),
        actions: {
          index: indexOf,
          skuId: sku.id,
          warehouseId: warehouse.id,
          supplyLotId: values.supplyLotId,
        },
      }

      tableValues.push(value)
    })

    setOrderedItems(tableValues)

    return tableValues
  }, [dataListSupplyLots])

  function converter(dateConverter: string) {
    const parts = dateConverter.split('/')

    return new Date(
      parseInt(parts[2], 10),
      parseInt(parts[1], 10) - 1,
      parseInt(parts[0], 10)
    )
  }

  function sortDateASC() {
    listSupplyLotsValues.sort(function (a, b) {
      if (converter(a.date) > converter(b.date)) {
        return 1
      }

      if (converter(a.date) < converter(b.date)) {
        return -1
      }

      // a must be equal to b
      return 0
    })
  }

  function sortDateDESC() {
    listSupplyLotsValues.sort(function (a, b) {
      if (converter(a.date) < converter(b.date)) {
        return 1
      }

      if (converter(a.date) > converter(b.date)) {
        return -1
      }

      // a must be equal to b
      return 0
    })
  }

  function sortIndexASC() {
    listSupplyLotsValues.sort(function (a, b) {
      if (a.index > b.index) {
        return 1
      }

      if (a.index < b.index) {
        return -1
      }

      // a must be equal to b
      return 0
    })
  }

  function sortIndexDESC() {
    listSupplyLotsValues.sort(function (a, b) {
      if (a.index < b.index) {
        return 1
      }

      if (a.index > b.index) {
        return -1
      }

      // a must be equal to b
      return 0
    })
  }

  function sort({
    sortOrder,
    sortedBy,
  }: {
    sortOrder: string
    sortedBy: string
  }) {
    if (sortedBy === 'date') {
      if (sortOrder === 'ASC') {
        sortDateASC()
      } else {
        sortDateDESC()
      }
    } else if (sortOrder === 'ASC') {
      sortIndexASC()
    } else {
      sortIndexDESC()
    }

    setOrderedItems(listSupplyLotsValues)
    setSortOrder(sortOrder)
    setSortedBy(sortedBy)
  }

  useMemo(() => {
    listSupplyLotsValues.sort(function (a, b) {
      if (a.index > b.index) {
        return 1
      }

      if (a.index < b.index) {
        return -1
      }

      // a must be equal to b
      return 0
    })
  }, [listSupplyLotsValues])

  function colorLabel(
    keepSellingAfterExpiration: boolean,
    dateOfSupplyUtc: string
  ) {
    let color = '#8bc34a'
    let label = intl.formatMessage(provider.regular)
    const dateNow = new Date()
    const dateUTC = dateNow.toUTCString()

    const secondsdateOfSupplyUtc = Date.parse(dateOfSupplyUtc)
    const secondsNow = Date.parse(dateUTC)

    if (secondsdateOfSupplyUtc < secondsNow && !keepSellingAfterExpiration) {
      label = intl.formatMessage(provider.expired)
      color = 'red'
    } else if (
      secondsdateOfSupplyUtc < secondsNow &&
      keepSellingAfterExpiration
    ) {
      label = intl.formatMessage(provider.expiredYes)
      color = 'red'
    } else if (
      secondsdateOfSupplyUtc > secondsNow &&
      secondsdateOfSupplyUtc - secondsNow < 259200000
    ) {
      const days = Math.ceil(
        (secondsdateOfSupplyUtc - secondsNow) / (1000 * 60 * 60 * 24)
      ).toString()

      let notice = ''

      if (days === '1') {
        notice =
          // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
          intl.formatMessage(provider.expiring) +
          days +
          intl.formatMessage(provider.day)
      } else {
        notice =
          // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
          intl.formatMessage(provider.expiring) +
          days +
          intl.formatMessage(provider.days)
      }

      label = notice
      color = '#ffd700'
    }

    return { color, label }
  }

  const schemaTable = {
    properties: {
      index: {
        title: intl.formatMessage(provider.index),
        width: 80,
        sortable: true,
      },
      date: {
        title: intl.formatMessage(provider.date),
        minWidth: 100,
        sortable: true,
      },
      total: {
        title: intl.formatMessage(provider.total),
      },
      reserved: {
        title: intl.formatMessage(provider.reserved),
      },
      available: {
        title: intl.formatMessage(provider.available),
      },
      keepSelling: {
        minWidth: 200,
        headerRenderer: () => {
          return (
            <>
              <p>{intl.formatMessage(provider.keep)}</p>
              <div className="ml2">
                <Tooltip label={intl.formatMessage(provider.info)}>
                  <span className="c-on-base pointer">
                    <IconInfo />
                  </span>
                </Tooltip>
              </div>
            </>
          )
        },
      },
      color: {
        title: intl.formatMessage(provider.status),
        minWidth: 200,
        cellRenderer: ({ cellData }: any) => {
          return (
            <Tag color="#ffff" bgColor={cellData?.color}>
              <span className="nowrap"> {cellData?.label} </span>
            </Tag>
          )
        },
      },
      actions: {
        title: intl.formatMessage(provider.actions),
        cellRenderer: ({ cellData }: any) => {
          return (
            <>
              <Tooltip label={intl.formatMessage(provider.edit)}>
                <Button
                  icon={true}
                  variation="tertiary"
                  onClick={(e: SyntheticEvent) => {
                    e.preventDefault()
                    clickEdit(cellData?.index, cellData?.supplyLotId)
                  }}
                >
                  <IconEdit />
                </Button>
              </Tooltip>
              <Tooltip label={intl.formatMessage(provider.delete)}>
                <Button
                  icon={true}
                  variation="tertiary"
                  onClick={(e: SyntheticEvent) => {
                    e.preventDefault()
                    clickDelete(cellData.supplyLotId)
                  }}
                >
                  <IconDelete />
                </Button>
              </Tooltip>
              <Tooltip label={intl.formatMessage(provider.transfer)}>
                <Button
                  icon={true}
                  variation="tertiary"
                  onClick={(e: SyntheticEvent) => {
                    e.preventDefault()
                    clickTransfer(cellData.supplyLotId)
                  }}
                >
                  <a>
                    <IconTransfer />
                  </a>
                </Button>
              </Tooltip>
            </>
          )
        },
      },
    },
  }

  return (
    <WarehouseContext.Provider
      value={{
        warehouse,
        sku,
        newSupplyLot,
        orderedItems,
        schemaTable,
        modal,
        setModal,
        setDate,
        date,
        setKeep,
        keep,
        items,
        updateItems,
        modalDelete,
        setDelete,
        modalTransfer,
        setTransfer,
        addSupplyLot,
        editSupplyLot,
        deleteSupplyLots,
        transferSupplyLots,
        text,
        limit,
        sortedByValue,
        sortOrderValue,
        sort,
        setText,
      }}
    >
      {props.children}
    </WarehouseContext.Provider>
  )
}

export default injectIntl(WarehouseProvider)

```


[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 supply-lots/react/components/ProductsTable/index.tsx from the supply-lots VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { ComponentType } from 'react'
import React, { useContext } from 'react'
import { PageBlock, PageHeader, Table } from 'vtex.styleguide'
import { useRuntime } from 'vtex.render-runtime'
import type { InjectedIntlProps, IntlShape } from 'react-intl'
import { injectIntl } from 'react-intl'

import WarehouseContext from '../Context/WarehouseContext'
import ModalAdd from '../Modal/add'
import ModalDelete from '../Modal/delete'
import ModalTransfer from '../Modal/transfer'
import { productTable } from '../../utils/definedMessages'

interface Props {
  intl: IntlShape
}
const ProductsTable: ComponentType<Props & InjectedIntlProps> = ({ intl }) => {
  const provider = useContext(WarehouseContext)

  const { history } = useRuntime()

  if (provider.modal !== 0) return <ModalAdd></ModalAdd>
  if (provider.modalDelete) return <ModalDelete></ModalDelete>
  if (provider.modalTransfer) return <ModalTransfer></ModalTransfer>

  return (
    <>
      <PageBlock>
        <PageHeader
          title={intl.formatMessage(productTable.titleProdutctTable)}
          linkLabel={intl.formatMessage(productTable.link)}
          onLinkClick={() => {
            history.goBack()
          }}
        />
        <Table
          fullWidth
          toolbar={{
            newLine: {
              label: intl.formatMessage(productTable.toolbar),
              handleCallback: () => provider.newSupplyLot(),
            },
          }}
          totalizers={[
            {
              label: intl.formatMessage(productTable.totalizersSku),
              value: provider.sku.id,
            },
            {
              label: intl.formatMessage(productTable.totalizersProduct),
              value: provider.sku.name,
            },
            {
              label: intl.formatMessage(productTable.totalizersWarehouseId),
              value: provider.warehouse.id,
            },
            {
              label: intl.formatMessage(productTable.totalizersWarehouse),
              value: provider.warehouse.name,
            },
          ]}
          schema={provider.schemaTable}
          items={provider.orderedItems}
          sort={{
            sortedBy: provider.sortedByValue,
            sortOrder: provider.sortOrderValue,
          }}
          onSort={provider.sort}
        ></Table>
      </PageBlock>
    </>
  )
}

export default injectIntl(ProductsTable)

```


[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 supply-lots/react/components/Modal/add.tsx from the supply-lots VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { ComponentType, SyntheticEvent } from 'react'
import React, { useContext } from 'react'
import type { InjectedIntlProps, IntlShape } from 'react-intl'
import { injectIntl } from 'react-intl'
import { Button, DatePicker, Dropdown, Input, Modal } from 'vtex.styleguide'

import {
  commonModal,
  modalAddTexts,
  optionModalAdd,
} from '../../utils/definedMessages'
import WarehouseContext from '../Context/WarehouseContext'
import ModalLimit from './limit'

interface Props {
  intl: IntlShape
}

const ModalAdd: ComponentType<Props & InjectedIntlProps> = ({ intl }) => {
  const provider = useContext(WarehouseContext)

  function closeModal() {
    provider.setModal(0)
    provider.setText('')
  }

  const options = [
    {
      value: true,
      label: intl.formatMessage(optionModalAdd.optionsTrue),
    },
    {
      value: false,
      label: intl.formatMessage(optionModalAdd.optionsFalse),
    },
  ]

  const currentDate = new Date()
  const minDate = currentDate.setDate(currentDate.getDate() + 1)

  if (provider.limit) return <ModalLimit></ModalLimit>

  return (
    <Modal
      centered
      isOpen={provider.modal}
      title={
        provider.modal === 1
          ? intl.formatMessage(modalAddTexts.titleAdd)
          : intl.formatMessage(modalAddTexts.titleEdit)
      }
      responsiveFullScreen
      bottomBar={
        <div>
          <span className="mr4">
            <Button
              variation="tertiary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                closeModal()
              }}
            >
              {intl.formatMessage(commonModal.cancel)}
            </Button>
          </span>
          <span>
            <Button
              variation="primary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                if (provider.modal === 1) provider.addSupplyLot()
                else provider.editSupplyLot()
              }}
            >
              {intl.formatMessage(commonModal.save)}
            </Button>
          </span>
        </div>
      }
      onClose={(e: SyntheticEvent) => {
        e.preventDefault
        closeModal()
      }}
    >
      <div>
        <div className="w-90 mv6">
          <DatePicker
            label={intl.formatMessage(modalAddTexts.date)}
            size="large"
            value={provider.date ? provider.date : undefined}
            placeholder={intl.formatMessage(modalAddTexts.datePlaceholder)}
            onChange={(date: Date) => provider.setDate(date)}
            locale="pt-BR"
            minDate={minDate}
          />
        </div>
        <div className="w-90 mv6">
          <Input
            placeholder={intl.formatMessage(modalAddTexts.totalPlaceholder)}
            size="large"
            label={intl.formatMessage(modalAddTexts.total)}
            type="number"
            min="0"
            onChange={(e: any) => {
              provider.updateItems(parseInt(e.target.value, 10))
            }}
            value={
              provider.items?.toString()
                ? provider.items?.toString()
                : undefined
            }
          />
        </div>
        <div className="w-90 mv6">
          <Dropdown
            size="large"
            label={intl.formatMessage(modalAddTexts.keep)}
            placeholder={intl.formatMessage(modalAddTexts.keepPlaceholder)}
            options={options}
            value={provider.keep !== undefined ? provider.keep : undefined}
            onChange={(_: any, v: string) => {
              provider.setKeep(v === 'true')
            }}
          />
        </div>
        <p className="mt2" style={{ color: 'red', fontSize: '12px' }}>
          {provider.text}
        </p>
      </div>
    </Modal>
  )
}

export default injectIntl(ModalAdd)

```


[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 supply-lots/react/components/Modal/limit.tsx from the supply-lots VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { ComponentType, FC, SyntheticEvent } from 'react'
import React, { useContext } from 'react'
import type { InjectedIntlProps, IntlShape } from 'react-intl'
import { injectIntl } from 'react-intl'
import { Button, Modal } from 'vtex.styleguide'

import { commonModal, modalLimit } from '../../utils/definedMessages'
import WarehouseContext from '../Context/WarehouseContext'

interface Props {
  intl: IntlShape
}
const ModalLimit: ComponentType<Props & InjectedIntlProps> = ({ intl }) => {
  const provider = useContext(WarehouseContext)

  function closeModal() {
    provider.setModal(0)
  }

  return (
    <Modal
      title={intl.formatMessage(modalLimit.limit)}
      centered
      isOpen={provider.modal}
      responsiveFullScreen
      bottomBar={
        <div className="nowrap">
          <span className="mr4">
            <Button
              variation="tertiary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                closeModal()
              }}
            >
              {intl.formatMessage(commonModal.cancel)}
            </Button>
          </span>
        </div>
      }
      onClose={(e: SyntheticEvent) => {
        e.preventDefault
        closeModal()
      }}
    ></Modal>
  )
}

export default injectIntl(ModalLimit)

```


[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 supply-lots/react/components/Modal/transfer.tsx from the supply-lots VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { ComponentType, FC, SyntheticEvent } from 'react'
import React, { useContext } from 'react'
import type { InjectedIntlProps, IntlShape } from 'react-intl'
import { injectIntl } from 'react-intl'
import { Button, Modal } from 'vtex.styleguide'

import IconTransferBig from '../../icons/IconsTransferBig'
import { commonModal, modalTransfer } from '../../utils/definedMessages'
import WarehouseContext from '../Context/WarehouseContext'

interface Props {
  intl: IntlShape
}
const ModalTransfer: ComponentType<Props & InjectedIntlProps> = ({ intl }) => {
  const provider = useContext(WarehouseContext)

  function closeModal() {
    provider.setTransfer(false)
  }

  return (
    <Modal
      isOpen={provider.modalTransfer}
      responsiveFullScreen
      bottomBar={
        <div className="nowrap">
          <span className="mr4">
            <Button
              variation="tertiary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                closeModal()
              }}
            >
              {intl.formatMessage(commonModal.cancel)}
            </Button>
          </span>
          <span>
            <Button
              variation="primary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                provider.transferSupplyLots()
              }}
            >
              {intl.formatMessage(modalTransfer.transfer)}
            </Button>
          </span>
        </div>
      }
      onClose={(e: SyntheticEvent) => {
        e.preventDefault
        closeModal()
      }}
    >
      <div className="flex flex-column items-center justify-center t-heading-5">
        <IconTransferBig />
        <div className="pv3 t-heading-4">
          {intl.formatMessage(modalTransfer.transferText)}
        </div>

        <div className="pv3 t-body c-muted-2">
          {intl.formatMessage(modalTransfer.transferQuestion)}{' '}
        </div>
      </div>
    </Modal>
  )
}

export default injectIntl(ModalTransfer)

```


[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 supply-lots/react/components/Modal/delete.tsx from the supply-lots VTEX app.

[Assistant]
Here's the implementation:

```tsx
import type { ComponentType, SyntheticEvent } from 'react'
import React, { useContext } from 'react'
import type { IntlShape, InjectedIntlProps } from 'react-intl'
import { injectIntl } from 'react-intl'
import { Button, Modal } from 'vtex.styleguide'

import IconTrashCan from '../../icons/IconTrashCan'
import { commonModal, modalDelete } from '../../utils/definedMessages'
import WarehouseContext from '../Context/WarehouseContext'

interface Props {
  intl: IntlShape
}
const ModalDelete: ComponentType<Props & InjectedIntlProps> = ({ intl }) => {
  const provider = useContext(WarehouseContext)

  function closeModal() {
    provider.setDelete(false)
  }

  return (
    <Modal
      isOpen={provider.modalDelete}
      bottomBar={
        <div className="nowrap">
          <span className="mr4">
            <Button
              variation="tertiary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                closeModal()
              }}
            >
              {intl.formatMessage(commonModal.cancel)}
            </Button>
          </span>
          <span>
            <Button
              variation="primary"
              onClick={(e: SyntheticEvent) => {
                e.preventDefault
                provider.deleteSupplyLots()
              }}
            >
              {intl.formatMessage(commonModal.delete)}
            </Button>
          </span>
        </div>
      }
      onClose={(e: SyntheticEvent) => {
        e.preventDefault
        closeModal()
      }}
    >
      <div className="flex flex-column items-center justify-center t-heading-5">
        <IconTrashCan />
        <div className="pv3 t-heading-4">
          {intl.formatMessage(modalDelete.deleteText)}
        </div>

        <div className="pv3 t-body c-muted-2">
          {intl.formatMessage(modalDelete.deleteQuestion)}
        </div>
        <div className="pv3 t-body c-muted-2">
          {intl.formatMessage(modalDelete.deleteReason)}
        </div>
      </div>
    </Modal>
  )
}

export default injectIntl(ModalDelete)

```


[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 broadcaster/docs/README.md from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Broadcaster

The Broadcaster app is designed to adapt catalog broadcaster changes to an event in VTEX IO's Events system.

Typically, it's used when developing another IO app that receives the events and calls handler functions to treat the events. For more details about this use, see the [Receiving Catalog Changes on VTEX IO](https://developers.vtex.com/docs/guides/how-to-receive-catalog-changes-on-vtex-io) guide.

For example, the [Availability Notify](https://developers.vtex.com/vtex-developer-docs/docs/vtex-availability-notify) app uses the Broadcaster app to monitor inventory updates. Once the requested SKU is back in stock, the app will email shoppers who asked to be notified.

```mermaid
flowchart LR
a1("Catalog changes\n(Catalog broadcaster)\n\n")
a2("Broadcaster app")
b1("Event system")
b2("Changes broadcast\nto other apps\n(e.g.: Availability Notify)\n\n")

a1 -- \nSKU that\nchanged\n\n\n --> a2 --> b1 --> b2
```

The Broadcaster app receives a POST request from the catalog broadcaster with the details of the SKU that changed and pushes an event to the Event system to broadcast to apps that listen to these changes.

> ⚠ The Broadcaster app receives catalog changes from the same account where the app is installed and not from sellers.

## SKU information

When the Broadcaster app sends an event, it contains a payload with the following fields:

| Field name | Description | Type |
| - | - | - |
| `IdSku` | SKU ID on VTEX. | string |
| `ProductId` | Product ID on VTEX. This field is optional and is only sent in marketplace contexts when an event occurs in the affiliate catalog. | long |
| `An` | Account name on VTEX, shown in the store’s VTEX Admin URL. | string |
| `IdAffiliate` | ID code of the affiliate that generated the event. This field is optional and is only sent in marketplace contexts when an event occurs in the affiliate catalog. | string |
| `SellerChain` | Sellers involved in the chain. This field is optional and is only sent in marketplace contexts with [Multilevel Omnichannel Inventory](https://help.vtex.com/en/tutorial/multilevel-omnichannel-inventory--7M1xyCZWUyCB7PcjNtOyw4) when an event occurs in the affiliate catalog. When there is more than one seller in the chain, they're all included in this field separated by a forward slash (`/`). Example: `"cea/rihappy"`. | string |
| `DateModified` | Date when the item was updated. | string |
| `IsActive` | Identifies whether the product is active or not. If `true`, the product/SKU is active. | boolean |
| `StockModified` | Indicates that the inventory level has changed. If `false`, the inventory level hasn't changed. | boolean |
| `PriceModified` | Indicates that the price has changed. If `false`, the product/SKU price hasn't changed. | boolean |
| `HasStockKeepingUnitModified` | Indicates that the product/SKU details have changed, such as name, description, weight, etc. If `true`, the product/SKU details have changed. | boolean |
| `HasStockKeepingUnitRemovedFromAffiliate` | Indicates that the product is no longer associated with the trade policy. If `true`, the trade policy has changed. | boolean |

## Notifications in subaccounts

When attempting to listen for catalog change notifications in a [subaccount](https://help.vtex.com/en/tutorial/creating-subaccount-multi-store-multi-domain--tutorials_510), you'll likely find that your app isn't receiving notifications. This is because, by default, catalog change notifications are only sent to the Broadcaster app installed in the main account.

### "Notify Subaccounts" setting

The Broadcaster app installed in the main (parent) account can be configured to push a notification event to all associated subaccounts.

To configure this setting, follow the steps below:

1. Go to **My Apps** in the VTEX Admin.
2. In the list of installed apps, search for **Broadcaster**.
3. Click `Settings` in the app box.
4. Check the `Notify Subaccounts` box.
5. Click `Save`.

## Testing the app

By default, when the Broadcaster Adapter app sends events, they're only sent in the master workspace of each account. If you work in a **[development workspace](https://developers.vtex.com/vtex-developer-docs/docs/vtex-io-documentation-workspace)**, there's a way to receive events there:

### "Notify Target Workspace" setting

The app installed in the master workspace can be configured to push a notification event to a selected target workspace in addition to the master workspace.

To configure this setting, follow the steps below:

1. Go to **My Apps** in the VTEX Admin.
2. In the list of installed apps, search for **Broadcaster**.
3. Click `Settings`.
4. Enter the name of the workspace you want to notify in the **Notify Target Workspace** field.
5. Click `Save`.

```


[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 broadcaster/node/service.json from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 10,
  "timeout": 2,
  "minReplicas": 2,
  "maxReplicas": 10,
  "workers": 4,
  "routes": {
    "notify": {
      "path": "/notify",
      "public": false
    },
    "notifySelf": {
      "path": "/_v/self/notify",
      "public": false,
      "policies": [
        {
          "effect": "allow",
          "actions": ["post"],
          "principals": ["vrn:apps:*:*:*:app/vtex.broadcaster@*"]
        }
      ]
    }
  }
}

```


[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 broadcaster/node/package.json from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "co-body": "^6.0.0"
  },
  "devDependencies": {
    "@types/co-body": "^0.0.3",
    "@types/node": "12.x",
    "@vtex/api": "6.45.12",
    "vtex.broadcaster": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.broadcaster@0.7.8/public/_types/react"
  },
  "scripts": {
    "lint": "tsc --noEmit --pretty && eslint -c .eslintrc.json --fix './**/*.ts'"
  },
  "version": "0.10.2"
}

```


[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 broadcaster/node/typings.ts from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

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

import { Clients } from './clients'

declare global {
  type Context = ServiceContext<Clients, State>

  interface State extends RecorderState, BroadcasterEvent {
    payload: BroadcasterEvent
  }

  interface BroadcasterEvent {
    HasStockKeepingUnitModified: boolean
    IdSku: string
  }

  type ID = string
  type Float = number
  type Int = number
}

```


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

[Assistant]
Here's the implementation:

```typescript
export const ENABLED_GLOBALLY = true

export const BROADCASTER_NOTIFICATION = 'broadcaster.notification'

```


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

[Assistant]
Here's the implementation:

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

import { Clients } from './clients'
import { parseAndValidate } from './middlewares/parse'
import { throttle } from './middlewares/throttle'
import { pushNotification } from './middlewares/pushNotification'
import { notifyTargetWorkspace } from './middlewares/notifyTargetWorkspace'
import { notifyAllSubaccounts } from './middlewares/notifyAllSubaccounts'

const TREE_SECONDS_MS = 3 * 1000
const CONCURRENCY = 10

const clients: ClientsConfig<Clients> = {
  implementation: Clients,
  options: {
    events: {
      exponentialTimeoutCoefficient: 2,
      exponentialBackoffCoefficient: 2,
      initialBackoffDelay: 50,
      retries: 1,
      timeout: TREE_SECONDS_MS,
      concurrency: CONCURRENCY,
    },
  },
}

export default new Service<Clients, State, ParamsContext>({
  clients,
  routes: {
    // notifications from catalog
    notify: method({
      POST: [
        throttle,
        parseAndValidate,
        pushNotification,
        notifyAllSubaccounts,
        notifyTargetWorkspace,
      ],
    }),
    // notifications from other vtex.broadcaster instances
    notifySelf: method({
      POST: [
        throttle,
        parseAndValidate,
        pushNotification,
        notifyAllSubaccounts,
        notifyTargetWorkspace,
      ],
    }),
  },
})

```


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

[Assistant]
Here's the implementation:

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

export class BroadcasterClient extends AppClient {
  constructor(ioContext: IOContext, options?: InstanceOptions) {
    super('vtex.broadcaster@0.x', ioContext, {
      ...options,
      headers: {
        VtexIdclientAutCookie: ioContext.authToken,
        ...options?.headers,
      },
    })
  }

  public notify(payload: BroadcasterEvent): Promise<any> {
    return this.http.post(`/_v/self/notify`, payload, {
      headers: {
        ...this.options?.headers,
      },
    })
  }
}

```


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

[Assistant]
Here's the implementation:

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

import { BroadcasterClient } from './broadcaster'

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

```


[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 broadcaster/node/middlewares/pushNotification.ts from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { BROADCASTER_NOTIFICATION } from '../constants'

export async function pushNotification(ctx: Context, next: () => Promise<any>) {
  const {
    clients: { events },
  } = ctx

  await events.sendEvent('', BROADCASTER_NOTIFICATION, ctx.state.payload)
  ctx.status = 200

  next()
}

```


[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 broadcaster/node/middlewares/throttle.ts from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

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

const MAX_REQUEST = 50
let COUNTER = 0

export async function throttle(ctx: Context, next: () => Promise<void>) {
  const {
    vtex: { platform },
  } = ctx

  if (platform !== 'vtex') {
    return
  }

  COUNTER++
  try {
    if (COUNTER > MAX_REQUEST) {
      throw new TooManyRequestsError()
    }
    await next()
  } finally {
    COUNTER--
  }
}

```


[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 broadcaster/node/middlewares/parse.ts from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { json } from 'co-body'

import { ENABLED_GLOBALLY } from '../constants'

export async function parseAndValidate(ctx: Context, next: () => Promise<any>) {
  if (!ENABLED_GLOBALLY) {
    ctx.body = 'Service not enabled.'
    ctx.status = 200
    return
  }

  const body = (await json(ctx.req)) as BroadcasterEvent

  ctx.state.payload = body

  await next()
}

```


[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 broadcaster/node/middlewares/notifyAllSubaccounts.ts from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { BroadcasterClient } from '../clients/broadcaster'

const TIMEOUT_MS = 3000
const RETRIES = 2

export async function notifyAllSubaccounts(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    clients: { apps, licenseManager },
    state: { payload },
    vtex: { account, authToken, logger, workspace },
  } = ctx

  if (workspace !== 'master') {
    return next()
  }

  const { notifySubaccounts = false } = await apps.getAppSettings(
    `${process.env.VTEX_APP_ID}`
  )

  if (!notifySubaccounts) {
    return next()
  }

  const { accountName, sites = [] } = await licenseManager
    .getAccountData(authToken)
    .catch((error) => {
      logger.error({
        message: 'getAccountData-error',
        error,
      })
      return {}
    })

  // if accountName doesn't match the current account, then the app is running in a subaccount
  if (!accountName || accountName !== account) return next()

  // instance new client for each target subaccount
  for (const subaccount of sites) {
    // skip the main account
    if (subaccount.name !== account) {
      const broadcasterClient = new BroadcasterClient(
        {
          ...ctx.vtex,
          account: subaccount.name,
          workspace: 'master',
        },
        {
          retries: RETRIES,
          timeout: TIMEOUT_MS,
        }
      )
      broadcasterClient.notify(payload).catch((error) => {
        logger.warn({
          message: 'notifySubaccount-error',
          error,
        })
      })
    }
  }
  next()
}

```


[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 broadcaster/node/middlewares/notifyTargetWorkspace.ts from the broadcaster VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { BroadcasterClient } from '../clients/broadcaster'

const TIMEOUT_MS = 3000
const RETRIES = 2

export async function notifyTargetWorkspace(
  ctx: Context,
  next: () => Promise<any>
) {
  const {
    clients: { apps },
    state: { payload },
    vtex: { workspace },
  } = ctx

  if (workspace !== 'master') {
    return next()
  }

  const { targetWorkspace } = await apps.getAppSettings(
    `${process.env.VTEX_APP_ID}`
  )

  if (!targetWorkspace || targetWorkspace === workspace) {
    return next()
  }

  // instance new client for target workspace
  const broadcasterClient = new BroadcasterClient(
    {
      ...ctx.vtex,
      workspace: targetWorkspace,
    },
    {
      retries: RETRIES,
      timeout: TIMEOUT_MS,
    }
  )

  broadcasterClient.notify(payload).catch((error) => {
    if (error?.response?.status === 404) {
      ctx.vtex.logger.warn("Target workspace not set or doesn't exist")
    }
  })
  next()
}

```


[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 place-components/messages/sl.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Prejemnik",
  "place-components.label.country": "Država",
  "place-components.label.state": "Zvezna država",
  "place-components.label.city": "Mesto",
  "place-components.label.neighborhood": "Soseska",
  "place-components.label.streetRoadAvenue": "Ulica, cesta, avenija...",
  "place-components.label.numberOption": "Številka",
  "place-components.label.complement": "Dopolnilo",
  "place-components.label.stateAbbreviation": "Zvezna država",
  "place-components.error.fieldRequired": "To polje je obvezno",
  "place-components.label.withoutNumber": "Brez števeilke",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Uredi",
  "place-components.label.province": "Provinca",
  "place-components.label.department": "Oddelek",
  "place-components.label.region": "Regija",
  "place-components.label.community": "Skupnost",
  "place-components.label.municipality": "Občina",
  "place-components.label.district": "Okrožje",
  "place-components.label.locality": "Predel",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brazilija",
  "place-components.label.BOL": "Bolivija",
  "place-components.label.KOR": "Koreja",
  "place-components.label.useCurrentLocation": "Uporabi trenutno lokacijo",
  "place-components.label.postalCode": "Poštna številka",
  "place-components.error.postalCode": "Sporočite veljavno poštno kodo.",
  "place-components.label.dontKnowPostalCode": "Ne vem svoje poštne številke",
  "place-components.label.autocompleteAddress": "Naslov (ulica, številka, trg...)",
  "place-components.label.autocompleteAddressFail": "Nismo našli nobenih rezultatov"
}

```


[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 place-components/messages/nl.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Ontvanger",
  "place-components.label.country": "Land",
  "place-components.label.state": "Staat",
  "place-components.label.city": "Stad",
  "place-components.label.neighborhood": "Buurt",
  "place-components.label.streetRoadAvenue": "Straat, weg, laan...",
  "place-components.label.numberOption": "Nummer",
  "place-components.label.complement": "Aanvulling",
  "place-components.label.stateAbbreviation": "Staat",
  "place-components.error.fieldRequired": "Dit veld is verplicht",
  "place-components.label.withoutNumber": "Zonder nummer",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Bewerk",
  "place-components.label.province": "Provincie",
  "place-components.label.department": "Afdeling",
  "place-components.label.region": "Regio",
  "place-components.label.community": "Gemeenschap",
  "place-components.label.municipality": "Gemeente",
  "place-components.label.district": "Regio",
  "place-components.label.locality": "Plaats",
  "place-components.label.ARG": "Argentinië",
  "place-components.label.BRA": "Brazilië",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Korea",
  "place-components.label.useCurrentLocation": "Gebruik huidige locatie",
  "place-components.label.postalCode": "Postcode",
  "place-components.error.postalCode": "Geef een geldige postcode op.",
  "place-components.label.dontKnowPostalCode": "Ik ken mijn postcode niet",
  "place-components.label.autocompleteAddress": "Adres (straat, nummer, plein...)",
  "place-components.label.autocompleteAddressFail": "Geen resultaten gevonden"
}

```


[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 place-components/messages/ja.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "受取人",
  "place-components.label.country": "国",
  "place-components.label.state": "州",
  "place-components.label.city": "都市",
  "place-components.label.neighborhood": "近所",
  "place-components.label.streetRoadAvenue": "通り、道、アベニュー…",
  "place-components.label.numberOption": "番号",
  "place-components.label.complement": "補足",
  "place-components.label.stateAbbreviation": "州",
  "place-components.error.fieldRequired": "このフィールドは必須です",
  "place-components.label.withoutNumber": "数字なし",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "編集する",
  "place-components.label.province": "県",
  "place-components.label.department": "部門",
  "place-components.label.region": "地域",
  "place-components.label.community": "コミュニティ",
  "place-components.label.municipality": "自治体",
  "place-components.label.district": "地区",
  "place-components.label.locality": "地方",
  "place-components.label.ARG": "アルゼンチン",
  "place-components.label.BRA": "ブラジル",
  "place-components.label.BOL": "ボリビア",
  "place-components.label.KOR": "大韓民国",
  "place-components.label.useCurrentLocation": "現在のロケーションを使う",
  "place-components.label.postalCode": "郵便番号",
  "place-components.error.postalCode": "有効な郵便番号を知らせてください。",
  "place-components.label.dontKnowPostalCode": "郵便番号が分かりません",
  "place-components.label.autocompleteAddress": "住所 (通り、番地、街区…)",
  "place-components.label.autocompleteAddressFail": "結果が見つかりません"
}

```


[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 place-components/messages/uk.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Одержувач",
  "place-components.label.country": "Країна",
  "place-components.label.state": "Штат",
  "place-components.label.city": "Місто",
  "place-components.label.neighborhood": "Мікрорайон",
  "place-components.label.streetRoadAvenue": "Вулиця, проспект, провулок...",
  "place-components.label.numberOption": "Номер",
  "place-components.label.complement": "Доповнення",
  "place-components.label.stateAbbreviation": "Штат",
  "place-components.error.fieldRequired": "Це поле обов’язкове",
  "place-components.label.withoutNumber": "Без номера",
  "place-components.label.wn": "Б/Н",
  "place-components.label.edit": "Редагувати",
  "place-components.label.province": "Провінція",
  "place-components.label.department": "Округ (якщо є)",
  "place-components.label.region": "Область",
  "place-components.label.community": "Мікрорайон",
  "place-components.label.municipality": "Муніципалітет",
  "place-components.label.district": "Район",
  "place-components.label.locality": "Населений пункт",
  "place-components.label.ARG": "Аргентина",
  "place-components.label.BRA": "Бразилія",
  "place-components.label.BOL": "Болівія",
  "place-components.label.KOR": "Корея",
  "place-components.label.useCurrentLocation": "Використовувати поточне місцезнаходження",
  "place-components.label.postalCode": "Поштовий індекс",
  "place-components.error.postalCode": "Вкажіть правильний поштовий індекс.",
  "place-components.label.dontKnowPostalCode": "Я не знаю свого поштового індексу",
  "place-components.label.autocompleteAddress": "Адреса (вулиця, номер...)",
  "place-components.label.autocompleteAddressFail": "Результати не знайдено"
}

```


[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 place-components/messages/fi.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Vastaanottaja",
  "place-components.label.country": "Maa",
  "place-components.label.state": "Osavaltio",
  "place-components.label.city": "Kaupunki",
  "place-components.label.neighborhood": "Alue",
  "place-components.label.streetRoadAvenue": "Katu",
  "place-components.label.numberOption": "Numero",
  "place-components.label.complement": "Täydennä",
  "place-components.label.stateAbbreviation": "Osavaltio",
  "place-components.error.fieldRequired": "Tämä kenttä on pakollinen",
  "place-components.label.withoutNumber": "Ilman numeroa",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Muokkaa",
  "place-components.label.province": "Lääni",
  "place-components.label.department": "Osasto",
  "place-components.label.region": "Maakunta",
  "place-components.label.community": "Kunta",
  "place-components.label.municipality": "Kunta",
  "place-components.label.district": "Kaupunginosa",
  "place-components.label.locality": "Paikkakunta",
  "place-components.label.ARG": "Argentiina",
  "place-components.label.BRA": "Brasilia",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Korea",
  "place-components.label.useCurrentLocation": "Käytä nykyistä sijaintia",
  "place-components.label.postalCode": "Postinumero",
  "place-components.error.postalCode": "Anna kelpaava postinumero.",
  "place-components.label.dontKnowPostalCode": "En tiedä postinumeroani",
  "place-components.label.autocompleteAddress": "Osoite (katu, numero...)",
  "place-components.label.autocompleteAddressFail": "Tuloksia ei löytynyt"
}

```


[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 place-components/messages/sk.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Príjemca",
  "place-components.label.country": "Krajina",
  "place-components.label.state": "Štát",
  "place-components.label.city": "Mesto",
  "place-components.label.neighborhood": "Štvrť",
  "place-components.label.streetRoadAvenue": "Názov ulice...",
  "place-components.label.numberOption": "Číslo",
  "place-components.label.complement": "Dodatok",
  "place-components.label.stateAbbreviation": "Štát",
  "place-components.error.fieldRequired": "Toto pole je povinné",
  "place-components.label.withoutNumber": "Bez čísla",
  "place-components.label.wn": "S číslom",
  "place-components.label.edit": "Upraviť",
  "place-components.label.province": "Provincia",
  "place-components.label.department": "Departement",
  "place-components.label.region": "Región",
  "place-components.label.community": "Komunita",
  "place-components.label.municipality": "Samospráva",
  "place-components.label.district": "Oblasť",
  "place-components.label.locality": "Lokalita",
  "place-components.label.ARG": "Argentína",
  "place-components.label.BRA": "Brazília",
  "place-components.label.BOL": "Bolívia",
  "place-components.label.KOR": "Kórea",
  "place-components.label.useCurrentLocation": "Použiť aktuálnu polohu",
  "place-components.label.postalCode": "PSČ",
  "place-components.error.postalCode": "Zadajte platné poštové smerovacie číslo.",
  "place-components.label.dontKnowPostalCode": "Neviem PSČ",
  "place-components.label.autocompleteAddress": "Adresa (ulica, číslo, námestie…)",
  "place-components.label.autocompleteAddressFail": "Nenašli sa žiadne výsledky"
}

```


[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 place-components/messages/pt.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Destinatário",
  "place-components.label.country": "País",
  "place-components.label.state": "Estado",
  "place-components.label.city": "Cidade",
  "place-components.label.neighborhood": "Bairro",
  "place-components.label.streetRoadAvenue": "Rua, Avenida...",
  "place-components.label.numberOption": "Número",
  "place-components.label.complement": "Complemento",
  "place-components.label.stateAbbreviation": "Estado",
  "place-components.error.fieldRequired": "Este campo é obrigatório",
  "place-components.label.withoutNumber": "Sem número",
  "place-components.label.wn": "S/N",
  "place-components.label.edit": "Editar",
  "place-components.label.province": "Província",
  "place-components.label.department": "Departamento",
  "place-components.label.region": "Região",
  "place-components.label.community": "Comunidade",
  "place-components.label.municipality": "Municipalidade",
  "place-components.label.district": "Distrito",
  "place-components.label.locality": "Localidade",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brasil",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Coreia do Sul",
  "place-components.label.useCurrentLocation": "Usar localização atual",
  "place-components.label.postalCode": "CEP",
  "place-components.error.postalCode": "Informe um CEP válido.",
  "place-components.label.dontKnowPostalCode": "Não sei meu CEP",
  "place-components.label.autocompleteAddress": "Endereço (rua, número, quadra...)",
  "place-components.label.autocompleteAddressFail": "Nenhum resultado encontrado"
}

```


[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 place-components/messages/en.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Receiver",
  "place-components.label.country": "Country",
  "place-components.label.state": "State",
  "place-components.label.city": "City",
  "place-components.label.neighborhood": "Neighborhood",
  "place-components.label.streetRoadAvenue": "Street, Road, Avenue...",
  "place-components.label.numberOption": "Number",
  "place-components.label.complement": "Complement",
  "place-components.label.stateAbbreviation": "State",
  "place-components.error.fieldRequired": "This field is required",
  "place-components.label.withoutNumber": "Without number",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Edit",
  "place-components.label.province": "Province",
  "place-components.label.department": "Department",
  "place-components.label.region": "Region",
  "place-components.label.community": "Community",
  "place-components.label.municipality": "Municipality",
  "place-components.label.district": "District",
  "place-components.label.locality": "Locality",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brazil",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Korea",
  "place-components.label.useCurrentLocation": "Use current location",
  "place-components.label.postalCode": "Postal Code",
  "place-components.error.postalCode": "Inform a valid postal code.",
  "place-components.label.dontKnowPostalCode": "I don't know my postal code",
  "place-components.label.autocompleteAddress": "Address (street, number, square...)",
  "place-components.label.autocompleteAddressFail": "No results found"
}

```


[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 place-components/messages/fr.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Destinataire",
  "place-components.label.country": "Pays",
  "place-components.label.state": "État",
  "place-components.label.city": "Ville",
  "place-components.label.neighborhood": "Voisinage",
  "place-components.label.streetRoadAvenue": "Rue, Route, Avenue...",
  "place-components.label.numberOption": "Numéro",
  "place-components.label.complement": "Complément",
  "place-components.label.stateAbbreviation": "État",
  "place-components.error.fieldRequired": "Ce champ est obligatoire",
  "place-components.label.withoutNumber": "Sans numéro",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Modifier",
  "place-components.label.province": "Province",
  "place-components.label.department": "Département",
  "place-components.label.region": "Région",
  "place-components.label.community": "Agglomération",
  "place-components.label.municipality": "Municipalité",
  "place-components.label.district": "Quartier",
  "place-components.label.locality": "Lieu-dit",
  "place-components.label.ARG": "Argentine",
  "place-components.label.BRA": "Brésil",
  "place-components.label.BOL": "Bolivie",
  "place-components.label.KOR": "Korea",
  "place-components.label.useCurrentLocation": "Utiliser la position actuelle",
  "place-components.label.postalCode": "Code postal",
  "place-components.error.postalCode": "Code postal non valable.",
  "place-components.label.dontKnowPostalCode": "Je ne connais pas mon code postal",
  "place-components.label.autocompleteAddress": "Adresse (rue, numéro, quartier...)",
  "place-components.label.autocompleteAddressFail": "Aucun résultat"
}

```


[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 place-components/messages/el.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Παραλήπτης",
  "place-components.label.country": "Χώρα",
  "place-components.label.state": "Πολιτεία",
  "place-components.label.city": "Πόλη",
  "place-components.label.neighborhood": "Γειτονιά",
  "place-components.label.streetRoadAvenue": "Οδός, δρόμος, λεωφόρος...",
  "place-components.label.numberOption": "Αριθμός",
  "place-components.label.complement": "Συμπλήρωμα",
  "place-components.label.stateAbbreviation": "Πολιτεία",
  "place-components.error.fieldRequired": "Αυτό το πεδίο είναι υποχρεωτικό",
  "place-components.label.withoutNumber": "Χωρίς αριθμό",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Επεξεργασία",
  "place-components.label.province": "Επαρχία",
  "place-components.label.department": "Τμήμα",
  "place-components.label.region": "Περιοχή",
  "place-components.label.community": "Κοινότητα",
  "place-components.label.municipality": "Δήμος",
  "place-components.label.district": "Περιοχή",
  "place-components.label.locality": "Τοποθεσία",
  "place-components.label.ARG": "Αργεντινή",
  "place-components.label.BRA": "Βραζιλία",
  "place-components.label.BOL": "Βολιβία",
  "place-components.label.KOR": "Κορέα",
  "place-components.label.useCurrentLocation": "Χρήση τρέχουσας τοποθεσίας",
  "place-components.label.postalCode": "Ταχυδρομικός κώδικας",
  "place-components.error.postalCode": "Ενημέρωση εγκύρου ταχυδρομικού κώδικα.",
  "place-components.label.dontKnowPostalCode": "Δεν γνωρίζω τον ταχυδρομικό μου κώδικα",
  "place-components.label.autocompleteAddress": "Διεύθυνση (οδός, αριθμός, πλατεία...)",
  "place-components.label.autocompleteAddressFail": "Δεν βρέθηκαν αποτελέσματα"
}

```


[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 place-components/messages/ro.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Destinatar",
  "place-components.label.country": "Țara",
  "place-components.label.state": "Stat",
  "place-components.label.city": "Oraș",
  "place-components.label.neighborhood": "Cartier",
  "place-components.label.streetRoadAvenue": "Stradă, alee, bulevard...",
  "place-components.label.numberOption": "Număr",
  "place-components.label.complement": "Complement",
  "place-components.label.stateAbbreviation": "Stat",
  "place-components.error.fieldRequired": "Acest câmp este obligatoriu",
  "place-components.label.withoutNumber": "Fără număr",
  "place-components.label.wn": "Fără număr",
  "place-components.label.edit": "Editează",
  "place-components.label.province": "Provincie",
  "place-components.label.department": "Raion",
  "place-components.label.region": "Regiune",
  "place-components.label.community": "Sat",
  "place-components.label.municipality": "Municipalitate",
  "place-components.label.district": "Sector",
  "place-components.label.locality": "Localitate",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brazilia",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Coreea",
  "place-components.label.useCurrentLocation": "Folosește locația actuală",
  "place-components.label.postalCode": "Cod poștal",
  "place-components.error.postalCode": "Introdu un cod poștal valid.",
  "place-components.label.dontKnowPostalCode": "Nu îmi știu codul poștal",
  "place-components.label.autocompleteAddress": "Adresa (stradă, număr, piață...)",
  "place-components.label.autocompleteAddressFail": "Nu s-au găsit rezultate"
}

```


[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 place-components/messages/ko.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "받는 사람",
  "place-components.label.country": "국가",
  "place-components.label.state": "주",
  "place-components.label.city": "도시",
  "place-components.label.neighborhood": "인근 지역",
  "place-components.label.streetRoadAvenue": "거리, 도로...",
  "place-components.label.numberOption": "숫자",
  "place-components.label.complement": "보완",
  "place-components.label.stateAbbreviation": "주",
  "place-components.error.fieldRequired": "해당 입력란은 필수 입력 사항입니다",
  "place-components.label.withoutNumber": "숫자없이",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "편집",
  "place-components.label.province": "주",
  "place-components.label.department": "부문",
  "place-components.label.region": "지역",
  "place-components.label.community": "커뮤니티",
  "place-components.label.municipality": "시",
  "place-components.label.district": "지역",
  "place-components.label.locality": "인근",
  "place-components.label.ARG": "아르헨티나",
  "place-components.label.BRA": "브라질",
  "place-components.label.BOL": "볼리비아",
  "place-components.label.KOR": "한국",
  "place-components.label.useCurrentLocation": "현재 위치 사용",
  "place-components.label.postalCode": "우편번호",
  "place-components.error.postalCode": "유효한 우편 번호를 알려 주세요.",
  "place-components.label.dontKnowPostalCode": "우편 번호를 모릅니다",
  "place-components.label.autocompleteAddress": "주소(거리, 번호, 스퀘어...)",
  "place-components.label.autocompleteAddressFail": "결과를 찾을 수 없음"
}

```


[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 place-components/messages/no.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Mottaker",
  "place-components.label.country": "Land",
  "place-components.label.state": "Stat",
  "place-components.label.city": "By",
  "place-components.label.neighborhood": "Nabolag",
  "place-components.label.streetRoadAvenue": "Gate, vei, allé ...",
  "place-components.label.numberOption": "Nummer",
  "place-components.label.complement": "Komplement",
  "place-components.label.stateAbbreviation": "Stat",
  "place-components.error.fieldRequired": "Dette feltet er obligatorisk",
  "place-components.label.withoutNumber": "Uten nummer",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Rediger",
  "place-components.label.province": "Provins",
  "place-components.label.department": "Avdeling",
  "place-components.label.region": "Region",
  "place-components.label.community": "Samfunn",
  "place-components.label.municipality": "Kommune",
  "place-components.label.district": "Distrikt",
  "place-components.label.locality": "Lokalitet",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brasil",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Korea",
  "place-components.label.useCurrentLocation": "Bruk nåværende posisjon",
  "place-components.label.postalCode": "Postnummer",
  "place-components.error.postalCode": "Informer om gyldig postnummer.",
  "place-components.label.dontKnowPostalCode": "Jeg vet ikke postnummeret mitt",
  "place-components.label.autocompleteAddress": "Adresse (gate, nummer, plass...)",
  "place-components.label.autocompleteAddressFail": "Fant ingen resultater"
}

```


[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 place-components/messages/da.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Modtager",
  "place-components.label.country": "Land",
  "place-components.label.state": "Stat",
  "place-components.label.city": "By",
  "place-components.label.neighborhood": "Nabolag",
  "place-components.label.streetRoadAvenue": "Gade, vej, boulevard...",
  "place-components.label.numberOption": "Nummer",
  "place-components.label.complement": "Udførsel",
  "place-components.label.stateAbbreviation": "Stat",
  "place-components.error.fieldRequired": "Dette felt er påkrævet",
  "place-components.label.withoutNumber": "Uden nummer",
  "place-components.label.wn": "W/N",
  "place-components.label.edit": "Rediger",
  "place-components.label.province": "Provins",
  "place-components.label.department": "Afdeling",
  "place-components.label.region": "Region",
  "place-components.label.community": "Fællesskab",
  "place-components.label.municipality": "Kommune",
  "place-components.label.district": "Distrikt",
  "place-components.label.locality": "Lokalitet",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brasilien",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Korea",
  "place-components.label.useCurrentLocation": "Brug nuværende placering",
  "place-components.label.postalCode": "Postnummer",
  "place-components.error.postalCode": "Skriv et gyldigt postnummer.",
  "place-components.label.dontKnowPostalCode": "Jeg kender ikke min postnummer",
  "place-components.label.autocompleteAddress": "Adresse (gade, nummer, torv...)",
  "place-components.label.autocompleteAddressFail": "Ingen resultater blev fundet"
}

```


[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 place-components/messages/es.json from the place-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "place-components.label.receiverName": "Destinatario",
  "place-components.label.country": "País",
  "place-components.label.state": "Estado",
  "place-components.label.city": "Ciudad",
  "place-components.label.neighborhood": "Barrio",
  "place-components.label.streetRoadAvenue": "Calle, Avenida...",
  "place-components.label.numberOption": "Número",
  "place-components.label.complement": "Complemento",
  "place-components.label.stateAbbreviation": "Estado",
  "place-components.error.fieldRequired": "Este campo es obligatorio",
  "place-components.label.withoutNumber": "Sin número",
  "place-components.label.wn": "S/N",
  "place-components.label.edit": "Editar",
  "place-components.label.province": "Provincia",
  "place-components.label.department": "Departamento",
  "place-components.label.region": "Región",
  "place-components.label.community": "Comunidad",
  "place-components.label.municipality": "Municipalidad",
  "place-components.label.district": "Distrito",
  "place-components.label.locality": "Localidad",
  "place-components.label.ARG": "Argentina",
  "place-components.label.BRA": "Brasil",
  "place-components.label.BOL": "Bolivia",
  "place-components.label.KOR": "Corea del Sur",
  "place-components.label.useCurrentLocation": "Usar ubicación actual",
  "place-components.label.postalCode": "Código Postal",
  "place-components.error.postalCode": "Ingresse un código postal válido.",
  "place-components.label.dontKnowPostalCode": "No sé mi código postal",
  "place-components.label.autocompleteAddress": "Dirección (calle, número, plaza...)",
  "place-components.label.autocompleteAddressFail": "Sin resultados"
}

```


[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 place-components/docs/README.md from the place-components VTEX app.

[Assistant]
Here's the implementation:

```markdown
# Place Components

⚠ **This is an ongoing, unsupported, unfinished and undocumented project. We do not guarantee any results after installation.** ⚠

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

The Place Components are three components (`PlaceDetails`, `AddressForm`, and `LocationForm`) that are meant to replace the [AddressForm](https://github.com/vtex/address-form) repository.

The Place Components should always be rendered inside their wrapper orchestrator, called [AddressContext](https://github.com/vtex-apps/address-context). This orchestrator provides the address information and an API to alter it.

For all the following components, you can run tests with `vtex test` from the root repository.

To manually test internationalization, you can switch the locale information by adding the query string `?cultureInfo={locale}`, like `?cultureInfo=en`. More information in the [Locale Switcher repository](https://github.com/vtex-apps/locale-switcher).

Country data is sorted according to [Figma designs](https://www.figma.com/file/umwHrHA8nifvQIPEN3DHpX/Onda-Store---Place-Components?node-id=0%3A1) for this project, more specifically, to the [spreadsheet](https://docs.google.com/spreadsheets/d/1_sbwzLlgzFPsddPRTq6kcpbMyoxgOBfb1T8YRQs3k7k/edit#gid=0) defining the mapping between the API names and the "fantasy" names. This fantasy name is explicitly set in the "label" property, and that one is always placed first. The fantasy name of the field determines the styling it receives.

## Place Details

The Place Details component displays a summary of a place according to the address it receives from the wrapper orchestrator, and the description of the structure that receives as prop. There are three variations of PlaceDetails according to the amount of information that needs to be shown in a particular scenario. Below you can see a description of them.

- **Extended**: complete address, with all information that's necessary for carriers and users to identify it.
- **Compact**: displays details gathered through LocationForm or from its info.
- **Minimal**: only the information that the user inputed in LocationInput or LocationSelect.

## Address Form

The Address Form component displays inputs and selects to add/edit information contained in the `Address` object it receives from the wrapper orchestrator, and it also displays already filled data using the `PlaceDetails` component.

At first, the `AddressForm` renders a `PlaceDetails` with compact display mode, and edit button, and the rest of the fields as inputs/selects to complete the information. When the user clicks the edit button, it changes to render a `PlaceDetails` component in minimal display mode, and the rest of the fields as inputs/selects.

In the previous [AddressForm](https://github.com/vtex/address-form) repository, some of the fields are rendered as dropdowns, and some of those dropdowns depend on another (imagine selecting state, and then selecting city). In the new place components, that complex logic is only meant for the `LocationForm` (that is, when first selecting the address).

## Location Form

The Location Form is a component that is used when the user wants to **inserts** address information to a system, it's built up of many components.

### LocationCountry

The Location Country component is meant to replace the current `CountrySelector` component from Checkout V6. It's main task is to let the user select a country, and it has the added functionality of trying to guess a suitable country so that the user is not bothered in selecting such a (nowadays) obvious-to-get information.

### LocationForm

The Location Form component gathers the most basic details about a particular address, and it is formed by three inner components.

#### LocationField (Search)

The Location Search is a component that suggests a list of addresses based on a search term. A plug and play feature allows the usage of a custom address database and search algorithm (this feature is currently under construction).

#### LocationField (Input)

To be done.

#### LocationField (Select)

The LocationField Select renders a set of select components (called `Dropdown` in our styleguide) such that one depends on the other. This is used, for example, to first display a list of states, and based on that selection of states then display a list of cities, and based on the selected cities, to display a list of neighborhoods, etc.

### DeviceCoordinates

The `DeviceCoordinates` component renders a simple button that will ask for your permission to get the location from your device. In case the user allows this, the component will modify the address object from the `address-context` automatically filling data based on the lat/lng information gained through the browser. To do this autocompletion, this component communicates with the `places-graphql` project.

## Configuration

TBC

## Customization

🚧 To be defined.

<!-- 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 -->
<!-- markdownlint-enable -->
<!-- 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 -->

```


[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 place-components/react/formatAddressToString.ts from the place-components VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { Address } from 'vtex.checkout-graphql'
import { CountryRules, AddressFields } from 'vtex.address-context/types'
import msk from 'msk'
import { DisplayData } from 'vtex.country-data-settings'

import { FieldName } from './useAddressForm'

const isAddressField = (field: string): field is AddressFields =>
  (field as AddressFields) !== undefined

export default function formatAddressToString(
  address: Address,
  rules: CountryRules,
  displayType: keyof Omit<DisplayData, '__typename'> = 'compact'
) {
  const displaySpec = rules.display[displayType]

  return displaySpec
    .map((line) =>
      line.filter(({ name }) => isAddressField(name) && address[name])
    )
    .filter((line) => line.length > 0)
    .map((line) =>
      line
        .map((fragment, index) => {
          const hasPreviousFragment =
            index > 0 && address[line[index - 1].name as FieldName]

          const hasNextFragment =
            index + 1 < line.length &&
            address[line[index + 1].name as FieldName]

          const hasDifferentDelimiter = fragment.delimiterAfter !== '-'
          const shouldShowDelimiter = hasNextFragment ?? hasDifferentDelimiter

          const valueMask =
            fragment.name in rules.fields
              ? rules.fields[fragment.name as FieldName]?.mask
              : undefined

          const fragmentValue = valueMask
            ? msk(address[fragment.name as FieldName] as string, valueMask)
            : address[fragment.name as FieldName]

          return [
            hasPreviousFragment && fragment.delimiter,
            fragmentValue,
            shouldShowDelimiter && fragment.delimiterAfter,
          ]
            .filter(Boolean)
            .join(' ')
        })
        .join(' ')
    )
    .join(' ')
}

```


[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 place-components/react/LocationInput.tsx from the place-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect, useCallback, useRef } from 'react'
import { useAddressContext } from 'vtex.address-context/AddressContext'
import { IconSearch, Input, Button, ButtonPlain } from 'vtex.styleguide'
import { FormattedMessage, useIntl } from 'react-intl'
import { useLazyQuery } from 'react-apollo'
import msk from 'msk'
import {
  Address,
  Query,
  QueryGetAddressFromPostalCodeArgs,
} from 'vtex.places-graphql'

import GET_ADDRESS_FROM_POSTAL_CODE from './graphql/getAddressFromPostalCode.graphql'
import styles from './LocationInput.css'
import { useCountry } from './useCountry'

interface Props {
  onSuccess?: (address: Address) => void | Promise<void>
  variation?: 'primary' | 'secondary'
}

const LocationInput: React.FC<Props> = ({
  variation = 'secondary',
  onSuccess,
}) => {
  const { setAddress, rules } = useAddressContext()
  const intl = useIntl()
  const [inputValue, setInputValue] = useState('')
  // the network-only fetch policy asserts that if an incorrect postal code
  // has been submitted twice in a row, it won't return the cached error,
  // re-triggering the effect hook and avoiding an infinite loop state
  const [executeGetAddressFromPostalCode, { error, data }] = useLazyQuery<
    Query,
    QueryGetAddressFromPostalCodeArgs
  >(GET_ADDRESS_FROM_POSTAL_CODE, { fetchPolicy: 'network-only' })

  const [loading, setLoading] = useState(false)
  const [invalidPostalCode, setInvalidPostalCode] = useState(false)

  const country = useCountry()
  const countryRules = rules[country]

  const prevCountryRulesRef = useRef(countryRules)

  const formatAndValidate = useCallback(() => {
    const { mask, pattern } = countryRules?.fields.postalCode ?? {}

    if (!mask) {
      return
    }

    setInputValue(msk(inputValue, mask))
    const patternInvalid =
      inputValue.length && pattern && !inputValue.match(pattern)

    if (patternInvalid) {
      setInvalidPostalCode(true)
    }
  }, [countryRules?.fields.postalCode, inputValue])

  useEffect(() => {
    if (prevCountryRulesRef.current === countryRules) {
      return
    }

    prevCountryRulesRef.current = countryRules
    setInvalidPostalCode(false)
    formatAndValidate()
  }, [countryRules, formatAndValidate])

  useEffect(() => {
    let cancelled = false

    if (data?.getAddressFromPostalCode) {
      // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
      ;(onSuccess?.(data.getAddressFromPostalCode) || Promise.resolve())
        .then(() => {
          setAddress((prevAddress) => ({
            ...prevAddress,
            ...data.getAddressFromPostalCode,
          }))

          if (cancelled) {
            return
          }

          setLoading(false)
        })
        .catch(() => {
          if (cancelled) {
            return
          }

          setInvalidPostalCode(true)
          setLoading(false)
        })
    }

    if (error) {
      console.error(error.message)
      setInvalidPostalCode(true)
      setLoading(false)
    }

    return () => {
      cancelled = true
    }
  }, [data, error, onSuccess, setAddress])

  const handleSubmit: React.EventHandler<
    React.FormEvent<HTMLFormElement> | React.MouseEvent<HTMLButtonElement>
  > = (event) => {
    event.preventDefault()
    if (invalidPostalCode) {
      return
    }

    setLoading(true)
    executeGetAddressFromPostalCode({
      variables: {
        postalCode: inputValue,
        countryCode: country,
      },
    })
  }

  const handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (
    event
  ) => {
    if (invalidPostalCode) {
      setInvalidPostalCode(false)
    }

    setInputValue(event.target.value)
  }

  const handleKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (
    event
  ) => {
    if (event.key === 'Enter') {
      formatAndValidate()
    }
  }

  if (!countryRules) {
    return null
  }

  return (
    <div className="w-100">
      <form className={`${styles.locationInput} mb4`} onSubmit={handleSubmit}>
        <Input
          id="postal-code-input"
          label={<FormattedMessage id="place-components.label.postalCode" />}
          suffix={
            <Button
              id="submit-postal-code-button"
              type="submit"
              onClick={handleSubmit}
              isLoading={loading}
              variation={variation}
            >
              <IconSearch />
            </Button>
          }
          size="large"
          value={inputValue}
          onChange={handleInputChange}
          onBlur={formatAndValidate}
          onKeyDown={handleKeyDown}
          disabled={loading}
          error={invalidPostalCode}
          errorMessage={
            invalidPostalCode
              ? intl.formatMessage({ id: 'place-components.error.postalCode' })
              : undefined
          }
        />
      </form>
      {countryRules.fields.postalCode?.additionalData?.forgottenURL && (
        <ButtonPlain
          href={countryRules.fields.postalCode.additionalData.forgottenURL}
          target="_blank noreferrer"
        >
          <FormattedMessage id="place-components.label.dontKnowPostalCode" />
        </ButtonPlain>
      )}
    </div>
  )
}

export default LocationInput

```


[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 place-components/react/LocationInput.css from the place-components VTEX app.

[Assistant]
Here's the implementation:

```css
.locationInput :global(.vtex-input) input {
  width: auto;
  flex: 1;
  min-width: 0;
}

.locationInput :global(.vtex-input__suffix) {
  padding: 0;
}

.locationInput :global(.vtex-button) {
  min-height: auto;
  margin: .125rem;
  align-self: stretch;
}

@media only screen and (min-width: 40em) {
  .locationInput :global(.vtex-input-prefix__group) {
    height: 2.5rem;
  }

  .locationInput :global(.vtex-button) {
    width: 3.25rem;
  }

  .locationInput :global(.vtex-button__label) {
    padding: 0;
  }
}

```


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

[User] Show me the implementation of place-components/react/PlaceDetails.tsx from the place-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import msk from 'msk'
import React from 'react'
import { useAddressContext } from 'vtex.address-context/AddressContext'
import { AddressFields } from 'vtex.address-context/types'
import { ButtonPlain } from 'vtex.styleguide'
import { useIntl, defineMessages } from 'react-intl'
import { DisplayData } from 'vtex.country-data-settings'

import { FieldName } from './useAddressForm'
import { useCountry } from './useCountry'

interface Props {
  display?: keyof Omit<DisplayData, '__typename'>
  hiddenFields?: AddressFields[]
  onEdit?: () => void
}

const messages = defineMessages({
  edit: {
    defaultMessage: '',
    id: 'place-components.label.edit',
  },
})

const PlaceDetails: React.FC<Props> = ({
  display = 'extended',
  hiddenFields = [],
  onEdit,
}) => {
  const { address, rules } = useAddressContext()
  const country = useCountry()
  const countryRules = rules[country]

  const intl = useIntl()

  if (!countryRules) {
    return null
  }

  const displaySpec = countryRules.display[display]

  return (
    <div className="flex flex-column">
      {displaySpec
        .map((line) => {
          return line.filter(
            (fragment) =>
              address[fragment.name as FieldName] &&
              !hiddenFields.includes(fragment.name as FieldName)
          )
        })
        .filter((line) => line.length > 0)
        .map((line, displayIndex) => (
          <div className="flex" key={displayIndex}>
            {line.map((fragment, index) => {
              const hasPreviousFragment =
                index > 0 && address[line[index - 1].name as FieldName]

              const hasNextFragment =
                index + 1 < line.length &&
                address[line[index + 1].name as FieldName]

              const hasDifferentDelimiter = fragment.delimiterAfter !== '-'
              const shouldShowDelimiter =
                hasNextFragment ?? hasDifferentDelimiter

              const valueMask =
                fragment.name in countryRules.fields
                  ? countryRules.fields[fragment.name as FieldName]?.mask
                  : undefined

              const addressValue = valueMask
                ? msk(address[fragment.name as FieldName] as string, valueMask)
                : address[fragment.name as FieldName]

              return (
                <div className="dib" key={fragment.name}>
                  {fragment.delimiter && hasPreviousFragment && (
                    <span style={{ whiteSpace: 'pre-wrap' }}>
                      {fragment.delimiter}
                    </span>
                  )}
                  <span className={fragment.name}>{addressValue}</span>
                  {fragment.delimiterAfter && shouldShowDelimiter && (
                    <span style={{ whiteSpace: 'pre-wrap' }}>
                      {fragment.delimiterAfter}
                    </span>
                  )}
                </div>
              )
            })}
            {onEdit && displayIndex === 0 && (
              <div className="ml4 flex items-center">
                <ButtonPlain onClick={onEdit}>
                  <span className="ttl">
                    {intl.formatMessage(messages.edit)}
                  </span>
                </ButtonPlain>
              </div>
            )}
          </div>
        ))}
    </div>
  )
}

export default PlaceDetails

```