[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 search/react/components/Autocomplete/index.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
// /* eslint-disable no-restricted-syntax */
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
import React from 'react'
import { withApollo, WithApolloClient } from 'react-apollo'
import { FormattedMessage } from 'react-intl'
import { IconClose, IconClock } from 'vtex.styleguide'
import { ProductListContext } from 'vtex.product-list-context'
import { withDevice } from 'vtex.device-detector'
import debounce from 'debounce'
import { withPixel } from 'vtex.pixel-manager/PixelContext'

import BiggyClient from '../../utils/biggy-client'
import stylesCss from './styles.css'
import TileList from './components/TileList/TileList'
import {
  Item,
  instanceOfAttributeItem,
  AttributeItem,
} from './components/ItemList/types'
import { ItemList } from './components/ItemList/ItemList'
import { withRuntime } from '../../utils/withRuntime'
import { decodeUrlString, encodeUrlString } from '../../utils/string-utils'
import {
  EventType,
  handleAutocompleteSearch,
  handleItemClick,
  handleProductClick,
  handleSeeAllClick,
} from '../../utils/pixel'
import getSession from '../../utils/getSession'

const MAX_TOP_SEARCHES_DEFAULT = 10
const MAX_SUGGESTED_TERMS_DEFAULT = 5
const MAX_SUGGESTED_PRODUCTS_DEFAULT = 3
const MAX_HISTORY_DEFAULT = 5

// eslint-disable-next-line no-shadow, no-restricted-syntax
export enum ProductLayout {
  Horizontal = 'HORIZONTAL',
  Vertical = 'VERTICAL',
}

interface AutoCompleteProps {
  isOpen: boolean
  runtime: { page: string; rootPath?: string }
  inputValue: string
  maxTopSearches: number
  maxSuggestedTerms: number
  maxSuggestedProducts: number
  maxHistory: number
  autocompleteWidth: number
  productLayout?: ProductLayout
  hideTitles: boolean
  historyFirst: boolean
  isMobile: boolean
  customBreakpoints?: {
    md: {
      width: number
      maxSuggestedProducts: number
    }
    lg: {
      width: number
      maxSuggestedProducts: number
    }
    xlg: {
      width: number
      maxSuggestedProducts: number
    }
  }
  __unstableProductOrigin: 'BIGGY' | 'VTEX'
  __unstableProductOriginVtex: boolean
  simulationBehavior: 'default' | 'skip' | null
  hideUnavailableItems: boolean
  push: (data: any) => void
  HorizontalProductSummary?: React.ComponentType<{
    product: Product
    placement: string
    actionOnClick: () => void
  }>
  customPage?: string
  closeMenu: () => void
  orderBy?: string
}

interface AutoCompleteState {
  topSearchedItems: Item[]
  suggestionItems: Item[]
  history: Item[]
  products: any[]
  totalProducts: number
  queryFromHover: { key?: string; value?: string }
  dynamicTerm: string
  isProductsLoading: boolean
  currentHeightWhenOpen: number
  searchId: string
}

const { ProductListProvider } = ProductListContext

class AutoComplete extends React.Component<
  WithApolloClient<AutoCompleteProps>,
  Partial<AutoCompleteState>
> {
  autocompleteRef: React.RefObject<any>
  client: BiggyClient
  isIOS: boolean

  public readonly state: AutoCompleteState = {
    topSearchedItems: [],
    history: [],
    products: [],
    suggestionItems: [],
    totalProducts: 0,
    queryFromHover: {},
    dynamicTerm: '',
    isProductsLoading: false,
    currentHeightWhenOpen: 0,
    searchId: '',
  }

  constructor(props: WithApolloClient<AutoCompleteProps>) {
    super(props)

    this.client = new BiggyClient(this.props.client)
    this.autocompleteRef = React.createRef()
    this.isIOS = navigator && !!navigator.userAgent.match(/(iPod|iPhone|iPad)/)
  }

  fitAutocompleteInWindow() {
    if (
      !window ||
      !this.autocompleteRef.current ||
      !this.props.isMobile ||
      this.isIOS
    ) {
      return
    }

    const windowHeight = window.innerHeight
    const autocompletePosition = this.autocompleteRef.current.getBoundingClientRect()
      .y

    const autocompleteHeight = this.autocompleteRef.current.offsetHeight
    // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
    const autocompleteEnd = autocompletePosition + autocompleteHeight

    const currentHeight = autocompleteHeight - (autocompleteEnd - windowHeight)

    this.autocompleteRef.current.style.maxHeight = `${currentHeight}px`
  }

  addEvents() {
    window.addEventListener(
      'resize',
      debounce(this.fitAutocompleteInWindow.bind(this), 100)
    )
  }

  componentDidMount() {
    this.updateTopSearches()
    this.updateHistory()
    this.addEvents()
  }

  shouldUpdate(prevProps: AutoCompleteProps) {
    return (
      prevProps.inputValue !== this.props.inputValue ||
      (!prevProps.isOpen && this.props.isOpen)
    )
  }

  addTermToHistory() {
    const path = window.location.href.split('_q=')

    if (path[1]) {
      const term = path[1].split('&')[0]

      try {
        return this.client.prependSearchHistory(decodeURI(term))
      } catch {
        return this.client.prependSearchHistory(term)
      }
    }
  }

  closeModal() {
    if (this.props.closeMenu) {
      this.props.closeMenu()
    }
  }

  componentDidUpdate(prevProps: AutoCompleteProps) {
    if (!this.shouldUpdate(prevProps)) {
      return
    }

    this.addTermToHistory()
    this.fitAutocompleteInWindow()

    const { inputValue } = this.props

    this.setState({
      dynamicTerm: inputValue,
      queryFromHover: undefined,
    })

    if (inputValue === null || inputValue === '') {
      this.updateTopSearches()
      this.updateHistory()

      this.setState({
        suggestionItems: [],
        products: [],
      })
    } else {
      this.updateSuggestions()
        .then(() => {
          this.fitAutocompleteInWindow()

          return this.updateProducts(inputValue)
        })
        .then(() => this.fitAutocompleteInWindow())
    }
  }

  highlightTerm(label: string, query: string) {
    const splittedLabel = label.split(query)

    return (
      <>
        {splittedLabel.map((str: string, index: number) => {
          return (
            <>
              {str}
              {index !== splittedLabel.length - 1 ? (
                <span className="b">{query}</span>
              ) : null}
            </>
          )
        })}
      </>
    )
  }

  async updateSuggestions() {
    const result = await this.client.suggestionSearches(this.props.inputValue)
    const { searches } = result.data.autocompleteSearchSuggestions
    const { maxSuggestedTerms = MAX_SUGGESTED_TERMS_DEFAULT } = this.props

    const items = searches.slice(0, maxSuggestedTerms).map(query => {
      const attributes = query.attributes || []

      return {
        term: query.term,
        attributes: attributes.map(att => ({
          label: att.labelValue,
          value: att.value,
          link: `/${query.term}/${att.value}/?map=ft,${att.key}`,
          groupValue: query.term,
          key: att.key,
        })),
      }
    })

    const suggestionItems: Item[] = items.map(suggestion => ({
      label: this.highlightTerm(
        suggestion.term.toLowerCase(),
        this.props.inputValue.toLocaleLowerCase()
      ),
      value: suggestion.term,
      groupValue: suggestion.term,
      link: `/${suggestion.term}?map=ft`,
      attributes: suggestion.attributes,
    }))

    this.setState({ suggestionItems })
  }

  async updateProducts(itemTerm: string) {
    const term = itemTerm

    const {
      __unstableProductOrigin,
      __unstableProductOriginVtex = false,
      simulationBehavior = 'default',
      hideUnavailableItems = false,
      orderBy,
    } = this.props

    const { queryFromHover } = this.state

    if (!term) {
      this.setState({
        products: [],
        totalProducts: 0,
      })

      return
    }

    if (__unstableProductOrigin) {
      console.warn(
        'The prop `__unstableProductOrigin` has been deprecated. Use the boolean prop `__unstableProductOriginVtex` instead.'
      )
    }

    this.setState({
      isProductsLoading: true,
    })

    const session = await getSession(this.props.runtime.rootPath)
    const shippingOptions =
      session?.map((item: Record<string, string>) => item.value) ?? []

    const advertisementOptions: AdvertisementOptions = {
      showSponsored: true,
      sponsoredCount: 2,
      repeatSponsoredProducts: false,
      advertisementPlacement: 'autocomplete',
    }

    const result = await this.client.suggestionProducts(
      term,
      queryFromHover ? queryFromHover.key : undefined,
      queryFromHover ? queryFromHover.value : undefined,
      __unstableProductOrigin === 'VTEX' || __unstableProductOriginVtex,
      simulationBehavior,
      hideUnavailableItems,
      orderBy,
      this.props.maxSuggestedProducts || MAX_SUGGESTED_PRODUCTS_DEFAULT,
      shippingOptions,
      advertisementOptions
    )

    if (!queryFromHover) {
      const { count, operator, misspelled } = result.data.productSuggestions

      handleAutocompleteSearch(
        this.props.push,
        operator,
        misspelled,
        count,
        term
      )
    }

    this.setState({
      isProductsLoading: false,
    })

    const { productSuggestions } = result.data

    const products = productSuggestions.products.slice(
      0,
      this.getProductCount()
    )

    this.setState({
      products,
      totalProducts: productSuggestions.count,
      searchId: productSuggestions.searchId || '',
    })
  }

  async updateTopSearches() {
    const result = await this.client.topSearches()
    const { searches } = result.data.topSearches
    const { maxTopSearches = MAX_TOP_SEARCHES_DEFAULT } = this.props

    const topSearchedItems = searches.slice(0, maxTopSearches).map(
      (query, index) =>
        ({
          prefix: (
            <>
              {`${index + 1}`}
              <FormattedMessage id="store/ordinalNumber" />
            </>
          ),
          value: query.term,
          label: query.term,
          link: `/${query.term}?map=ft`,
        } as Item)
    )

    this.setState({ topSearchedItems })
  }

  updateHistory() {
    const history = this.client
      .searchHistory()
      .slice(0, this.props.maxHistory || MAX_HISTORY_DEFAULT)
      .map((item: string) => {
        return {
          label: decodeUrlString(item),
          value: item,
          link: `/${item}?map=ft`,
          icon: <IconClock />,
        }
      })

    this.setState({
      history,
    })
  }

  handleItemHover = (item: Item | AttributeItem) => {
    if (instanceOfAttributeItem(item)) {
      this.setState({
        dynamicTerm: item.groupValue,
        queryFromHover: {
          key: item.key,
          value: item.value,
        },
      })
      this.updateProducts(item.groupValue)
    } else {
      this.setState({
        dynamicTerm: item.value,
        queryFromHover: {
          key: undefined,
          value: undefined,
        },
      })
      this.updateProducts(item.value)
    }
  }

  renderSuggestions() {
    const hasSuggestion =
      !!this.state.suggestionItems && this.state.suggestionItems.length > 0

    const titleMessage = hasSuggestion ? (
      <FormattedMessage id="store/suggestions" />
    ) : (
      <FormattedMessage id="store/emptySuggestion" />
    )

    return (
      <ItemList
        title={titleMessage}
        items={this.state.suggestionItems || []}
        modifier="suggestion"
        showTitle={!hasSuggestion || !this.props.hideTitles}
        onItemHover={this.handleItemHover}
        showTitleOnEmpty={this.props.maxSuggestedTerms !== 0}
        onItemClick={(value, position) => {
          handleItemClick(
            this.props.push,
            this.props.runtime.page,
            EventType.SearchSuggestionClick
          )(value, position)
          this.closeModal()
        }}
        customPage={this.props.customPage}
        closeModal={() => this.closeModal()}
      />
    )
  }

  contentWhenQueryIsEmpty() {
    return (
      <div
        className={stylesCss['history-and-top-wrapper']}
        style={{
          flexDirection: this.props.historyFirst ? 'row-reverse' : 'row',
        }}
      >
        {!this.props.isMobile ||
        (this.props.isMobile && !this.props.historyFirst) ||
        this.state.history.length === 0 ? (
          <ItemList
            modifier="top-search"
            title={<FormattedMessage id="store/topSearches" />}
            items={this.state.topSearchedItems || []}
            showTitle={!this.props.hideTitles}
            onItemClick={(value, position) => {
              handleItemClick(
                this.props.push,
                this.props.runtime.page,
                EventType.TopSearchClick
              )(value, position)
              this.closeModal()
            }}
            customPage={this.props.customPage}
            closeModal={() => this.closeModal()}
          />
        ) : null}

        {!this.props.isMobile ||
        (this.props.isMobile && this.props.historyFirst) ? (
          <ItemList
            modifier="history"
            title={<FormattedMessage id="store/history" />}
            items={this.state.history || []}
            showTitle={!this.props.hideTitles}
            onItemClick={(value, position) => {
              handleItemClick(
                this.props.push,
                this.props.runtime.page,
                EventType.HistoryClick
              )(value, position)
              this.closeModal()
            }}
            customPage={this.props.customPage}
            closeModal={() => this.closeModal()}
          />
        ) : null}
      </div>
    )
  }

  contentWhenQueryIsNotEmpty() {
    const { products, totalProducts, isProductsLoading, searchId } = this.state
    const { hideTitles, push, runtime, inputValue } = this.props
    const inputValueEncoded = encodeUrlString(inputValue)

    return (
      <>
        {this.renderSuggestions()}
        <TileList
          term={inputValueEncoded || ''}
          customPage={this.props.customPage}
          shelfProductCount={this.getProductCount()}
          title={
            <FormattedMessage
              id="store/suggestedProducts"
              values={{ term: inputValue }}
            />
          }
          products={products || []}
          showTitle={!hideTitles}
          totalProducts={totalProducts || 0}
          layout={this.getProductLayout()}
          isLoading={isProductsLoading}
          onProductClick={(id, position, term) => {
            handleProductClick(push, runtime.page)(id, position, term)
            this.closeModal()
          }}
          onSeeAllClick={term => {
            handleSeeAllClick(push, runtime.page)(term)
            this.closeModal()
          }}
          HorizontalProductSummary={this.props.HorizontalProductSummary}
          searchId={searchId}
        />
      </>
    )
  }

  renderContent() {
    const query = this.props.inputValue.trim()

    return query && query !== ''
      ? this.contentWhenQueryIsNotEmpty()
      : this.contentWhenQueryIsEmpty()
  }

  hasContent() {
    const { topSearchedItems, suggestionItems, history, products } = this.state

    return (
      topSearchedItems.length > 0 ||
      suggestionItems.length > 0 ||
      history.length > 0 ||
      products.length > 0
    )
  }

  getProductLayout = () => {
    const { productLayout, isMobile } = this.props

    if (typeof productLayout !== 'undefined') {
      return productLayout
    }

    return isMobile ? ProductLayout.Horizontal : ProductLayout.Vertical
  }

  getProductCount() {
    const {
      customBreakpoints,
      isMobile,
      maxSuggestedProducts = MAX_SUGGESTED_PRODUCTS_DEFAULT,
    } = this.props

    if (!window || isMobile || !customBreakpoints) {
      return maxSuggestedProducts
    }

    const windowWidth = window.innerWidth

    if (
      !customBreakpoints.md ||
      !customBreakpoints.lg ||
      !customBreakpoints.xlg
    ) {
      return maxSuggestedProducts
    }

    if (windowWidth >= customBreakpoints.xlg.width) {
      return customBreakpoints.xlg.maxSuggestedProducts
    }

    if (windowWidth >= customBreakpoints.lg.width) {
      return customBreakpoints.lg.maxSuggestedProducts
    }

    if (windowWidth >= customBreakpoints.md.width) {
      return customBreakpoints.md.maxSuggestedProducts
    }

    return maxSuggestedProducts
  }

  render() {
    const hiddenClass =
      !this.props.isOpen || !this.hasContent()
        ? stylesCss['biggy-js-container--hidden']
        : ''

    return (
      <div
        className={stylesCss['biggy-autocomplete-wrapper']}
        style={{
          width: this.props.autocompleteWidth
            ? `${this.props.autocompleteWidth}vw`
            : undefined,
        }}
      >
        <section
          ref={this.autocompleteRef}
          // tslint:disable-next-line: max-line-length
          className={`${stylesCss['biggy-autocomplete']} ${hiddenClass} w-100`}
          style={{
            flexDirection:
              this.getProductLayout() === ProductLayout.Horizontal
                ? 'column'
                : 'row',
          }}
        >
          <ProductListProvider listName="autocomplete-result-list">
            {this.renderContent()}
            {this.props.isMobile ? (
              <button
                onClick={() => this.closeModal()}
                className={stylesCss['close-btn']}
              >
                <IconClose />
              </button>
            ) : null}
          </ProductListProvider>
        </section>
      </div>
    )
  }
}

export default withPixel(withDevice(withApollo(withRuntime(AutoComplete))))

```


[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 search/react/components/Autocomplete/styles.css from the search VTEX app.

[Assistant]
Here's the implementation:

```css
.biggy-autocomplete-wrapper {
  width: 50vw;
}

.biggy-autocomplete {
  position: absolute;
  transition: opacity 0.15s ease-in 0.05s, max-height 0.3s ease-out,
    padding 0.6s ease-out;
  padding: 20px 0 10px 0;
  max-height: 630px;
  box-shadow: 0 5px 7px rgba(0, 0, 0, 0.2);
  background: #fff;
  overflow: auto;
  display: flex;
}

.close-btn {
  cursor: pointer;
  position: absolute;
  top: 10px;
  right: 10px;
  background: none;
  border: none;
  outline: none;
}

.history-and-top-wrapper {
  display: flex;
  flex: 1;
}

.biggy-js-container--hidden {
  opacity: 0;
  max-height: 0 !important;
  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 search/react/components/Suggestions/index.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { Link } from 'vtex.render-runtime'
import { FormattedMessage } from 'react-intl'
import searchSuggestionsQuery from 'vtex.store-resources/QuerySearchSuggestions'
import { useSearchPage } from 'vtex.search-page-context/SearchPageContext'
import { useQuery } from 'react-apollo'

import styles from './styles.css'

interface SuggestionsProps {
  customPage: string
}

interface Suggestion {
  searches: Array<{
    term: string
    count: number
  }>
}

const Suggestions: FC<SuggestionsProps> = ({ customPage }) => {
  const {
    searchQuery: {
      variables: { fullText },
    },
  } = useSearchPage()

  if (!fullText) {
    return null
  }

  const { loading, data } = useQuery(searchSuggestionsQuery, {
    variables: {
      fullText,
    },
  })

  const suggestion: Suggestion | undefined = data?.searchSuggestions

  if (loading || !suggestion || suggestion.searches.length === 0) {
    return null
  }

  return (
    <div
      className={`${styles.suggestionListWrapper} flex flex-row items-center`}
    >
      <p className={`${styles.suggestionsListPrefix} mr5 b f7 ma0`}>
        <FormattedMessage id="store/searchSuggestions" />
        {': '}
      </p>
      <ul className={`${styles.suggestionsList} list flex pa0 ma0`}>
        {suggestion.searches.map(search => (
          <li className={styles.suggestionsListItem} key={search.term}>
            <Link
              className={`${styles.suggestionsListLink} link f7`}
              page={customPage || 'store.search'}
              query="map=ft"
              params={{
                term: search.term,
              }}
            >
              {search.term}
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

export default Suggestions

```


[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 search/react/components/Suggestions/styles.css from the search VTEX app.

[Assistant]
Here's the implementation:

```css
.suggestionsList li:not(:first-child):before {
    content: "-";
    margin: 0 15px;
}

.suggestionsListLink {}

.suggestionsListPrefix {}

.suggestionListWrapper {}

.suggestionsListItem {}

```


[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 search/react/components/DidYouMean/index.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { Link } from 'vtex.render-runtime'
import { useCssHandles } from 'vtex.css-handles'
import correctionQuery from 'vtex.store-resources/QueryCorrection'
import { useSearchPage } from 'vtex.search-page-context/SearchPageContext'
import { useQuery } from 'react-apollo'
import { FormattedMessage } from 'react-intl'
import React from 'react'

interface Correction {
  correction: boolean
  misspelled: boolean
  text: string
  highlighted: string
}

const CSS_HANDLES = ['didYouMeanPrefix', 'didYouMeanTerm']

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

  const {
    searchQuery: {
      variables: { fullText },
    },
  } = useSearchPage()

  const { loading, data } = useQuery(correctionQuery, {
    variables: {
      fullText,
    },
  })

  const correction: Correction = data?.correction?.correction

  return !loading && correction?.correction ? (
    <p>
      <span className={`${handles.didYouMeanPrefix} c-muted-1`}>
        <FormattedMessage id="store/didYouMean" />
        {': '}
      </span>
      <span className={handles.didYouMeanTerm}>
        <Link className="link" to={`/${correction.text}?map=ft`}>
          {correction.text}
        </Link>
      </span>
    </p>
  ) : null
}

export default DidYouMean

```


[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 search/react/components/Banner/index.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable no-restricted-syntax */
import { useCssHandles } from 'vtex.css-handles'
import bannersQuery from 'vtex.store-resources/QueryBanners'
import { useSearchPage } from 'vtex.search-page-context/SearchPageContext'
import { useQuery } from 'react-apollo'
import React from 'react'

interface ElasticBanner {
  id: string
  name: string
  area: string
  html: string
}

// eslint-disable-next-line no-shadow
enum HorizotalAlignment {
  Left = 'left',
  Right = 'right',
  Center = 'center',
}

interface BannerProps {
  area: string
  blockClass?: string
  horizontalAlignment?: HorizotalAlignment
}

interface SelectedFacet {
  key: string
  value: string
}

const getAlignmentClass = (alignment: HorizotalAlignment | undefined) => {
  switch (alignment) {
    case 'left':
      return 'justify-start'

    case 'right':
      return 'justify-end'

    default:
      return 'justify-center'
  }
}

const Banner = (props: BannerProps) => {
  const { area, horizontalAlignment } = props

  const CSS_HANDLES = ['searchBanner']
  const handles = useCssHandles(CSS_HANDLES)

  const { searchQuery } = useSearchPage()

  if (!searchQuery) {
    return null
  }

  const {
    variables: { fullText, selectedFacets },
  } = searchQuery

  const { loading, data } = useQuery(bannersQuery, {
    variables: {
      fullText,
      selectedFacets: selectedFacets.filter(
        (facet: SelectedFacet) => facet.key !== 'ft'
      ),
    },
  })

  if (loading || !data) {
    return null
  }

  const banners = data?.banners?.banners || []

  const selectedBanner = banners.find(
    (banner: ElasticBanner) => banner.area === area
  )

  if (!selectedBanner) {
    return null
  }

  const className = `flex ${getAlignmentClass(horizontalAlignment)} ${
    handles.searchBanner
  }`

  return (
    <div
      className={className}
      dangerouslySetInnerHTML={{ __html: selectedBanner.html }}
    />
  )
}

export default Banner

```


[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 search/react/components/Autocomplete/components/ItemList/styles.css from the search VTEX app.

[Assistant]
Here's the implementation:

```css
.itemList {
  flex: 1;
  vertical-align: top;
  font-family: Open Sans, Roboto, sans-serif;
}

.itemListList {
  padding: 0;
  margin: 0;
}

.itemListList li {
  padding: 0;
  margin: 0;
}

.itemList ol, .itemList ul {
  padding: 0;
  list-style: none;
}

.itemListTitle {
  margin-bottom: 5px;
  padding: 0 20px;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
}

.itemListItem a, .itemListItem a:hover {
  display: block;
  height: 35px;
  line-height: 35px;
  padding: 0 20px;
  font-size: 13px;
  text-decoration: none;
  max-width: 100%;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

.itemListItem a:hover {
  background: #eee;
}

.itemListSubItem a {
  padding: 0 30px;
  font-weight: 600;
  text-transform: capitalize;
  white-space: nowrap;
  text-overflow: ellipsis;
  margin-right: 16px;
  overflow: hidden;
}

.itemListSubItemLink {}

.itemListPrefix, .itemListIcon {
  display: inline-block;
  width: 30px;
  font-weight: 600;
  color: #999;
}

.itemListLink {}

.itemListLinkTitle {}

.itemList--suggestion {}

.itemList--history {}

.itemList--top-search {
  width: 100%;
}

@media only screen and (min-width: 1025px) {
  .itemList {
    overflow: hidden;
  }
}

```


[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 search/react/components/Autocomplete/components/ItemList/Attribute.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { Link } from 'vtex.render-runtime'

import { Item } from './types'
import stylesCss from './styles.css'

interface IAttributeProps {
  item: Item
  onMouseOver: (ee: React.MouseEvent | React.FocusEvent, item: Item) => void
  onMouseOut: () => void
  closeModal: () => void
  onItemClick: (term: string, position: number) => void
}

const Attribute = (props: IAttributeProps) =>
  props.item?.attributes ? (
    <ul className={stylesCss.itemListSubList}>
      {props.item.attributes.map((attribute, index) => (
        <li
          key={index}
          className={`${stylesCss.itemListSubItem} c-on-base pointer`}
          onMouseOver={e => props.onMouseOver(e, attribute)}
          onFocus={e => props.onMouseOver(e, attribute)}
          onMouseOut={() => props.onMouseOut()}
          onBlur={() => props.onMouseOut()}
        >
          <Link
            className={`${stylesCss.itemListSubItemLink} c-on-base`}
            to={`/${props.item.value}/${attribute.value}`}
            query={`map=ft,${attribute.key}`}
            onClick={() => {
              props.closeModal()
              props.onItemClick(attribute.label, index)
            }}
          >
            {attribute.label}
          </Link>
        </li>
      ))}
    </ul>
  ) : null

export default Attribute

```


[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 search/react/components/Autocomplete/components/ItemList/types.ts from the search VTEX app.

[Assistant]
Here's the implementation:

```typescript
export interface Item {
  label: string | JSX.Element
  value: string
  link: string
  attributes?: AttributeItem[]
  icon?: JSX.Element
  prefix?: string | JSX.Element
}

export interface AttributeItem {
  groupValue: string
  value: string
  label: string
  link: string
  key: string
}

export function instanceOfAttributeItem(object: any): object is AttributeItem {
  return 'groupValue' in object
}

```


[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 search/react/components/Autocomplete/components/ItemList/ItemList.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
import * as React from 'react'
import { Link } from 'vtex.render-runtime'

import { Item, AttributeItem } from './types'
import stylesCss from './styles.css'
import Attribute from './Attribute'

interface ItemListProps {
  title: string | JSX.Element
  items: Item[]
  showTitle: boolean
  onItemClick: (term: string, position: number) => void
  modifier?: string
  onItemHover?: (item: Item | AttributeItem) => void
  showTitleOnEmpty?: boolean
  customPage?: string
  closeModal: () => void
}

interface ItemListState {
  currentTimeoutId: ReturnType<typeof setTimeout> | null
}

export class ItemList extends React.Component<ItemListProps> {
  public readonly state: ItemListState = {
    currentTimeoutId: null,
  }

  handleMouseOver = (e: React.MouseEvent | React.FocusEvent, item: Item) => {
    e.stopPropagation()

    const { currentTimeoutId } = this.state

    if (!currentTimeoutId) {
      const timeoutId = setTimeout(() => {
        this.props.onItemHover ? this.props.onItemHover(item) : null
        this.setState({ currentTimeoutId: null })
      }, 100)

      this.setState({ currentTimeoutId: timeoutId })
    }
  }

  handleMouseOut = () => {
    const { currentTimeoutId } = this.state

    if (currentTimeoutId) {
      clearTimeout(currentTimeoutId)
      this.setState({ currentTimeoutId: null })
    }
  }

  render() {
    if (this.props.items.length === 0 && !this.props.showTitleOnEmpty) {
      return null
    }

    const modifier = this.props.modifier
      ? stylesCss[`itemList--${this.props.modifier}`]
      : ''

    return (
      <article className={`${stylesCss.itemList} ${modifier}`}>
        {this.props.showTitle ? (
          <p className={`${stylesCss.itemListTitle} c-on-base`}>
            {this.props.title}
          </p>
        ) : null}
        {this.props.items.length > 0 && (
          <ol className={stylesCss.itemListList}>
            {this.props.items.map((item, index) => {
              return (
                <li
                  key={item.value}
                  className={`${stylesCss.itemListItem}`}
                  onMouseOver={e => this.handleMouseOver(e, item)}
                  onFocus={e => this.handleMouseOver(e, item)}
                  onMouseOut={() => this.handleMouseOut()}
                  onBlur={() => this.handleMouseOut()}
                >
                  <Link
                    page={this.props.customPage ?? 'store.search'}
                    params={{
                      term: item.value,
                    }}
                    query={`map=ft&_q=${item.value}`}
                    onClick={() => this.props.onItemClick(item.value, index)}
                    className={stylesCss.itemListLink}
                  >
                    {item.icon ? (
                      <span className={stylesCss.itemListIcon}>
                        {item.icon}
                      </span>
                    ) : null}

                    {item.prefix ? (
                      <span className={stylesCss.itemListPrefix}>
                        {item.prefix}
                      </span>
                    ) : null}

                    <span
                      className={`${stylesCss.itemListLinkTitle} c-on-base`}
                    >
                      {item.label}
                    </span>
                  </Link>
                  <Attribute
                    item={item}
                    onMouseOver={this.handleMouseOver}
                    onMouseOut={this.handleMouseOut}
                    closeModal={this.props.closeModal}
                    onItemClick={this.props.onItemClick}
                  />
                </li>
              )
            })}
          </ol>
        )}
      </article>
    )
  }
}

```


[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 search/react/components/Autocomplete/components/CustomListItem/styles.css from the search VTEX app.

[Assistant]
Here's the implementation:

```css

.clearLink {}

.element {
    position: relative;
}

.imageContainer {
    max-height: 80px;
}

.image {}

.information {}

.productNameContainer {}

.productBrand {}

.priceContainer {}

.priceOld {}

.priceNew {}

.discount {
    background: rgb(228, 1, 46);
    color: #fff;
    position: absolute;
    top: 1px;
    left: 1px;
    font-size: 14px;
}
```


[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 search/react/components/Autocomplete/components/CustomListItem/CustomListItem.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable jsx-a11y/alt-text */
import React, { FC } from 'react'
import { Link } from 'vtex.render-runtime'
import { SellingPrice, ListPrice } from 'vtex.product-price'
import { ProductContextProvider } from 'vtex.product-context'

import styles from './styles.css'

interface CustomListItemProps {
  product: Product
  onClick: () => void
}

const CustomListItem: FC<CustomListItemProps> = ({ product, onClick }) => {
  const sku = product?.sku
  const taxPercentage = sku?.sellers?.[0]?.commertialOffer?.taxPercentage

  return (
    <div>
      <Link
        params={{
          slug: product?.linkText,
          id: product?.productId,
        }}
        page="store.product"
        className="no-underline"
        onClick={onClick}
      >
        <article
          className={`${styles.element} flex flex-row justify-start items-center pa3 bg-animate hover-bg-light-gray`}
        >
          <div className={`${styles.imageContainer} h3`}>
            <img
              className={`${styles.image} h-100 w-auto mw-none`}
              src={sku?.image?.imageUrl}
            />
          </div>
          <div
            className={`${styles.information} flex flex-column justify-between items-start ml4`}
          >
            <div className={styles.productNameContainer}>
              <span className={`${styles.productBrand} f5 c-on-base`}>
                {product.productName}
              </span>
            </div>
            <div className={styles.priceContainer}>
              <ProductContextProvider
                product={product}
                query={{
                  skuId: sku?.itemId,
                }}
              >
                <span className="db f7 c-muted-2">
                  <ListPrice
                    message={
                      taxPercentage ? '{listPriceWithTax}' : '{listPriceValue}'
                    }
                  />
                </span>
                <span className="dib t-small c-muted-2">
                  <SellingPrice
                    message={
                      taxPercentage
                        ? '{sellingPriceWithTax}'
                        : '{sellingPriceValue}'
                    }
                  />
                </span>
              </ProductContextProvider>
            </div>
          </div>
        </article>
      </Link>
    </div>
  )
}

export default CustomListItem

```


[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 search/react/components/Autocomplete/components/TileList/TileList.tsx from the search VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FC } from 'react'
import { ExtensionPoint, Link } from 'vtex.render-runtime'
import { Spinner } from 'vtex.styleguide'
import ProductSummary from 'vtex.product-summary/ProductSummaryCustom'
import { FormattedMessage } from 'react-intl'

import styles from './styles.css'
import CustomListItem from '../CustomListItem/CustomListItem'
import { ProductLayout } from '../..'

interface TileListProps {
  term: string
  title: string | JSX.Element
  customPage?: string
  products: any[]
  showTitle: boolean
  shelfProductCount: number
  totalProducts: number
  layout: ProductLayout
  isLoading: boolean
  onProductClick: (product: string, position: number, term: string) => void
  onSeeAllClick: (term: string) => void
  HorizontalProductSummary?: React.ComponentType<{
    product: Product
    placement: string
    actionOnClick: () => void
  }>
  searchId: string
}

const AUTOCOMPLETE_PLACEMENT = 'autocomplete'

const TileList: FC<TileListProps> = ({
  term,
  title,
  products,
  showTitle,
  totalProducts,
  layout,
  isLoading,
  onProductClick,
  onSeeAllClick,
  HorizontalProductSummary,
  customPage,
  searchId,
}) => {
  if (products.length === 0 && !isLoading) {
    return null
  }

  return (
    <section
      className={styles.tileList}
      data-af-element={searchId ? 'search-autocomplete' : undefined}
      data-af-onimpression={searchId ? true : undefined}
      data-af-search-id={searchId}
    >
      {showTitle ? (
        <p className={`${styles.tileListTitle} c-on-base`}>{title}</p>
      ) : null}
      {isLoading ? (
        <div className={styles.tileListSpinner}>
          <Spinner />
        </div>
      ) : (
        <>
          <ul
            className={styles.tileListList}
            style={{
              flexDirection:
                layout === ProductLayout.Horizontal ? 'column' : 'row',
            }}
          >
            {products.map((product, index: number) => {
              const productSummary: Product = ProductSummary.mapCatalogProductToProductSummary(
                product
              )

              return (
                <li
                  key={product.productId}
                  className={styles.tileListItem}
                  data-af-element={searchId ? 'search-autocomplete' : undefined}
                  data-af-onclick={
                    searchId && product.productId ? true : undefined
                  }
                  data-af-search-id={searchId}
                  data-af-product-position={index + 1}
                  data-af-product-id={product.productId}
                  data-af-product-specification={product.specification}
                >
                  {layout === ProductLayout.Horizontal ? (
                    HorizontalProductSummary ? (
                      <HorizontalProductSummary
                        product={productSummary}
                        placement={AUTOCOMPLETE_PLACEMENT}
                        actionOnClick={() => {
                          onProductClick(productSummary.productId, index, term)
                        }}
                      />
                    ) : (
                      <CustomListItem
                        product={productSummary}
                        onClick={() => {
                          onProductClick(productSummary.productId, index, term)
                        }}
                      />
                    )
                  ) : (
                    <ExtensionPoint
                      id="product-summary"
                      product={productSummary}
                      placement={AUTOCOMPLETE_PLACEMENT}
                      actionOnClick={() => {
                        onProductClick(productSummary.productId, index, term)
                      }}
                    />
                  )}
                </li>
              )
            })}
          </ul>

          <footer className={styles.tileListFooter}>
            {totalProducts > 0 ? (
              <Link
                query={`map=ft&_q=${term}`}
                params={{
                  term,
                }}
                page={customPage || 'store.search'}
                className={styles.tileListSeeMore}
                onClick={() => onSeeAllClick(term)}
              >
                <FormattedMessage
                  id="store/seeMore"
                  values={{ count: totalProducts }}
                />
              </Link>
            ) : null}
          </footer>
        </>
      )}
    </section>
  )
}

export default TileList

```


[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 search/react/components/Autocomplete/components/TileList/styles.css from the search VTEX app.

[Assistant]
Here's the implementation:

```css
.tileList {
  flex: 2;
  vertical-align: top;
  border-left: 1px solid #eee;
}

.tileListList {}

.tileList ul {
  padding: 0;
  display: flex;
}

.tileListTitle {
  margin-bottom: 5px;
  padding: 0 20px;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
}

.tileListItem {
  display: flex;
  flex: 1;
}

.tileListSeeMore {
  display: block;
  height: 60px;
  line-height: 60px;
  font-size: 13px;
  color: #787878;
  text-align: center;
}

.tileListSpinner {
  display: flex;
  height: 80%;
  justify-content: center;
  align-items: center;
}

.tileListFooter {}

@media only screen and (min-width: 1024px) {
  .tileList {
    display: inline-block;
  }
}

```


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

[Assistant]
Here's the implementation:

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

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

# BrightEdge

This app implements BrightEdge AutoPilot - Self Connecting Pages within VTEX IO. The app provides a block which can be placed in your store layout and which will be populated with dynamic link content designed to improve SEO.

## Configuration

1. [Install](https://vtex.io/docs/recipes/store/installing-an-app) `vtex.brightedge-integration` in the desired account.
2. In your account's admin dashboard, go to `Apps > My Apps` and then click the box for `BrightEdge`.
3. Enter your BrightEdge `Account ID` in the provided settings field and then click Save.
4. In your `store-theme`, add BrightEdge as a dependency:

```json
"dependencies": {
    "vtex.brightedge-integration": "0.x"
  }
```

5. In your `store-theme`'s `store/` folder, place the `brightedge` block in the desired location (BrightEdge recommends displaying their link content in the store's footer). For example:

```json
"footer-layout.desktop": {
    "children": [
      "brightedge",
      "flex-layout.row#footer-1-desktop",
      "flex-layout.row#footer-2-desktop",
      "flex-layout.row#footer-3-desktop"
    ]
  },
```

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- 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 welcome!

```


[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 brightedge-integration/react/index.tsx from the brightedge-integration VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { FunctionComponent, useState, useEffect } from 'react'

import useScript from './hooks/useScriptLoader'

interface Props {
  appSettings: any
}

const BrightEdgeScript: FunctionComponent<{ accountId: string }> = ({
  accountId,
}) => {
  const [loaded, error] = useScript(
    `//cdn.bc0a.com/autopilot/${accountId}/autopilot_sdk.js`
  )

  if (!loaded || error) return null
  return null
}

const BrightEdge: FunctionComponent<Props> = ({ appSettings }) => {
  const { accountId } = appSettings
  const [shouldLoadScript, setShouldLoadScript] = useState(false)

  useEffect(() => {
    setShouldLoadScript(true)
  }, [])

  if (!accountId) return null
  return (
    <div>
      <div className="be-ix-link-block" />
      {shouldLoadScript ? <BrightEdgeScript accountId={accountId} /> : null}
    </div>
  )
}

export default BrightEdge

```


[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 brightedge-integration/react/package.json from the brightedge-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "brightedge-integration",
  "version": "0.0.2",
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "apollo-client": "^2.6.8",
    "react": "^16.12.0",
    "react-apollo": "^3.1.3",
    "react-dom": "^16.12.0",
    "react-intl": "^3.12.0"
  },
  "devDependencies": {
    "@apollo/react-testing": "^3.1.3",
    "@types/jest": "^25.1.4",
    "@types/node": "^13.9.8",
    "@types/react": "^16.9.31",
    "@vtex/test-tools": "^3.1.0",
    "@vtex/tsconfig": "^0.4.4",
    "apollo-cache-inmemory": "^1.6.5",
    "graphql": "^14.6.0",
    "prop-types": "^15.7.2",
    "typescript": "3.8.3",
    "vtex.pixel-interfaces": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-interfaces@1.1.1/public/_types/react",
    "vtex.product-context": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-context@0.8.0/public/@types/vtex.product-context",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.111.0/public/@types/vtex.render-runtime",
    "vtex.store": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store@2.99.1/public/@types/vtex.store"
  }
}

```


[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 brightedge-integration/store/interfaces.json from the brightedge-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "brightedge": {
    "component": "index"
  }
}

```


[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 brightedge-integration/react/__tests__/index.test.tsx from the brightedge-integration VTEX app.

[Assistant]
Here's the implementation:

```tsx
describe('Orders List Scenarios', () => {
  it('should work', () => {
    expect(1).toBe(1)
  })
})

```


[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 brightedge-integration/react/hooks/useScriptLoader.tsx from the brightedge-integration VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useEffect, useState } from 'react'

const cachedScripts: string[] = []
function useScript(src: string) {
  // Keeping track of script loaded and error state
  const [state, setState] = useState({
    loaded: false,
    error: false,
  })

  useEffect(() => {
    // If cachedScripts array already includes src that means another instance ...
    // ... of this hook already loaded this script, so no need to load again.
    if (cachedScripts.includes(src)) {
      setState({
        loaded: true,
        error: false,
      })
      return
    }
    cachedScripts.push(src)

    // Create script
    const script = document.createElement('script')
    script.src = src

    // Script event listener callbacks for load and error
    const onScriptLoad = () => {
      setState({
        loaded: true,
        error: false,
      })
    }

    const onScriptError = () => {
      // Remove from cachedScripts we can try loading again
      const index = cachedScripts.indexOf(src)
      if (index >= 0) cachedScripts.splice(index, 1)
      script.remove()

      setState({
        loaded: true,
        error: true,
      })
    }

    script.addEventListener('load', onScriptLoad)
    script.addEventListener('error', onScriptError)

    // Add script to document head

    const [t] = document.getElementsByTagName('script')
    t.parentNode?.insertBefore(script, t)

    // Remove event listeners on cleanup
    return () => {
      script.removeEventListener('load', onScriptLoad)
      script.removeEventListener('error', onScriptError)
    }
  }, [src])

  return [state.loaded, state.error]
}

export default useScript

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "B2B-informatie",
  "admin/storefront-permissions.button.cancel": "Annuleren",
  "admin/storefront-permissions.button.delete": "B2B-info verwijderen",
  "admin/storefront-permissions.button.save": "Opslaan",
  "admin/storefront-permissions.description": "Rollen en gebruikersbeheer",
  "admin/storefront-permissions.navigation.keywords": "B2B, rollen, profielen",
  "admin/storefront-permissions.navigation.label": "Storefront-machtigingen",
  "admin/storefront-permissions.required": "Vereist",
  "admin/storefront-permissions.tab.new.button": "Nieuwe aanmaken",
  "admin/storefront-permissions.tab.roles": "Rollen",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Kan geen apps vinden die verbonden zijn met de storefront-machtigingen",
  "admin/storefront-permissions.tab.roles.name.label": "Rol",
  "admin/storefront-permissions.tab.users": "Gebruikers",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Kan imiteren",
  "admin/storefront-permissions.tab.users.email.label": "E-mailadres",
  "admin/storefront-permissions.tab.users.organization.label": "Organisatie",
  "admin/storefront-permissions.tab.users.costCenter.label": "Kostencentrum",
  "admin/storefront-permissions.tab.users.error": "Fout bij opslaan B2B-info",
  "admin/storefront-permissions.tab.users.name.label": "Naam",
  "admin/storefront-permissions.tab.users.success": "B2B-info opgeslagen",
  "admin/storefront-permissions.title": "Storefront-machtigingen",
  "admin/storefront-permissions.alert-pick": "U moet een kostencentrum kiezen voordat u wijzigingen kunt opslaan",
  "admin/storefront-permissions.searchOrganizations": "Organisaties zoeken..."
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "B2B 情報",
  "admin/storefront-permissions.button.cancel": "キャンセル",
  "admin/storefront-permissions.button.delete": "B2B 情報を削除する",
  "admin/storefront-permissions.button.save": "保存",
  "admin/storefront-permissions.description": "役割およびユーザー管理",
  "admin/storefront-permissions.navigation.keywords": "B2B, 役割, プロファイル",
  "admin/storefront-permissions.navigation.label": "店頭権限",
  "admin/storefront-permissions.required": "必須",
  "admin/storefront-permissions.tab.new.button": "新規作成",
  "admin/storefront-permissions.tab.roles": "役割",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "店頭権限に接続したアプリは見つかりませんでした",
  "admin/storefront-permissions.tab.roles.name.label": "役割",
  "admin/storefront-permissions.tab.users": "ユーザー",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "偽装することができます",
  "admin/storefront-permissions.tab.users.email.label": "メール",
  "admin/storefront-permissions.tab.users.organization.label": "組織",
  "admin/storefront-permissions.tab.users.costCenter.label": "コストセンター",
  "admin/storefront-permissions.tab.users.error": "B2B 情報を保存する時にエラーが発生しました",
  "admin/storefront-permissions.tab.users.name.label": "名前",
  "admin/storefront-permissions.tab.users.success": "B2B 情報を保存しました",
  "admin/storefront-permissions.title": "店頭権限",
  "admin/storefront-permissions.alert-pick": "変更を保存する前にコストセンターを選択しなければなりません",
  "admin/storefront-permissions.searchOrganizations": "組織を検索…"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "Informações B2B",
  "admin/storefront-permissions.button.cancel": "Cancelar",
  "admin/storefront-permissions.button.delete": "Remover informações B2B",
  "admin/storefront-permissions.button.save": "Salvar",
  "admin/storefront-permissions.description": "Gerenciamento de perfis de acesso e usuários",
  "admin/storefront-permissions.navigation.keywords": "B2B, perfis de acesso, usuários",
  "admin/storefront-permissions.navigation.label": "Permissões da loja",
  "admin/storefront-permissions.required": "Obrigatório",
  "admin/storefront-permissions.tab.new.button": "Criar nova",
  "admin/storefront-permissions.tab.roles": "Perfis de acesso",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Não foi possível encontrar nenhum app conectado às permissões da loja",
  "admin/storefront-permissions.tab.roles.name.label": "Perfil de acesso",
  "admin/storefront-permissions.tab.users": "Usuários",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Pode personificar",
  "admin/storefront-permissions.tab.users.email.label": "Email",
  "admin/storefront-permissions.tab.users.organization.label": "Organização",
  "admin/storefront-permissions.tab.users.costCenter.label": "Centro de custo",
  "admin/storefront-permissions.tab.users.error": "Erro ao salvar informações B2B",
  "admin/storefront-permissions.tab.users.name.label": "Nome",
  "admin/storefront-permissions.tab.users.success": "Informações B2B salvas",
  "admin/storefront-permissions.title": "Permissões da loja",
  "admin/storefront-permissions.alert-pick": "Você precisa selecionar um centro de custo antes de salvar as alterações",
  "admin/storefront-permissions.searchOrganizations": "Buscar organizações..."
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "B2B Information",
  "admin/storefront-permissions.button.cancel": "Cancel",
  "admin/storefront-permissions.button.delete": "Remove B2B Info",
  "admin/storefront-permissions.button.save": "Save",
  "admin/storefront-permissions.description": "Roles and User Management",
  "admin/storefront-permissions.navigation.keywords": "B2B, Roles, Profiles",
  "admin/storefront-permissions.navigation.label": "Storefront Permissions",
  "admin/storefront-permissions.required": "Required",
  "admin/storefront-permissions.tab.new.button": "Create new",
  "admin/storefront-permissions.tab.roles": "Roles",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Couldn't find any apps connected to the storefront permissions",
  "admin/storefront-permissions.tab.roles.name.label": "Role",
  "admin/storefront-permissions.tab.users": "Users",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Can impersonate",
  "admin/storefront-permissions.tab.users.email.label": "Email",
  "admin/storefront-permissions.tab.users.organization.label": "Organization",
  "admin/storefront-permissions.tab.users.costCenter.label": "Cost Center",
  "admin/storefront-permissions.tab.users.error": "Error saving B2B info",
  "admin/storefront-permissions.tab.users.name.label": "Name",
  "admin/storefront-permissions.tab.users.success": "B2B info saved",
  "admin/storefront-permissions.title": "Storefront Permissions",
  "admin/storefront-permissions.alert-pick": "You need to choose a cost center before saving changes",
  "admin/storefront-permissions.searchOrganizations": "Search organizations..."
}

```


[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 storefront-permissions-components/messages/it.json from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "Informazioni B2B",
  "admin/storefront-permissions.button.cancel": "Annulla",
  "admin/storefront-permissions.button.delete": "Rimuovi informazioni B2B",
  "admin/storefront-permissions.button.save": "Salva",
  "admin/storefront-permissions.description": "Ruoli e gestione utenti",
  "admin/storefront-permissions.navigation.keywords": "B2B, ruoli, profili",
  "admin/storefront-permissions.navigation.label": "Permessi del negozio",
  "admin/storefront-permissions.required": "Obbligatorio",
  "admin/storefront-permissions.tab.new.button": "Crea nuovo permesso",
  "admin/storefront-permissions.tab.roles": "Ruoli",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Non è stato possibile trovare nessuna app associata ai permessi del negozio",
  "admin/storefront-permissions.tab.roles.name.label": "Ruolo",
  "admin/storefront-permissions.tab.users": "Utenti",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Può impersonare",
  "admin/storefront-permissions.tab.users.email.label": "Email",
  "admin/storefront-permissions.tab.users.organization.label": "Organizzazione",
  "admin/storefront-permissions.tab.users.costCenter.label": "Centro di costo",
  "admin/storefront-permissions.tab.users.error": "Errore durante il salvataggio delle informazioni B2B",
  "admin/storefront-permissions.tab.users.name.label": "Nome",
  "admin/storefront-permissions.tab.users.success": "Informazioni B2B salvate",
  "admin/storefront-permissions.title": "Permessi del negozio",
  "admin/storefront-permissions.alert-pick": "È necessario scegliere un centro di costo prima di salvare le modifiche",
  "admin/storefront-permissions.searchOrganizations": "Cerca organizzazioni..."
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "Information B2B",
  "admin/storefront-permissions.button.cancel": "Annuler",
  "admin/storefront-permissions.button.delete": "Supprimer les infos B2B",
  "admin/storefront-permissions.button.save": "Sauvegarder",
  "admin/storefront-permissions.description": "Rôles et gestion des utilisateurs",
  "admin/storefront-permissions.navigation.keywords": "B2B, rôles, profiles",
  "admin/storefront-permissions.navigation.label": "Autorisations de la vitrine",
  "admin/storefront-permissions.required": "Requis",
  "admin/storefront-permissions.tab.new.button": "Créer nouveau",
  "admin/storefront-permissions.tab.roles": "Rôles",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Impossible de trouver les applications connectées aux autorisations de la vitrine",
  "admin/storefront-permissions.tab.roles.name.label": "Rôle",
  "admin/storefront-permissions.tab.users": "Utilisateurs",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Peut se faire passer pour",
  "admin/storefront-permissions.tab.users.email.label": "Email",
  "admin/storefront-permissions.tab.users.organization.label": "Organisation",
  "admin/storefront-permissions.tab.users.costCenter.label": "Centre de coûts",
  "admin/storefront-permissions.tab.users.error": "Erreur lors de l’enregistrement des infos B2B",
  "admin/storefront-permissions.tab.users.name.label": "Nom",
  "admin/storefront-permissions.tab.users.success": "Infos B2B enregistrées",
  "admin/storefront-permissions.title": "Autorisations de la vitrine",
  "admin/storefront-permissions.alert-pick": "Vous devez choisir un centre de coûts avant d’enregistrer les modifications",
  "admin/storefront-permissions.searchOrganizations": "Rechercher des organisations..."
}

```


[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 storefront-permissions-components/messages/bg.json from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "Информация за B2B",
  "admin/storefront-permissions.button.cancel": "Отказ",
  "admin/storefront-permissions.button.delete": "Премахване на информация за B2B",
  "admin/storefront-permissions.button.save": "Запазване",
  "admin/storefront-permissions.description": "Управление на роли и потребители",
  "admin/storefront-permissions.navigation.keywords": "B2B, роли, профили",
  "admin/storefront-permissions.navigation.label": "Разрешения на витрината",
  "admin/storefront-permissions.required": "Задължително",
  "admin/storefront-permissions.tab.new.button": "Създаване на нов",
  "admin/storefront-permissions.tab.roles": "Роли",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Не са открити приложения, свързани с разрешенията за витрината",
  "admin/storefront-permissions.tab.roles.name.label": "Роля",
  "admin/storefront-permissions.tab.users": "Потребители",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Може да въплъщава",
  "admin/storefront-permissions.tab.users.email.label": "Имейл адрес",
  "admin/storefront-permissions.tab.users.organization.label": "Организация",
  "admin/storefront-permissions.tab.users.costCenter.label": "Разходен център",
  "admin/storefront-permissions.tab.users.error": "Грешка при запазването на информацията за B2B",
  "admin/storefront-permissions.tab.users.name.label": "Име",
  "admin/storefront-permissions.tab.users.success": "Информация за B2B е запазена",
  "admin/storefront-permissions.title": "Разрешения на витрината",
  "admin/storefront-permissions.alert-pick": "Трябва да изберете разходен център, преди да запазите промените",
  "admin/storefront-permissions.searchOrganizations": "Търсене на организации..."
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "Informații B2B",
  "admin/storefront-permissions.button.cancel": "Anulare",
  "admin/storefront-permissions.button.delete": "Ștergere informații B2B",
  "admin/storefront-permissions.button.save": "Salvare",
  "admin/storefront-permissions.description": "Funcții și gestionare utilizatori",
  "admin/storefront-permissions.navigation.keywords": "B2B, funcții și profiluri",
  "admin/storefront-permissions.navigation.label": "Permisiuni magazin",
  "admin/storefront-permissions.required": "Obligatoriu",
  "admin/storefront-permissions.tab.new.button": "Creare nou",
  "admin/storefront-permissions.tab.roles": "Funcții",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "Nu am putut găsi nicio aplicație conectată la permisiunile magazinului",
  "admin/storefront-permissions.tab.roles.name.label": "Funcții",
  "admin/storefront-permissions.tab.users": "Utilizatori",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Pot înlocui",
  "admin/storefront-permissions.tab.users.email.label": "E-mail",
  "admin/storefront-permissions.tab.users.organization.label": "Organizație",
  "admin/storefront-permissions.tab.users.costCenter.label": "Centru de Cost",
  "admin/storefront-permissions.tab.users.error": "Eroare la salvarea informațiilor B2B",
  "admin/storefront-permissions.tab.users.name.label": "Nume",
  "admin/storefront-permissions.tab.users.success": "Informații B2B salvate",
  "admin/storefront-permissions.title": "Permisiuni storefront",
  "admin/storefront-permissions.alert-pick": "Trebuie să alegi un centru de cost înainte de a salva modificările",
  "admin/storefront-permissions.searchOrganizations": "Căutare organizații..."
}

```


[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 storefront-permissions-components/messages/context.json from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "admin/storefront-permissions.b2bInfo.title",
  "admin/storefront-permissions.button.cancel": "admin/storefront-permissions.button.cancel",
  "admin/storefront-permissions.button.delete": "admin/storefront-permissions.button.delete",
  "admin/storefront-permissions.button.save": "admin/storefront-permissions.button.save",
  "admin/storefront-permissions.description": "admin/storefront-permissions.description",
  "admin/storefront-permissions.navigation.keywords": "admin/storefront-permissions.navigation.keywords",
  "admin/storefront-permissions.navigation.label": "admin/storefront-permissions.navigation.label",
  "admin/storefront-permissions.required": "admin/storefront-permissions.required",
  "admin/storefront-permissions.tab.new.button": "admin/storefront-permissions.tab.new.button",
  "admin/storefront-permissions.tab.roles": "admin/storefront-permissions.tab.roles",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "admin/storefront-permissions.tab.roles.featuresNotFound",
  "admin/storefront-permissions.tab.roles.name.label": "admin/storefront-permissions.tab.roles.name.label",
  "admin/storefront-permissions.tab.users": "admin/storefront-permissions.tab.users",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "admin/storefront-permissions.tab.users.canImpersonate.label",
  "admin/storefront-permissions.tab.users.email.label": "admin/storefront-permissions.tab.users.email.label",
  "admin/storefront-permissions.tab.users.organization.label": "admin/storefront-permissions.tab.users.organization.label",
  "admin/storefront-permissions.tab.users.costCenter.label": "admin/storefront-permissions.tab.users.costCenter.label",
  "admin/storefront-permissions.tab.users.error": "admin/storefront-permissions.tab.users.error",
  "admin/storefront-permissions.tab.users.name.label": "admin/storefront-permissions.tab.users.name.label",
  "admin/storefront-permissions.tab.users.success": "admin/storefront-permissions.tab.users.success",
  "admin/storefront-permissions.title": "admin/storefront-permissions.title",
  "admin/storefront-permissions.alert-pick": "admin/storefront-permissions.alert-pick",
  "admin/storefront-permissions.searchOrganizations": "admin/storefront-permissions.searchOrganizations"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "B2B 정보",
  "admin/storefront-permissions.button.cancel": "취소",
  "admin/storefront-permissions.button.delete": "B2B 정보 제거",
  "admin/storefront-permissions.button.save": "저장",
  "admin/storefront-permissions.description": "역할 및 사용자 관리",
  "admin/storefront-permissions.navigation.keywords": "B2B, 역할, 프로필",
  "admin/storefront-permissions.navigation.label": "스토어프론트 권한",
  "admin/storefront-permissions.required": "필수",
  "admin/storefront-permissions.tab.new.button": "새로 만들기",
  "admin/storefront-permissions.tab.roles": "역할",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "스토어프론트 권한에 연결된 앱을 찾을 수 없습니다.",
  "admin/storefront-permissions.tab.roles.name.label": "역할",
  "admin/storefront-permissions.tab.users": "사용자",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "가장할 수 있음",
  "admin/storefront-permissions.tab.users.email.label": "이메일",
  "admin/storefront-permissions.tab.users.organization.label": "조직",
  "admin/storefront-permissions.tab.users.costCenter.label": "비용 센터",
  "admin/storefront-permissions.tab.users.error": "B2B 정보를 저장하는 동안 오류가 발생했습니다.",
  "admin/storefront-permissions.tab.users.name.label": "이름",
  "admin/storefront-permissions.tab.users.success": "B2B 정보 저장됨",
  "admin/storefront-permissions.title": "스토어프론트 권한",
  "admin/storefront-permissions.alert-pick": "변경 사항을 저장하기 전에 비용 센터를 선택해야 합니다.",
  "admin/storefront-permissions.searchOrganizations": "조직 검색..."
}

```


[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 storefront-permissions-components/messages/th.json from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "ข้อมูล B2B",
  "admin/storefront-permissions.button.cancel": "ยกเลิก",
  "admin/storefront-permissions.button.delete": "ลบข้อมูล B2B ออก",
  "admin/storefront-permissions.button.save": "บันทึก",
  "admin/storefront-permissions.description": "บทบาทและการบริหารจัดผู้ใช้",
  "admin/storefront-permissions.navigation.keywords": "B2B, บทบาท, โปรไฟล์",
  "admin/storefront-permissions.navigation.label": "สิทธิ์หน้าร้าน",
  "admin/storefront-permissions.required": "บังคับ",
  "admin/storefront-permissions.tab.new.button": "สร้างใหม่",
  "admin/storefront-permissions.tab.roles": "บทบาท",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "ไม่พบว่ามีแอปใดเชือมต่อกับสิทธิ์หน้าร้าน",
  "admin/storefront-permissions.tab.roles.name.label": "บทบาท",
  "admin/storefront-permissions.tab.users": "ผู้ใช้",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "สามารถเลียนแบบ",
  "admin/storefront-permissions.tab.users.email.label": "อีเมล",
  "admin/storefront-permissions.tab.users.organization.label": "องค์กร",
  "admin/storefront-permissions.tab.users.costCenter.label": "ศูนย์ต้นทุน",
  "admin/storefront-permissions.tab.users.error": "มีข้อผิดพลาดขณะบันทึกข้อมูล B2B",
  "admin/storefront-permissions.tab.users.name.label": "ชื่อ",
  "admin/storefront-permissions.tab.users.success": "บันทึกข้อมูล B2B แล้ว",
  "admin/storefront-permissions.title": "สิทธิ์หน้าร้าน",
  "admin/storefront-permissions.alert-pick": "คุณต้องเลือกศูนย์ต้นทุนก่อนบันทึกการเปลี่ยนแปลง",
  "admin/storefront-permissions.searchOrganizations": "ค้นหาองค์กร..."
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/storefront-permissions.b2bInfo.title": "Información B2B",
  "admin/storefront-permissions.button.cancel": "Cancelar",
  "admin/storefront-permissions.button.delete": "Eliminar información B2B",
  "admin/storefront-permissions.button.save": "Guardar",
  "admin/storefront-permissions.description": "Gestión de roles y usuarios",
  "admin/storefront-permissions.navigation.keywords": "B2B, roles, perfiles",
  "admin/storefront-permissions.navigation.label": "Permisos del storefront",
  "admin/storefront-permissions.required": "Obligatorio",
  "admin/storefront-permissions.tab.new.button": "Nueva",
  "admin/storefront-permissions.tab.roles": "Roles",
  "admin/storefront-permissions.tab.roles.featuresNotFound": "No pudo encontrar ninguna aplicación conectada a los permisos del storefront",
  "admin/storefront-permissions.tab.roles.name.label": "Rol",
  "admin/storefront-permissions.tab.users": "Usuarios",
  "admin/storefront-permissions.tab.users.canImpersonate.label": "Puede suplantar",
  "admin/storefront-permissions.tab.users.email.label": "Email",
  "admin/storefront-permissions.tab.users.organization.label": "Organización",
  "admin/storefront-permissions.tab.users.costCenter.label": "Centro de costos",
  "admin/storefront-permissions.tab.users.error": "Error al guardar información B2B",
  "admin/storefront-permissions.tab.users.name.label": "Nombre",
  "admin/storefront-permissions.tab.users.success": "Información B2B guardada",
  "admin/storefront-permissions.title": "Permisos del storefront",
  "admin/storefront-permissions.alert-pick": "Debes elegir un centro de costos antes de guardar los cambios",
  "admin/storefront-permissions.searchOrganizations": "Buscar organizaciones..."
}

```


[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 storefront-permissions-components/react/StorefrontPermissions.tsx from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import StorefrontPermissions from './components/customers-admin'

export default StorefrontPermissions

```


[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 storefront-permissions-components/react/package.json from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "vtex.storefront-permissions-components",
  "version": "2.0.1",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "devDependencies": {
    "@types/faker": "^4.1.5",
    "@types/node": "^11.12.1",
    "@types/react": "^16.8.10",
    "@types/react-intl": "^3.0.0",
    "apollo-client": "^2.4.7",
    "graphql": "^14.0.2",
    "prop-types": "^15.7.2",
    "typescript": "3.9.7",
    "vtex.admin-customers-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.admin-customers-graphql@3.0.2/public/@types/vtex.admin-customers-graphql",
    "vtex.b2b-organizations-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.b2b-organizations-graphql@0.19.7/public/@types/vtex.b2b-organizations-graphql",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.132.4/public/@types/vtex.render-runtime",
    "vtex.storefront-permissions": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.storefront-permissions@1.23.0/public/@types/vtex.storefront-permissions",
    "vtex.storefront-permissions-components": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.storefront-permissions-components@0.2.0/public/@types/vtex.storefront-permissions-components",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.146.13/public/@types/vtex.styleguide"
  },
  "dependencies": {
    "faker": "^4.1.0",
    "react": "^16.8.6",
    "react-apollo": "^3.1.5",
    "react-dom": "^16.8.6",
    "react-intl": "^5.13.4"
  }
}

```


[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 storefront-permissions-components/react/mutations/deleteUser.gql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation DeleteUser($id: ID!, $userId: ID, $email: String!, $clId: ID!) {
  removeUser(id: $id, userId: $userId, email: $email, clId: $clId)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


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

[User] Show me the implementation of storefront-permissions-components/react/mutations/addUser.gql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation add(
  $id: ID
  $roleId: ID!
  $userId: ID
  $orgId: ID
  $costId: ID
  $canImpersonate: Boolean
  $name: String!
  $email: String!
) {
  addUser(
    id: $id
    roleId: $roleId
    userId: $userId
    orgId: $orgId
    costId: $costId
    canImpersonate: $canImpersonate
    name: $name
    email: $email
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


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

[User] Show me the implementation of storefront-permissions-components/react/typings/graphql.d.ts from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

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

  const value: DocumentNode
  export default value
}

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

  const value: DocumentNode
  export default value
}

```


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

[User] Show me the implementation of storefront-permissions-components/react/queries/getUser.gql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetUser($id: ID!) {
  getUser(id: $id) @context(provider: "vtex.storefront-permissions") {
    id
    roleId
    orgId
    costId
    userId
    name
    email
    canImpersonate
  }
}

```


[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 storefront-permissions-components/react/queries/getOrganizationsByEmail.graphql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganizationsByEmail($email: String!) {
  getOrganizationsByEmail(email: $email)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    costId
    orgId
    roleId
    clId
    organizationName
    costCenterName
    role {
      name
    }
  }
}

```


[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 storefront-permissions-components/react/queries/costCentersByOrg.gql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
query CostCenters(
  $id: ID!
  $page: Int
  $pageSize: Int
  $sortOrder: String
  $search: String
  $sortedBy: String
) {
  getCostCentersByOrganizationId(
    id: $id
    search: $search
    page: $page
    pageSize: $pageSize
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    data {
      id
      name
    }
    pagination {
      page
      pageSize
      total
    }
  }
}

```


[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 storefront-permissions-components/react/queries/getOrganization.graphql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganization($id: ID) {
  getOrganizationById(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    status
    created
    collections {
      id
      name
    }
    paymentTerms {
      id
      name
    }
    priceTables
    costCenters
  }
}

```


[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 storefront-permissions-components/react/queries/ListRoles.gql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
query ListRoles {
  listRoles @context(provider: "vtex.storefront-permissions") {
    id
    name
  }
}

```


[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 storefront-permissions-components/react/queries/listOrganizations.gql from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Organizations(
  $search: String
  $page: Int
  $pageSize: Int
  $sortOrder: String
  $sortedBy: String
) {
  getOrganizations(
    status: ["active"]
    search: $search
    page: $page
    pageSize: $pageSize
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    data {
      id
      name
      costCenters
    }
    pagination {
      page
      pageSize
      total
    }
  }
}

```


[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 storefront-permissions-components/react/components/OrganizationsAutocomplete.tsx from the storefront-permissions-components VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useEffect, useState, useMemo, useCallback } from 'react'
import { useQuery } from 'react-apollo'
import { AutocompleteInput } from 'vtex.styleguide'
import { useIntl } from 'react-intl'

import { messages } from './customers-admin'
import GET_ORGANIZATIONS from '../queries/listOrganizations.gql'
import GET_ORGANIZATION_BY_ID from '../queries/getOrganization.graphql'
import { SEARCH_TERM_DELAY_MS } from '../constants/debounceDelay'

const initialState = {
  status: ['active', 'on-hold', 'inactive'],
  search: '',
  page: 1,
  pageSize: 500,
  sortOrder: 'ASC',
  sortedBy: 'name',
}

interface Props {
  onChange: (value: { value: string | null; label: string }) => void
  organizationId: string
}

const OrganizationsAutocomplete = ({ onChange, organizationId }: Props) => {
  const { formatMessage } = useIntl()
  const [term, setTerm] = useState('')
  const [debouncedTerm, setDebouncedTerm] = useState(term)

  const [values, setValues] = useState<Array<{ value: string; label: string }>>(
    []
  )

  const { data, loading, refetch } = useQuery(GET_ORGANIZATIONS, {
    variables: initialState,
    ssr: false,
    notifyOnNetworkStatusChange: true,
  })

  const { data: organization, loading: orgLoading } = useQuery(
    GET_ORGANIZATION_BY_ID,
    {
      variables: { id: organizationId },
      ssr: false,
      fetchPolicy: 'network-only',
      notifyOnNetworkStatusChange: true,
      skip: !organizationId,
    }
  )

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedTerm(term)
    }, SEARCH_TERM_DELAY_MS) // 500ms delay

    return () => clearTimeout(handler)
  }, [term])

  useEffect(() => {
    if (debouncedTerm.length > 2) {
      refetch({
        ...initialState,
        search: debouncedTerm,
      })
    } else if (debouncedTerm === '') {
      refetch({
        ...initialState,
        search: '',
      })
    }
  }, [debouncedTerm, refetch])

  useEffect(() => {
    if (!organization?.getOrganizationById) {
      return
    }

    const { name, id } = organization.getOrganizationById

    setTerm(name)
    onChange({ value: id, label: name })
  }, [organization, onChange])

  useEffect(() => {
    if (data?.getOrganizations?.data) {
      setValues(
        data.getOrganizations.data.map(
          (item: { id: string; name: string }) => ({
            value: item.id,
            label: item.name,
          })
        )
      )
    }
  }, [data])

  const onClear = useCallback(() => {
    setTerm('')

    refetch({
      ...initialState,
      search: '',
    })
    onChange({ value: null, label: '' })
  }, [onChange, refetch])

  const options = useMemo(
    () => ({
      maxHeight: 250,
      onSelect: onChange,
      loading,
      value: values,
    }),
    [loading, values, onChange, orgLoading]
  )

  useEffect(() => {
    if (term && term.length > 1) {
      refetch({
        ...initialState,
        search: term,
      })
    } else if (term === '') {
      onClear()
    }
  }, [term])

  const input = useMemo(
    () => ({
      onChange: (_term: string) => setTerm(_term),
      onClear,
      placeholder: formatMessage(messages.searchOrganizations),
      value: term,
    }),
    [term, onClear, formatMessage]
  )

  return <AutocompleteInput input={input} options={options} />
}

export default OrganizationsAutocomplete

```