[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 vtex-ads/react/components/SponsoredBrands/types.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type SponsoredBrandsTemplates = 'rounded'

interface SponsoredBrandsInnerProps {
  handleProducts?: (products: Product[]) => void
  hideHeader?: boolean
  hideLogo?: boolean
  hideHeadline?: boolean
  hideDescription?: boolean
  hideBrandName?: boolean
  template?: SponsoredBrandsTemplates | null
}

//

type VTEXAdsSponsoredBrandsProps = {
  active?: boolean
  placementName?: string
  placementNameAdmin?: string
  quantity?: number
  quantityAdmin?: string
  categoryName?: string
  categoryNameAdmin?: string

  hideHeader?: boolean
  hideLogo?: boolean
  hideHeadline?: boolean
  hideDescription?: boolean
  hideBrandName?: boolean

  template
}

interface OnProductClickData {
  brand: string
  brandId: number
  cacheId: string
  categoryTree: CategoryTree[]
  description: string
  items: Item[]
  link: string
  linkText: string
  priceRange: PriceRange
  productClusters: ProductCluster[]
  productId: string
  productName: string
  productReference: string
  properties: string[]
  specificationGroups: string[]
  __typename: string
  sku: Sku
}

interface Sku {
  images: Image[]
  itemId: string
  measurementUnit: string
  name: string
  sellers: Seller[]
  unitMultiplier: number
  variations: string[]
  __typename: string
  seller: Seller
  referenceId: ReferenceId
  image: Image
}

interface ReferenceId {
  Value: string
}

interface ProductCluster {
  id: string
  name: string
  __typename: string
}

interface PriceRange {
  listPrice: ListPrice
  sellingPrice: ListPrice
  __typename: string
}

interface ListPrice {
  highPrice: number
  lowPrice: number
  __typename: string
}

interface Item {
  images: Image[]
  itemId: string
  measurementUnit: string
  name: string
  sellers: Seller[]
  unitMultiplier: number
  variations: string[]
  __typename: string
}

interface Seller {
  commertialOffer: CommertialOffer
  sellerId: string
  __typename: string
}

interface CommertialOffer {
  AvailableQuantity: number
  Installments: Installment[]
  ListPrice: number
  Price: number
  PriceWithoutDiscount: number
  Tax: number
  discountHighlights: DiscountHighlight[]
  taxPercentage: number
  teasers: string[]
  __typename: string
}

interface DiscountHighlight {
  name: string
  __typename: string
}

interface Installment {
  InterestRate: number
  Name: string
  NumberOfInstallments: number
  TotalValuePlusInterestRate: number
  Value: number
  __typename: string
}

interface Image {
  imageLabel: string
  imageTag: string
  imageUrl: string
  __typename: string
}

interface CategoryTree {
  slug: string
  __typename: string
}

```


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

[User] Show me the implementation of vtex-ads/react/components/SponsoredBrands/ContentHeader.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useMemo } from 'react'

export const SponsoredBrandsContentHeader = ({
  handles,

  hideHeadline,
  hideDescription,
  handleClick,
  hideBrandName,
  data,
}: {
  handles: Record<string, string>

  hideHeadline: boolean
  hideDescription: boolean
  handleClick: () => void
  hideBrandName: boolean
  data: SponsoredBrandAd
}) => {
  const {
    brand_name: brandName,
    destination_url: destinationUrl,
    headline,
    description,
  } = data

  const buttonLabel = useMemo(() => {
    if (hideBrandName && brandName) {
      return `Veja mais de ${brandName}`
    }

    return 'Veja mais'
  }, [hideBrandName, brandName])

  return (
    <section
      className={`${handles['sponsored-brands-header-content']} flex flex-column`}
    >
      {!hideHeadline && headline && (
        <strong className={`${handles['sponsored-brands-header-headline']} f5`}>
          {headline}
        </strong>
      )}

      {!hideDescription && description && (
        <span
          className={`${handles['sponsored-brands-header-description']} f6`}
        >
          {description}
        </span>
      )}

      {destinationUrl && (
        <a
          href={destinationUrl}
          target="_blank"
          rel="noopener noreferrer"
          className={`${handles['sponsored-brands-header-button']}`}
          onClick={handleClick}
        >
          {buttonLabel}
        </a>
      )}
    </section>
  )
}

export default SponsoredBrandsContentHeader

```


[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 vtex-ads/react/components/SponsoredBrands/SponsoredBrandsTag.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

interface SponsoredBrandsTagProps {
  handles: Record<string, string>
  text?: string
}

const SponsoredBrandsTag: React.FC<SponsoredBrandsTagProps> = ({
  handles,
  text = 'Patrocinado',
}) => {
  return (
    <aside
      className={`${handles['sponsored-brands-label-container']} ml-auto items-end`}
    >
      <small className={`${handles['sponsored-brands-label-text']} black-50`}>
        {text}
      </small>
    </aside>
  )
}

export default SponsoredBrandsTag

```


[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 vtex-ads/react/components/SponsoredBrands/Logo.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

type SponsoredBrandLogoProps = {
  handles: Record<string, string>
  assets?: SponsoredBrandAd | null
}

const SponsoredBrandLogo = ({ handles, assets }: SponsoredBrandLogoProps) => {
  return assets?.brand_url ? (
    <div className={`${handles['sponsored-brands-logo-container']} flex`}>
      <img
        src={assets?.brand_url}
        alt={assets?.brand_name}
        className={`${handles['sponsored-brands-logo']} b--silver mw3 w4 h3 br3 ba b--silver mr4`}
        style={{
          objectFit: 'cover',
        }}
      />
    </div>
  ) : (
    <></>
  )
}

export default SponsoredBrandLogo

```


[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 vtex-ads/react/components/ProductSponsoredTag/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useCallback, useMemo, useRef } from 'react'
import { useProduct } from 'vtex.product-context'
import { useCssHandles } from 'vtex.css-handles'

import type { ProductContextValue } from '../../typings/ProductContextValue'
import { useOnView } from '../../hooks/useOnView'
import { useAds } from '../../hooks/useAds'

const CSS_HANDLES = ['product-tag-label'] as const

const ProductSponsoredTag: StorefrontFunctionComponent = () => {
  const { handles } = useCssHandles(CSS_HANDLES)

  const adRef = useRef<HTMLDivElement | null>(null)

  const { handleEvents } = useAds()

  const productContextValue = useProduct() as
    | Partial<ProductContextValue>
    | undefined

  const itemId = useMemo(
    () => productContextValue?.product?.sku?.itemId ?? null,

    [productContextValue]
  )

  const onView = useCallback(() => {
    if (itemId) {
      handleEvents({ type: 'product', event: 'impression', itemId })
    }
  }, [handleEvents, itemId])

  useOnView({
    ref: adRef,
    onView,
    once: true,
    initializeOnInteraction: true,
  })

  return (
    <small className={handles['product-tag-label']} ref={adRef}>
      patrocinado
    </small>
  )
}

export default ProductSponsoredTag

```


[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 vtex-ads/react/components/PixelEvent/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useCallback, useMemo, useRef } from 'react'
import { useProduct } from 'vtex.product-context'
import { useCssHandles } from 'vtex.css-handles'

import type { ProductContextValue } from '../../typings/ProductContextValue'
import { useOnView } from '../../hooks/useOnView'
import { useAds } from '../../hooks/useAds'

const CSS_HANDLES = ['product-pixel-event'] as const

const PixelEvent: StorefrontFunctionComponent = () => {
  const { handles } = useCssHandles(CSS_HANDLES)

  const adRef = useRef<HTMLDivElement | null>(null)

  const { handleEvents } = useAds()

  const productContextValue = useProduct() as
    | Partial<ProductContextValue>
    | undefined

  const itemId = useMemo(
    () => productContextValue?.product?.sku?.itemId ?? null,
    [productContextValue]
  )

  const onView = useCallback(() => {
    if (itemId) {
      handleEvents({ type: 'product', event: 'impression', itemId })
    }
  }, [handleEvents, itemId])

  useOnView({
    ref: adRef,
    onView,
    once: true,
    initializeOnInteraction: true,
  })

  return (
    <span
      className={handles['product-pixel-event']}
      ref={adRef}
      style={{ width: 0, height: 0, zIndex: -1 }}
    />
  )
}

export default PixelEvent

```


[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 vtex-ads/react/components/Conversion/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useCallback } from 'react'
import { canUseDOM } from 'vtex.render-runtime'

import { useAds } from '../../hooks/useAds'

const Conversion: React.FC = () => {
  const { handleConversion } = useAds()

  const handleEvents = useCallback(
    (event: VtexEvent) => {
      const { data } = event

      if (data.eventName === 'vtex:orderPlaced') {
        handleConversion(data)
      }
    },
    [handleConversion]
  )

  if (canUseDOM) {
    window.addEventListener('message', handleEvents)
  }

  return <></>
}

export default Conversion

```


[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 vtex-ads/react/components/Shelf/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { useCssHandles } from 'vtex.css-handles'

import { useAds } from '../../hooks/useAds'
import ProductShelf from '../UI/ProductShelf'
import { useProductQuery } from '../../hooks/useProductQuery'

const CSS_HANDLES = ['shelf-container'] as const

function Shelf() {
  const { handles } = useCssHandles(CSS_HANDLES)

  const { skuProducts } = useAds()

  const { offers } = useProductQuery()

  return (
    <>
      {!!skuProducts?.length && (
        <section className={handles['shelf-container']}>
          {!!offers && <ProductShelf products={offers} />}
        </section>
      )}
    </>
  )
}

export default Shelf

```


[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 vtex-ads/react/components/Shelf/types.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type NewtailMediaShelfProps = {
  active?: boolean
  placementName?: string
  placementNameAdmin?: string
  quantity?: number
  quantityAdmin?: string
  categoryName?: string
  categoryNameAdmin?: string
}

type NewtailMediaProductsProps = {
  active?: boolean
  placementName?: string
  placementNameAdmin?: string
  quantity?: number
  quantityAdmin?: string
  categoryName?: string
  categoryNameAdmin?: string

  handleProducts?: (products: Product[]) => void
}

interface OnProductClickData {
  brand: string
  brandId: number
  cacheId: string
  categoryTree: CategoryTree[]
  description: string
  items: Item[]
  link: string
  linkText: string
  priceRange: PriceRange
  productClusters: ProductCluster[]
  productId: string
  productName: string
  productReference: string
  properties: string[]
  specificationGroups: string[]
  __typename: string
  sku: Sku
}

interface Sku {
  images: Image[]
  itemId: string
  measurementUnit: string
  name: string
  sellers: Seller[]
  unitMultiplier: number
  variations: string[]
  __typename: string
  seller: Seller
  referenceId: ReferenceId
  image: Image
}

interface ReferenceId {
  Value: string
}

interface ProductCluster {
  id: string
  name: string
  __typename: string
}

interface PriceRange {
  listPrice: ListPrice
  sellingPrice: ListPrice
  __typename: string
}

interface ListPrice {
  highPrice: number
  lowPrice: number
  __typename: string
}

interface Item {
  images: Image[]
  itemId: string
  measurementUnit: string
  name: string
  sellers: Seller[]
  unitMultiplier: number
  variations: string[]
  __typename: string
}

interface Seller {
  commertialOffer: CommertialOffer
  sellerId: string
  __typename: string
}

interface CommertialOffer {
  AvailableQuantity: number
  Installments: Installment[]
  ListPrice: number
  Price: number
  PriceWithoutDiscount: number
  Tax: number
  discountHighlights: DiscountHighlight[]
  taxPercentage: number
  teasers: string[]
  __typename: string
}

interface DiscountHighlight {
  name: string
  __typename: string
}

interface Installment {
  InterestRate: number
  Name: string
  NumberOfInstallments: number
  TotalValuePlusInterestRate: number
  Value: number
  __typename: string
}

interface Image {
  imageLabel: string
  imageTag: string
  imageUrl: string
  __typename: string
}

interface CategoryTree {
  slug: string
  __typename: string
}

```


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

[User] Show me the implementation of vtex-ads/react/components/Banner/ItemBanner.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import { useCssHandles } from 'vtex.css-handles'

import { useAds } from '../../hooks/useAds'
import { useOnView } from '../../hooks/useOnView'
import { ImageFixedSize } from '../UI/Image'

const CSS_HANDLES = ['banner-item', 'banner-image'] as const

const ItemBanner = ({ data }: { data: BannerAd }) => {
  const { handles } = useCssHandles(CSS_HANDLES)

  const bannerRef = useRef<HTMLDivElement | null>(null)

  const { handleEvents } = useAds()

  const adId = useMemo(
    () => data.ad_id || null,

    [data]
  )

  const handleImpression = useCallback(() => {
    if (adId) {
      handleEvents({ type: 'banner', event: 'impression', adId })
    }
  }, [handleEvents, adId])

  const onView = useCallback(() => {
    if (adId) {
      handleEvents({ type: 'banner', event: 'view', adId })
    }
  }, [handleEvents, adId])

  const handleClick = useCallback(() => {
    if (adId) {
      handleEvents({ type: 'banner', event: 'click', adId })
    }
  }, [handleEvents, adId])

  useOnView({
    ref: bannerRef,
    onView,
    once: true,
    initializeOnInteraction: true,
  })

  useEffect(() => {
    handleImpression()
  }, [handleImpression])

  return (
    <div
      ref={bannerRef}
      className={`${handles['banner-item']} ${handles['banner-item']}__${data.ad_id}`}
      data-van-aid={data.ad_id}
    >
      {data.destination_url ? (
        <a href={data.destination_url} onClick={handleClick}>
          <ImageFixedSize data={data} handles={handles} prefix="banner" />
        </a>
      ) : (
        <ImageFixedSize data={data} handles={handles} prefix="banner" />
      )}
    </div>
  )
}

export default ItemBanner

```


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

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import { useCssHandles } from 'vtex.css-handles'

import { useAds } from '../../hooks/useAds'
import ItemBanner from './ItemBanner'

const CSS_HANDLES = ['banner-container'] as const

const Banner = () => {
  const { handles } = useCssHandles(CSS_HANDLES)

  const { banners } = useAds()

  return banners?.length ? (
    <section className={handles['banner-container']}>
      {banners.map((banner) => (
        <ItemBanner data={banner} key={banner.ad_id} />
      ))}
    </section>
  ) : (
    <></>
  )
}

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 vtex-ads/react/components/Banner/types.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type NewtailMediaBannerProps = {
  active?: boolean

  placementName?: string
  placementNameAdmin?: string

  size?: string
  sizeAdmin?: string

  sizeMobile?: string
  sizeMobileAdmin?: string

  quantity?: number
  quantityAdmin?: string

  categoryName?: string
  categoryNameAdmin?: string
}

```


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

[User] Show me the implementation of vtex-ads/react/components/UI/Image/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

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

type ImageFixedSizeProps = {
  data: Partial<{
    media_url: string
    altText?: string
    ad_id: string
  }>
  handles: Record<string, string>
  prefix: string
  fixedMinWidth?: boolean
}

export const ImageFixedSize = ({
  prefix,
  data,
  handles,
  fixedMinWidth = false,
}: ImageFixedSizeProps) => {
  const [imageSize, setImageSize] = useState<{
    width: number | string
    height: number | string
  }>({
    height: 'auto',
    width: 'auto',
  })

  useEffect(() => {
    if (!data.media_url) return
    const img = new Image()

    img.src = data.media_url
    img.onload = () => {
      setImageSize({ width: img.width, height: img.height })
    }
  }, [data.media_url])

  return (
    <>
      <style>
        {`
        .${handles[`${prefix}-item`]}__${data.ad_id} {
          max-width: ${imageSize.width}px;
          min-width: ${fixedMinWidth ? `${imageSize.width}px` : 'auto'};
          margin: 0 auto;
        }
        .${handles[`${prefix}-image`]}.vtex-ads-banner__${data.ad_id} {
          width: 100vw;
          max-width: 100%;
          height: auto;
          max-height: ${imageSize.height}px;
          margin: auto;
        }
      `}
      </style>

      <img
        src={data.media_url}
        alt={data.altText ?? 'Banner'}
        className={`${handles[`${prefix}-image`]} vtex-ads-component-banner__${
          data.ad_id
        }`}
        width={imageSize.width}
        height={imageSize.height}
      />
    </>
  )
}

```


[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 vtex-ads/react/components/UI/ProductShelf/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

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

import { useAds } from '../../../hooks/useAds'
import { handleAvailableItems } from '../../../helpers/availableitems'

interface Props {
  products: Product[]
}

const ProductShelf = ({ products }: Props) => {
  const { handleProductClickOnShelf } = useAds()

  const productAds = handleAvailableItems(products)

  return (
    <>
      {!!productAds?.length && (
        <>
          <ExtensionPoint id="rich-text" />

          <ExtensionPoint
            id="list-context.product-list-static"
            products={productAds}
            hideUnavailableItems
            actionOnProductClick={(data: OnProductClickData) =>
              handleProductClickOnShelf(data)
            }
          />
        </>
      )}
    </>
  )
}

export default ProductShelf

```


[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 vtex-ads/react/components/SponsoredBrands/styles/templates.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const templateStyles = {
  rounded: {
    contentContainer: 'pa2 pa4-ns ba br3 b--silver',
  },
}

```


[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 vtex-ads/react/components/SponsoredBrands/styles/handles.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const CSS_HANDLES = [
  'sponsored-brands-container',
  'sponsored-brands-header',
  'sponsored-brands-header-container',
  'sponsored-brands-header-content',
  'sponsored-brands-header-headline',
  'sponsored-brands-header-description',
  'sponsored-brands-header-button',
  'sponsored-brands-content',
  'sponsored-brands-label-container',
  'sponsored-brands-label-text',
  'sponsored-brands-logo-container',
  'sponsored-brands-logo',
  'sponsored-brands-banner-container',
  'sponsored-brands-products-container',
  'sponsored-brands-banner-image',
  'sponsored-brands-banner-item',
] as const

```


[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 vtex-ads/react/hooks/useProductQuery/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useLazyQuery } from 'react-apollo'
import { useEffect, useMemo } from 'react'

import productsByIdentifier from '../../queries/productsByIdentifier.gql'
import { useAds } from '../useAds'

const getAdId = ({
  productAds,
  product,
}: {
  productAds: ProductAd[] | null
  product: Record<string, any>
}) =>
  productAds?.find((item) => item.product_sku === product?.items?.[0]?.itemId)
    ?.ad_id ?? null

const useProductQuery = () => {
  const { skuProducts, products } = useAds()

  const [
    queryBaseProductsByID,
    {
      data: baseProductsData,
      loading: loadingBaseProducts,
      called: queryBaseProductsCalled,
      refetch: baseProductsRefetch,
    },
  ] = useLazyQuery(productsByIdentifier, { notifyOnNetworkStatusChange: true })

  useEffect(() => {
    if (!!skuProducts && skuProducts.length === 0) {
      return
    }

    const executeQuery = (variables: Record<string, any>) =>
      queryBaseProductsCalled
        ? baseProductsRefetch(variables)
        : queryBaseProductsByID({ variables })

    if (skuProducts) {
      executeQuery({
        field: 'sku',
        values: skuProducts,
      })
    }
  }, [
    queryBaseProductsCalled,
    queryBaseProductsByID,
    baseProductsRefetch,
    skuProducts,
  ])

  const productsByIdentifierWithAds = useMemo(() => {
    if (loadingBaseProducts) return null

    return baseProductsData?.productsByIdentifier?.map(
      (product: Record<string, any>) => ({
        ...product,
        advertisement: {
          adId: getAdId({ productAds: products, product }),
          campaignId: null,
          adRequestId: null,
          adResponseId: null,
          actionCost: null,
        },
      })
    )
  }, [loadingBaseProducts, baseProductsData?.productsByIdentifier, products])

  return { offers: productsByIdentifierWithAds }
}

export { useProductQuery }

```


[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 vtex-ads/react/hooks/useAds/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable no-console */
import React, {
  useEffect,
  createContext,
  useCallback,
  useState,
  useContext,
  useMemo,
} from 'react'
import { useRuntime } from 'vtex.render-runtime'

import { getNewtailMedia, postNewtailMediaConversionURL } from '../../services'
import { getUserIdByEmail } from '../../helpers/getUserId'
import { useAdsEvents } from '../useAdEvents'
import { getSkusEventData } from '../useNewtailMediaSearch/utils'
import { useRequestBody } from '../useNewtailMediaSearch/formatRequestBody'
import { useSessionData } from '../useSessionData'
import { debugTemplates } from '../../utils/debug'
import { hashEmail } from '../../utils/hash'

const NewtailMediaContext = createContext<NewtailMediaContextData | null>(
  {} as NewtailMediaContextData
)

type VTEXAdsProviderType = {
  adType: AdTypes | 'conversion'
} & NewtailMediaBannerProps

const VTEXAdsProvider: React.FC<VTEXAdsProviderType> = ({
  adType,
  children,
  placementName,
  placementNameAdmin,
  size,
  sizeAdmin,
  sizeMobile,
  sizeMobileAdmin,
  quantity,
  quantityAdmin,
  categoryName: categoryNameProps,
  categoryNameAdmin,
}) => {
  const { query: queryRaw } = useRuntime()

  const debug = useMemo(() => queryRaw?.debug ?? null, [queryRaw])

  const publisherId = window?.newtailMedia?.publisherId

  const placement =
    placementNameAdmin || placementName || `placement_${adType}_default`

  const mediaSize = sizeAdmin || size
  const mobileMediaSize = sizeMobileAdmin || sizeMobile
  const categoryName = categoryNameAdmin || categoryNameProps

  const defaultQuantity = adType === 'banner' ? 1 : 20
  const quantityAds = Number(quantityAdmin) || quantity || defaultQuantity

  const [loading, setLoading] = useState(true)

  const [products, setProducts] = useState<ProductAd[] | null>(null)
  const [productsSB, setProductsSB] = useState<
    SponsoredBrandAdProduct[] | null
  >(null)

  const [skuProducts, setSkuProducts] = useState<string[] | null>(null)
  const [banners, setBanners] = useState<BannerAd[] | null>(null)
  const [assetsSB, setAssetsSB] = useState<SponsoredBrandAd | null>(null)

  /**
   * Handle session and user id
   */
  const { sessionId, userId } = useSessionData()

  /**
   * Handle request payload
   */

  const requestBody = useRequestBody({
    placement,
    adType: adType as AdTypes,
    mediaSize,
    mobileMediaSize,
    quantityAds,
    categoryName,
  })

  const handleResponse = useCallback(
    (data: AdsResponse) => {
      const response = data?.[placement]

      if (!response) return

      if (adType === 'product') {
        const adsData = response as ProductAd[]

        setProducts(adsData)
        setSkuProducts(adsData.map((item) => item.product_sku) || null)
      }

      if (adType === 'banner') {
        const adsData = response as BannerAd[]

        setBanners(adsData)
      }

      if (adType === 'sponsored_brand') {
        const [adData] = response as SponsoredBrandAd[]
        const productsData = adData?.products
        // max products === quantityAds
        const sliceProducts = productsData?.slice(0, quantityAds) || []

        setProductsSB(productsData)
        setSkuProducts(sliceProducts.map((item) => item.product_sku) || null)
        setAssetsSB(adData || null)
      }
    },
    [adType, placement, quantityAds]
  )

  const handleRequestAds = useCallback(async () => {
    if (!sessionId || adType === 'conversion') return

    try {
      setLoading(true)

      if (!requestBody) return

      const body = {
        publisherId,
        body: requestBody,
      }

      if (debug === 'vtexads') {
        console.log(
          `%c 🚀 VTEXAdsProvider :: Request :: ${placement}`,
          debugTemplates.primary,
          body
        )
      }

      const { data } = await getNewtailMedia(body)

      if (debug === 'vtexads') {
        console.log(
          `%c 🚀 VTEXAdsProvider :: Response :: ${placement}`,
          debugTemplates.primary,
          data
        )
      }

      handleResponse(data)
    } catch (error) {
      console.log(error)
    } finally {
      setLoading(false)
    }
  }, [
    adType,
    debug,
    handleResponse,
    placement,
    publisherId,
    requestBody,
    sessionId,
  ])

  useEffect(() => {
    if (adType !== 'conversion') {
      handleRequestAds()
    }
  }, [handleRequestAds, adType])

  /**
   * Handle events
   * @function handleEvents()
   */

  const fireEvent = useCallback(
    ({ url }) => {
      const body = {
        session_id: sessionId,
      } as {
        session_id: string
        user_id: string
      }

      if (userId) {
        body.user_id = userId
      }

      navigator.sendBeacon(url, new URLSearchParams(body))
    },
    [sessionId, userId]
  )

  /**
   * Handle banner events
   * @function handleBannerClick()
   * @function handleBannrImpression()
   * @function handleBannerView()
   */

  const handleEvents = useCallback(
    ({ type, event, adId, itemId }: HandleEvents) => {
      // console.log('handleEvents', type, event, adId, itemId)

      let adData = null
      let url = null
      const eventKey = `${event}_url` as keyof EventsUrl

      if (type === 'banner') {
        adData = banners?.find((item) => item.ad_id === adId)
      }

      if (type === 'sponsored_brand') {
        adData = assetsSB
      }

      if (type === 'product' && adType === 'product') {
        adData = products?.find((item) => item.product_sku === itemId)
      }

      // Tratamento extra por estar usando o mesmo componente de produto para SB
      if (type === 'product' && adType === 'sponsored_brand') {
        adData = assetsSB?.products?.find((item) => item.product_sku === itemId)
      }

      url = adData?.[eventKey]

      !!url && fireEvent({ url })
    },
    [adType, assetsSB, banners, fireEvent, products]
  )

  /**
   * Handle product events
   */

  const { handleAdsEvents } = useAdsEvents()

  const handleProductClickOnShelf = useCallback(
    (data: OnProductClickData) => {
      const eventName = 'vtex:productClickOnShelf'

      const skusEventData = getSkusEventData?.[eventName]?.(data)

      const productsData = adType === 'product' ? products : productsSB

      let adsData: ProductAd[] | SponsoredBrandAdProduct[] | undefined

      if (adType === 'product') {
        adsData = (productsData as ProductAd[] | undefined)?.filter((ad) =>
          skusEventData.includes(ad.product_sku)
        )
      }

      if (adType === 'sponsored_brand') {
        adsData = (
          productsData as SponsoredBrandAdProduct[] | undefined
        )?.filter((ad) => skusEventData.includes(ad.product_sku))
      }

      handleAdsEvents({ ads: adsData, event: eventName })
    },
    [adType, handleAdsEvents, products, productsSB]
  )

  /**
   * Handle conversion
   */

  const handleConversion = useCallback(
    async (data: Order) => {
      if (!sessionId) {
        return
      }

      let verifiedUserId: string | null = userId

      const [email] = data.visitorContactInfo

      if (!userId) {
        await getUserIdByEmail(email)
          .then((responseUserId) => {
            verifiedUserId = responseUserId
          })
          .catch((error) => {
            console.error('Error:', error)
          })
      }

      const formatItens = (listProducts: ProductOrder[]) =>
        listProducts.map((item) => ({
          sku: item.sku,
          quantity: item.quantity,
          price: item.price,
          promotional_price: item.sellingPrice,
        })) as ConversionItem[]

      const emailHashed = await hashEmail(email)

      const body = {
        publisher_id: publisherId,
        user_id: verifiedUserId ?? emailHashed,
        email_hashed: emailHashed,
        session_id: sessionId,
        order_id: data.ordersInOrderGroup?.[0] || data.orderGroup,
        items: formatItens(data.transactionProducts),
        created_at: data.transactionDate,
        channel: 'ecommerce',
      } as ConversionBody

      const jsonData = JSON.stringify(body)
      const blobData = new Blob([jsonData], { type: 'application/json' })

      navigator.sendBeacon(postNewtailMediaConversionURL, blobData)
    },
    [publisherId, sessionId, userId]
  )

  return (
    <NewtailMediaContext.Provider
      value={{
        loading,
        products,
        productsSB,
        skuProducts,
        assetsSB,
        banners,
        placement,
        handleEvents,
        handleProductClickOnShelf,
        handleConversion,
      }}
    >
      {children}
    </NewtailMediaContext.Provider>
  )
}

function useAds(): NewtailMediaContextData {
  const context = useContext(NewtailMediaContext)

  if (!context) {
    throw new Error('useAds must be used within an VTEXAdsProvider')
  }

  return context
}

export { NewtailMediaContext, VTEXAdsProvider, useAds }

```


[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 vtex-ads/react/hooks/useSearchPageContext/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useMemo } from 'react'
import { useSearchPage } from 'vtex.search-page-context/SearchPageContext'

export const useSearchPageContext = () => {
  const responseUseSearchPage = useSearchPage()

  const { searchQuery } = responseUseSearchPage

  const products: ContextProduct[] = useMemo(
    () => searchQuery?.data?.productSearch?.products,
    [searchQuery?.data?.productSearch?.products]
  )

  return { products }
}

```


[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 vtex-ads/react/hooks/useSearchPageContext/types.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
// Context

type ContextProduct = {
  cacheId: string
  productId: string
  description: string
  productName: string
  productReference: string
  linkText: string
  brand: string
  brandId: number
  link: string
  categories: string[]
  categoryId: string
  releaseDate: string
  priceRange: PriceRange
  specificationGroups: SpecificationGroup[]
  skuSpecifications: any[]
  productClusters: any[]
  clusterHighlights: any[]
  properties: Property[]
  __typename: string
  advertisement: null
  items: Item[]
  selectedProperties: null
  rule: null
}

interface Item {
  itemId: string
  name: string
  nameComplete: string
  complementName: string
  ean: string
  variations: any[]
  referenceId: ReferenceId[]
  measurementUnit: string
  unitMultiplier: number
  images: Image[]
  __typename: string
  sellers: Seller[]
}

interface Seller {
  sellerId: string
  sellerName: string
  sellerDefault: boolean
  __typename: string
  commertialOffer: CommertialOffer
}

interface CommertialOffer {
  discountHighlights: any[]
  teasers: any[]
  Price: number
  ListPrice: number
  Tax: number
  taxPercentage: number
  spotPrice: number
  PriceWithoutDiscount: number
  RewardValue: number
  PriceValidUntil: string
  AvailableQuantity: number
  __typename: string
  Installments: any[]
}

interface Image {
  cacheId: string
  imageId: string
  imageLabel: string
  imageTag: string
  imageUrl: string
  imageText: string
  __typename: string
}

interface ReferenceId {
  Key: string
  Value: string
  __typename: string
}

interface Property {
  name: string
  values: string[]
  __typename: string
}

interface SpecificationGroup {
  name: string
  originalName: string
  specifications: Specification[]
  __typename: string
}

interface Specification {
  name: string
  originalName: string
  values: string[]
  __typename: string
}

interface PriceRange {
  sellingPrice: SellingPrice
  listPrice: SellingPrice
  __typename: string
}

interface SellingPrice {
  highPrice: number
  lowPrice: number
  __typename: string
}

```


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

[User] Show me the implementation of vtex-ads/react/hooks/useAdEvents/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useCallback } from 'react'

import { useSessionData } from '../useSessionData'

type UseAdEvents = () => {
  handleAdsEvents: (props: HandleAdEvents) => void
}

type HandleAdEvents = {
  event: ValidVtexEvent
  ads?: SponsoredBrandAdProduct[] | ProductAd[] | BannerAd[] | null | undefined
}

type FireEventBody =
  | {
      session_id: string
    } & {
      user_id: string
    }

export const useAdsEvents: UseAdEvents = () => {
  const { sessionId, userId } = useSessionData()

  const sendEvent = useCallback(
    (finalUrl: string) => {
      const body: FireEventBody = {
        session_id: sessionId as string,
      } as FireEventBody

      if (userId) {
        body.user_id = userId as string
      }

      navigator.sendBeacon(finalUrl, new URLSearchParams(body))
    },
    [sessionId, userId]
  )

  const fireEvent = useCallback(
    ({ url }) => {
      if (!sessionId) {
        let retries = 0
        const maxRetries = 5
        const interval = setInterval(() => {
          if (sessionId) {
            clearInterval(interval)
            sendEvent(url)
          }

          retries++
          if (retries >= maxRetries) {
            clearInterval(interval)
          }
        }, 1000)

        return
      }

      sendEvent(url)
    },
    [sendEvent, sessionId]
  )

  const handleAdsEvents = useCallback(
    ({ ads, event }: HandleAdEvents) => {
      const eventsKeys = {
        'vtex:productImpression': 'impression',
        'vtex:productView': 'view',
        'vtex:productClick': 'click',
        'vtex:productClickOnShelf': 'click',
      }

      const eventKey = eventsKeys[event]

      ads?.forEach((ad: ProductAd | BannerAd | SponsoredBrandAdProduct) => {
        let url = null
        const eventKeyUrl = `${eventKey}_url` as keyof EventsUrl

        url = ad?.[eventKeyUrl]

        !!url && fireEvent({ url })
      })
    },
    [fireEvent]
  )

  return { handleAdsEvents }
}

```


[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 vtex-ads/react/hooks/useNewtailMediaSearch/index.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable no-console */
import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react'
import { useIntl } from 'react-intl'
import { useRuntime } from 'vtex.render-runtime'

import { getNewtailMedia } from '../../services'
import { useSearchPageContext } from '../useSearchPageContext'
import { extractSKUs } from './extractSKUs'
import { useRequestBody } from './formatRequestBody'
import { useAdsEvents } from '../useAdEvents'
import { handleQuantityAds, eventIsValid, getSkusEventData } from './utils'
// Default settings
import * as D from '../../settings'

const NewtailMediaSearchContext =
  createContext<NewtailMediaSearchContextData | null>(
    {} as NewtailMediaSearchContextData
  )

const NewtailMediaSearchProvider: React.FC<NewtailMediaSearchProviderProps> = ({
  children,
  onlyFirstSKU = false,
  onlyFirstSKUAdmin = false,
  parentSearchSelector,
  parentSearchSelectorAdmin,
  placementName,
  placementNameAdmin,
  tagClassname,
  tagClassnameAdmin,
  tagPositionAdmin,
  tagPosition,
  tagText,
  tagTextAdmin,
  quantity,
  quantityAdmin,
  // Sponsored Skus at the beginning
  // do not use if using infinite scrolling
  sponsoredSkusAtTop = true,
}) => {
  const { query: queryRaw } = useRuntime()

  const debug = useMemo(() => queryRaw?.debug ?? null, [queryRaw])

  /**
   * Handle settings
   */

  const i18n = useIntl()

  const quantityAds = handleQuantityAds({
    quantityAdmin,
    quantity,
    defaultValue: 20,
  })

  const publisherId = window?.newtailMedia?.publisherId
  const placement =
    placementNameAdmin || placementName || `placement_search_default`

  const parentSelector =
    parentSearchSelectorAdmin || parentSearchSelector || D.searchSelectorDefault

  const HTMLElementTag = 'small'
  const tagPositionElement: TagPosition =
    tagPositionAdmin || tagPosition || 'start'

  const onlyFirstSKUInner = onlyFirstSKUAdmin || onlyFirstSKU || false

  const classNameTag =
    tagClassnameAdmin || tagClassname || D.tagClassnameDefault

  const labelTag =
    tagTextAdmin ||
    tagText ||
    i18n.formatMessage({
      id: 'admin/vtex-vtex-ads.search.tagText.default',
      defaultMessage: 'Patrocinado',
    })

  // Handle states hook

  const [productAds, setProductAds] = useState<ProductAd[] | null>(null)
  const [skusProductAds, setSkusProductAds] = useState<string[] | null>(null)

  /**
   * Get search result
   */

  const { products } = useSearchPageContext()

  const skus = useMemo(
    () => extractSKUs({ products, onlyFirstSKU: onlyFirstSKUInner }),
    [onlyFirstSKUInner, products]
  )

  /**
   * Handle request ads
   */

  const requestBody = useRequestBody({
    skus,
    placement,
    quantityAds,
    forceSearchContext: true,
  })

  const handleRequestAds = useCallback(async () => {
    if (!requestBody) return

    try {
      const body = {
        publisherId,
        body: requestBody,
      }

      if (debug === 'vtexads') {
        console.log(
          `%c 🚧 🚧 🚧 🚀 NewtailMediaSearchProvider :: Request :: ${placement}`,
          'color:white;background:#E31C58;',
          body
        )
      }

      const { data } = await getNewtailMedia(body)

      if (debug === 'vtexads') {
        console.log(
          `%c 🚧 🚧 🚧 🚀 NewtailMediaSearchProvider :: Response :: ${placement}`,
          'color:white;background:#E31C58;',
          data
        )
      }

      const response = data?.[placement] as ProductAd[]

      if (!response) return

      const responseSkus = response?.map((item) => item.product_sku) || null

      setProductAds(response)
      setSkusProductAds(responseSkus)
    } catch (error) {
      console.error(error)
    }
  }, [debug, placement, publisherId, requestBody])

  useEffect(() => {
    if (products?.length && requestBody) {
      handleRequestAds()
    }
  }, [handleRequestAds, products, requestBody])

  /**
   * Handle sponsored SKUs
   */
  const sponsoredSkus = useMemo(
    () =>
      skusProductAds
        ? skus.filter((sku) => skusProductAds.includes(sku))
        : null,
    [skus, skusProductAds]
  )

  /**
   * Handle sponsored tags
   */
  const handleSponsoredTag = useCallback(() => {
    const container = document.querySelector(parentSelector)

    if (!skusProductAds || !container || !sponsoredSkus?.length) return

    sponsoredSkus.forEach((item) => {
      const searchResultItem = products.find((product) =>
        product.items.some((productItem) => productItem.itemId === item)
      )

      if (!searchResultItem) return

      const getItemElements = () => {
        const byLink = container.querySelectorAll(
          `a[href*='${searchResultItem.link}']`
        )

        if (byLink.length) {
          return byLink
        }

        const byLinkText = container.querySelectorAll(
          `a[href*='${searchResultItem.linkText}']`
        )

        return byLinkText
      }

      const itemElements = getItemElements()

      itemElements.forEach((element: Element) => {
        if (sponsoredSkusAtTop) {
          // handle product summary container
          // div.vtex-search-result-3-x-galleryItem > section.vtex-product-summary-2-x-container
          const sectionParent = element?.parentElement

          const containerParent = sectionParent?.parentElement

          if (containerParent) {
            containerParent.classList.add(`sponsored-product-container`)
            containerParent.style.order = '-1'
          }
        }

        if (element.querySelector(`.${classNameTag}`)) {
          return
        }

        const sponsoredTag = document.createElement(HTMLElementTag)

        sponsoredTag.textContent = labelTag
        sponsoredTag.className = classNameTag

        const insertActions: TagPositionAction = {
          start: () => element.prepend(sponsoredTag),
          end: () => element.appendChild(sponsoredTag),
          // custom: () => customHandle()
        }

        insertActions?.[tagPositionElement]?.()
      })
    })
  }, [
    parentSelector,
    skusProductAds,
    sponsoredSkus,
    products,
    sponsoredSkusAtTop,
    classNameTag,
    labelTag,
    tagPositionElement,
  ])

  useEffect(() => {
    handleSponsoredTag()
  }, [handleSponsoredTag])

  /**
   * Handle events
   */

  const { handleAdsEvents } = useAdsEvents()

  const handleEvents = useCallback(
    (e: PixelMessage) => {
      const eventName = e?.data?.eventName as ValidVtexEvent

      if (!eventName || !eventIsValid(eventName)) return

      const eventData: EventData = e.data

      const skusEventData = getSkusEventData?.[eventName]?.(eventData as any)

      const adsData = productAds?.filter((ad) =>
        skusEventData.includes(ad.product_sku)
      )

      handleAdsEvents({ ads: adsData, event: eventName })
    },
    [handleAdsEvents, productAds]
  )

  return (
    <NewtailMediaSearchContext.Provider
      value={{
        handleEvents,
      }}
    >
      {children}
    </NewtailMediaSearchContext.Provider>
  )
}

function useAdsSearch(): NewtailMediaSearchContextData {
  const context = useContext(NewtailMediaSearchContext)

  if (!context) {
    throw new Error(
      'useAdsSearch must be used within an NewtailMediaSearchProvider'
    )
  }

  return context
}

export { NewtailMediaSearchContext, NewtailMediaSearchProvider, useAdsSearch }

```


[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 vtex-ads/react/hooks/useNewtailMediaSearch/types.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type NewtailMediaSearchContextData = {
  handleEvents: (e: PixelMessage) => void
}

type NewtailMediaSearchProviderProps = React.PropsWithChildren<
  {
    publisherId?: string
    sponsoredSkusAtTop?: boolean
  } & NewtailMediaSearchProps
>

type ValidVtexEvent =
  | 'vtex:productImpression'
  | 'vtex:productView'
  | 'vtex:productClick'
  | 'vtex:productClickOnShelf'

type GetSkusEventData = {
  'vtex:productImpression': (eventData: ProductImpressionData) => string[]
  'vtex:productView': (eventData: ProductViewData) => string[]
  'vtex:productClick': (eventData: ProductClickData) => string[]
  'vtex:productClickOnShelf': (eventData: OnProductClickData) => string[]
}

type EventData = ProductImpressionData | ProductClickData | ProductViewData

type TagPosition = 'start' | 'end'

type TagPositionAction = {
  [key in TagPosition]: () => void
}

```


[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 vtex-ads/react/hooks/useNewtailMediaSearch/utils.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
const extractSkusFromItems = (data: Item[] | ItemSummary[]) =>
  data.map((item: Item | ItemSummary) => item.itemId)

const extractSkus = {
  impressions: (data: ProductImpressionData) => {
    const products = data.impressions.map((impression) => ({
      ...impression.product,
    }))

    const items = products.reduce(
      (acc, product) => [...acc, ...product.items],
      [] as ItemSummary[]
    )

    return extractSkusFromItems(items)
  },
  clicks: (data: ProductClickData) => extractSkusFromItems(data.product.items),
  clicksOnShelf: (data: OnProductClickData) => extractSkusFromItems(data.items),
  views: (data: ProductViewData) => extractSkusFromItems(data.product.items),
}

export const getSkusEventData: GetSkusEventData = {
  'vtex:productImpression': (data) => extractSkus.impressions(data),
  'vtex:productView': (data) => extractSkus.views(data),
  'vtex:productClick': (data) => extractSkus.clicks(data),
  'vtex:productClickOnShelf': (data) => extractSkus.clicksOnShelf(data),
}

const validEvents: ValidVtexEvent[] = Object.keys(
  getSkusEventData
) as ValidVtexEvent[]

export const eventIsValid = (eventName: ValidVtexEvent | string) =>
  validEvents.includes(eventName as ValidVtexEvent)

/**
 * Handle quantity ads
 */
export const handleQuantityAds = ({
  quantity,
  quantityAdmin,
  defaultValue,
}: {
  quantity?: string | number
  quantityAdmin?: string | number
  defaultValue: number
}) => {
  const validQuantity = (value?: string | number) =>
    !Number.isNaN(Number(value)) && Number(value) > 0

  const validQuantityAdmin = (value?: string | number) =>
    !Number.isNaN(Number(value)) && Number(value) > 0

  if (validQuantityAdmin(quantityAdmin)) return Number(quantityAdmin)

  if (validQuantity(quantity)) return Number(quantity)

  return defaultValue
}

```


[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 vtex-ads/react/hooks/useNewtailMediaSearch/formatRequestBody.tsx from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```tsx
import { useMemo } from 'react'

import { useDeviceType } from '../useDeviceType'
import { useSessionData } from '../useSessionData'
import { usePageContext } from '../usePageContext'

type FormatRequestBodyProps = {
  skus?: string[]
  placement: string
  mediaSize?: string
  mobileMediaSize?: string
  categoryName?: string
  quantityAds?: number
  adType?: AdTypes
  forceSearchContext?: boolean
}

type FormatRequestBody = (props: FormatRequestBodyProps) => null | RequestBody

type ContextData = {
  category: CategoryContextData
  brand_page: BrandPageContextData
  search: SearchContextData
  home: HomeContextData
  product_page: ProductPageContextData
}

const adTypesKeys = {
  product: 'product',
  banner: 'banner',
  sponsored_brand: 'sponsored_brand',
} as { [key in AdTypes]: AdTypes }

export const useRequestBody: FormatRequestBody = ({
  skus,
  placement = 'search',
  quantityAds = 20,
  mediaSize,
  mobileMediaSize,
  adType = 'product',
  forceSearchContext = false,
  categoryName: categoryNameOverride,
}) => {
  const { sessionId, userId } = useSessionData()
  const { context, term, brandName, categoryName, productSKU } =
    usePageContext()

  const brandCode = window?.newtailMedia?.brandCode

  const device = useDeviceType()

  const mediaSizeByDevice =
    device === 'mobile' && mobileMediaSize ? mobileMediaSize : mediaSize

  const contextData: ContextData = useMemo(
    () => ({
      category: {
        context: 'category',
        category_name: categoryName || '',
      },
      brand_page: {
        context: 'brand_page',
        brand_name: brandName || '',
      },
      search: {
        context: 'search',
        term,
        skus,
      },
      home: {
        context: 'home',
      },
      product_page: {
        context: 'product_page',
        product_sku: productSKU,
      },
    }),
    [brandName, categoryName, productSKU, skus, term]
  )

  const contextDataFinal = useMemo(() => {
    if (forceSearchContext) {
      return { ...contextData?.[context], skus }
    }

    if (categoryNameOverride) {
      return {
        context: contextData?.[context].context,
        category_name: categoryNameOverride,
      }
    }

    return contextData?.[context]
  }, [categoryNameOverride, context, contextData, forceSearchContext, skus])

  const placementData = useMemo(
    () => ({
      [adTypesKeys.banner]: {
        size: mediaSizeByDevice,
        quantity: quantityAds,
        types: [adTypesKeys.banner],
      },
      [adTypesKeys.product]: {
        quantity: quantityAds,
        types: [adTypesKeys.product],
      },
      [adTypesKeys.sponsored_brand]: {
        size: mediaSizeByDevice,
        quantity: 1,
        types: [adTypesKeys.sponsored_brand],
      },
    }),
    [mediaSizeByDevice, quantityAds]
  )

  const body = useMemo(
    () =>
      !sessionId
        ? null
        : ({
            device,
            term,
            user_id: userId,
            session_id: sessionId,
            placements: {
              [placement]: placementData[adType],
            },
            ...contextDataFinal,
          } as RequestBody),
    [
      adType,
      contextDataFinal,
      device,
      placement,
      placementData,
      sessionId,
      term,
      userId,
    ]
  )

  if (body?.term === null) {
    delete body.term
  }

  if (body && !!brandCode?.length) {
    body.brand = brandCode
  }

  return body
}

```


[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 vtex-ads/react/hooks/useNewtailMediaSearch/extractSKUs.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type HandleProductsProps = {
  products: ContextProduct[]
  onlyFirstSKU?: boolean
}

type HandleProducts = (props: HandleProductsProps) => string[]

export const extractSKUs: HandleProducts = ({
  products,
  onlyFirstSKU = false,
}) => {
  if (!products?.length) return []

  const filteredSKUs = products.reduce((acc, item) => {
    const itemIds = onlyFirstSKU
      ? [item.items[0].itemId]
      : item.items.map((product) => product.itemId)

    return [...acc, ...itemIds]
  }, [] as string[])

  return filteredSKUs
}

```


[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 vtex-ads/react/hooks/useAds/types/context.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type PlacementName = string

type NewtailMediaContextData = {
  loading: boolean
  placement: PlacementName
  skuProducts: string[] | null
  products: ProductAd[] | null
  productsSB: SponsoredBrandAdProduct[] | null
  assetsSB: SponsoredBrandAd | null
  banners: BannerAd[] | null
  handleConversion(data: Order): void
  handleEvents(data: HandleEvents): void
  handleProductClickOnShelf: (data: OnProductClickData) => void
}

```


[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 vtex-ads/react/hooks/useAds/types/functions.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
type ExtendEventType =
  | {
      type: 'product'
      itemId: string
    }
  | {
      type: 'banner'
      adId: string
    }
  | {
      type: 'sponsored_brand'
      adId?: string
    }

type HandleEvents = {
  type: AdTypes
  event: 'view' | 'impression' | 'click'
  itemId?: string
  adId?: string
  ad?: ProductAd | BannerAd | SponsoredBrandAd | null | undefined
} & ExtendEventType

```


[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 vtex-ads/react/hooks/useAdEvents/types/impression.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface ProductImpressionEvent {
  currency: string
  eventName: 'vtex:productImpression'
  event: 'productImpression'
  list: string
  impressions: Impression[]
}

interface Impression {
  product: Product
  position: number
}

interface Product {
  cacheId: string
  productId: string
  description: string
  productName: string
  productReference: string
  linkText: string
  brand: string
  brandId: number
  link: string
  categories: string[]
  categoryId: string
  releaseDate: string
  priceRange: PriceRange
  specificationGroups: SpecificationGroup[]
  skuSpecifications: any[]
  productClusters: any[]
  clusterHighlights: any[]
  properties: Property[]
  __typename: string
  advertisement: null
  items: Item[]
  selectedProperties: null
  rule: null
  sku: Sku
}

interface Sku {
  itemId: string
  name: string
  nameComplete: string
  complementName: string
  ean: string
  variations: any[]
  referenceId: ReferenceId2
  measurementUnit: string
  unitMultiplier: number
  images: Image[]
  __typename: string
  sellers: Seller[]
  seller: Seller
  image: Image
}

interface ReferenceId2 {
  Key: string
  Value: null | string
  __typename: string
}

interface Item {
  itemId: string
  name: string
  nameComplete: string
  complementName: string
  ean: string
  variations: any[]
  referenceId: ReferenceId[]
  measurementUnit: string
  unitMultiplier: number
  images: Image[]
  __typename: string
  sellers: Seller[]
}

interface Seller {
  sellerId: string
  sellerName: string
  sellerDefault: boolean
  __typename: string
  commertialOffer: CommertialOffer
}

interface CommertialOffer {
  discountHighlights: any[]
  teasers: any[]
  Price: number
  ListPrice: number
  Tax: number
  taxPercentage: number
  spotPrice: number
  PriceWithoutDiscount: number
  RewardValue: number
  PriceValidUntil: string
  AvailableQuantity: number
  __typename: string
  Installments: any[]
}

interface Image {
  cacheId: string
  imageId: string
  imageLabel: string
  imageTag: string
  imageUrl: string
  imageText: string
  __typename: string
}

interface ReferenceId {
  Key: string
  Value: null | null | string | string
  __typename: string
}

interface Property {
  name: string
  values: string[]
  __typename: string
}

interface SpecificationGroup {
  name: string
  originalName: string
  specifications: Specification[]
  __typename: string
}

interface Specification {
  name: string
  originalName: string
  values: string[]
  __typename: string
}

interface PriceRange {
  sellingPrice: SellingPrice
  listPrice: SellingPrice
  __typename: string
}

interface SellingPrice {
  highPrice: number
  lowPrice: number
  __typename: string
}

```


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

[User] Show me the implementation of vtex-ads/react/hooks/useAdEvents/types/click.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface ProductClickEvent {
  currency: string
  eventName: 'vtex:productClick'
  event: 'productClick'
  product: Product
  query: string
  map: string
  position: number
  list: string
}

interface Product {
  cacheId: string
  productId: string
  description: string
  productName: string
  productReference: string
  linkText: string
  brand: string
  brandId: number
  link: string
  categories: string[]
  categoryId: string
  releaseDate: string
  priceRange: PriceRange
  specificationGroups: SpecificationGroup[]
  skuSpecifications: any[]
  productClusters: any[]
  clusterHighlights: any[]
  properties: Property[]
  __typename: string
  advertisement: null
  items: Item[]
  selectedProperties: null
  rule: null
  sku: Sku
}

interface Sku {
  itemId: string
  name: string
  nameComplete: string
  complementName: string
  ean: string
  variations: any[]
  referenceId: ReferenceId
  measurementUnit: string
  unitMultiplier: number
  images: Image[]
  __typename: string
  sellers: Seller[]
  seller: Seller
  image: Image
}

interface Item {
  itemId: string
  name: string
  nameComplete: string
  complementName: string
  ean: string
  variations: any[]
  referenceId: ReferenceId[]
  measurementUnit: string
  unitMultiplier: number
  images: Image[]
  __typename: string
  sellers: Seller[]
}

interface Seller {
  sellerId: string
  sellerName: string
  sellerDefault: boolean
  __typename: string
  commertialOffer: CommertialOffer
}

interface CommertialOffer {
  discountHighlights: any[]
  teasers: any[]
  Price: number
  ListPrice: number
  Tax: number
  taxPercentage: number
  spotPrice: number
  PriceWithoutDiscount: number
  RewardValue: number
  PriceValidUntil: string
  AvailableQuantity: number
  __typename: string
  Installments: any[]
}

interface Image {
  cacheId: string
  imageId: string
  imageLabel: string
  imageTag: string
  imageUrl: string
  imageText: string
  __typename: string
}

interface ReferenceId {
  Key: string
  Value: string
  __typename: string
}

interface Property {
  name: string
  values: string[]
  __typename: string
}

interface SpecificationGroup {
  name: string
  originalName: string
  specifications: Specification[]
  __typename: string
}

interface Specification {
  name: string
  originalName: string
  values: string[]
  __typename: string
}

interface PriceRange {
  sellingPrice: SellingPrice
  listPrice: SellingPrice
  __typename: string
}

interface SellingPrice {
  highPrice: number
  lowPrice: number
  __typename: string
}

```


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

[User] Show me the implementation of vtex-ads/react/hooks/useAdEvents/types/view.d.ts from the vtex-ads VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface ProductViewEvent {
  currency: string
  eventName: 'vtex:productView'
  event: 'productView'
  product: Product
  list: string
}

interface Product {
  detailUrl: string
  brand: string
  brandId: number
  productReference: string
  linkText: string
  categoryId: string
  categories: string[]
  categoryTree: CategoryTree[]
  productId: string
  productName: string
  items: Item[]
  selectedSku: Item
}

interface Item {
  itemId: string
  name: string
  ean: string
  referenceId: ReferenceId[]
  imageUrl: string
  sellers: Seller[]
}

interface Seller {
  sellerId: string
  sellerName: string
  sellerDefault: boolean
  commertialOffer: CommertialOffer
}

interface CommertialOffer {
  Price: number
  ListPrice: number
  AvailableQuantity: number
  PriceWithoutDiscount: number
}

interface ReferenceId {
  Key: string
  Value: string
  __typename: string
}

interface CategoryTree {
  id: number
  name: string
  href: string
  __typename: string
}

```


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

[User] Show me the implementation of shelf-components/messages/hu.json from the shelf-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Polc",
  "admin/editor.shelf.description": "Leírás",
  "admin/editor.buy-together.title": "Vásárlás együtt",
  "store/shelf.buy-together.title": "Vásárlás együtt",
  "admin/editor.title.label": "Cím",
  "admin/editor.secondary-title.label": "Másodlagos cím",
  "store/shelf.buy-together.change.label": "Módosítás",
  "store/shelf.buy-together.remove.label": "Eltávolítás",
  "store/shelf.buy-together.add.label": "Hozzáadás",
  "store/shelf.buy-together.total-products.label": "{total} {total, plural, one {termék} other {termék}} vásárlása a következő áron:",
  "admin/editor.shelf.collection.title": "Gyűjteményazonosító",
  "admin/editor.refresh-shelf.title": "Polc frissítése",
  "admin/editor.refresh-shelf.base-product.label": "Alaptermék címe",
  "admin/editor.refresh-shelf.secondary-base-product.label": "Másodlagos alaptermék címe",
  "admin/editor.refresh-shelf.suggested-products.label": "Ajánlott termékek címe",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "Másodlagos ajánlott termékek címe",
  "admin/editor.refresh-shelf.slider-layout.title": "Csúszka elrendezése",
  "admin/editor.refresh-shelf.suggested-products-list.title": "Ajánlott termékek listái",
  "admin/editor.refresh-shelf.suggested-products-list.description": "Fontos: ha kitölti az „ajánlott termékazonosítók” mezőt, az alatta lévő összes többi mező (kategóriaazonosító, gyűjtemény stb.) figyelmen kívül hagyásra kerül.",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "Alaptermék-azonosító",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "Ajánlott termékek azonosítói",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "Az azonosítókat vesszővel kell elválasztani (pl. 1,2,3)",
  "store/shelf.refresh.refresh-product-summary.title": "A következőt látta:",
  "store/shelf.refresh.suggested-products.title": "Önnek ajánlott"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Hylly",
  "admin/editor.shelf.description": "Kuvaus",
  "admin/editor.buy-together.title": "Osta yhdessä",
  "store/shelf.buy-together.title": "Osta yhdessä",
  "admin/editor.title.label": "Nimi",
  "admin/editor.secondary-title.label": "Toissijainen ruutu",
  "store/shelf.buy-together.change.label": "Muuta",
  "store/shelf.buy-together.remove.label": "Poista",
  "store/shelf.buy-together.add.label": "Lisää",
  "store/shelf.buy-together.total-products.label": "Osta {total} {total, plural, one {tuote} other {tuotetta}} hintaan",
  "admin/editor.shelf.collection.title": "Kokoelman tunnus",
  "admin/editor.refresh-shelf.title": "Päivitä hylly",
  "admin/editor.refresh-shelf.base-product.label": "Perustuotenimike",
  "admin/editor.refresh-shelf.secondary-base-product.label": "Toissijainen tuotteen pohjanimike",
  "admin/editor.refresh-shelf.suggested-products.label": "Ehdotettu tuotenimike",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "Toissijaisten ehdotettu tuotenimike",
  "admin/editor.refresh-shelf.slider-layout.title": "Liukusäätimen asettelu",
  "admin/editor.refresh-shelf.suggested-products-list.title": "Ehdotetut tuoteluettelot",
  "admin/editor.refresh-shelf.suggested-products-list.description": "Tärkeää: jos täytät ”ehdotetut tuotetunnukset” -kentän, kaikki muut tämän alla olevat kentät (kategorian tunnus, kokoelma jne.) sivuutetaan.",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "Perustuotetunnus",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "Ehdotetut tuotetunnukset",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "Tunnukset tulee erottaa pilkuilla (esim.: 1,2,3)",
  "store/shelf.refresh.refresh-product-summary.title": "Näit tämän",
  "store/shelf.refresh.suggested-products.title": "Suositellaan sinulle"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Vitrine",
  "admin/editor.shelf.description": "Descrição",
  "admin/editor.buy-together.title": "Compre junto",
  "store/shelf.buy-together.title": "Compre junto",
  "admin/editor.title.label": "Título",
  "admin/editor.secondary-title.label": "Título Secundário",
  "store/shelf.buy-together.change.label": "Mudar",
  "store/shelf.buy-together.remove.label": "Remover",
  "store/shelf.buy-together.add.label": "Adicionar",
  "store/shelf.buy-together.total-products.label": "Comprar {total} {total, plural, one {produto} other {produtos}} por",
  "admin/editor.shelf.collection.title": "ID da Coleção",
  "admin/editor.refresh-shelf.title": "Vitrine atualizável",
  "admin/editor.refresh-shelf.base-product.label": "Título do produto base",
  "admin/editor.refresh-shelf.secondary-base-product.label": "Título secundário do produto base",
  "admin/editor.refresh-shelf.suggested-products.label": "Título dos produtos sugeridos",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "Título secundário dos produtos sugeridos",
  "admin/editor.refresh-shelf.slider-layout.title": "Slider Layout",
  "admin/editor.refresh-shelf.suggested-products-list.title": "Listas de produtos sugeridos",
  "admin/editor.refresh-shelf.suggested-products-list.description": "Importante: se você preencher o campo 'IDs dos produtos sugeridos', todos os campos abaixo deste serão ignorados (ID da categoria, collection, etc.)",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "ID do produto base",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "IDs dos produtos sugeridos",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "Os IDs devem estar separados por vírgula (ex. 1,2,3)",
  "store/shelf.refresh.refresh-product-summary.title": "Você viu",
  "store/shelf.refresh.suggested-products.title": "Sugeridos para você"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Shelf",
  "admin/editor.shelf.description": "Description",
  "admin/editor.buy-together.title": "Buy Together",
  "store/shelf.buy-together.title": "Buy Together",
  "admin/editor.title.label": "Title",
  "admin/editor.secondary-title.label": "Secondary Title",
  "store/shelf.buy-together.change.label": "Change",
  "store/shelf.buy-together.remove.label": "Remove",
  "store/shelf.buy-together.add.label": "Add",
  "store/shelf.buy-together.total-products.label": "Buy {total} {total, plural, one {product} other {products}} for",
  "admin/editor.shelf.collection.title": "Collection ID",
  "admin/editor.refresh-shelf.title": "Refresh Shelf",
  "admin/editor.refresh-shelf.base-product.label": "Base Product Title",
  "admin/editor.refresh-shelf.secondary-base-product.label": "Secondary Base Product Title",
  "admin/editor.refresh-shelf.suggested-products.label": "Suggested Products Title",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "Secondary Suggested Products Title",
  "admin/editor.refresh-shelf.slider-layout.title": "Slider Layout",
  "admin/editor.refresh-shelf.suggested-products-list.title": "Suggested Products Lists",
  "admin/editor.refresh-shelf.suggested-products-list.description": "Important: if you fill in the 'suggested product ids' field, all other fields below this (category ID, collection, etc.) will be ignored.",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "Base product ID",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "Suggested products IDs",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "IDs must be separated by a comma (e.g: 1,2,3)",
  "store/shelf.refresh.refresh-product-summary.title": "You saw",
  "store/shelf.refresh.suggested-products.title": "Suggested for you"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Shelf title",
  "admin/editor.shelf.description": "Shelf description",
  "admin/editor.buy-together.title": "Buy Together editor title",
  "store/shelf.buy-together.title": "Buy together title",
  "admin/editor.title.label": "Title label",
  "admin/editor.secondary-title.label": "Secondary title label",
  "store/shelf.buy-together.change.label": "Change label",
  "store/shelf.buy-together.remove.label": "Remove label",
  "store/shelf.buy-together.add.label": "Add label",
  "store/shelf.buy-together.total-products.label": "Total products label",
  "admin/editor.shelf.collection.title": "Collection title",
  "admin/editor.refresh-shelf.title": "Refresh Shelf title",
  "admin/editor.refresh-shelf.base-product.label": "Base Product Title label",
  "admin/editor.refresh-shelf.secondary-base-product.label": "Secondary Base Product Title label",
  "admin/editor.refresh-shelf.suggested-products.label": "Suggested Products Title label",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "Secondary Suggested Products Title label",
  "admin/editor.refresh-shelf.slider-layout.title": "Slider Layout title",
  "admin/editor.refresh-shelf.suggested-products-list.title": "Suggested products list title",
  "admin/editor.refresh-shelf.suggested-products-list.description": "Description for suggested products list",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "Base product title",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "Suggested products title",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "Suggested products description",
  "store/shelf.refresh.refresh-product-summary.title": "Refresh Product Summary title",
  "store/shelf.refresh.suggested-products.title": "Refresh Suggested Products title"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "Escaparate",
  "admin/editor.shelf.description": "Description",
  "admin/editor.buy-together.title": "Comprar juntos",
  "store/shelf.buy-together.title": "Comprar juntos",
  "admin/editor.title.label": "Título",
  "admin/editor.secondary-title.label": "Título secundario",
  "store/shelf.buy-together.change.label": "Cambiar",
  "store/shelf.buy-together.remove.label": "Eliminar",
  "store/shelf.buy-together.add.label": "Agregar",
  "store/shelf.buy-together.total-products.label": "Comprar {total} {total, plural, one {producto} other {productos}} por",
  "admin/editor.shelf.collection.title": "ID de la Colección",
  "admin/editor.refresh-shelf.title": "Escaparate actualizable",
  "admin/editor.refresh-shelf.base-product.label": "Título del producto base",
  "admin/editor.refresh-shelf.secondary-base-product.label": "Título secundario del producto base",
  "admin/editor.refresh-shelf.suggested-products.label": "Título de productos sugeridos",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "Título secundario de productos sugeridos",
  "admin/editor.refresh-shelf.slider-layout.title": "Slider Layout",
  "admin/editor.refresh-shelf.suggested-products-list.title": "Listas de productos sugeridos",
  "admin/editor.refresh-shelf.suggested-products-list.description": "Importante: si completa el campo 'ID de productos sugeridos', se ignorarán todos los demás campos debajo de este (ID de categoría, colección, etc.)",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "ID del producto base",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "ID de productos sugeridos",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "Los IDs deben estar separados por una coma (p. ej. 1,2,3)",
  "store/shelf.refresh.refresh-product-summary.title": "Has visto",
  "store/shelf.refresh.suggested-products.title": "Sugeridos para ti"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.shelf.title": "الرفوف",
  "admin/editor.shelf.description": "الوصف",
  "admin/editor.buy-together.title": "الشراء معا",
  "store/shelf.buy-together.title": "الشراء معا",
  "admin/editor.title.label": "العنوان",
  "admin/editor.secondary-title.label": "عنوان ثانوي",
  "store/shelf.buy-together.change.label": "تغيير",
  "store/shelf.buy-together.remove.label": "حذف",
  "store/shelf.buy-together.add.label": "إضافة",
  "store/shelf.buy-together.total-products.label": "شراء {total} {total, plural, one {منتج} other {منتجات}} لـ",
  "admin/editor.shelf.collection.title": "معرّف المجموعة",
  "admin/editor.refresh-shelf.title": "تحديث الرفوف",
  "admin/editor.refresh-shelf.base-product.label": "عنوان المنتج الأساسي",
  "admin/editor.refresh-shelf.secondary-base-product.label": "عنوان المنتج الثانوي",
  "admin/editor.refresh-shelf.suggested-products.label": "عنوان المنتجات المقترحة",
  "admin/editor.refresh-shelf.secondary-suggested-products.label": "عنوان المنتجات الثانوية المقترحة",
  "admin/editor.refresh-shelf.slider-layout.title": "تصميم شريط التمرير",
  "admin/editor.refresh-shelf.suggested-products-list.title": "قوائم المنتجات المقترحة",
  "admin/editor.refresh-shelf.suggested-products-list.description": "هام: إذا قمت بملء حقل \"معرفات المنتج المقترحة\"، فسيتم تجاهل جميع الحقول الأخرى الموجودة أسفل هذه (معرف الفئة، المجموعة، إلخ).",
  "admin/editor.refresh-shelf.suggested-products-list.base-product.title": "معرّف المنتج الأساسي",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title": "معرّفات المنتجات المقترحة",
  "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description": "يجب فصل المعرفات بفاصلة (على سبيل المثال: 1، 2، 3)",
  "store/shelf.refresh.refresh-product-summary.title": "رأيتَ",
  "store/shelf.refresh.suggested-products.title": "مقترحة لك"
}

```


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

[Assistant]
Here's the implementation:

```markdown
📢 Use this project, [contribute](https://github.com/vtex-apps/shelf-components) to it or open issues to help evolve it.

# Shelf Components

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

VTEX Shelf Components is a collection of components that can be used to create shelves in your store, which are responsible for displaying a list of products.

:loudspeaker: **Disclaimer:** Don't fork this project; use, contribute, or open issue with your feature request.

## Table of Contents

- [Usage](#usage)
  - [Styles API](#styles-api)
- [Components Specs](#components-specs)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)

## Usage

This app uses our store builder with the blocks architecture. To know more about Store Builder [click here.](https://help.vtex.com/en/tutorial/understanding-storebuilder-and-stylesbuilder#structuring-and-configuring-our-store-with-object-object)

To use this app, you need to import in your dependencies on `manifest.json`.

```json
  "dependencies": {
    "vtex.shelf-components": "0.x"
  }
```

### Styles API

This app provides some CSS classes as an API for style customization.

To use this CSS API, you must add the `styles` builder and create an app styling CSS file.

1. Add the `styles` builder to your `manifest.json`:

```json
  "builders": {
    "styles": "1.x"
  }
```

2. Create a file called `vtex.shelf-components.css` inside the `styles/css` folder. Add your custom styles:

```css
.container {
  margin-top: 10px;
}
```

## Components Specs

Below we have a README for each component of this project that explains how to use them.

- [Shelf](Shelf.md)
- [Refresh Shelf](RefreshShelf.md)

## Troubleshooting

You can check if others are passing through similar issues [here](https://github.com/vtex-apps/shelf-components/issues). Also feel free to [open issues](https://github.com/vtex-apps/shelf-components/issues/new) or contribute with pull requests.

## Contributing

Check it out [how to contribute](https://github.com/vtex-apps/awesome-io#contributing) with this project.

<!-- DOCS-IGNORE:start -->
## 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 -->
<table>
  <tr>
    <td align="center"><a href="https://github.com/pgrimaud"><img src="https://avatars1.githubusercontent.com/u/1866496?v=4" width="100px;" alt=""/><br /><sub><b>Pierre Grimaud</b></sub></a><br /><a href="https://github.com/vtex-apps/shelf-components/commits?author=pgrimaud" title="Documentation">📖</a></td>
  </tr>
</table>

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

<!-- 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 shelf-components/react/package.json from the shelf-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "shelf-components",
  "version": "0.10.1",
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "apollo-client": "^2.6.8",
    "classnames": "^2.2.6",
    "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/classnames": "^2.2.10",
    "@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.7.0",
    "prop-types": "^15.7.2",
    "react-content-loader": "^5.1.0",
    "typescript": "3.9.7",
    "vtex.add-to-cart-button": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.add-to-cart-button@0.20.1/public/@types/vtex.add-to-cart-button",
    "vtex.css-handles": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.css-handles@0.4.4/public/@types/vtex.css-handles",
    "vtex.device-detector": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.device-detector@0.2.5/public/@types/vtex.device-detector",
    "vtex.flex-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.flex-layout@0.15.1/public/@types/vtex.flex-layout",
    "vtex.format-currency": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.format-currency@0.2.0/public/@types/vtex.format-currency",
    "vtex.messages": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.messages@1.60.2/public/@types/vtex.messages",
    "vtex.pixel-manager": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.pixel-manager@1.4.0/public/@types/vtex.pixel-manager",
    "vtex.product-context": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-context@0.9.2/public/@types/vtex.product-context",
    "vtex.product-group-context": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-group-context@0.2.0/public/@types/vtex.product-group-context",
    "vtex.product-list-context": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-list-context@0.3.0/public/@types/vtex.product-list-context",
    "vtex.product-price": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-price@1.10.0/public/@types/vtex.product-price",
    "vtex.product-summary": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.product-summary@2.63.1/public/@types/vtex.product-summary",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.126.0/public/@types/vtex.render-runtime",
    "vtex.responsive-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.responsive-layout@0.1.2/public/@types/vtex.responsive-layout",
    "vtex.search-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.search-graphql@0.36.0/public/_types/react",
    "vtex.slider-layout": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.slider-layout@0.15.2/public/@types/vtex.slider-layout",
    "vtex.store-components": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-components@3.132.0/public/@types/vtex.store-components",
    "vtex.store-resources": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.store-resources@0.74.0/public/_types/react",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.133.2/public/@types/vtex.styleguide"
  }
}

```


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

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

[Assistant]
Here's the implementation:

```tsx
export { default } from './components/BuyTogether'

```


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

[Assistant]
Here's the implementation:

```tsx
export { default } from './components/RefreshShelf'

```


[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 shelf-components/store/contentSchemas.json from the shelf-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "definitions": {
    "Shelf": {
      "type": "object",
      "properties": {
        "title": {
          "title": "admin/editor.title.label",
          "type": "string"
        },
        "secondaryTitle": {
          "title": "admin/editor.secondary-title.label",
          "type": "string"
        }
      }
    },
    "BuyTogether": {
      "type": "object",
      "properties": {
        "title": {
          "title": "admin/editor.title.label",
          "type": "string"
        }
      }
    },
    "RefreshShelf": {
      "type": "object",
      "properties": {
        "baseProductTitle": {
          "title": "admin/editor.refresh-shelf.base-product.label",
          "type": "string"
        },
        "secondaryBaseProductTitle": {
          "title": "admin/editor.refresh-shelf.secondary-base-product.label",
          "type": "string"
        },
        "suggestedProductsTitle": {
          "title": "admin/editor.refresh-shelf.suggested-products.label",
          "type": "string"
        },
        "secondarySuggestedProductsTitle": {
          "title": "admin/editor.refresh-shelf.secondary-suggested-products.label",
          "type": "string"
        },
        "suggestedLists": {
          "title": "admin/editor.refresh-shelf.suggested-products-list.title",
          "description": "admin/editor.refresh-shelf.suggested-products-list.description",
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "baseProductId": {
                "type": "string",
                "title": "admin/editor.refresh-shelf.suggested-products-list.base-product.title"
              },
              "suggestedProductsIds": {
                "type": "string",
                "title": "admin/editor.refresh-shelf.suggested-products-list.suggested-products.title",
                "description": "admin/editor.refresh-shelf.suggested-products-list.suggested-products.description"
              },
              "$ref": "#/definitions/SearchProperties"
            }
          }
        },
        "sliderLayout": {
          "type": "object",
          "title": "admin/editor.refresh-shelf.slider-layout.title",
          "properties": {
            "showNavigationArrows": {
              "default": "always",
              "enum": ["mobileOnly", "desktopOnly", "always", "never"],
              "title": "admin/editor.slider-layout.showNavigation",
              "type": "string"
            },
            "showPaginationDots": {
              "default": "always",
              "enum": ["mobileOnly", "desktopOnly", "always", "never"],
              "title": "admin/editor.slider-layout.showPaginationDots",
              "type": "string"
            }
          }
        }
      }
    },
    "SearchProperties": {
      "category": {
        "title": "admin/editor.productSummaryList.category.title",
        "description": "admin/editor.productSummaryList.category.description",
        "type": "string",
        "isLayout": false
      },
      "specificationFilters": {
        "title": "admin/editor.productSummaryList.specificationFilters.title",
        "type": "array",
        "items": {
          "title": "admin/editor.productSummaryList.specificationFilters.item.title",
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "title": "admin/editor.productSummaryList.specificationFilters.item.id.title"
            },
            "value": {
              "type": "string",
              "title": "admin/editor.productSummaryList.specificationFilters.item.value.title"
            }
          }
        }
      },
      "collection": {
        "title": "admin/editor.shelf.collection.title",
        "type": "string",
        "isLayout": false
      },
      "orderBy": {
        "title": "admin/editor.productSummaryList.orderBy.title",
        "type": "string",
        "$ref": "#/definitions/OrderByOptions",
        "isLayout": false
      },
      "hideUnavailableItems": {
        "title": "admin/editor.productSummaryList.hideUnavailableItems",
        "type": "boolean",
        "default": false,
        "isLayout": false
      },
      "maxItems": {
        "title": "admin/editor.productSummaryList.maxItems.title",
        "type": "number",
        "isLayout": false,
        "default": 10
      },
      "skusFilter": {
        "title": "admin/editor.productSummaryList.skusFilter.title",
        "description": "admin/editor.productSummaryList.skusFilter.description",
        "type": "string",
        "default": "ALL_AVAILABLE",
        "enum": ["ALL_AVAILABLE", "ALL", "FIRST_AVAILABLE"],
        "enumNames": [
          "admin/editor.productSummaryList.skusFilter.all-available",
          "admin/editor.productSummaryList.skusFilter.none",
          "admin/editor.productSummaryList.skusFilter.first-available"
        ]
      },
      "installmentCriteria": {
        "title": "admin/editor.productSummaryList.installmentCriteria.title",
        "description": "admin/editor.productSummaryList.installmentCriteria.description",
        "type": "string",
        "default": "MAX_WITHOUT_INTEREST",
        "enum": ["MAX_WITHOUT_INTEREST", "MAX_WITH_INTEREST"],
        "enumNames": [
          "admin/editor.productSummaryList.installmentCriteria.max-without-interest",
          "admin/editor.productSummaryList.installmentCriteria.max-with-interest"
        ]
      }
    },
    "OrderByOptions": {
      "enum": [
        "OrderByScoreDESC",
        "OrderByTopSaleDESC",
        "OrderByPriceDESC",
        "OrderByPriceASC",
        "OrderByNameASC",
        "OrderByNameDESC",
        "OrderByReleaseDateDESC",
        "OrderByBestDiscountDESC"
      ],
      "enumNames": [
        "admin/editor.productSummaryList.orderType.relevance",
        "admin/editor.productSummaryList.orderType.sales",
        "admin/editor.productSummaryList.orderType.priceDesc",
        "admin/editor.productSummaryList.orderType.priceAsc",
        "admin/editor.productSummaryList.orderType.nameAsc",
        "admin/editor.productSummaryList.orderType.nameDesc",
        "admin/editor.productSummaryList.orderType.releaseDate",
        "admin/editor.productSummaryList.orderType.discount"
      ],
      "default": "OrderByTopSaleDESC"
    }
  }
}

```


[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 shelf-components/store/blocks.json from the shelf-components VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "add-to-cart-button#my-add-to-cart": {},
  "buy-button#my-add-to-cart": {},

  "flex-layout.col#product-image": {
    "children": ["product-summary-image#shelf"]
  },

  "product-summary-image#shelf": {
    "props": {
      "showBadge": false,
      "aspectRatio": "1:1",
      "maxHeight": 300
    }
  },

  "product-list-price#summary": {
    "props": {
      "blockClass": "summary"
    }
  },
  "product-selling-price#summary": {
    "props": {
      "blockClass": "summary"
    }
  },

  "flex-layout.row#selling-price-savings": {
    "props": {
      "colGap": 2,
      "preserveLayoutOnMobile": true,
      "preventHorizontalStretch": true,
      "marginBottom": 4
    },
    "children": [
      "product-selling-price#summary",
      "product-price-savings#summary"
    ]
  },

  "product-installments#summary": {
    "props": {
      "blockClass": "summary"
    }
  },

  "product-price-savings#summary": {
    "props": {
      "markers": ["discount"],
      "blockClass": "summary"
    }
  },

  "product-summary-sku-selector#buy-together": {
    "props": {
      "thumbnailImage": "skuvariation",
      "imageHeight": 28,
      "blockClass": "buyTogether",
      "visibility": "more-than-one"
    }
  },

  "flex-layout.col#product-summary-details": {
    "props": {
      "marginLeft": 4
    },
    "children": [
      "product-summary-name",
      "product-summary-space",
      "product-list-price#summary",
      "flex-layout.row#selling-price-savings",
      "product-installments#summary",
      "product-summary-sku-selector#buy-together"
    ]
  },

  "flex-layout.row#product-summary-mobile": {
    "children": [
      "flex-layout.col#product-image",
      "flex-layout.col#product-summary-details"
    ],
    "props": {
      "blockClass": "buyTogether"
    }
  },

  "flex-layout.col#product-summary-desktop": {
    "children": [
      "product-summary-image#shelf",
      "product-summary-name",
      "product-summary-space",
      "product-list-price#summary",
      "flex-layout.row#selling-price-savings",
      "product-installments#summary",
      "product-summary-sku-selector#buy-together"
    ]
  },
  "flex-layout.row#product-summary-desktop": {
    "children": ["flex-layout.col#product-summary-desktop"]
  },

  "responsive-layout.phone#product-summary": {
    "children": ["flex-layout.row#product-summary-mobile"]
  },
  "responsive-layout.tablet#product-summary": {
    "children": ["flex-layout.row#product-summary-mobile"]
  },

  "responsive-layout.desktop#product-summary": {
    "children": ["flex-layout.row#product-summary-desktop"]
  },

  "product-summary.shelf#buy-together": {
    "children": [
      "responsive-layout.desktop#product-summary",
      "responsive-layout.tablet#product-summary",
      "responsive-layout.phone#product-summary"
    ],
    "props": {
      "blockClass": "buyTogether"
    }
  },

  "product-summary.shelf": {
    "children": [
      "product-summary-image#shelf",
      "product-summary-name",
      "product-summary-space",
      "product-list-price#summary",
      "flex-layout.row#selling-price-savings",
      "product-installments#summary",
      "add-to-cart-button"
    ]
  },

  "slider-layout#shelf": {
    "props": {
      "itemsPerPage": {
        "desktop": 5,
        "tablet": 3,
        "phone": 1
      },
      "infinite": true,
      "fullWidth": false,
      "blockClass": "shelf"
    }
  },

  "list-context.product-list": {
    "blocks": ["product-summary.shelf"],
    "children": ["slider-layout#shelf"]
  },

  "list-context.product-list-static": {
    "blocks": ["product-summary.shelf"],
    "children": ["slider-layout#shelf"]
  },

  "buy-together": {
    "blocks": ["product-summary.shelf#buy-together"],
    "props": {
      "BuyButton": "add-to-cart-button#my-add-to-cart"
    }
  },

  "refresh-shelf": {
    "blocks": ["product-summary.shelf"]
  },

  "default-shelf": {
    "blocks": ["list-context.product-list", "list-context.product-list-static"]
  }
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "buy-together": {
    "required": ["product-summary"],
    "allowed": ["responsive-layout"],
    "component": "BuyTogether",
    "composition": "children",
    "content": {
      "$ref": "#/definitions/BuyTogether"
    }
  },
  "refresh-shelf": {
    "required": ["product-summary"],
    "component": "RefreshShelf",
    "content": {
      "$ref": "#/definitions/RefreshShelf"
    }
  },
  "default-shelf": {
    "allowed": ["list-context.product-list", "list-context.product-list-static"],
    "component": "Shelf",
    "content": {
      "$ref": "#/definitions/Shelf"
    }
  }
}

```