[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 quickorder/react/TextAreaBlock.tsx from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
import type { FunctionComponent } from 'react'
import React, { useState, useContext } from 'react'
import type { WrappedComponentProps } from 'react-intl'
import { FormattedMessage, injectIntl } from 'react-intl'
import { Button, Textarea, ToastContext, Spinner } from 'vtex.styleguide'
import { OrderForm } from 'vtex.order-manager'
import type { OrderForm as OrderFormType } from 'vtex.checkout-graphql'
import { addToCart as ADD_TO_CART } from 'vtex.checkout-resources/Mutations'
import { useCssHandles } from 'vtex.css-handles'
import { useMutation } from 'react-apollo'
import { usePWA } from 'vtex.store-resources/PWAContext'
import { usePixel } from 'vtex.pixel-manager/PixelContext'

import { categoryMessages as messages } from './utils/messages'
import ReviewBlock from './components/ReviewBlock'
import { ParseText, GetText } from './utils'
import getAppSettings from './utils/getAppSettings'

interface ItemType {
  id: string
  quantity: number
}

const TextAreaBlock: FunctionComponent<
  TextAreaBlockInterface & WrappedComponentProps
> = ({ intl, value, text, hiddenColumns, description, componentOnly }: any) => {
  const [state, setState] = useState<any>({
    reviewState: false,
    showAddToCart: null,
    textAreaValue: value || '',
    reviewItems: [],
  })

  const appSettings = getAppSettings()
  const checkoutUrl = appSettings?.checkoutUrl ?? '/checkout#/cart'
  const [refidLoading, setRefIdLoading] = useState<any>()

  const { textAreaValue, reviewItems, reviewState, showAddToCart } = state

  const [
    addToCart,
    { error: mutationError, loading: mutationLoading },
  ] = useMutation<{ addToCart: OrderFormType }, { items: [] }>(ADD_TO_CART)

  const { push } = usePixel()
  const { settings = {}, showInstallPrompt = undefined } = usePWA() || {}
  const { promptOnCustomEvent } = settings

  const { setOrderForm }: OrderFormContext = OrderForm.useOrderForm()
  const orderForm = OrderForm.useOrderForm()
  const { showToast } = useContext(ToastContext)

  const translateMessage = (message: MessageDescriptor) => {
    return intl.formatMessage(message)
  }

  const resolveToastMessage = (success: boolean, isNewItem: boolean) => {
    if (!success) return translateMessage(messages.error)
    if (!isNewItem) return translateMessage(messages.duplicate)

    return translateMessage(messages.success)
  }

  const toastMessage = ({
    success,
    isNewItem,
  }: {
    success: boolean
    isNewItem: boolean
  }) => {
    const message = resolveToastMessage(success, isNewItem)

    const action = success
      ? {
          label: translateMessage(messages.seeCart),
          href:
            typeof checkoutUrl === 'string' && checkoutUrl !== ''
              ? checkoutUrl
              : '/checkout/#/cart',
        }
      : undefined

    showToast({ message, action })
  }

  const backList = () => {
    setState({
      ...state,
      reviewState: false,
    })
  }

  const callAddToCart = async (items: any) => {
    const currentItemsInCart = orderForm.orderForm.items
    const mutationResult = await addToCart({
      variables: {
        items: items.map((item: ItemType) => {
          const [existsInCurrentOrder] = currentItemsInCart.filter(
            (el) => el.id === item.id.toString()
          )

          if (existsInCurrentOrder) {
            item.quantity += parseInt(existsInCurrentOrder.quantity, 10)
          }

          return {
            ...item,
          }
        }),
      },
    })

    if (mutationError) {
      console.error(mutationError)
      toastMessage({ success: false, isNewItem: false })

      return
    }

    // Update OrderForm from the context
    mutationResult.data && setOrderForm(mutationResult.data.addToCart)

    const adjustSkuItemForPixelEvent = (item: any) => {
      return {
        skuId: item.id,
        quantity: item.quantity,
      }
    }

    // Send event to pixel-manager
    const pixelEventItems = items.map(adjustSkuItemForPixelEvent)

    push({
      event: 'addToCart',
      items: pixelEventItems,
    })

    if (
      mutationResult.data?.addToCart?.messages?.generalMessages &&
      mutationResult.data.addToCart.messages.generalMessages.length
    ) {
      mutationResult.data.addToCart.messages.generalMessages.map((msg: any) => {
        return showToast({
          message: msg.text,
          action: undefined,
          duration: 30000,
        })
      })
    } else {
      toastMessage({ success: true, isNewItem: true })
    }

    if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) {
      showInstallPrompt()
    }

    backList()

    return showInstallPrompt
  }

  const onReviewItems = (items: any) => {
    if (items) {
      const show =
        items.filter((item: any) => {
          return item.error
        }).length === 0

      setState({
        ...state,
        reviewItems: items,
        reviewState: true,
        showAddToCart: show,
        textAreaValue: GetText(items),
      })
    }

    return true
  }

  const parseText = () => {
    const items: any = ParseText(textAreaValue) || []
    const error = !!items.filter((item: any) => {
      return item.error !== null
    }).length

    setState({
      ...state,
      reviewItems: items,
      reviewState: true,
      hasError: error,
      toValidate: true,
    })
    onReviewItems(items)
  }

  const setTextareaValue = ($textAreaValue: string) => {
    setState({
      ...state,
      textAreaValue: $textAreaValue,
    })
  }

  const CSS_HANDLES = [
    'textAreaBlock',
    'buttonValidate',
    'textContainer',
    'componentContainer',
    'reviewBlock',
    'buttonsBlock',
    'textContainerTitle',
    'textContainerDescription',
  ] as const

  const handles = useCssHandles(CSS_HANDLES)

  const addToCartCopyNPaste = () => {
    const items: any = reviewItems
      .filter((item: any) => item.error === null && item.vtexSku !== null)
      .map(({ vtexSku, quantity, seller }: any) => {
        return {
          id: parseInt(vtexSku, 10),
          quantity: parseFloat(quantity),
          seller,
        }
      })

    const merge = (internalItems) => {
      return internalItems.reduce((acc, val) => {
        const { id, quantity }: ItemType = val
        const ind = acc.findIndex((el) => el.id === id)

        if (ind !== -1) {
          acc[ind].quantity += quantity
        } else {
          acc.push(val)
        }

        return acc
      }, [])
    }

    const mergedItems = merge(items)

    callAddToCart(mergedItems)
  }

  const onRefidLoading = (data: boolean) => {
    setRefIdLoading(data)
  }

  return (
    <div className={`${handles.textAreaBlock}`}>
      {!componentOnly && (
        <div className={`${handles.textContainer} w-20-l w-100-ns fl-l`}>
          <h2
            className={`t-heading-3 mb3 ml5 ml3-ns mt4 ${handles.textContainerTitle}`}
          >
            {text}
          </h2>
          <div
            className={`t-body lh-copy c-muted-1 mb7 ml3 false ${handles.textContainerDescription}`}
          >
            {description}
          </div>
        </div>
      )}

      <div
        className={`${handles.componentContainer} ${
          !componentOnly ? 'w-80-l w-100-ns fr-l pb6' : ''
        }`}
      >
        {!reviewState && (
          <div className="w-100 mb5">
            <div className="bg-base t-body c-on-base ph6 br3 b--muted-4">
              <Textarea
                value={textAreaValue}
                onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
                  setTextareaValue(e.target.value)
                }
              />
              <div className={`mt2 flex justify-end ${handles.buttonValidate}`}>
                {textAreaValue && (
                  <Button
                    variation="secondary"
                    size="regular"
                    onClick={() => {
                      parseText()
                    }}
                  >
                    <FormattedMessage id="store/quickorder.validate" />
                  </Button>
                )}
              </div>
            </div>
          </div>
        )}

        {reviewState && (
          <div className={`w-100 ph6 ${handles.reviewBlock}`}>
            <ReviewBlock
              reviewedItems={reviewItems}
              hiddenColumns={hiddenColumns ?? []}
              onReviewItems={onReviewItems}
              refidLoading={refidLoading}
              onRefidLoading={onRefidLoading}
              backList={backList}
            />
            <div
              className={`mb4 mt4 flex justify-between ${handles.buttonsBlock}`}
            >
              <Button
                variation="tertiary"
                size="small"
                onClick={() => {
                  backList()
                }}
              >
                <FormattedMessage id="store/quickorder.back" />
              </Button>
              {refidLoading && <Spinner />}
              {showAddToCart && (
                <Button
                  variation="primary"
                  size="small"
                  isLoading={mutationLoading}
                  onClick={() => {
                    addToCartCopyNPaste()
                  }}
                >
                  <FormattedMessage id="store/quickorder.addToCart" />
                </Button>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

interface MessageDescriptor {
  id: string
  description?: string | any
  defaultMessage?: string
}

interface OrderFormContext {
  loading: boolean
  orderForm: OrderFormType | undefined
  setOrderForm: (orderForm: Partial<OrderFormType>) => void
}

interface TextAreaBlockInterface {
  value: string
  onRefidLoading: any
  text?: string
  description?: string
  componentOnly?: boolean
}

export default injectIntl(TextAreaBlock)

```


[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 quickorder/react/global.css from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```css
.vtex-quickorder-2-x-inputQuantity > label > div > input {
  padding-left: 0;
  padding-right: 0;
  text-align: center;
}

```


[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 quickorder/react/UploadBlock.tsx from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
import type { FunctionComponent } from 'react'
import React, { useState, useContext } from 'react'
import type { WrappedComponentProps } from 'react-intl'
import { FormattedMessage, injectIntl } from 'react-intl'
import { Button, Dropzone, ToastContext } from 'vtex.styleguide'
import { OrderForm } from 'vtex.order-manager'
import type { OrderForm as OrderFormType } from 'vtex.checkout-graphql'
import { addToCart as ADD_TO_CART } from 'vtex.checkout-resources/Mutations'
import { useCssHandles } from 'vtex.css-handles'
import { useMutation } from 'react-apollo'
import { usePWA } from 'vtex.store-resources/PWAContext'
import { usePixel } from 'vtex.pixel-manager/PixelContext'
import XLSX from 'xlsx'

import { categoryMessages as messages } from './utils/messages'
import { ParseText, GetText } from './utils'
import ReviewBlock from './components/ReviewBlock'
import { DropzoneIcon } from './assets/DropZoneIcon'
import getAppSettings from './utils/getAppSettings'

interface ItemType {
  id: string
  quantity: number
}

const UploadBlock: FunctionComponent<
  UploadBlockInterface & WrappedComponentProps
> = ({
  text,
  hiddenColumns,
  description,
  downloadText,
  componentOnly,
  intl,
  alwaysShowAddToCart = true,
}: any) => {
  let productsArray: any = []
  const [state, setState] = useState<any>({
    reviewItems: [],
    reviewState: false,
    showAddToCart: false,
  })

  const appSettings = getAppSettings()
  const checkoutUrl = appSettings?.checkoutUrl ?? '/checkout#/cart'

  const [showValidateButton, setShowValidateButton] = useState<boolean>(false)

  const [refidLoading, setRefIdLoading] = useState<any>()
  const [productsQueue, setproductsQueue] = useState<any>()
  const { reviewItems, reviewState, showAddToCart } = state

  const [
    addToCart,
    { error: mutationError, loading: mutationLoading },
  ] = useMutation<{ addToCart: OrderFormType }, { items: [] }>(ADD_TO_CART)

  const { push } = usePixel()
  const { settings = {}, showInstallPrompt = undefined } = usePWA() || {}
  const { promptOnCustomEvent } = settings

  const { setOrderForm }: OrderFormContext = OrderForm.useOrderForm()
  const orderForm = OrderForm.useOrderForm()
  const { showToast } = useContext(ToastContext)

  const translateMessage = (message: MessageDescriptor) => {
    return intl.formatMessage(message)
  }

  const resolveToastMessage = (success: boolean, isNewItem: boolean) => {
    if (!success) return translateMessage(messages.error)
    if (!isNewItem) return translateMessage(messages.duplicate)

    return translateMessage(messages.success)
  }

  const toastMessage = ({
    success,
    isNewItem,
  }: {
    success: boolean
    isNewItem: boolean
  }) => {
    const message = resolveToastMessage(success, isNewItem)

    const action = success
      ? {
          label: translateMessage(messages.seeCart),
          href:
            typeof checkoutUrl === 'string' && checkoutUrl !== ''
              ? checkoutUrl
              : '/checkout/#/cart',
        }
      : undefined

    showToast({ message, action })
  }

  const download = () => {
    const finalHeaders = ['SKU', 'Quantity']
    const data = [
      { SKU: 'AB120', Quantity: 2 },
      { SKU: 'AB121', Quantity: 3 },
      { SKU: 'AB122', Quantity: 5 },
      { SKU: 'AB123', Quantity: 10 },
      { SKU: 'AB124', Quantity: 1 },
      { SKU: 'AB125', Quantity: 20 },
    ]

    const ws = XLSX.utils.json_to_sheet(data, { header: finalHeaders })
    const wb = XLSX.utils.book_new()

    XLSX.utils.book_append_sheet(wb, ws, 'SheetJS')
    const exportFileName = `model-quickorder.xls`

    XLSX.writeFile(wb, exportFileName)
  }

  const onRefidLoading = (data: boolean) => {
    setRefIdLoading(data)
  }

  const onReviewItems = (items: any) => {
    if (items) {
      const show = !items.some((item: any) => item.error)

      setState({
        ...state,
        reviewItems: items,
        reviewState: true,
        showAddToCart: alwaysShowAddToCart || show,
        textAreaValue: GetText(items),
      })
    }

    return true
  }

  const parseText = () => {
    let textAreaValue = ''

    productsQueue.forEach((element) => {
      textAreaValue += `${element[0]},${element[1]}\n`
    })

    const items: any = ParseText(textAreaValue) || []
    const error = !!items.filter((item: any) => {
      return item.error !== null
    }).length

    setState({
      ...state,
      reviewItems: items,
      hasError: error,
    })
    onReviewItems(items)
  }

  const processWb = (() => {
    const toJson = function toJson(workbook: any) {
      const result: any = {}

      workbook.SheetNames.forEach((sheetName: any) => {
        const roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {
          header: 1,
        })

        if (roa.length) result[sheetName] = roa
      })

      return result
    }

    return (wb: any) => {
      let output: any = null

      output = toJson(wb)

      return output
    }
  })()

  const doFile = ([f]: any) => {
    const reader: any = new FileReader()

    reader.onload = (e: any) => {
      let data = e.target.result

      data = new Uint8Array(data)
      const result = processWb(XLSX.read(data, { type: 'array' }))
      const [sheetName] = Object.getOwnPropertyNames(result)

      result[sheetName].splice(0, 1)
      productsArray = result[sheetName]
      productsArray = productsArray.filter((item) => item.length)
      productsArray.forEach((p) => {
        p[0] = (p[0] || '').toString().trim()
        p[1] = (p[1] || '').toString().trim()
      })

      setShowValidateButton(true)
      setproductsQueue(productsArray)
    }

    reader.onerror = () => {
      // error
    }

    reader.readAsArrayBuffer(f)
  }

  const handleFile = (files: any) => {
    doFile(files)
    onRefidLoading(false)
  }

  const handleReset = () => {
    setShowValidateButton(false)
  }

  const backList = () => {
    setState({
      ...state,
      reviewState: false,
    })
    setShowValidateButton(false)
  }

  const callAddToCart = async (items: any) => {
    const splitBy = 10
    const tempItems = items
    const loopCount = Math.floor(items.length / splitBy) + 1

    const promises: any = []

    for (let i = 0; i < loopCount; i++) {
      const chunk = tempItems.splice(0, splitBy)

      if (chunk.length) {
        const currentItemsInCart = orderForm.orderForm.items

        const mutationChunk = addToCart({
          variables: {
            items: chunk.map((item: ItemType) => {
              const [existsInCurrentOrder] = currentItemsInCart.filter(
                (el) => el.id === item.id.toString()
              )

              if (existsInCurrentOrder) {
                item.quantity += parseInt(existsInCurrentOrder.quantity, 10)
              }

              return {
                ...item,
              }
            }),
          },
        }).then((mutationRes: any) => {
          mutationRes.data && setOrderForm(mutationRes.data.addToCart)

          if (mutationRes?.data.addToCart?.messages?.generalMessages?.length) {
            mutationRes.addToCart.messages.generalMessages.map((msg: any) => {
              return showToast({
                message: msg.text,
                action: undefined,
                duration: 30000,
              })
            })
          } else {
            toastMessage({ success: true, isNewItem: true })
          }
        })

        promises.push(mutationChunk)
      }
    }

    Promise.all(promises).catch(() => {
      console.error(mutationError)
      toastMessage({ success: false, isNewItem: false })
    })

    // Update OrderForm from the context

    const adjustSkuItemForPixelEvent = (item: any) => {
      return {
        skuId: item.id,
        quantity: item.quantity,
      }
    }

    // Send event to pixel-manager
    const pixelEventItems = items.map(adjustSkuItemForPixelEvent)

    push({
      event: 'addToCart',
      items: pixelEventItems,
    })

    if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) {
      showInstallPrompt()
    }

    backList()

    return showInstallPrompt
  }

  const addToCartUpload = () => {
    const items: any = reviewItems
      .filter((item: any) => item.error === null && item.vtexSku !== null)
      .map(({ vtexSku, quantity, seller }: any) => {
        return {
          id: parseInt(vtexSku, 10),
          quantity: parseFloat(quantity),
          seller,
        }
      })

    const merge = (internalItems) => {
      return internalItems.reduce((acc: any, val) => {
        const { id, quantity }: ItemType = val
        const ind = acc.findIndex((el) => el.id === id)

        if (ind !== -1) {
          acc[ind].quantity += quantity
        } else {
          acc.push(val)
        }

        return acc
      }, [])
    }

    const mergedItems = merge(items)

    callAddToCart(mergedItems)
  }

  const CSS_HANDLES = [
    'uploadBlock',
    'buttonValidate',
    'dropzoneContainer',
    'dropzoneIcon',
    'dropzoneText',
    'dropzoneLink',
    'downloadLink',
    'textContainer',
    'componentContainer',
    'reviewBlock',
    'buttonsBlock',
    'textContainerTitle',
    'textContainerDescription',
  ] as const

  const handles = useCssHandles(CSS_HANDLES)

  return (
    <div className={`${handles.uploadBlock}`}>
      {!componentOnly && (
        <div className={`${handles.textContainer} w-20-l w-100-ns fl-l`}>
          <h2
            className={`t-heading-3 mb3 ml5 ml3-ns mt4 ${handles.textContainerTitle}`}
          >
            {text}
          </h2>
          <div
            className={`t-body lh-copy c-muted-1 mb7 ml3 false ${handles.textContainerDescription}`}
          >
            {description}{' '}
            {downloadText && (
              <button
                className={`${handles.downloadLink} pointer c-link hover-c-link active-c-link no-underline underline-hover bn bg-transparent pl0`}
                onClick={() => {
                  download()
                }}
              >
                {downloadText}
              </button>
            )}
          </div>
        </div>
      )}
      <div
        className={`${handles.componentContainer} ${
          !componentOnly ? 'w-80-l w-100-ns fr-l' : ''
        }`}
      >
        {!reviewState && (
          <div className="w-100 mb5">
            <div
              className={`bg-base t-body c-on-base ph6 pb6 br3 b--muted-4 ${handles.dropzoneContainer}`}
            >
              <Dropzone
                onDropAccepted={handleFile}
                onFileReset={handleReset}
                accept=".xls,.xlsx"
                icon={<DropzoneIcon className={handles.dropzoneIcon} />}
              >
                <div className="pt7">
                  <div>
                    <span className={`f4 ${handles.dropzoneText}`}>
                      <FormattedMessage id="store/quickorder.upload.drop" />{' '}
                    </span>
                    <span
                      className={`f4 ${handles.dropzoneLink} c-link"`}
                      style={{ cursor: 'pointer' }}
                    >
                      <FormattedMessage id="store/quickorder.upload.choose" />
                    </span>
                  </div>
                </div>
              </Dropzone>
              <div className={`mt2 flex justify-end ${handles.buttonValidate}`}>
                {showValidateButton && (
                  <Button
                    variation="secondary"
                    size="regular"
                    onClick={() => {
                      parseText()
                    }}
                  >
                    <FormattedMessage id="store/quickorder.validate" />
                  </Button>
                )}
              </div>
            </div>
          </div>
        )}

        {reviewState && (
          <div className={`w-100 ph6 ${handles.reviewBlock}`}>
            <ReviewBlock
              reviewedItems={reviewItems}
              hiddenColumns={hiddenColumns ?? []}
              onReviewItems={onReviewItems}
              refidLoading={refidLoading}
              onRefidLoading={onRefidLoading}
              backList={backList}
            />
            <div
              className={`mb4 mt4 flex justify-between ${handles.buttonsBlock}`}
            >
              <Button
                variation="tertiary"
                size="small"
                onClick={() => {
                  backList()
                }}
              >
                <FormattedMessage id="store/quickorder.back" />
              </Button>
              {showAddToCart && (
                <Button
                  variation="primary"
                  size="small"
                  isLoading={mutationLoading || refidLoading}
                  onClick={() => {
                    addToCartUpload()
                  }}
                >
                  <FormattedMessage id="store/quickorder.addToCart" />
                </Button>
              )}
            </div>
          </div>
        )}
      </div>
    </div>
  )
}

interface MessageDescriptor {
  id: string
  description?: string | any
  defaultMessage?: string
}

interface OrderFormContext {
  loading: boolean
  orderForm: OrderFormType | undefined
  setOrderForm: (orderForm: Partial<OrderFormType>) => void
}

interface UploadBlockInterface {
  text?: string
  description?: string
  componentOnly?: boolean
  downloadText?: string
  alwaysShowAddToCart?: boolean
}

export default injectIntl(UploadBlock)

```


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

[Assistant]
Here's the implementation:

```json
{
  "name": "quickorder",
  "scripts": {
    "test": "vtex-test-tools test",
    "lint": "tsc --noEmit && eslint --ext ts,tsx ."
  },
  "dependencies": {
    "@vtex/css-handles": "^1.0.0",
    "classnames": "^2.2.6",
    "debounce": "^1.2.0",
    "prop-types": "^15.7.2",
    "ramda": "^0.26.1",
    "react-apollo": "^3.1.5",
    "react-dom": "^16.9.2",
    "react-intl": "3.9.1",
    "xlsx": "0.15.6"
  },
  "devDependencies": {
    "@types/classnames": "^2.2.7",
    "@types/jest": "^24.0.18",
    "@types/node": "^12.7.5",
    "@types/prop-types": "^15.7.0",
    "@types/ramda": "^0.26.5",
    "@types/react": "^16.9.2",
    "@vtex/test-tools": "^3.4.3",
    "apollo-client": "^2.5.1",
    "graphql": "^14.6.0",
    "react": "^16.9.2"
  },
  "version": "3.16.3"
}

```


[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 quickorder/react/css.d.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module '*.css' {
  const css: any
  export default css
}

```


[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 quickorder/react/CategoryBlock.tsx from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```tsx
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable react/jsx-key */
import PropTypes from 'prop-types'
import type { FunctionComponent } from 'react'
import React, { useState, useContext } from 'react'
import type { WrappedComponentProps } from 'react-intl'
import { FormattedMessage, injectIntl } from 'react-intl'
import {
  Collapsible,
  Input,
  Button,
  ToastContext,
  Spinner,
  Tag,
} from 'vtex.styleguide'
import { OrderForm } from 'vtex.order-manager'
import type { OrderForm as OrderFormType } from 'vtex.checkout-graphql'
import { addToCart as ADD_TO_CART } from 'vtex.checkout-resources/Mutations'
import { usePWA } from 'vtex.store-resources/PWAContext'
import { usePixel } from 'vtex.pixel-manager/PixelContext'
import { useCssHandles } from 'vtex.css-handles'
import { graphql, useApolloClient, useMutation } from 'react-apollo'

import { categoryMessages as messages } from './utils/messages'
import getCategories from './queries/categoriesQuery.gql'
import SearchByCategory from './queries/productsByCategory.gql'
import getAppSettings from './utils/getAppSettings'

const CategoryBlock: FunctionComponent<WrappedComponentProps & any> = ({
  text,
  description,
  componentOnly,
  intl,
  data: { categories },
}) => {
  const [state, setState] = useState<any>({
    categoryItems: {},
    quantitySelected: {},
    defaultSeller: {},
    // All the items with their respective units
    unitMultiplierList: {},
  })

  const appSettings = getAppSettings()
  const checkoutUrl = appSettings?.checkoutUrl ?? '/checkout#/cart'

  const { showToast } = useContext(ToastContext)

  const client = useApolloClient()

  const {
    categoryItems,
    quantitySelected,
    defaultSeller,
    unitMultiplierList,
  } = state

  const [addToCart, { error, loading }] = useMutation<
    { addToCart: OrderFormType },
    { items: [] }
  >(ADD_TO_CART)

  const { push } = usePixel()
  const { settings = {}, showInstallPrompt = undefined } = usePWA() || {}
  const { promptOnCustomEvent } = settings

  const { setOrderForm }: OrderFormContext = OrderForm.useOrderForm()

  const resolveToastMessage = (success: boolean, isNewItem: boolean) => {
    if (!success) return intl.formatMessage(messages.error)
    if (!isNewItem) return intl.formatMessage(messages.duplicate)

    return intl.formatMessage(messages.success)
  }

  const toastMessage = (arg: any) => {
    let message
    let action

    if (typeof arg === 'string') {
      message = intl.formatMessage(messages[arg])
    } else {
      const {
        success,
        isNewItem,
      }: {
        success: boolean
        isNewItem: boolean
      } = arg

      message = resolveToastMessage(success, isNewItem)

      action = success
        ? {
            label: intl.formatMessage(messages.seeCart),
            href:
              typeof checkoutUrl === 'string' && checkoutUrl !== ''
                ? checkoutUrl
                : '/checkout/#/cart',
          }
        : undefined
    }

    showToast({ message, action })
  }

  const _setState = (props: any) => {
    setState((previousState: any) => {
      const newState = { ...previousState, props }

      return newState
    })
  }

  const onAddToCart = async (items: any, skus: any) => {
    const mutationResult = await addToCart({
      variables: {
        items: items.map((item: any) => {
          return {
            ...item,
          }
        }),
      },
    })

    if (error || mutationResult.errors?.length) {
      if (error) {
        console.error(error)
      }

      if (mutationResult.errors?.length) {
        for (let i = 0; i < mutationResult.errors.length; i++) {
          console.error(mutationResult.errors[i].message)
        }
      }

      toastMessage({ success: false, isNewItem: false })

      return
    }

    // Update OrderForm from the context
    mutationResult.data && setOrderForm(mutationResult.data.addToCart)

    const adjustSkuItemForPixelEvent = (item: any) => {
      return {
        skuId: item.id,
        quantity: item.quantity,
      }
    }

    // Send event to pixel-manager
    const pixelEventItems = items.map(adjustSkuItemForPixelEvent)

    push({
      event: 'addToCart',
      items: pixelEventItems,
    })

    if (
      mutationResult.data?.addToCart?.messages?.generalMessages &&
      mutationResult.data.addToCart.messages.generalMessages.length
    ) {
      mutationResult.data.addToCart.messages.generalMessages.map((msg: any) => {
        return showToast({
          message: msg.text,
          action: undefined,
          duration: 30000,
        })
      })
    } else {
      toastMessage({ success: true, isNewItem: true })
      const quantitiesCopy = quantitySelected

      skus.map((sku: any) => {
        quantitiesCopy[sku] = 0

        return true
      })
      _setState({
        quantitySelected: quantitiesCopy,
      })
    }

    if (promptOnCustomEvent === 'addToCart' && showInstallPrompt) {
      showInstallPrompt()
    }

    return showInstallPrompt
  }

  const CSS_HANDLES = [
    'categoryContainer',
    'categoryTitle',
    'categoryHelper',
    'categoryProductLabel',
    'categoryProductTitle',
    'categoryProductThumb',
    'categoryProductReference',
    'categoryInputQuantity',
    'categoryButtonAdd',
    'categoriesSubCategory',
    'categoriesProductContainer',
    'categoryLoadingProducts',
    'textContainer',
    'componentContainer',
    'categoryProductItem',
  ] as const

  const handles = useCssHandles(CSS_HANDLES)

  const setOptions = (categoryId: any, result: any) => {
    const copy = categoryItems

    copy[categoryId] = result
    _setState({
      categoryItems: copy,
    })
  }

  const handleSearch = async (categoryId: number, categoryName: string) => {
    const selectedFacets = categoryName
      .split('/')
      .filter((cat: string) => {
        return !!cat
      })
      .map((cat: string) => {
        return { key: 'c', value: cat }
      })

    if (!categoryItems[categoryId]) {
      const { data: dataProducts } = await client.query({
        query: SearchByCategory,
        variables: { selectedFacets },
      })

      for (const product of dataProducts.productSearch.products) {
        for (const item of product.items) {
          if (item.unitMultiplier > 1) {
            unitMultiplierList[item.itemId] = item
          }
        }
      }

      setOptions(
        categoryId,
        !!dataProducts &&
          !!dataProducts.productSearch &&
          !!dataProducts.productSearch.products
          ? dataProducts.productSearch.products
          : []
      )
    }

    return true
  }

  const calculateDivisible = (quantity: number, contentItemId: string) => {
    if (contentItemId in unitMultiplierList) {
      const multiplier = unitMultiplierList[contentItemId].unitMultiplier

      return quantity / multiplier
    }

    return quantity
  }

  const callAddToCart = () => {
    const skus: any = Object.getOwnPropertyNames(quantitySelected).filter(
      (sku: any) => {
        return quantitySelected[sku] !== 0
      }
    )

    if (skus?.length) {
      const items = skus.map((item: any) => {
        return {
          id: parseInt(item, 10),
          quantity: calculateDivisible(
            parseFloat(quantitySelected[item]),
            item
          ),
          seller: defaultSeller[item],
        }
      })

      onAddToCart(items, skus)
    } else {
      toastMessage('noneSelection')
    }
  }

  const thumb = (url: string) => {
    const td = url.split('/')
    const ids = td[td.indexOf('ids') + 1]

    return url.replace(ids, `${ids}-50-50`)
  }

  const roundToNearestMultiple = (quantity: number, contentItemId: string) => {
    if (contentItemId in unitMultiplierList) {
      const multiplier = unitMultiplierList[contentItemId].unitMultiplier

      toastMessage('multiplier')

      return Math.round(quantity / multiplier) * multiplier
    }

    return quantity
  }

  const drawProducts = (a: any) => {
    return a.length ? (
      a.map((b: any, i: number) => {
        return (
          <div key={`ifany_${i}`}>
            {b.items.length
              ? b.items.map((content: any) => {
                  const [referenceId] = content.referenceId
                  const [image] = content.images

                  return (
                    <div
                      className="flex flex-row pa2 pl4 bg-white hover-bg-near-white"
                      key={`prod_${i}_${content.itemId}`}
                    >
                      <div
                        className={`flex flex-row w-90 fl ${handles.categoryProductLabel}`}
                      >
                        {image?.imageUrl && (
                          <img
                            src={thumb(image.imageUrl)}
                            title={image.imageLabel}
                            alt={image.imageLabel}
                            width="50"
                            height="50"
                            className={`pr5 ${handles.categoryProductThumb}`}
                          />
                        )}
                        <span className={handles.categoryProductTitle}>
                          {content.nameComplete}
                        </span>
                        {referenceId && (
                          <span
                            className={`pl5 ${handles.categoryProductReference}`}
                          >
                            {referenceId.Value}
                          </span>
                        )}
                        {content.itemId in unitMultiplierList && (
                          <span className="pl5 mr4">
                            <Tag type="warning" variation="low">
                              Unit Multiplier of{' '}
                              {
                                unitMultiplierList[content.itemId]
                                  .unitMultiplier
                              }
                            </Tag>
                          </span>
                        )}
                      </div>
                      <div
                        className={`flex flex-column w-10 ph5-l ph2 p fl ${handles.categoryInputQuantity}`}
                      >
                        <Input
                          value={quantitySelected[content.itemId] ?? 0}
                          size="small"
                          type="number"
                          min={0}
                          disabled={loading}
                          onChange={(e: any) => {
                            const newQtd = quantitySelected

                            newQtd[content.itemId] = e.target.value
                            const newSeller = defaultSeller
                            const seller = content.sellers.find((s: any) => {
                              return s.sellerDefault === true
                            })

                            newSeller[content.itemId] =
                              seller?.sellerId ||
                              (content.sellers.length
                                ? content.sellers[0].sellerId
                                : '1')

                            _setState({
                              quantitySelected: newQtd,
                              defaultSeller: newSeller,
                            })
                          }}
                          onBlur={() => {
                            const roundedValue = roundToNearestMultiple(
                              quantitySelected[content.itemId] || 0,
                              content.itemId
                            )

                            const newQtd = quantitySelected

                            quantitySelected[content.itemId] = String(
                              roundedValue
                            )
                            _setState({
                              quantitySelected: newQtd,
                            })
                          }}
                        />
                      </div>
                    </div>
                  )
                })
              : ''}
          </div>
        )
      })
    ) : (
      <span>No products</span>
    )
  }

  const openClose = (id: number, name: string) => {
    const findNChange = (source: any) => {
      const obj: any = source.map((item: any) => {
        const ret = item

        if (item.id === id) {
          ret.isOpen = !item.isOpen
        }

        if (item.id !== id && item.hasChildren) {
          ret.children = findNChange(item.children)
        }

        return ret
      })

      return obj
    }

    const newCategories = findNChange(categories)

    _setState({
      categories: newCategories,
    })
    handleSearch(id, name)
  }

  const collapsible = (item: any) => {
    return (
      <Collapsible
        key={`collapsable_${item.slug}_${item.id}`}
        header={<span className="ml5 fw5">{item.name}</span>}
        isOpen={item.isOpen}
        onClick={() => {
          openClose(item.id, item.href)
        }}
      >
        <div className={`${handles.categoriesProductContainer}`}>
          {(!categoryItems || !categoryItems[item.id]) && (
            <span className={`${handles.categoryLoadingProducts}`}>
              <Spinner size={10} />{' '}
              <FormattedMessage id="store/quickorder.category.loading" />
            </span>
          )}
          {!!categoryItems &&
            !!categoryItems[item.id] &&
            drawProducts(categoryItems[item.id])}
        </div>
        {item.hasChildren && (
          <div className={`${handles.categoriesSubCategory} pl5`}>
            {item.children.map((child: any) => {
              return (
                <div key={`${child.slug}_${child.slug}`}>
                  {collapsible(child)}
                </div>
              )
            })}
          </div>
        )}
      </Collapsible>
    )
  }

  return (
    <div className={`${handles.categoryContainer}`}>
      {!componentOnly && (
        <div className={`${handles.textContainer} w-third-l w-100-ns fl-l`}>
          <h2
            className={`t-heading-3 mb3 ml5 ml3-ns mt4 ${handles.categoryTitle}`}
          >
            {text}
          </h2>
          <div
            className={`t-body lh-copy c-muted-1 mb7 ml3 false ${handles.categoryHelper}`}
          >
            {description}
          </div>
        </div>
      )}
      <div
        className={`${handles.componentContainer} ${
          !componentOnly ? 'w-two-thirds-l w-100-ns fr-l' : ''
        }`}
      >
        {!categories && (
          <div>
            <Spinner />
          </div>
        )}
        {categories && (
          <div className={`${handles.categoryProductItem}`}>
            <div className="flex flex-row">
              <div
                className={`flex flex-column w-100 items-end fl pr7 ${handles.categoryButtonAdd}`}
              >
                <Button
                  variation="primary"
                  size="small"
                  isLoading={loading}
                  onClick={() => {
                    callAddToCart()
                  }}
                >
                  <FormattedMessage id="store/quickorder.category.addButton" />
                </Button>
              </div>
            </div>
            {categories.map((item: any) => {
              return <div key={item.id}>{collapsible(item)}</div>
            })}
          </div>
        )}
      </div>
    </div>
  )
}

CategoryBlock.propTypes = {
  intl: PropTypes.any,
  componentOnly: PropTypes.bool,
  text: PropTypes.string,
  description: PropTypes.string,
  data: PropTypes.shape({
    loading: PropTypes.bool,
    success: PropTypes.bool,
    categories: PropTypes.any,
  }),
}

interface OrderFormContext {
  loading: boolean
  orderForm: OrderFormType | undefined
  setOrderForm: (orderForm: Partial<OrderFormType>) => void
}

export default injectIntl(graphql(getCategories)(CategoryBlock))

```


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

[Assistant]
Here's the implementation:

```json
{
  "store.quickorder": {
    "blocks": [
      "flex-layout.row#title",
      "flex-layout.row#textarea",
      "flex-layout.row#upload",
      "flex-layout.row#autocomplete",
      "flex-layout.row#categories"
    ]
  },
  "flex-layout.row#title": {
    "children": ["flex-layout.col#title"]
  },
  "flex-layout.col#title": {
    "children": ["rich-text#title"],
    "props": {
      "blockClass": "titleQuickorder",
      "preventVerticalStretch": true
    }
  },
  "rich-text#title": {
    "props": {
      "text": "## Quick Order"
    }
  },

  "flex-layout.row#textarea": {
    "children": ["flex-layout.col#textarea"]
  },
  "flex-layout.col#textarea": {
    "children": ["quickorder-textarea"]
  },
  "quickorder-textarea": {
    "props": {
      "componentOnly": false,
      "text": "Copy/Paste Skus",
      "description": "[SKU Reference ID],[Quantity]",
      "hiddenColumns": []
    }
  },

  "flex-layout.row#upload": {
    "children": ["flex-layout.col#upload"]
  },
  "flex-layout.col#upload": {
    "children": ["quickorder-upload"]
  },
  "quickorder-upload": {
    "props": {
      "componentOnly": false,
      "text": "Upload",
      "description": "Upload a Spreadsheet with two columns (SKU, Quantity) to bulk order",
      "downloadText": "Click here to download a spreadsheet model",
      "hiddenColumns": []
    }
  },

  "flex-layout.row#autocomplete": {
    "children": ["flex-layout.col#autocomplete"]
  },
  "flex-layout.col#autocomplete": {
    "children": ["quickorder-autocomplete"]
  },
  "quickorder-autocomplete": {
    "props": {
      "componentOnly": false,
      "text": "One by One",
      "description": "Type the product name, select, enter quantity, add to the cart"
    }
  },

  "flex-layout.row#categories": {
    "children": ["flex-layout.col#categories"]
  },
  "flex-layout.col#categories": {
    "children": ["quickorder-categories"]
  },
  "quickorder-categories": {
    "props": {
      "componentOnly": false,
      "text": "Categories",
      "description": "Add products directly from their categories"
    }
  }
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "quickorder-upload": {
    "component": "UploadBlock"
  },
  "quickorder-categories": {
    "component": "CategoryBlock"
  },
  "quickorder-autocomplete": {
    "component": "AutocompleteBlock"
  },
  "quickorder-textarea": {
    "component": "TextAreaBlock"
  },
  "store.quickorder": {}
}

```


[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 quickorder/store/routes.json from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "store.quickorder": {
    "title": "Quickorder",
    "path": "/quickorder"
  }
}

```


[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 quickorder/public/metadata/messages/es-AR.json from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "Quickorder",
  "headline": "Permita que los usuarios de B2B agreguen varios productos al carrito a la vez.",
  "overview": "La aplicación Quickorder está hecha a medida para las necesidades B2B: crea una página personalizada en su tienda para compras masivas, ofreciendo herramientas como la carga de una hoja de cálculo para facilitar los pedidos masivos.",
  "features": [
    "Copia y pega los SKUs en la página de compra rápida;",
    "Sube una hoja de cálculo con la información del SKU;",
    "Busca SKUs en la barra de búsqueda personalizada;",
    "Añade productos de acuerdo a tu categoría."
  ],
  "websiteURL": "https://vtex.com/",
  "support": {
    "url": "https://support.vtex.com/hc/requests"
  }
}

```


[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 quickorder/public/metadata/messages/pt-BR.json from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "Quickorder",
  "headline": "Permite que usuários B2B adicionem múltiplos produtos ao carrinho de uma só vez.",
  "overview": "O aplicativo Quickorder é feito sob medida para necessidades B2B: cria uma página personalizada na sua loja destinada a compras em massa, oferecendo ferramentas tais como o carregamento de uma planilha para tornar os pedidos em massa mais simples.",
  "features": [
    "Copie e cole SKUs na página de compra rápida;",
    "Carregue uma planilha com informação do SKU;",
    "Pesquise por SKUs na barra de pesquisa personalizada;",
    "Adicione produtos de acordo com a sua categoria."
  ],
  "websiteURL": "https://vtex.com/",
  "support": {
    "url": "https://support.vtex.com/hc/requests"
  }
}

```


[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 quickorder/public/metadata/messages/en-US.json from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "Quickorder",
  "headline": "Allow B2B users to add multiple products to the cart at once.",
  "overview": "The Quickorder app is tailor-made to B2B needs: it creates a custom page in your store aimed at purchases in bulk, offering tools such as uploading a spreadsheet to make bulk orders more simple.",
  "features": [
    "Copy and paste SKUs in the Quick Order page",
    "Upload a spreadsheet with SKU information",
    "Search for SKUs in the Custom Search Bar",
    "Add products according to their category"
  ],
  "websiteURL": "https://vtex.com/",
  "support": {
    "url": "https://support.vtex.com/hc/requests"
  }
}

```


[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 quickorder/graphql/types/Sellers.graphql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
type SellersType {
  items: [SellerInfo]
}
type SellerInfo {
  id: String
  name: 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 quickorder/graphql/types/Refids.graphql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
type Refids {
  items: [ItemsRefId]
}
type ItemsRefId {
  sku: String
  refid: String
  sellers: [ItemsSeller]
}

type ItemsSeller {
  id: String
  name: String
  availability: String
  unitMultiplier: Float
  availableQuantity: Int
}

```


[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 quickorder/node/directives/withSegment.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { GraphQLField } from 'graphql'
import { defaultFieldResolver } from 'graphql'
import { SchemaDirectiveVisitor } from 'graphql-tools'
import atob from 'atob'

export class WithSegment extends SchemaDirectiveVisitor {
  public visitFieldDefinition(field: GraphQLField<any, any>) {
    const { resolve = defaultFieldResolver } = field

    field.resolve = async (root, args, ctx: Context, info) => {
      const {
        vtex: { segmentToken },
        clients: { segment },
      } = ctx

      ctx.vtex.segment = segmentToken
        ? JSON.parse(atob(segmentToken))
        : await segment.getSegment()

      return resolve(root, args, ctx, info)
    }
  }
}

```


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

[Assistant]
Here's the implementation:

```typescript
import { WithSegment } from './withSegment'

export const schemaDirectives = {
  withSegment: WithSegment,
}

```


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

[Assistant]
Here's the implementation:

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

export class Search extends JanusClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, {
      ...options,
      headers: {
        ...options?.headers,
        VtexIdClientAutCookie: context.authToken,
      },
      timeout: 5000,
    })
  }

  public skuFromRefIds = async (refids: any): Promise<any> => {
    const url = `/api/catalog_system/pub/sku/stockkeepingunitidsbyrefids`

    return this.http.postRaw(url, refids, {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `bearer ${this.context.authToken}`,
      },
    })
  }

  public getOrderForm = async (orderFormId: string): Promise<any> => {
    return this.http.get(`/api/checkout/pub/orderForm/${orderFormId}`, {
      headers: {
        'Content-Type': 'application/json',
        VtexIdclientAutCookie: `${this.context.authToken}`,
      },
    })
  }

  public simulate = async ({
    refids,
    orderForm,
    refIdSellerMap,
    salesChannel,
  }: SimulateArgs): Promise<any> => {
    const {
      salesChannel: orderFormSC,
      storePreferencesData: { countryCode },
      shippingData,
    } = orderForm

    const simulateItems: any = []

    refids
      .filter((item: any) => {
        return !!item.sku
      })
      .forEach((item: any) => {
        refIdSellerMap[item.refid].forEach(sellerId => {
          simulateItems.push({
            id: item.sku,
            quantity: item.quantity,
            seller: sellerId,
          })
        })
      })

    return this.http.post(
      `/api/checkout/pub/orderForms/simulation?sc=${
        salesChannel ?? orderFormSC
      }`,
      {
        items: simulateItems,
        country: countryCode,
        postalCode: shippingData?.address?.postalCode ?? '',
      }
    )
  }

  public sellerBySku = async (skuId: string): Promise<any> => {
    const url = `/api/catalog_system/pvt/sku/stockkeepingunitbyid/${skuId}`

    return this.http.getRaw(url, {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `bearer ${this.context.authToken}`,
      },
    })
  }

  public sellers = async (salesChannel?: string): Promise<any> => {
    const sc = salesChannel ? `sc=${salesChannel}` : ''
    const params = `?${sc}`
    const url = `/api/seller-register/pvt/sellers${params}`

    return this.http.getRaw(url, {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `bearer ${this.context.authToken}`,
      },
    })
  }
}

```


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

[Assistant]
Here's the implementation:

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

import { Search } from './search'

export class Clients extends IOClients {
  public get search(): any {
    return this.getOrSet('search', Search)
  }
}

```


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

[Assistant]
Here's the implementation:

```typescript
interface SearchRefIdItem {
  sku: string
}

interface SearchRefIdUnit {
  items: SearchRefIdItem[]
}

interface Items {
  id: string
  quantity: number
  seller: string
}

interface RefIdSellerMap {
  [key: string]: [string]
}

interface SimulateArgs {
  refids: [Items]
  orderForm: any
  refIdSellerMap: RefIdSellerMap
  salesChannel: 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 quickorder/node/typings/Autocomplete.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface SearchAutocompleteItem {
    productId: string
    itemId: string
    name: string
    nameComplete: string
    imageUrl: string
  }

interface SearchAutocompleteUnit {
    items: SearchAutocompleteItem[]
    thumb: string
    thumbUrl: string | null
    name: string
    href: 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 quickorder/node/typings/Checkout.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface OrderFormMarketingData {
  utmCampaign?: string
  utmMedium?: string
  utmSource?: string
  utmiCampaign?: string
  utmiPart?: string
  utmipage?: string
  marketingTags?: string
}

interface CheckoutAddress {
  addressType: string
  receiverName: string
  addressId: string
  postalCode: string
  city: string
  state: string
  country: string
  street: string
  number: string
  neighborhood: string
  complement: string
  reference: string | null
  geoCoordinates: [number, number]
}
interface OrderFormItem {
  id: string
  name: string
  detailUrl: string
  imageUrl: string
  productRefId: string
  skuName: string
  quantity: number
  uniqueId: string
  productId: string
  refId: string
  ean: string
  priceValidUntil: string
  price: number
  tax: number
  listPrice: number
  sellingPrice: number
  rewardValue: number
  isGift: boolean
  parentItemIndex: number | null
  parentAssemblyBinding: string | null
  productCategoryIds: string
  priceTags: string[]
  measurementUnit: string
  additionalInfo: {
    brandName: string
    brandId: string
    offeringInfo: any | null
    offeringType: any | null
    offeringTypeId: any | null
  }
  productCategories: Record<string, string>
  seller: string
  sellerChain: string[]
  availability: string
  unitMultiplier: number
}
interface OrderForm {
  orderFormId: string
  salesChannel: string
  loggedIn: boolean
  isCheckedIn: boolean
  storeId: string | null
  checkedInPickupPointId: string | null
  allowManualPrice: boolean
  canEditData: boolean
  userProfileId: string | null
  userType: string | null
  ignoreProfileData: boolean
  value: number
  messages: any[]
  items: OrderFormItem[]
  selectableGifts: any[]
  totalizers: Array<{ id: string; name: string; value: number }>
  shippingData: {
    address: CheckoutAddress
    logisticsInfo: Array<{
      itemIndex: number
      selectedSla: string
      selectedDeliveryChannel: string
      addressId: string
      slas: Array<{
        id: string
        deliveryChannel: string
        name: string
        deliveryIds: Array<{
          courierId: string
          warehouseId: string
          dockId: string
          courierName: string
          quantity: number
        }>
        shippingEstimate: string
        shippingEstimateDate: string | null
        lockTTL: string | null
        availableDeliveryWindows: any[]
        deliveryWindow: string | null
        price: number
        listPrice: number
        tax: number
        pickupStoreInfo: {
          isPickupStore: boolean
          friendlyName: string | null

          address: CheckoutAddress | null
          additionalInfo: any | null
          dockId: string | null
        }
        pickupPointId: string | null
        pickupDistance: number
        polygonName: string | null
      }>
      shipsTo: string[]
      itemId: string
      deliveryChannels: Array<{ id: string }>
    }>
    selectedAddresses: CheckoutAddress[]
    availableAddresses: CheckoutAddress[]
    pickupPoints: Array<{
      friendlyName: string
      address: CheckoutAddress
      additionalInfo: string
      id: string
      businessHours: Array<{
        DayOfWeek: number
        OpeningTime: string
        ClosingTime: string
      }>
    }>
  }
  clientProfileData: any | null
  paymentData: {
    installmentOptions: Array<{
      paymentSystem: string
      bin: string | null
      paymentName: string | null
      paymentGroupName: string | null
      value: number
      installments: Array<{
        count: number
        hasInterestRate: false
        interestRate: number
        value: number
        total: number
        sellerMerchantInstallments: Array<{
          count: number
          hasInterestRate: false
          interestRate: number
          value: number
          total: number
        }>
      }>
    }>
    paymentSystems: Array<{
      id: string
      name: string
      groupName: string
      validator: {
        regex: string
        mask: string
        cardCodeRegex: string
        cardCodeMask: string
        weights: number[]
        useCvv: boolean
        useExpirationDate: boolean
        useCardHolderName: boolean
        useBillingAddress: boolean
      }
      stringId: string
      template: string
      requiresDocument: boolean
      isCustom: boolean
      description: string | null
      requiresAuthentication: boolean
      dueDate: string
      availablePayments: any | null
    }>
    payments: any[]
    giftCards: any[]
    giftCardMessages: any[]
    availableAccounts: any[]
    availableTokens: any[]
  }
  marketingData: OrderFormMarketingData | null
  sellers: Array<{
    id: string
    name: string
    logo: string
  }>
  clientPreferencesData: {
    locale: string
    optinNewsLetter: any | null
  }
  commercialConditionData: any | null
  storePreferencesData: {
    countryCode: string
    saveUserData: boolean
    timeZone: string
    currencyCode: string
    currencyLocale: number
    currencySymbol: string
    currencyFormatInfo: {
      currencyDecimalDigits: number
      currencyDecimalSeparator: string
      currencyGroupSeparator: string
      currencyGroupSize: number
      startsWithCurrencySymbol: boolean
    }
  }
  giftRegistryData: any | null
  openTextField: any | null
  invoiceData: any | null
  customData: any | null
  itemMetadata: {
    items: MetadataItem[]
  }
  hooksData: any | null
  ratesAndBenefitsData: {
    rateAndBenefitsIdentifiers: any[]
    teaser: any[]
  }
  subscriptionData: any | null
  itemsOrdination: any | null
}

interface PayloadItem {
  id: string
  quantity: number
  seller: string
  parentItemIndex?: number | null
  parentAssemblyBinding?: string | null
}

interface SimulationPayload {
  country?: string
  items: PayloadItem[]
  postalCode?: string
  isCheckedIn?: boolean
  priceTables?: string[]
  marketingData?: Record<string, 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 quickorder/node/typings/ItemMetadata.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/**
 * Assembly options related types
 */

interface CompositionItem {
  id: string
  minQuantity: number
  maxQuantity: number
  initialQuantity: number
  priceTable: string
  seller: string
}

interface Composition {
  minQuantity: number
  maxQuantity: number
  items: CompositionItem[]
}

interface AssemblyOption {
  id: string
  name: string
  composition: Composition | null
  inputValues: InputValues
}

interface InputValues {
  [key: string]: RawInputValue
}

interface RawInputValue {
  maximumNumberOfCharacters: number
  domain: string[]
}

interface SearchMetadataItem {
  Name: string
  NameComplete: string
  MainImage: string
  BrandName: string
  CategoryId: number
  ProductId: number
  id: string
  seller: string
  assemblyOptions: AssemblyOption[]
}

interface MetadataItem {
  id: string
  name: string
  imageUrl: string
  detailUrl: string
  seller: string
  assemblyOptions: AssemblyOption[]
  skuName: string
  productId: string
  refId: string
  ean: string | null
}
interface AddedItem {
  choiceType: string
  compositionItem: CompositionItem
  extraQuantity: number
  item: OrderFormItem
  normalizedQuantity: number
}

interface RemovedItem {
  initialQuantity: number
  name: string
  removedQuantity: number
}

```


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

[User] Show me the implementation of quickorder/node/tests/resolvers.test.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import vtexContext from './vtexContext'

describe('Graphql resolvers', () => {
  const { Query, clients, vtex } = vtexContext()

  it('[GraphQL] skuFromRefIds', async () => {
    const data = await Query.skuFromRefIds(
      {},
      {
        refids: true,
        orderFormId: '',
        refIdSellerMap: {},
        refIdQuantityMap: {},
      },
      {
        clients,
        vtex,
      }
    )

    expect(data).toBeDefined()
  })

  it('[GraphQL] sellers', async () => {
    const data = await Query.sellers(
      {},
      {
        refids: true,
        orderFormId: '',
        refIdSellerMap: {},
      },
      {
        clients,
        vtex,
      }
    )

    expect(data).toBeDefined()
  })
})

```


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

[Assistant]
Here's the implementation:

```typescript
import vtexContext from './vtexContext'

describe('Main file', () => {
  const { Query, resolvers, Service } = vtexContext()

  it('Instances should be defined', () => {
    expect(Service).toBeDefined()
    expect(resolvers).toBeDefined()
    expect(Query).toBeDefined()
  })
})

```


[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 quickorder/node/tests/vtexContext.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { IOContext } from '@vtex/api'

import Service from '../index'
import { Search } from '../clients/search'

type GraphQLResolver = {
  resolvers: any
}

const vtexContext = () => {
  const { resolvers } = Service.config.graphql as GraphQLResolver
  const { Query } = resolvers
  const context = {} as IOContext
  const clients = {
    search: new Search(context),
  }

  const vtex = {} as CustomIOContext

  return {
    context,
    clients,
    Query,
    resolvers,
    Service,
    vtex,
  }
}

export default vtexContext

```


[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 quickorder/node/tests/setupTests.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

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

if (!global.metrics) {
  global.metrics = new MetricsAccumulator()
}

jest.mock('@vtex/api', () => {
  const getStockMocked = () => ({
    Id: 2001773,
    ProductId: 2001426,
    NameComplete: 'Tabela de Basquete',
    ProductName: 'Tabela de Basquete',
    ProductDescription: 'Tabela de Basquete',
    SkuName: 'Tabela de Basquete',
    IsActive: true,
    IsTransported: true,
    IsInventoried: true,
    IsGiftCardRecharge: false,
    ImageUrl:
      'https://ambienteqa.vteximg.com.br/arquivos/ids/168952-55-55/7508800GG.jpg',
    DetailUrl: '/tabela-de-basquete/p',
    CSCIdentification: null,
    BrandId: '2000018',
    BrandName: 'MARCA ARGOLO TESTE',
    Dimension: {
      cubicweight: 81.6833,
      height: 65,
      length: 58,
      weight: 10000,
      width: 130,
    },
    RealDimension: {
      realCubicWeight: 274.1375,
      realHeight: 241,
      realLength: 65,
      realWeight: 9800,
      realWidth: 105,
    },
    ManufacturerCode: '',
    IsKit: false,
    KitItems: [],
    Services: [],
    Categories: [],
    Attachments: [
      {
        Id: 3,
        Name: 'Mensagem',
        Keys: ['nome;20', 'foto;40'],
        Fields: [
          {
            FieldName: 'nome',
            MaxCaracters: '20',
            DomainValues: 'Adalberto,Pedro,João',
          },
          {
            FieldName: 'foto',
            MaxCaracters: '40',
            DomainValues: null,
          },
        ],
        IsActive: true,
        IsRequired: false,
      },
    ],
    Collections: [],
    SkuSellers: [
      {
        SellerId: '1',
        StockKeepingUnitId: 2001773,
        SellerStockKeepingUnitId: '2001773',
        IsActive: true,
        FreightCommissionPercentage: 0,
        ProductCommissionPercentage: 0,
      },
    ],
    SalesChannels: [1, 2, 3, 10],
    Images: [
      {
        ImageUrl:
          'https://ambienteqa.vteximg.com.br/arquivos/ids/168952/7508800GG.jpg',
        ImageName: '',
        FileId: 168952,
      },
      {
        ImageUrl:
          'https://ambienteqa.vteximg.com.br/arquivos/ids/168953/7508800_1GG.jpg',
        ImageName: '',
        FileId: 168953,
      },
      {
        ImageUrl:
          'https://ambienteqa.vteximg.com.br/arquivos/ids/168954/7508800_2GG.jpg',
        ImageName: '',
        FileId: 168954,
      },
    ],
    SkuSpecifications: [
      {
        FieldId: 102,
        FieldName: 'Cor',
        FieldValueIds: [266],
        FieldValues: ['Padrão'],
      },
    ],
    ProductSpecifications: [
      {
        FieldId: 7,
        FieldName: 'Faixa Etária',
        FieldValueIds: [58, 56, 55, 52],
        FieldValues: [
          '5 a 6 anos',
          '7 a 8 anos',
          '9 a 10 anos',
          'Acima de 10 anos',
        ],
      },
      {
        FieldId: 23,
        FieldName: 'Fabricante',
        FieldValueIds: [],
        FieldValues: ['Xalingo'],
      },
    ],
    ProductClustersIds: '176,187,192,194,211,217,235,242',
    ProductCategoryIds: '/59/',
    ProductGlobalCategoryId: null,
    ProductCategories: {
      '59': 'Brinquedos',
    },
    CommercialConditionId: 1,
    RewardValue: 100,
    AlternateIds: {
      Ean: '8781',
      RefId: '878181',
    },
    AlternateIdValues: ['8781', '878181'],
    EstimatedDateArrival: null,
    MeasurementUnit: 'un',
    UnitMultiplier: 1,
    InformationSource: 'Indexer',
    ModalType: '',
  })

  const getSellersMocked = () => ({
    items: [
      {
        id: '1',
        SellerId: 'externalseller',
        name: 'External Seller',
        email: 'seller@email.com',
        description: '',
        exchangeReturnPolicy: '',
        deliveryPolicy: '',
        useHybridPaymentOptions: false,
        userName: '',
        password: '',
        secutityPrivacyPolicy: '',
        CNPJ: '',
        CSCIdentification: '',
        ArchiveId: null,
        UrlLogo: '',
        ProductCommissionPercentage: 30.0,
        FreightCommissionPercentage: 10.0,
        CategoryCommissionPercentage: null,
        FulfillmentEndpoint: 'https://sellerendpoint.com/',
        CatalogSystemEndpoint: null,
        isActive: true,
        MerchantName: '',
        FulfillmentSellerId: '',
        SellerType: 1,
        IsBetterScope: false,
        availableSalesChannels: [
          {
            id: 2,
          },
          {
            id: 4,
          },
        ],
      },
    ],
  })

  const orderFormMocked = () => ({
    salesChannel: '1',
    storePreferencesData: {
      countryCode: 'BR',
    },
    shippingData: {},
  })

  const postStockMocked = () => ({
    'D25133K-B2': 100,
    '14-556': 5,
    '123': 100,
    'DCF880L2-BR': 1515,
  })

  const simulationMocked = () => ({
    items: [
      {
        sku: 'SKU-MOCKED-1',
        id: '100',
        quantity: 12,
        seller: '1',
      },
    ],
  })

  return {
    IOContext: jest.fn(),
    CustomIOContext: jest.fn((): any => ({
      segment: jest.fn(() => ({
        channel: '1',
      })),
    })),
    MetricsAccumulator: jest.fn((): any => ({
      trackCache: jest.fn(),
    })),
    JanusClient: jest.fn(() => ({
      http: {
        getRaw: jest.fn((url): any => {
          if (url.match(/stockkeep/)) {
            return {
              status: 200,
              data: getStockMocked(),
            }
          }

          if (url.match(/sellers/)) {
            return {
              status: 200,
              data: getSellersMocked(),
            }
          }
        }),
        get: jest.fn((url: string): any => {
          if (url.match(/orderForm/)) {
            return orderFormMocked()
          }
        }),
        post: jest.fn((url: string): any => {
          if (url.match(/simulation/)) {
            return simulationMocked()
          }
        }),
        postRaw: jest.fn((url: string): any => {
          if (url.match(/stockkeep/)) {
            return {
              status: 200,
              data: postStockMocked(),
            }
          }
        }),
      },
      context: {
        authToken: 'tokenMocked',
      },
    })),
    IOClients: jest.fn(() => ({
      getOrSet: jest.fn(),
    })),
    LRUCache: jest.fn(),
    RecorderState: jest.fn(),
    UserInputError: jest.fn(),
    Service: jest.fn((config): any => {
      return { config }
    }),
  } as any
})

```


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

[Assistant]
Here's the implementation:

```typescript

import {
  fieldResolvers as searchFieldResolvers,
  queries as searchQueries,
} from './search'

export const resolvers = {
  ...searchFieldResolvers,
  Query: {
    ...searchQueries,
  },
}

```


[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 quickorder/node/resolvers/search/refids.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
export const resolvers = {
  Refids: {
    items({ items }: any): any {
      return items
    },
  },
}

```


[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 quickorder/node/resolvers/search/autocomplete.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { path, split } from 'ramda'

/**
 * It will extract the slug from the HREF in the item
 * passed as parameter.
 *
 * That is needed once the API provide only the old link
 * (from CMS portal) to access the product page, nothing
 * more.
 *
 * HREF provided:
 * https://portal.vtexcommercestable.com.br/:slug/p
 *
 * @param item The item to extract the information
 */
const extractSlug = (item: SearchAutocompleteUnit) => {
  const href = split('/', item.href)

  return href.length > 3 ? href[3] : ''
}

export const resolvers = {
  Items: {
    slug: (root: SearchAutocompleteUnit): string => extractSlug(root),

    productId: ({ items }: SearchAutocompleteUnit): any =>
      items ? path([0, 'productId'], items) : null,
  },
}

```


[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 quickorder/node/resolvers/search/utils.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Functions } from '@gocommerce/utils'

/**
 * We are doing this because the `get category` API is not returning the values
 * for slug and href. So we get the whole category tree and get that info from
 * there instead until the Search team fixes this issue with the category API.
 */

/**
 * That's a recursive function to fill an object like { [categoryId]: Category }
 * It will go down the category.children appending its children and so on.
 */

export const searchEncodeURI = (account: string) => (str: string) => {
  if (!Functions.isGoCommerceAcc(account)) {
    return str.replace(/[%"'.()]/g, (c: string) => {
      switch (c) {
        case '%':
          return '@perc@'

        case '"':
          return '@quo@'

        case "'":
          return '@squo@'

        case '.':
          return '@dot@'

        case '(':
          return '@lpar@'

        case ')':
          return '@rpar@'

        default: {
          return c
        }
      }
    })
  }

  return str
}

```


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

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { UserInputError } from '@vtex/api'

import { resolvers as refidsResolvers } from './refids'

export const fieldResolvers = {
  ...refidsResolvers,
}

const getSellers = async (context: Context, salesChannel?: string) => {
  const {
    clients: { search },
    vtex: { segment, logger },
  } = context

  let items: any = []

  try {
    const { data } = await search.sellers(salesChannel ?? segment?.channel)

    items = data.items
      .filter((item: any) => {
        return item.isActive === true
      })
      .map(({ id, name, availableSalesChannels }: any) => {
        const availableSalesChannelsIds = availableSalesChannels.map(
          (sc: { id: number }) => sc.id
        )

        return {
          id,
          name,
          availableSalesChannels: availableSalesChannelsIds,
        }
      })
  } catch (error) {
    logger.error({
      error,
      message: 'quickOrder-sellersError',
    })
  }

  return {
    cacheId: 'sellers',
    items,
  }
}

const checkoutSimulation = async (
  { refids, orderForm, refIdSellerMap, salesChannel }: SimulateArgs,
  context: Context
) => {
  const {
    clients: { search },
    vtex: { logger },
  } = context

  let resItems: any = {}

  try {
    const { items: simulatedItems }: any = await search.simulate({
      refids,
      orderForm,
      refIdSellerMap,
      salesChannel,
    })

    if (!simulatedItems.length) {
      return resItems
    }

    resItems = simulatedItems.reduce((acc: any, item: any) => {
      const sellerInfo = {
        seller: item.seller,
        availability: item.availability ?? '',
        unitMultiplier: item.unitMultiplier ?? 1,
        quantity: item.quantity,
      }

      return {
        ...acc,
        [item.id]: {
          sellers: acc[item.id]?.sellers?.length
            ? acc[item.id].sellers.concat(sellerInfo)
            : [sellerInfo],
        },
      }
    }, {})
  } catch (error) {
    logger.error({
      error,
      message: 'quickOrder-simulateError',
    })
  }

  return resItems
}

const getSellerIdNameMap = (sellersList: any) => {
  const sellerMap = new Map()

  sellersList.forEach((seller: any) => sellerMap.set(seller.id, seller.name))

  return sellerMap
}

const getSkuSellers = async (
  context: Context,
  result: any,
  sellersList: any
) => {
  const {
    clients: { search },
    vtex: { logger },
  } = context

  const sellerIdNameMap = getSellerIdNameMap(sellersList)
  const sellersIds = new Set(sellersList?.map((seller: any) => seller.id))

  result = await Promise.all(
    result.map(async (item: any) => {
      const { sku, refid, quantity } = item

      if (sku === null) {
        return {
          sku,
          refid,
          sellers: [],
          quantity,
        }
      }

      return search
        .sellerBySku(sku)
        .then((res: any) => {
          const validSellers = res.data?.SkuSellers
            ? res.data.SkuSellers.filter((seller: any) => {
              // check if seller is active and available in current sales channel
              return (
                seller.IsActive === true && sellersIds.has(seller.SellerId)
              )
            }).map(({ SellerId }: any) => {
              return {
                id: SellerId,
                name: sellerIdNameMap.get(SellerId),
              }
            })
            : null

          return {
            sku,
            refid,
            sellers: validSellers,
            quantity,
          }
        })
        .catch((error: any) => {
          logger.error({
            error,
            sku,
            refid,
            message: 'quickOrder-sellerBySkuError',
          })

          return {
            sku,
            refid,
            sellers: null,
            quantity,
          }
        })
    })
  )

  return result
}

const getSkuSellerInfo = (simulationResults: any, result: any) => {
  let items: any = []

  if (Object.keys(simulationResults).length !== 0) {
    items = result.map((item: any) => {
      const skuInfoBySeller = item.sellers?.flatMap((seller: any) => {
        if (!simulationResults[item.sku]) {
          return [];
        }

        const currSeller = simulationResults[item.sku].sellers.find(
          (s: any) => s.seller === seller.id
        )

        const {
          availability = '',
          unitMultiplier = 1,
          quantity: availableQuantity = undefined,
        } = currSeller ?? {}

        const isPartiallyAvailable = availableQuantity < item.quantity

        return {
          ...seller,
          availability: isPartiallyAvailable
            ? 'partiallyAvailable'
            : availability,
          unitMultiplier,
          availableQuantity,
        }
      })

      return {
        ...item,
        sellers: skuInfoBySeller,
      }
    })
  }

  return items
}

export const queries = {
  skuFromRefIds: async (
    _: any,
    args: {
      refids: string
      orderFormId: string
      refIdSellerMap: any
      refIdQuantityMap: any
    },
    ctx: Context
  ): Promise<any> => {
    const {
      clients: { search },
      vtex: { segment, logger },
    } = ctx

    const { refids, orderFormId, refIdSellerMap, refIdQuantityMap } = args

    if (!refids) {
      throw new UserInputError('No refids provided')
    }

    let items: any = []

    try {
      const { data: skuIds } = await search.skuFromRefIds(refids)

      let result: any = []
      const resultStr: any = {}

      const orderForm = await search
        .getOrderForm(orderFormId)
        .catch((error: any) => {
          logger.error({
            error,
            orderFormId,
            message: 'quickOrder-getOrderFormError',
          })
        })

      const currentSC = segment?.channel ?? orderForm.salesChannel

      // filter out sellers that aren't available in current sales channel
      const { items: sellersList } = await getSellers(ctx, currentSC)

      const refs = Object.getOwnPropertyNames(skuIds)

      refs.forEach(id => {
        resultStr[id] = {
          sku: skuIds[id],
          refid: id,
          sellers: sellersList,
          quantity: refIdQuantityMap?.[id] ?? 1,
        }

        result.push(resultStr[id])
      })

      // gets SKU's sellers
      if (sellersList?.length) {
        result = await getSkuSellers(ctx, result, sellersList)
      }

      // update refIdSellerMap to include list of sellers by SKU
      result.forEach((item: any) => {
        refIdSellerMap[item.refid] = item.sellers
          ? item.sellers.map((seller: any) => seller.id)
          : null
      })

      await checkoutSimulation(
        {
          refids: result,
          orderForm,
          refIdSellerMap,
          salesChannel: currentSC,
        },
        ctx
      ).then(simulationResults => {
        if (Object.keys(simulationResults).length !== 0) {
          // include SKU's availability and unit multiplier info in given seller
          items = getSkuSellerInfo(simulationResults, result)
        } else {
          // ensures that each item in the result array has a sellers array that only includes sellers with a defined and non-null availability property.
          // If no such sellers exist, the sellers array will be empty.
          items = result.map((item: { sellers: any[] }) => ({
            ...item,
            sellers: item.sellers?.filter((seller: any) =>
              'availability' in seller &&
              seller.availability !== null
            ) || []
          }))
        }
      })
    } catch (error) {
      logger.error({
        error,
        message: 'quickOrder-skuFromRefIdsError',
      })
    }

    return {
      cacheId: refids,
      items,
    }
  },
  sellers: async (_: any, __: any, ctx: Context): Promise<any> => {
    return getSellers(ctx)
  },
}

```


[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 quickorder/react/typings/vtex.checkout-resources.d.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
declare module 'vtex.checkout-resources/Utils'
declare module 'vtex.checkout-resources/Mutations'

```


[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 quickorder/react/typings/css.d.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module '*.css' {
  const css: any
  export default css
}

```


[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 quickorder/react/typings/graphql.d.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module '*.graphql' {
  import type { DocumentNode } from 'graphql'

  const value: DocumentNode
  export default value
}

declare module '*.gql' {
  const gql: any
  export default gql
}

```


[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 quickorder/react/typings/vtex.styleguide.d.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module 'vtex.styleguide' {
  import type { ComponentType } from 'react'

  export const Input: ComponentType<InputProps>

  interface InputProps {
    [key: string]: any
  }

  export const Button
  export const Dropzone
  export const ToastContext
  export const Spinner
  export const Textarea
  export const Table
  export const ButtonWithIcon
  export const IconDelete
  export const IconInfo
  export const Tooltip
  export const Dropdown
  export const AutocompleteInput
  export const IconClear
  export const Tag
  export const Collapsible
}

```


[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 quickorder/react/queries/product.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Product($skuId: ID!) {
  product(identifier: { field: sku, value: $skuId })
    @context(provider: "vtex.search-graphql") {
    productName
    items {
      itemId
      name
      unitMultiplier
      sellers {
        sellerId
        sellerName
        sellerDefault
      }
      referenceId {
        Key
        Value
      }
      images {
        imageUrl
      }
    }
    skuSpecifications {
      field {
        name
      }
      values {
        name
      }
    }
  }
}

```


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

[User] Show me the implementation of quickorder/react/queries/refids.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query getSkuFromRefIds(
  $refids: [String]
  $orderFormId: String
  $refIdSellerMap: RefIdSellerMap
  $refIdQuantityMap: RefIdQuantityMap
) {
  skuFromRefIds(
    refids: $refids
    orderFormId: $orderFormId
    refIdSellerMap: $refIdSellerMap
    refIdQuantityMap: $refIdQuantityMap
  ) @context(provider: "vtex.quickorder") {
    items {
      sku
      refid
      sellers {
        id
        name
        availability
        unitMultiplier
        availableQuantity
      }
    }
  }
}

```


[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 quickorder/react/queries/orderForm.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query {
  orderForm @context(provider: "vtex.store-graphql") {
    orderFormId
    userType
    loggedIn
    allowManualPrice
    clientProfileData {
      email
    }
    customData {
      customApps {
        id
        major
        fields
      }
    }
    salesChannel
    totalizers {
      id
      name
      value
    }
    value
    items {
      name
      skuName
      refId
      id
      productId
      imageUrl
      listPrice
      price
      quantity
      sellingPrice
    }
    shippingData {
      address {
        street
        number
        complement
        postalCode
        city
        geoCoordinates
        neighborhood
        country
        state
      }
    }
  }
}

```


[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 quickorder/react/queries/sellers.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query getSellers {
  sellers {
    items {
      id
      name
    }
  }
}

```


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

[User] Show me the implementation of quickorder/react/queries/productById.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Product($identifier: ProductUniqueIdentifier) {
  product(identifier: $identifier) @context(provider: "vtex.search-graphql") {
    brand
    brandId
    cacheId
    categoryId
    description
    link
    linkText
    productId
    productName
    productReference
    titleTag
    metaTagDescription
    jsonSpecifications
    releaseDate
  }
}

```


[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 quickorder/react/queries/productsByCategory.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query SearchByCategory($selectedFacets: [SelectedFacetInput]) {
  productSearch(selectedFacets: $selectedFacets, from: 0, to: 90)
    @context(provider: "vtex.search-graphql") {
    products {
      items {
        itemId
        nameComplete
        unitMultiplier
        sellers {
          sellerId
          sellerName
          sellerDefault
        }
        images(quantity: 1) {
          imageUrl
          imageLabel
        }
        referenceId {
          Value
        }
      }
    }
  }
}

```


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

[User] Show me the implementation of quickorder/react/queries/categoriesQuery.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query {
  categories(treeLevel: 2) @context(provider: "vtex.store-graphql") {
    id
    name
    href
    slug
    hasChildren
    children {
      id
      name
      href
      slug
      hasChildren
      children {
        id
        name
        href
        slug
      }
    }
  }
}

```


[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 quickorder/react/queries/getSettings.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query getSettings($version: String!) {
  publicSettingsForApp(app: "vtex.quickorder", version: $version)
    @context(provider: "vtex.apps-graphql") {
    message
  }
}

```


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

[User] Show me the implementation of quickorder/react/queries/autocomplete.gql from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Autocomplete($inputValue: String!) {
  productSuggestions(fullText: $inputValue, hideUnavailableItems: true)
    @context(provider: "vtex.search-graphql") {
      products {
        productName
        productId
        items {
          itemId
          name
          images {
            imageUrl
          }
        }
        link
        linkText
      }
    }
}

```


[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 quickorder/react/utils/getAppSettings.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useQuery } from 'react-apollo'
import { useEffect, useState } from 'react'
/* eslint-disable no-restricted-imports */
import { pathOr } from 'ramda'

import AppSettings from '../queries/getSettings.gql'

const useAppSettings = () => {
  const { data: appSettingsData } = useQuery(AppSettings, {
    variables: {
      version: process.env.VTEX_APP_VERSION,
    },
    ssr: false,
  })

  const [appSettings, setAppSettings] = useState({
    checkoutUrl: '/checkout#/cart',
  })

  useEffect(() => {
    if (appSettingsData) {
      const settingsString = pathOr(
        `""`,
        ['publicSettingsForApp', 'message'],
        appSettingsData
      )

      try {
        const parsedAppSettings = JSON.parse(settingsString)

        setAppSettings(parsedAppSettings)
      } catch (error) {
        console.error('Error parsing app settings:', error)
      }
    }
  }, [appSettingsData])

  return appSettings
}

export default useAppSettings

```


[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 quickorder/react/utils/messages.ts from the quickorder VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { defineMessages } from 'react-intl'

const storePrefix = 'store/quickorder.'
const toasterPrefix = 'store/toaster.cart.'

export const reviewMessages = defineMessages({
  valid: {
    id: `${storePrefix}valid`,
  },
  available: {
    id: `${storePrefix}available`,
  },
  invalidPattern: {
    id: `${storePrefix}invalidPattern`,
  },
  withoutStock: {
    id: `${storePrefix}withoutStock`,
  },
  skuNotFound: {
    id: `${storePrefix}skuNotFound`,
  },
  partiallyAvailable: {
    id: `${storePrefix}partiallyAvailable`,
  },
  withoutPriceFulfillment: {
    id: `${storePrefix}withoutPriceFulfillment`,
  },
  limited: {
    id: `${storePrefix}limited`,
  },
  cannotBeDelivered: {
    id: `${storePrefix}cannotBeDelivered`,
  },
  inactive: {
    id: `${storePrefix}inactive`,
  },
  ORD002: {
    id: `${storePrefix}ORD002`,
  },
  ORD003: {
    id: `${storePrefix}ORD003`,
  },
  ORD004: {
    id: `${storePrefix}ORD004`,
  },
  ORD005: {
    id: `${storePrefix}ORD005`,
  },
  ORD006: {
    id: `${storePrefix}ORD006`,
  },
  ORD007: {
    id: `${storePrefix}ORD007`,
  },
  ORD008: {
    id: `${storePrefix}ORD008`,
  },
  ORD009: {
    id: `${storePrefix}ORD009`,
  },
  ORD011: {
    id: `${storePrefix}ORD011`,
  },
  ORD012: {
    id: `${storePrefix}ORD012`,
  },
  ORD013: {
    id: `${storePrefix}ORD013`,
  },
  ORD014: {
    id: `${storePrefix}ORD014`,
  },
  ORD015: {
    id: `${storePrefix}ORD015`,
  },
  ORD016: {
    id: `${storePrefix}ORD016`,
  },
  ORD017: {
    id: `${storePrefix}ORD017`,
  },
  ORD019: {
    id: `${storePrefix}ORD019`,
  },
  ORD020: {
    id: `${storePrefix}ORD020`,
  },
  ORD021: {
    id: `${storePrefix}ORD021`,
  },
  ORD022: {
    id: `${storePrefix}ORD022`,
  },
  ORD023: {
    id: `${storePrefix}ORD023`,
  },
  ORD024: {
    id: `${storePrefix}ORD024`,
  },
  ORD025: {
    id: `${storePrefix}ORD025`,
  },
  ORD026: {
    id: `${storePrefix}ORD026`,
  },
  ORD027: {
    id: `${storePrefix}ORD027`,
  },
  ORD028: {
    id: `${storePrefix}ORD028`,
  },
  ORD029: {
    id: `${storePrefix}ORD029`,
  },
  ORD030: {
    id: `${storePrefix}ORD030`,
  },
  ORD031: {
    id: `${storePrefix}ORD031`,
  },
  cannotGetSkuInfo: {
    id: `${storePrefix}cannotGetSkuInfo`,
  },
})

export const categoryMessages = defineMessages({
  success: {
    id: `${toasterPrefix}success`,
  },
  duplicate: {
    id: `${toasterPrefix}duplicate`,
  },
  noneSelection: {
    id: `${storePrefix}category.noneSelection`,
  },
  multiplier: {
    id: `${storePrefix}category.multiplier`,
  },
  error: {
    id: `${toasterPrefix}error`,
  },
  seeCart: {
    id: `${toasterPrefix}seeCart`,
  },
})

export const autocompleteMessages = defineMessages({
  placeholder: {
    id: `${storePrefix}autocomplete.placeholder`,
  },
  success: {
    id: `${toasterPrefix}success`,
  },
  duplicate: {
    id: `${toasterPrefix}duplicate`,
  },
  selectSku: {
    id: `${storePrefix}autocomplete.selectSku`,
  },
  multiplier: {
    id: `${storePrefix}category.multiplier`,
  },
  error: {
    id: `${toasterPrefix}error`,
  },
  seeCart: {
    id: `${toasterPrefix}seeCart`,
  },
})

```