[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 my-account-commons/react/__tests__/transformStates.test.ts from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```typescript
import transformStates from '../components/ProgressBar/transformStates'

describe('transformStates', () => {
  it('Should return the right states when the number of input states is even', () => {
    const states = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
      },
    ]

    const transformedStates = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 0,
      },
      { isLine: true, originalIndex: 0 },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
        originalIndex: 1,
      },
    ]
    expect(transformStates(states)).toEqual(transformedStates)
  })
  it('Should return the right states when the number of input states is odd', () => {
    const states = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
    ]

    const transformedStates = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 0,
      },
      { isLine: true, originalIndex: 0 },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
        originalIndex: 1,
      },
      { isLine: true, originalIndex: 1 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 2,
      },
    ]
    expect(transformStates(states)).toEqual(transformedStates)
  })

  it('Should return the right states when the the length of the input states is 7', () => {
    const states = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
    ]

    const transformedStates = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 0,
      },
      { isLine: true, originalIndex: 0 },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
        originalIndex: 1,
      },
      { isLine: true, originalIndex: 1 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 2,
      },
      { isLine: true, originalIndex: 2 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 3,
      },
      { isLine: true, originalIndex: 3 },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
        originalIndex: 4,
      },
      { isLine: true, originalIndex: 4 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 5,
      },
      { isLine: true, originalIndex: 5 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 6,
      },
    ]
    expect(transformStates(states)).toEqual(transformedStates)
  })

  it('Should return the right states when the the length of the input states is 10', () => {
    const states = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
      },
    ]

    const transformedStates = [
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 0,
      },
      { isLine: true, originalIndex: 0 },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
        originalIndex: 1,
      },
      { isLine: true, originalIndex: 1 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 2,
      },
      { isLine: true, originalIndex: 2 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 3,
      },
      { isLine: true, originalIndex: 3 },
      {
        todo: 'order.progress.approvePayment',
        done: 'order.progress.paymentApproved',
        doing: 'order.progress.approvingPayment',
        originalIndex: 4,
      },
      { isLine: true, originalIndex: 4 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 5,
      },
      { isLine: true, originalIndex: 5 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 6,
      },
      { isLine: true, originalIndex: 6 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 7,
      },
      { isLine: true, originalIndex: 7 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 8,
      },
      { isLine: true, originalIndex: 8 },
      {
        todo: 'order.progress.confirmOrder',
        done: 'order.progress.orderConfirmed',
        doing: 'order.progress.confirmingOrder',
        originalIndex: 9,
      },
    ]
    expect(transformStates(states)).toEqual(transformedStates)
  })
})

```


[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 my-account-commons/react/__tests__/utils.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import utils from '../utils'

describe('estimateShipping', () => {
  it('with unit as days should return the correct payload', () => {
    const currentDate = new Date()
    const mockDeliveryPackage = {
      shippingEstimate: '1d',
      shippingEstimateDate: currentDate,
    }

    const response = utils.estimateShipping(mockDeliveryPackage)

    expect(response.date).toBe(currentDate)
    expect(response.isEstimateInHoursOrMinutes).toBe(false)
  })

  it('with unit as hours should return the correct payload', () => {
    const currentDate = new Date()
    const mockDeliveryPackage = {
      shippingEstimate: '1h',
      shippingEstimateDate: currentDate,
    }

    const response = utils.estimateShipping(mockDeliveryPackage)

    expect(response.date).toBe(currentDate)
    expect(response.isEstimateInHoursOrMinutes).toBe(true)
  })

  it('with only shippingEstimate the correct payload', () => {
    const currentDate = new Date()
    const value = '1'
    const type = 'h'
    const mockDeliveryPackage = {
      shippingEstimate: `${value}${type}`,
    }

    const response = utils.estimateShipping(mockDeliveryPackage)

    expect(response.unit).toBe(parseInt(value))
    expect(response.type).toBe(type)
    expect(response.label).not.toBeNull()
  })

  it('with only shippingEstimateDate returns the correct payload', () => {
    const currentDate = new Date()
    const mockDeliveryPackage = {
      shippingEstimateDate: currentDate,
    }

    const response = utils.estimateShipping(mockDeliveryPackage)

    expect(response.date).toBe(currentDate)
  })

  it('without info returns null', () => {
    const mockedDeliveryPackage = {}

    const response = utils.estimateShipping(mockedDeliveryPackage)

    expect(response).toBeNull()
  })

  it('with empty shippingEstimate unit should return shippingEstimateDate', () => {
    const currentDate = new Date()
    const mockDeliveryPackage = {
      shippingEstimate: '1',
      shippingEstimateDate: currentDate,
    }

    const response = utils.estimateShipping(mockDeliveryPackage)

    expect(response.date).toBe(currentDate)
  })
})

```


[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 my-account-commons/react/components/ProgressBar/getNamespace.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
export default function getNamespace(isPackage) {
  return `myo-${isPackage ? 'package-' : ''}progress-bar`
}

```


[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 my-account-commons/react/components/ProgressBar/OrderStatus.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'

import getOrderProgress from './getOrderProgress'

class OrderStatus extends Component {
  render() {
    const { status, packages, render } = this.props
    return <Fragment>{render(getOrderProgress(status, packages))}</Fragment>
  }
}

OrderStatus.propTypes = {
  render: PropTypes.func.isRequired,
  status: PropTypes.string.isRequired,
  packages: PropTypes.arrayOf(PropTypes.object),
}

export default OrderStatus

```


[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 my-account-commons/react/components/ProgressBar/ProgressBarSection.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ProgressBar from './ProgressBar'
import { intlShape, injectIntl } from 'react-intl'

class ProgressBarSection extends Component {
  render() {
    const { currentState, states, intl, hasFinished } = this.props
    if (!currentState) return null
    return (
      <div className="myo-progress-bar w-100 h4-plus pb9 ph5 fl b--muted-5 bw1 ba">
        <div className="myo-progress-bar__title-font c-on-base mt2 mb5 tracked-mega lh-solid ttu f6 pt5">
          <span>
            {intl.formatMessage({
              id: 'progressBar.order.status',
            })}
          </span>
        </div>
        <div className="pt7">
          <ProgressBar
            states={states}
            currentState={currentState}
            hasFinished={hasFinished}
          />
        </div>
      </div>
    )
  }
}

ProgressBarSection.propTypes = {
  currentState: PropTypes.number,
  states: PropTypes.array.isRequired,
  intl: intlShape.isRequired,
  hasFinished: PropTypes.bool,
}

export default injectIntl(ProgressBarSection)

```


[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 my-account-commons/react/components/ProgressBar/utils.ts from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FIFTH_STEP, progressBarStates, THIRD_STEP } from './constants'
import getOrderProgress from './getOrderProgress'

const OutputPackageType = 'Output'

export function generateProgressBarStates(
  progressBarStates: any[],
  currentState: number,
  packages: any
) {
  const wasDelivered = isDelivered(packages)
  const isPickup = isOrderPickUp(packages)

  return progressBarStates.map((_state, index) => {
    let label
    const state = _state.pickup
      ? isPickup
        ? _state.pickup
        : _state.shipping
      : _state

    if (index < currentState) {
      label = state.done
    } else if (index === currentState) {
      if (index === FIFTH_STEP && wasDelivered) {
        label = state.done
      } else {
        label = state.doing
      }
    } else {
      label = state.todo
    }

    return {
      ...state,
      label: label,
    }
  })
}

export function getCurrentProgressBarState(status: string, packages: any) {
  const currentProgressIndex = getOrderProgress(status, packages)

  const generatedProgressBarStates = generateProgressBarStates(
    progressBarStates,
    currentProgressIndex,
    packages
  )

  return generatedProgressBarStates[currentProgressIndex]?.label
}

export function isDelivered(packages: any) {
  if (packages == null || packages.length === 0) {
    return false
  }

  const isDelivered = !packages.some(
    (pack: any) => {
      if (!pack?.package) return true // In case you can't tell whether the invoice is input or output, the order as a whole should be considered as not delivered.

      return pack?.package?.type === OutputPackageType &&
      !pack?.package?.courierStatus?.finished
    })

  return isDelivered
}

export function generatePackageProgressBarStates(
  states: any,
  currentState: any,
  pack: any
) {
  return states.map((state: any, index: number) => {
    let label = null
    if (
      index === THIRD_STEP &&
      currentState === THIRD_STEP &&
      pack.courierStatus &&
      pack.courierStatus.finished === true
    ) {
      label = state.done
    } else if (currentState === index) {
      label = state.doing
    } else if (currentState > index) {
      label = state.done
    } else {
      label = state.todo
    }
    return {
      ...state,
      label: label,
    }
  })
}

export function isOrderReadyToPickUp(packages: any) {
  if (packages == null || packages.length === 0) return false

  return packages.every((item: any) => {
    const isPickUp = item.deliveryChannel === 'pickup-in-point'
    const isReadyToPickUp =
      !item.shippingEstimateDate ||
      Date.now() >= new Date(item.shippingEstimateDate).getTime()
    return isPickUp && isReadyToPickUp
  })
}

export function isOrderPickUp(packages: any) {
  if (packages == null || packages.length === 0) return false

  return packages.every((pck: any) => pck.deliveryChannel === 'pickup-in-point')
}

```


[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 my-account-commons/react/components/ProgressBar/ConcludedLine.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import PropTypes from 'prop-types'

const ConcludedLine = ({ isPackage }) => (
  <div
    className={`${
      isPackage
        ? 'myo-package-progress-bar__line w3-ns w-50'
        : 'myo-progress-bar__line w-20'
    } myo-progress-bar__height1 bt bw1 b--success mt5`}
  />
)

ConcludedLine.propTypes = {
  isPackage: PropTypes.bool,
}

export default ConcludedLine

```


[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 my-account-commons/react/components/ProgressBar/CurrentCircle.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import PropTypes from 'prop-types'
import { intlShape, injectIntl } from 'react-intl'

import getNamespace from './getNamespace'

const CurrentCircle = ({ label, intl, isPackage }) => (
  <div
    className={`relative z-0 ${getNamespace(
      isPackage
    )}__margin flex items-center flex-column ma3 br-100`}>
    <div
      className={`br-100 mb2 myo-progress-bar__height1 w1 relative ba b--white bw1 ${
        isPackage ? 'myo-package-progress-bar' : 'myo-progress-bar'
      }__ma-inner-circle c-success bg-success`}
    />
    <div className="absolute myo-progress-bar__highlighted-circle myo-progress-bar__subtitle mt5 pa3 tc f6">
      <span className={`${getNamespace(isPackage)}__text c-on-base`}>
        {intl.formatMessage({
          id: label,
        })}
      </span>
    </div>
  </div>
)

CurrentCircle.propTypes = {
  label: PropTypes.string.isRequired,
  isPackage: PropTypes.bool,
  intl: intlShape.isRequired,
}

export default injectIntl(CurrentCircle)

```


[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 my-account-commons/react/components/ProgressBar/getOrderProgress.ts from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  FIRST_STEP,
  SECOND_STEP,
  THIRD_STEP,
  FOURTH_STEP,
  FIFTH_STEP,
} from './constants'
import { isDelivered, isOrderPickUp, isOrderReadyToPickUp } from './utils'

interface StatusMap {
  'order-created': number
  'order-completed': number
  'on-order-completed': number
  'payment-pending': number
  'window-to-cancel': number
  'approve-payment': number
  'payment-approved': number
  'ready-for-handling': number
  'authorize-fullfilment': number
  'release-to-fulfillment': number
  handling: number
  invoice: number
  invoiced: number
  [key: string]: number
}

const statusMap: StatusMap = {
  'order-created': FIRST_STEP,
  'order-completed': FIRST_STEP,
  'on-order-completed': FIRST_STEP,
  'payment-pending': SECOND_STEP,
  'window-to-cancel': THIRD_STEP,
  'approve-payment': SECOND_STEP,
  'payment-approved': THIRD_STEP,
  'ready-for-handling': THIRD_STEP,
  'authorize-fullfilment': THIRD_STEP,
  'release-to-fulfillment': THIRD_STEP,
  handling: THIRD_STEP,
  invoice: THIRD_STEP,
  invoiced: FOURTH_STEP,
}

function isCarrierHandling(packages: any) {
  if (packages == null || packages.length === 0) return false

  return packages.every(
    (pck: any) => pck.package?.courierStatus?.data?.length > 0
  )
}

export default function getOrderProgress(status: string, packages: any) {
  let progress = statusMap[status]
  const isPickup = isOrderPickUp(packages)
  if (progress === FOURTH_STEP) {
    if (
      isDelivered(packages) ||
      (isPickup && isOrderReadyToPickUp(packages)) ||
      (!isPickup && isCarrierHandling(packages))
    ) {
      progress = FIFTH_STEP
    }
  }
  return progress
}

```


[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 my-account-commons/react/components/ProgressBar/transformStates.ts from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```typescript
export default function transformStates(states: any) {
  const newStates = states.reduce((acc: any, state: any, index: number) => {
    return index === states.length - 1
      ? acc.concat({ ...state, originalIndex: index })
      : acc.concat(
          { ...state, originalIndex: index },
          { isLine: true, originalIndex: index }
        )
  }, [])

  return newStates
}

```


[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 my-account-commons/react/components/ProgressBar/constants.ts from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```typescript
export const ACTIVE = 'ACTIVE'

export const FIRST_STEP = 0
export const SECOND_STEP = 1
export const THIRD_STEP = 2
export const FOURTH_STEP = 3
export const FIFTH_STEP = 4

export const progressBarStates = [
  {
    todo: 'order.progress.confirmOrder',
    done: 'order.progress.orderConfirmed',
    doing: 'order.progress.confirmingOrder',
  },
  {
    todo: 'order.progress.approvePayment',
    done: 'order.progress.paymentApproved',
    doing: 'order.progress.approvingPayment',
  },
  {
    todo: 'order.progress.handleShipping',
    done: 'order.progress.shippingHandled',
    doing: 'order.progress.handlingShipping',
  },
  {
    shipping: {
      todo: 'order.progress.deliverToCarrier',
      done: 'order.progress.delivered',
      doing: 'order.progress.delivering',
    },
    pickup: {
      todo: 'order.progress.deliverToPickup',
      done: 'order.progress.deliveredToPickup',
      doing: 'order.progress.deliveringToPickup',
    },
  },
  {
    shipping: {
      todo: 'order.progress.ship',
      done: 'order.progress.shipped',
      doing: 'order.progress.shipping',
    },
    pickup: {
      todo: 'order.progress.pickup',
      done: 'order.state.pickedUp',
      doing: 'order.state.ready-for-pickup',
    },
  },
]

export const packageProgressBarStates = [
  {
    todo: 'package.progress.handleShipping',
    done: 'package.progress.shippingHandled',
    doing: 'package.progress.handlingShipping',
  },
  {
    todo: 'package.progress.deliverToCarrier',
    done: 'package.progress.delivered',
    doing: 'package.progress.delivering',
  },
  {
    todo: 'package.progress.ship',
    done: 'package.progress.shipped',
    doing: 'package.progress.shipping',
  },
]

```


[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 my-account-commons/react/components/ProgressBar/ProgressBar.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import PropTypes from 'prop-types'

import UnconcludedLine from './UnconcludedLine'
import ConcludedLine from './ConcludedLine'
import CurrentCircle from './CurrentCircle'
import ConcludedCircle from './ConcludedCircle'
import UnconcludedCircle from './UnconcludedCircle'
import Caption from './Caption'
import transformStates from './transformStates'
import { FIFTH_STEP } from './constants'

class ProgressBar extends Component {
  render() {
    const { states, currentState, hasFinished } = this.props
    if (!currentState) return null
    const progressStates = transformStates(states)
    return (
      <div className="myo-progress-bar">
        <div className="myo-progress-bar__mobile-text">
          <Caption
            numberOfStates={states.length}
            currentState={currentState}
            progressStates={progressStates}
          />
        </div>
        <div className="flex justify-center">
          {progressStates.map((state, index) => {
            if (state.isLine) {
              return currentState > state.originalIndex ? (
                <ConcludedLine key={index} />
              ) : (
                <UnconcludedLine key={index} />
              )
            }

            if (
              currentState > state.originalIndex ||
              (hasFinished && currentState === FIFTH_STEP)
            ) {
              return <ConcludedCircle key={index} label={state.label} />
            } else if (currentState === state.originalIndex) {
              return <CurrentCircle key={index} label={state.label} />
            }
            return <UnconcludedCircle key={index} label={state.label} />
          })}
        </div>
      </div>
    )
  }
}

ProgressBar.propTypes = {
  currentState: PropTypes.number.isRequired,
  states: PropTypes.array.isRequired,
  hasFinished: PropTypes.bool,
}

export default ProgressBar

```


[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 my-account-commons/react/components/ProgressBar/Caption.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import { intlShape, injectIntl } from 'react-intl'
import PropTypes from 'prop-types'

class Caption extends Component {
  render() {
    const { currentState, progressStates, numberOfStates, intl } = this.props
    return (
      <div className="flex">
        <div style={{ width: `${(currentState / 2) * 100}%` }} />
        <div className="flex-grow-1 tc nowrap">
          <span className="db b c-link hover-c-link c-link--visited">
            {intl.formatMessage({
              id: progressStates.find(
                state => state.originalIndex === currentState
              ).label,
            })}
          </span>
        </div>
        <div
          style={{
            width: `${(1 - currentState / (numberOfStates - 1)) * 100}%`,
          }}
        />
      </div>
    )
  }
}

Caption.propTypes = {
  currentState: PropTypes.number,
  progressStates: PropTypes.array.isRequired,
  intl: intlShape.isRequired,
  numberOfStates: PropTypes.number.isRequired,
}

export default injectIntl(Caption)

```


[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 my-account-commons/react/components/ProgressBar/UnconcludedLine.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import PropTypes from 'prop-types'

const UnconcludedLine = ({ isPackage }) => {
  return (
    <div
      className={`${
        isPackage
          ? 'myo-package-progress-bar__line w3-ns w-50'
          : 'myo-progress-bar__line w-20'
      } myo-progress-bar__height1 bt bw1 b--muted-3 mt5`}
    />
  )
}

UnconcludedLine.propTypes = {
  isPackage: PropTypes.bool,
}

export default UnconcludedLine

```


[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 my-account-commons/react/components/ProgressBar/ConcludedCircle.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import PropTypes from 'prop-types'
import { intlShape, injectIntl } from 'react-intl'

import getNamespace from './getNamespace'

const ConcludedCircle = ({ label, intl, isPackage }) => (
  <div
    className={`relative flex items-center flex-column br-100 myo-progress-bar__height1 ${
      isPackage
        ? 'myo-package-progress-bar__circle myo-package-progress-bar__margin'
        : 'myo-progress-bar__circle mh2'
    } w1 bg-success ba b--white bw1 mv3 `}>
    <div className="myo-progress-bar__subtitle mt5 pa3 tc f6">
      <span className={`c-on-base ${getNamespace(isPackage)}__text`}>
        {intl.formatMessage({
          id: label,
        })}
      </span>
    </div>
  </div>
)

ConcludedCircle.propTypes = {
  label: PropTypes.string.isRequired,
  intl: intlShape.isRequired,
  isPackage: PropTypes.bool,
}

export default injectIntl(ConcludedCircle)

```


[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 my-account-commons/react/components/ProgressBar/UnconcludedCircle.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React from 'react'
import { intlShape, injectIntl } from 'react-intl'
import PropTypes from 'prop-types'

import getNamespace from './getNamespace'

const UnconcludedCircle = ({ label, intl, isPackage }) => (
  <div
    className={`relative flex items-center flex-column br-100 myo-progress-bar__height1 w1 ${
      isPackage
        ? 'myo-package-progress-bar__circle myo-package-progress-bar__margin'
        : 'myo-progress-bar__circle'
    } bg-muted-3 ba b--white bw1 mv3 mh2`}>
    <div className="myo-progress-bar__subtitle mt5 pa3 tc f6">
      <span className={`c-muted-3 ${getNamespace(isPackage)}__text`}>
        {intl.formatMessage({
          id: label,
        })}
      </span>
    </div>
  </div>
)

UnconcludedCircle.propTypes = {
  label: PropTypes.string.isRequired,
  intl: intlShape.isRequired,
  isPackage: PropTypes.bool,
}

export default injectIntl(UnconcludedCircle)

```


[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 my-account-commons/react/components/ProgressBar/PackageProgressBar/PackageProgressBarSection.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { intlShape, injectIntl } from 'react-intl'
import transformStates from '../transformStates'
import PackageProgressBar from './PackageProgressBar'

class PackageProgressBarSection extends Component {
  render() {
    const { currentState, states } = this.props
    const progressStates = transformStates(states)
    if (currentState === null) return null
    return (
      <div className="myo-progress-bar pl6-l flex-column pt4-s pt0-l flex flex-row-l bl-l b--muted-5">
        <div className="tl-m tl-s pr3 myo-package-progress-bar__line-height">
          <span className="myo-package-progress-bar__maxWidth db f7 b--muted-3">
            {this.props.intl.formatMessage({
              id: 'progressBar.package.progress',
            })}
          </span>
          <span className="myo-package-progress-bar__maxWidth db f7 b b--emphasis">
            {this.props.intl.formatMessage({
              id: progressStates.find(
                state => state.originalIndex === currentState
              ).label,
            })}
          </span>
        </div>
        <PackageProgressBar currentState={currentState} states={states} />
      </div>
    )
  }
}

PackageProgressBarSection.propTypes = {
  currentState: PropTypes.number,
  states: PropTypes.array.isRequired,
  intl: intlShape.isRequired,
}

export default injectIntl(PackageProgressBarSection)

```


[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 my-account-commons/react/components/ProgressBar/PackageProgressBar/PackageProgressBar.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import { intlShape, injectIntl } from 'react-intl'

import ConcludedCircle from '../ConcludedCircle'
import CurrentCircle from '../CurrentCircle'
import UnconcludedLine from '../UnconcludedLine'
import UnconcludedCircle from '../UnconcludedCircle'
import ConcludedLine from '../ConcludedLine'
import Caption from '../Caption'
import transformStates from '../transformStates'

class PackageProgressBar extends Component {
  render() {
    const { currentState, states } = this.props
    if (currentState == null) return null
    const progressStates = transformStates(states)
    return (
      <Fragment>
        <div className="myo-progress-bar flex w-100 mv2-s ml7-l">
          {progressStates.map((state, index) => {
            if (state.isLine) {
              return currentState > state.originalIndex ? (
                <ConcludedLine isPackage key={index} />
              ) : (
                <UnconcludedLine isPackage key={index} />
              )
            }
            if (currentState === state.originalIndex) {
              return <CurrentCircle key={index} isPackage label={state.label} />
            }
            if (currentState > state.originalIndex) {
              return (
                <ConcludedCircle key={index} isPackage label={state.label} />
              )
            }
            return (
              <UnconcludedCircle key={index} isPackage label={state.label} />
            )
          })}
        </div>
        {currentState != null && (
          <div className="caption">
            <Caption
              numberOfStates={states.length}
              currentState={currentState}
              progressStates={progressStates}
            />
          </div>
        )}
      </Fragment>
    )
  }
}

PackageProgressBar.propTypes = {
  currentState: PropTypes.number,
  states: PropTypes.array.isRequired,
  intl: intlShape.isRequired,
}

export default injectIntl(PackageProgressBar)

```


[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 my-account-commons/react/components/ProgressBar/PackageProgressBar/getPackageProgress.ts from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FIRST_STEP, SECOND_STEP, THIRD_STEP } from '../constants'
import getOrderProgress from '../getOrderProgress'

export default function getPackageProgress(
  pack: any,
  orderStatus: any,
  orderPackages: any
) {
  if (
    getOrderProgress(orderStatus, orderPackages) < THIRD_STEP ||
    orderPackages.length < 2 ||
    !pack
  ) {
    return null
  }
  if (pack.courierStatus && pack.courierStatus.finished) {
    return THIRD_STEP
  }
  if (pack.trackingUrl || pack.trackingNumber) {
    return SECOND_STEP
  }
  return FIRST_STEP
}

```


[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 my-account-commons/react/components/ProgressBar/PackageProgressBar/PackageStatus.js from the my-account-commons VTEX app.

[Assistant]
Here's the implementation:

```javascript
import React, { Component, Fragment } from 'react'
import PropTypes from 'prop-types'
import getPackageProgress from './getPackageProgress'

class PackageStatus extends Component {
  render() {
    const { pack, status, packages, render } = this.props
    return (
      <Fragment>{render(getPackageProgress(pack, status, packages))}</Fragment>
    )
  }
}

PackageStatus.propTypes = {
  pack: PropTypes.any,
  render: PropTypes.func.isRequired,
  status: PropTypes.string.isRequired,
  packages: PropTypes.array.isRequired,
}

export default PackageStatus

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/glovo-integration.settings-title": "Glovo Integration",
  "admin/glovo-integration.settings.loading": "Loading application settings...",
  "admin/glovo-integration.settings.error": "Unable to retrieve application settings",
  "admin/glovo-integration.store-name": "Store name",
  "admin/glovo-integration.seller-id": "Seller ID",
  "admin/glovo-integration.seller-name": "Seller Name",
  "admin/glovo-integration.affiliate-id": "Affiliate ID",
  "admin/glovo-integration.sales-channel": "Sales Channel",
  "admin/glovo-integration.postal-code": "Postal Code",
  "admin/glovo-integration.country": "Country",
  "admin/glovo-integration.glovo-store-id": "Glovo Store ID",

  "admin/glovo-integration.table.title": "Stores",
  "admin/glovo-integration.table.subtitle": "List of stores integrated with the Glovo app",
  "admin/glovo-integration.table.edit-store": "Edit store",
  "admin/glovo-integration.table.remove-store": "Remove store",
  "admin/glovo-integration.table.empty": "There are no stores configured",
  "admin/glovo-integration.table.show-rows": "Show rows",
  "admin/glovo-integration.table.of": "of",
  "admin/glovo-integration.table.all": "All",
  "admin/glovo-integration.table.none": "None",
  "admin/glovo-integration.table.clear-all": "Clear all",
  "admin/glovo-integration.table.more-options": "more options",
  "admin/glovo-integration.table.apply": "Apply",

  "admin/glovo-integration.integration-settings.title": "Integration Settings",
  "admin/glovo-integration.integration-settings.subtitle": "Glovo integration settings",
  "admin/glovo-integration.integration-settings.glovo-token.description": "Token to perform calls to the Glovo API",
  "admin/glovo-integration.integration-settings.glovo-token": "Glovo Token *",
  "admin/glovo-integration.integration-settings.marketplace.description": "Toggle to use marketplace configuration",
  "admin/glovo-integration.integration-settings.marketplace.label": "Marketplace",
  "admin/glovo-integration.integration-settings.minimumStock.description": "Minimum stock to use for availability on Glovo store  (Must be between 1 and 20).",
  "admin/glovo-integration.integration-settings.minimumStock.label": "Minimum Stock",
  "admin/glovo-integration.integration-settings.production.description": "Toggle between development and production environment",
  "admin/glovo-integration.integration-settings.production.label": "Production",

  "admin/glovo-integration.client-info.title": "Client Information",
  "admin/glovo-integration.client-info.subtitle": "Information about the client from Glovo",
  "admin/glovo-integration.client-info.email": "Email *",
  "admin/glovo-integration.client-info.first-name": "First name * (used only if name is not present in received orders)",
  "admin/glovo-integration.client-info.last-name": "Last name * (used only if name is not present in received orders)",
  "admin/glovo-integration.client-info.document-type": "Document type *",
  "admin/glovo-integration.client-info.document": "Document *",
  "admin/glovo-integration.client-info.phone-number": "Phone number * (used only if name is not present in received orders)",
  "admin/glovo-integration.client-info.corporate-name": "Corporate name *",

  "admin/glovo-integration.modal.title": "Store Configuration",
  "admin/glovo-integration.modal.store-name.description": "Display name associated to the store",
  "admin/glovo-integration.modal.seller-id.description": "Seller ID associated to this store",
  "admin/glovo-integration.modal.affiliate-id.description": "Three letters ID associated for the affiliate. Format 'XYZ'",
  "admin/glovo-integration.modal.sales-channel.description": "Sales Channel associated with the store ID",
  "admin/glovo-integration.modal.postal-code.description": "The postal code for the store in charge of fulfillment",
  "admin/glovo-integration.modal.country.description": "The country of the store",
  "admin/glovo-integration.modal.glovo-store-id.description": "Glovo Store ID registered in Glovo for the configured Store ID",

  "admin/glovo-integration.delete-store-dialog.title": "Are you sure you want to delete the affiliation?",
  "admin/glovo-integration.delete-store-dialog.subtitle": "This action is irreversible, you will delete de affiliation",
  "admin/glovo-integration.delete-store-dialog.confirmation": "Remove the store",
  "admin/glovo-integration.delete-store-dialog.cancel": "Cancel",

  "admin/glovo-integration.inputs.error-message": "This field is mandatory",
  "admin/glovo-integration.alert.success": "Settings saved successfully",
  "admin/glovo-integration.alert.error": "Something went wrong",
  "admin/glovo-integration.add-more": "ADD STORE",
  "admin/glovo-integration.save": "SAVE"
}

```


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

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

[Assistant]
Here's the implementation:

```json
{
  "admin/glovo-integration.settings-title": "Glovo Integration",
  "admin/glovo-integration.settings.loading": "Loading application settings...",
  "admin/glovo-integration.settings.error": "Unable to retrieve application settings",
  "admin/glovo-integration.store-name": "Store name",
  "admin/glovo-integration.seller-id": "Seller ID",
  "admin/glovo-integration.seller-name": "Seller Name",
  "admin/glovo-integration.affiliate-id": "Affiliate ID",
  "admin/glovo-integration.sales-channel": "Sales Channel",
  "admin/glovo-integration.postal-code": "Postal Code",
  "admin/glovo-integration.country": "Country",
  "admin/glovo-integration.glovo-store-id": "Glovo Store ID",

  "admin/glovo-integration.table.title": "Stores",
  "admin/glovo-integration.table.subtitle": "List of stores integrated with the Glovo app",
  "admin/glovo-integration.table.edit-store": "Edit store",
  "admin/glovo-integration.table.remove-store": "Remove store",
  "admin/glovo-integration.table.empty": "There are no stores configured",
  "admin/glovo-integration.table.show-rows": "Show rows",
  "admin/glovo-integration.table.of": "of",
  "admin/glovo-integration.table.all": "All",
  "admin/glovo-integration.table.none": "None",
  "admin/glovo-integration.table.clear-all": "Clear all",
  "admin/glovo-integration.table.more-options": "more options",
  "admin/glovo-integration.table.apply": "Apply",

  "admin/glovo-integration.integration-settings.title": "Integration Settings",
  "admin/glovo-integration.integration-settings.subtitle": "Glovo integration settings",
  "admin/glovo-integration.integration-settings.glovo-token.description": "Token to perform calls to the Glovo API",
  "admin/glovo-integration.integration-settings.glovo-token": "Glovo Token *",
  "admin/glovo-integration.integration-settings.marketplace.description": "Toggle to use marketplace configuration",
  "admin/glovo-integration.integration-settings.marketplace.label": "Marketplace",
  "admin/glovo-integration.integration-settings.minimumStock.description": "Minimum stock to use for availability on Glovo store (Must be between 1 and 20).",
  "admin/glovo-integration.integration-settings.minimumStock.label": "Minimum Stock",
  "admin/glovo-integration.integration-settings.production.description": "Toggle between development and production environment",
  "admin/glovo-integration.integration-settings.production.label": "Production",

  "admin/glovo-integration.client-info.title": "Client Information",
  "admin/glovo-integration.client-info.subtitle": "Information about the client from Glovo",
  "admin/glovo-integration.client-info.email": "Email *",
  "admin/glovo-integration.client-info.first-name": "First name * (used only if name is not present in received orders)",
  "admin/glovo-integration.client-info.last-name": "Last name * (used only if name is not present in received orders)",
  "admin/glovo-integration.client-info.document-type": "Document type *",
  "admin/glovo-integration.client-info.document": "Document *",
  "admin/glovo-integration.client-info.phone-number": "Phone number * (used only if name is not present in received orders)",
  "admin/glovo-integration.client-info.corporate-name": "Corporate name *",

  "admin/glovo-integration.modal.title": "Store Configuration",
  "admin/glovo-integration.modal.store-name.description": "Display name associated to the store",
  "admin/glovo-integration.modal.seller-id.description": "Seller ID associated to this store",
  "admin/glovo-integration.modal.affiliate-id.description": "Three letters ID associated for the affiliate. Format 'XYZ'",
  "admin/glovo-integration.modal.sales-channel.description": "Sales Channel associated with the store ID",
  "admin/glovo-integration.modal.postal-code.description": "The postal code for the store in charge of fulfillment",
  "admin/glovo-integration.modal.country.description": "The country of the store",
  "admin/glovo-integration.modal.glovo-store-id.description": "Glovo Store ID registered in Glovo for the configured Store ID",

  "admin/glovo-integration.delete-store-dialog.title": "Are you sure you want to delete the affiliation?",
  "admin/glovo-integration.delete-store-dialog.subtitle": "This action is irreversible, you will delete de affiliation",
  "admin/glovo-integration.delete-store-dialog.confirmation": "Remove the store",
  "admin/glovo-integration.delete-store-dialog.cancel": "Cancel",

  "admin/glovo-integration.inputs.error-message": "This field is mandatory",
  "admin/glovo-integration.alert.success": "Settings saved successfully",
  "admin/glovo-integration.alert.error": "Something went wrong",
  "admin/glovo-integration.add-more": "ADD STORE",
  "admin/glovo-integration.save": "SAVE"
}

```


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

[User] Show me the implementation of glovo-integration/admin/navigation.json from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "section": "accountSettings",
  "titleId": "admin/glovo-integration.settings-title",
  "path": "/admin/glovo-integration"
}

```


[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 glovo-integration/admin/routes.json from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "admin.app.glovo-integration": {
    "component": "AdminPanel",
    "path": "/admin/app/glovo-integration"
  }
}

```


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

[Assistant]
Here's the implementation:

```markdown
# Glovo Integration

##  ⚠ Maintenance ⚠
*Starting June 1st 2023, this application will no longer be maintained by VTEX.*

---

The Glovo Integration allows European stores to be integrated with the Glovo Marketplace.\
_Note: Latin American stores are not supported_

## Main Features

- **Possibility to add multiple stores with independent catalogs**.
- **Product catalog update for stores** - Updates to the store's catalogs can be scheduled to keep prices and product availability up to date.
- **Order Integration** - The orders received from Glovo are integrated into VTEX.

## Configuration

_Prior to the following steps, you should have already reached out to Glovo to create the Catalog for the stores you will have available in Glovo, you should upload one catalog that includes all of the products you want to offer on the independent Glovo Stores. The App will take care of managing the availability for each store._

To configure the Glovo Integration you can follow these steps:

1. Run the following command in your store's CLI: `vtex install vtex.glovo-integration@3.x`
2. Make sure you have at least one (1) pick-up-point configured for each of the salesChannel where you want to offer the integration.
3. In your store's admin dashboard, on the side menu browse to **Apps -> Glovo Integration** and then click on it to open the application settings.\
4. Add the stores that will integrate with Glovo:

| Field          | Description                                                                                |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Store name     | Display name associated to the store                                                                                |
| Seller ID      | Seller ID associated to the store (the dropdown displays the seller's name)                                                        |
| Affiliate ID   | Three letters ID associated for the affiliate (you can find this ID going to **Store settings -> Orders' settings -> Affiliates**) |
| Sales channel  | The sales channel associated to the store                                                                                |
| Postal code    | The postal code for the store in charge of fulfilling the orders from Glovo                                                        |
| Country        | The country where the store is located                                                                                |
| Glovo Store ID | Glovo store ID assigned to the store by Glovo                                                                                |

5. Fill in the the integration settings and client information:

| Field                  | Description                                                               | Default value |
| ---------------------- | ------------------------------------------------------------------------- | ------------- |
| Glovo Token            | Glovo token (app key) provided by Glovo to connect to their APIs          |               |
| Minimum stock          | Minimum stock for a product to be marked as available on the Glovo store  | 1             |
| Marketplace            | Toggle to use a marketplace configuration                                 | `false`       |
| Production Environment | Toggle between Glovo's Test environment and production environment        | `false`       |
| Client information     | All orders will be created using this information for the customer fields |               |

6.  Using the example shown below, upload the catalog of your store's products that will be available on Glovo (include all the products from every store) by making a POST request to the following endpoint.

```
curl --request POST \
     --url https://app.io.vtex.com/vtex.glovo-integration/v2/{{account}}/{{workspace}}/_v/glovo/glovo-menu/ \
     --header 'VtexIdClientAutCookie: {authToken}' \
     --data '
        [
            "productId",
            "productId",
            "productId",
            .
            .
            .
            "productId",
        ]
     '
```

7. The catalog of products offered on Glovo can be updated completely or partially by using the following endpoints:

- **Complete update** - This endpoint will send a bulk update to every store for all the products in the menu.

```
curl --request POST \
     --url https://{{account}}.myvtex.com/_v/glovo/menu/update-all \
     --header 'VtexIdClientAutCookie: {authToken}' \
```

- **Partial update** - This endpoint will send a bulk update to every store only for products that have changed since the last update.\
  _The partial update requires the affiliate configuration described on step 5_

```
curl --request POST \
     --url https://{{account}}.myvtex.com/_v/glovo/menu/update-partial \
     --header 'VtexIdClientAutCookie: {authToken}' \
```

8. Inside your store's admin dashboard, on the side menu go to _Orders Management -> Settings -> Affiliate_ and configure a new [affiliate](https://help.vtex.com/en/tutorial/integration-guide-consuming-catalog-information-for-use-in-an-external-service) as follows:

   - Name: Give the affiliate a name
   - ID: a three (3) letter key for the affiliate (not compatible with numbers or vocals)
   - Trade Policy: number of the trade policy (sales channel) that will be linked to the Glovo Store
   - e-mail: email for notifications
   - Search Enpoint: `https://{{account}}.myvtex.com/_v/glovo/products/update`

## Store Menu

It is possible to see the current catalog offered in Glovo for any of the stores that have been added to the configuration. \
The following endpoint will respond with the store's current catalog and generate a new updated record in the background.

```
curl --request GET \
     --url https://app.io.vtex.com/vtex.glovo-integration/v3/{{account}}/{{workspace}}/_v/glovo/get-menu/{{affiliateId}}' \
     --header 'VtexIdClientAutCookie: {authToken} \
```

_The response has a property called `lastUpdated` that shows you the last date in which the the record was generated._

```


[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 glovo-integration/common/utils.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
type Inputs = Record<string, any>

export const validateInputs = (inputs: Inputs): boolean => {
  for (const key in inputs) {
    if (inputs[key] === '' || inputs[key] === undefined) {
      return false
    }

    if (typeof inputs[key] === 'object') {
      if (!validateInputs(inputs[key])) {
        return false
      }
    }
  }

  return true
}

```


[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 glovo-integration/graphql/schema.graphql from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```graphql
type Query {
  getGlovoIntegrationSettings: GlovoIntegrationSettings
    @cacheControl(scope: PUBLIC, maxAge: SHORT)

  getMaxItemsForSimulation: MaxItemsForSimulation
    @cacheControl(scope: PUBLIC, maxAge: SHORT)
}

type Mutation {
  saveGlovoIntegrationSettings(settings: SaveGlovoIntegrationSettings): Boolean

  updateMaxItemsForSimulation(max: Int!): MaxItemsForSimulation
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "memory": 1024,
  "ttl": 60,
  "timeout": 30,
  "minReplicas": 2,
  "maxReplicas": 6,
  "workers": 1,
  "routes": {
    "createOrder": {
      "path": "/_v/glovo/orders/create",
      "public": true
    },
    "updateProduct": {
      "path": "/_v/glovo/products/update",
      "public": true
    },
    "updateCompleteMenu": {
      "path": "/_v/glovo/menu/update-all",
      "public": true
    },
    "updatePartialMenu": {
      "path": "/_v/glovo/menu/update-partial",
      "public": true
    },
    "glovoMenu": {
      "path": "/_v/glovo/glovo-menu",
      "public": false
    },
    "getGlovoMenuByStore": {
      "path": "/_v/glovo/get-menu/:affiliateId",
      "public": false
    },
    "storeMenuUpdates": {
      "path": "/_v/glovo/store-menu-updates/:affiliateId",
      "public": false
    },
    "orderChange": {
      "path": "/pvt/orders/:orderId/changes",
      "public": true
    }
  },
  "events": {
    "updateGlovoOrder": {
      "sender": "vtex.orders-broadcast",
      "topics": ["invoiced"]
    }
  }
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "@vtex/clients": "^2.8.0",
    "co-body": "^6.0.0",
    "ramda": "^0.25.0"
  },
  "devDependencies": {
    "@types/co-body": "^0.0.3",
    "@types/jest": "^24.0.18",
    "@types/node": "^12.0.0",
    "@types/ramda": "types/npm-ramda#dist",
    "@vtex/api": "6.45.15",
    "@vtex/test-tools": "^1.0.0",
    "@vtex/tsconfig": "^0.5.6",
    "typescript": "3.9.7",
    "vtex.glovo-integration": "https://glovo--ametllerorigenqa.myvtex.com/_v/private/typings/linked/v1/vtex.glovo-integration@3.5.0+build1679072072/public/@types/vtex.glovo-integration",
    "vtex.native-types": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.native-types@0.9.0/public/@types/vtex.native-types",
    "vtex.sellers-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.sellers-graphql@7.5.2/public/@types/vtex.sellers-graphql",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.146.3/public/@types/vtex.styleguide"
  },
  "scripts": {
    "lint": "tsc --noEmit --pretty"
  },
  "version": "3.5.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 glovo-integration/node/index.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

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

import type { Clients } from './clients'
import { clientsConfig } from './clients'
import { events } from './middlewares/events'
import { routes } from './middlewares/routes'
import { resolvers } from './resolvers'

// Export a service that defines route handlers and client options.
export default new Service<Clients, State, ParamsContext>({
  clients: clientsConfig,
  routes,
  events,
  graphql: {
    resolvers,
  },
})

```


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

[Assistant]
Here's the implementation:

```tsx
import { AdminPanel } from './components/admin/AdminPanel'

export default AdminPanel

```


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

[Assistant]
Here's the implementation:

```json
{
  "name": "glovo",
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "dependencies": {
    "country-iso-2-to-3": "^1.1.0",
    "country-iso-3-to-2": "^1.1.0",
    "graphql": "^15.3.0",
    "react-apollo": "^3.1.5",
    "react-intl": "^5.20.6",
    "react-super-responsive-table": "^5.2.0",
    "uuid": "^8.3.2"
  },
  "devDependencies": {
    "@types/babel__core": "^7.1.18",
    "@types/jest": "^26.0.4",
    "@types/node": "^14.0.14",
    "@types/react": "^16.9.41",
    "@types/react-intl": "^2.3.17",
    "@vtex/test-tools": "^3.1.0",
    "@vtex/tsconfig": "^0.5.6",
    "vtex.glovo-integration": "https://glovo--ametllerorigenqa.myvtex.com/_v/private/typings/linked/v1/vtex.glovo-integration@3.5.0+build1679072072/public/@types/vtex.glovo-integration",
    "vtex.native-types": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.native-types@0.9.0/public/@types/vtex.native-types",
    "vtex.render-runtime": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.render-runtime@8.132.4/public/@types/vtex.render-runtime",
    "vtex.sellers-graphql": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.sellers-graphql@7.5.2/public/@types/vtex.sellers-graphql",
    "vtex.styleguide": "http://vtex.vtexassets.com/_v/public/typings/v1/vtex.styleguide@9.146.3/public/@types/vtex.styleguide"
  },
  "version": "3.5.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 glovo-integration/public/metadata/messages/es-AR.json from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "Integración Glovo Europa",
  "headline": "Solución nativa para integrar con Glovo Europa.",
  "overview": "¡La integración nativa de Glovo ahora está en VTEX!\\\\n Glovo es a día de hoy la mayor plataforma bajo demanda de Europa continental con más de 224 millones de pedidos entregados.\\\\n La integración de Glovo permitirá a sus clientes navegar por los productos de su tienda con la información de precios y stock más actualizada.",
  "features": [
    "Integración de Stock y Precio",
    "Integración de Ordenes",
    "Disponibilidad para integrar múltiples tiendas"
  ],
  "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 glovo-integration/public/metadata/messages/pt-BR.json from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "Glovo Europa Integration",
  "headline": "Solução nativa para integração com Glovo Europa.",
  "overview": "A integração nativa do Glovo está agora na VTEX!\\\\n Glovo é hoje a maior plataforma sob demanda da Europa continental, com mais de 224 milhões de pedidos entregues.\\\\n A integração do Glovo permitirá que seus clientes naveguem pelos produtos de sua loja com as informações de estoque e preços mais atualizadas.",
  "features": [
    "Integração de estoque e preço",
    "Integração de Pedidos",
    "Disponibilidade para integração de múltiplas lojas"
  ],
  "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 glovo-integration/public/metadata/messages/en-US.json from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "name": "Glovo Europe Integration",
  "headline": "Native solution to integrate with Glovo.",
  "overview": "Glovo native integration is now on VTEX!\\\\n Today, Glovo is the largest on-demand platform in continental Europe with more than 224 million orders delivered.\\\\n The Glovo integration will allow your clients to browse your store's products with the most up-to-date stock and price information.",
  "features": [
    "Integration of Stock and Prices",
    "Integration of Orders",
    "Multiple Store Capability"
  ],
  "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 glovo-integration/graphql/types/clientProfileData.graphql from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```graphql
type ClientProfileData {
  email: String!
  firstName: String!
  lastName: String!
  documentType: String
  document: String
  phone: String
  corporateName: String
  tradeName: String
  corporateDocument: String
  stateInscription: String
  corporatePhone: String
  isCorporate: Boolean
  userProfileId: String
}

input SaveClientProfileData {
  email: String!
  firstName: String!
  lastName: String!
  documentType: String
  document: String
  phone: String
  corporateName: 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 glovo-integration/graphql/types/store.graphql from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```graphql
type Store {
  id: String!
  sellerId: String!
  sellerName: String!
  storeName: String!
  affiliateId: String!
  salesChannel: String!
  postalCode: String!
  country: String!
  glovoStoreId: String!
}

input SaveStore {
  id: String!
  sellerId: String!
  sellerName: String!
  storeName: String!
  affiliateId: String!
  salesChannel: String!
  postalCode: String!
  country: String!
  glovoStoreId: 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 glovo-integration/graphql/types/appSettings.graphql from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```graphql
type GlovoIntegrationSettings {
  glovoToken: String!
  production: Boolean!
  marketplace: Boolean!
  stores: [Store!]!
  clientProfileData: ClientProfileData!
  minimumStock: Int!
}

input SaveGlovoIntegrationSettings {
  glovoToken: String!
  production: Boolean!
  marketplace: Boolean!
  stores: [SaveStore!]!
  clientProfileData: SaveClientProfileData!
  minimumStock: 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 glovo-integration/node/clients/recordManager.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

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

import {
  GLOVO,
  MENU,
  STORE_MENU,
  ORDERS,
  STORE_MENU_UPDATE,
} from '../constants'

export default class RecordsManager extends VBase {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, {
      ...options,
    })
  }

  // Glovo Menu Records
  public saveGlovoMenu(data: GlovoMenu) {
    return this.saveJSON<GlovoMenu>(GLOVO, MENU, data)
  }

  public getGlovoMenu() {
    return this.getJSON<GlovoMenu>(GLOVO, MENU, true)
  }

  // Store's Menu Updates Records
  public saveStoreMenuUpdates(affiliateId: string, data: StoreMenuUpdates) {
    return this.saveJSON<StoreMenuUpdates>(affiliateId, MENU, data)
  }

  public getStoreMenuUpdates(affiliateId: string) {
    return this.getJSON<StoreMenuUpdates>(affiliateId, MENU, true)
  }

  // Product's Records
  public saveProductRecord(
    affiliateId: string,
    skuId: string,
    data: ProductRecord
  ) {
    return this.saveJSON<ProductRecord>(affiliateId, skuId, data)
  }

  public getProductRecord(affiliateId: string, skuId: string) {
    return this.getJSON<ProductRecord>(affiliateId, skuId, true)
  }

  // Store's catalog
  public saveStoreMenuRecord(affiliateId: string, data: StoreMenuRecord) {
    return this.saveJSON<StoreMenuRecord>(affiliateId, STORE_MENU, data)
  }

  public getStoreMenuRecord(affiliateId: string) {
    return this.getJSON<StoreMenuRecord>(affiliateId, STORE_MENU, true)
  }

  // Store's catalog update
  public saveStoreCompleteMenuUpdate(
    affiliateId: string,
    data: CompleteUpdateRecord
  ) {
    return this.saveJSON(affiliateId, STORE_MENU_UPDATE, data)
  }

  public getStoreCompleteMenuUpdate(affiliateId: string) {
    return this.getJSON<{ items: GlovoProductPatch[]; lastUpdated: string }>(
      affiliateId,
      STORE_MENU_UPDATE,
      true
    )
  }

  // Order's Records
  public saveOrderRecord(orderId: string, data: OrderRecord) {
    return this.saveJSON<OrderRecord>(ORDERS, orderId, data)
  }

  public getOrderRecord(orderId: string) {
    return this.getJSON<OrderRecord>(ORDERS, orderId, true)
  }
}

```


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

[Assistant]
Here's the implementation:

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

export default class Orders extends JanusClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super(context, {
      ...options,
      headers: {
        ...options?.headers,
        VtexIdclientAutCookie: context.authToken,
      },
    })
  }

  public getOrder(orderId: string): Promise<VTEXOrder> {
    return this.http.get(`/api/oms/pvt/orders/${orderId}`)
  }

  public createOrder(
    data: CreateOrderPayload,
    sc: string,
    affiliateId: string
  ): Promise<VTEXOrder[]> {
    return this.http.post('/api/fulfillment/pvt/orders', [data], {
      params: {
        sc,
        affiliateId,
      },
    })
  }

  public createMarketplaceOrder(
    data: CreateOrderPayload,
    sc: string,
    affiliateId: string
  ): Promise<CreateMarketplaceOrderResponse> {
    return this.http.put('/api/checkout/pvt/orders', data, {
      params: {
        sc,
        affiliateId,
      },
    })
  }

  // eslint-disable-next-line max-params
  public authorizeOrder(
    data: AuthorizeOrderPayload,
    orderId: string,
    sc: string,
    affiliateId: string
  ): Promise<VTEXAuthorizedOrder> {
    return this.http.post(
      `/api/fulfillment/pvt/orders/${orderId}/fulfill`,
      data,
      {
        params: {
          sc,
          affiliateId,
        },
      }
    )
  }

  public authorizeMarketplaceOrder(
    data: AuthorizeMarketplaceOrderPayload,
    marketplaceOrderId: string
  ): Promise<VTEXAuthorizedOrder> {
    return this.http.post(
      `/api/checkout/pvt/orders/${marketplaceOrderId}/receipts/marketplace-order-authorization`,
      data
    )
  }
}

```


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

[User] Show me the implementation of glovo-integration/node/clients/index.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { Cached, ClientsConfig } from '@vtex/api'
import { IOClients, LRUCache } from '@vtex/api'
import { Checkout } from '@vtex/clients'

import { TIMEOUT_MS } from '../constants'
import Glovo from './glovo'
import Orders from './orders'
import RecordsManager from './recordManager'

// Extend the default IOClients implementation with our own custom clients.
export class Clients extends IOClients {
  public get glovo() {
    return this.getOrSet('glovo', Glovo)
  }

  public get orders() {
    return this.getOrSet('orders', Orders)
  }

  public get recordsManager() {
    return this.getOrSet('recordsManager', RecordsManager)
  }

  public get checkout() {
    return this.getOrSet('checkout', Checkout)
  }
}

const glovoCache = new LRUCache<string, Cached>({ max: 500 })

metrics.trackCache('glovo', glovoCache)

export const clientsConfig: ClientsConfig<Clients> = {
  implementation: Clients,
  options: {
    default: {
      retries: 2,
      timeout: TIMEOUT_MS,
    },
    glovo: {
      memoryCache: glovoCache,
    },
  },
}

```


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

[Assistant]
Here's the implementation:

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

export default class Glovo extends ExternalClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super('glovoapp.com', context, {
      ...options,
      headers: {
        contentType: 'application/json',
        Accept: 'application/json',
      },
    })
  }

  private baseUrl() {
    return PRODUCTION
      ? 'https://api.glovoapp.com'
      : 'https://stageapi.glovoapp.com'
  }

  public async bulkUpdateProducts(
    data: GlovoProductBulkUpdate,
    glovoStoreId: string,
    glovoToken: string
  ) {
    return this.http.post<GlovoBulkUpdateResponse>(
      `${this.baseUrl()}/webhook/stores/${glovoStoreId}/menu/updates`,
      data,
      {
        headers: {
          Authorization: glovoToken,
        },
      }
    )
  }

  public async updateOrderStatus(
    { glovoStoreId, glovoOrderId, status }: GlovoUpdateOrderStatus,
    glovoToken: string
  ) {
    return this.http.put(
      `${this.baseUrl()}/webhook/stores/${glovoStoreId}/orders/${glovoOrderId}/status`,
      {
        status,
      },
      {
        headers: {
          Authorization: glovoToken,
        },
      }
    )
  }

  public async modifyOrder(
    {
      glovoStoreId,
      glovoOrderId,
      replacements,
      removed_purchases,
      added_products,
    }: GlovoModifyOrderPayload,
    glovoToken: string
  ): Promise<GlovoOrder> {
    return this.http.post(
      `${this.baseUrl()}/webhook/stores/${glovoStoreId}/orders/${glovoOrderId}/replace_products`,
      {
        replacements,
        removed_purchases,
        added_products,
      },
      {
        headers: {
          Authorization: glovoToken,
        },
      }
    )
  }
}

```


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

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/naming-convention */
export const RESIDENTIAL = 'Residential'
export const HOME = 'Home'
export const APP_SETTINGS = 'app-settings'
export const AVAILABLE = 'available'

/** VTEX Order status */
export const WAITING_SELLER_HANDLING = 'waiting-seller-handling'
export const READY_FOR_HANDLING = 'ready-for-handling'
export const HANDLING = 'handling'
export const INVOICED = 'invoiced'

/** Glovo order status */
export const ACCEPTED = 'ACCEPTED'
export const READY_FOR_PICKUP = 'READY_FOR_PICKUP'

/** Records Manager */
export const GLOVO = 'Glovo'
export const MENU = 'Menu'
export const ORDERS = 'orders'
export const STORE_MENU = 'store-menu'
export const STORE_MENU_UPDATE = 'store-menu-update'
export const MAX_ITEMS_FOR_SIMULATION = 'max-items-for-simulation'

/** General */
export const TIMEOUT_MS = 10000

```


[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 glovo-integration/node/typings/general.d.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface CatalogChange {
  IdSku: string
  ProductId: string
  An: string
  IdAffiliate: string
  Version: string
  DateModified: Date
  IsActive: boolean
  StockModified: boolean
  PriceModified: boolean
  HasStockKeepingUnitModified: boolean
  HasStockKeepingUnitRemovedFromAffiliate: boolean
}

interface SimulationTotalsItem {
  id: string
  name: string
  value: number
}

interface SimulationItem {
  id: string
  quantity: number
  sellerId: string
}

interface SimulatedItem {
  price: number
  available: boolean
}

interface CreateSimulationArgs {
  items: PayloadItem[]
  postalCode?: string
  country?: string
  affiliateId: string
  salesChannel: string
}

interface ProductRecord {
  id: string
  price?: number
  available?: boolean
}

interface StoreMenuRecord {
  items: {
    [id: string]: ProductRecord
  }
  lastUpdated: string
}

interface GlovoMenu {
  [key: string]: boolean
}

interface StoreMenuUpdates {
  current: MenuUpdatesItem
  previous?: MenuUpdatesItem
}

interface MenuUpdatesItem {
  responseId: string | null
  createdAt: number
  storeId: string
  storeName: string
  glovoStoreId: string
  items: ProductRecord[]
}

interface CompleteUpdateRecord {
  items: GlovoProductPatch[]
  transactionId: string | null
  lastUpdated: string
  successful: boolean
  minimumStock: 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 glovo-integration/node/typings/errors.d.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface ErrorParams {
  message: string
  reason: string
  metric: ErrorMetric
  data?: unknown
  error?: unknown
}

type ErrorMetric = 'menu' | 'orders' | 'products'

```


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

[User] Show me the implementation of glovo-integration/node/typings/glovo.d.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
interface GlovoOrder {
  order_id: string
  store_id: string
  order_time: string
  estimated_pickup_time: string
  utc_offset_minutes: string
  payment_method: string
  currency: string
  courier: GlovoOrderCourier
  customer: GlovoCustomer
  /**
   * Alphanumeric identifier of the order used for historical identification or with Glovo support
   *
   * @type {string}
   * @memberOf GlovoOrder
   */
  order_code: string
  allergy_info: string
  /**
   * Estimated total price of the order products and attributes in cents. Delivery fee is not included
   *
   * @type {number}
   * @memberOf GlovoOrder
   */
  estimated_total_price: number
  /**
   * Marketplace partners: delivery price of the order in cents.
   * Normal partners: null
   *
   * @type {(number | null)}
   * @memberOf GlovoOrder
   */
  delivery_fee: number | null
  /**
   * Marketplace partners: minimum basket surcharge in cents.
   * Normal partners: null
   *
   * @type {(number | null)}
   * @memberOf GlovoOrder
   */
  minimum_basket_surcharge: number | null
  /**
   * Marketplace partners: cash amount that the customer will pay with. In cents or null if not informed.
   * Normal partners: null
   *
   * @type {(number | null)}
   * @memberOf GlovoOrder
   */
  customer_cash_payment_amount: number | null
  products: GlovoProduct[]
  /**
   * Marketplace partners: object containing information about the delivery address (Delivery address object)
   * Normal partners: null
   *
   * @type {(GlovoDeliveryAddress | null)}
   * @memberOf GlovoOrder
   */
  delivery_address: GlovoDeliveryAddress | null
  /**
   * Marketplace partners: empty array
   * Normal partners: array containing the list of the orders bundled with current order
   *
   * @type {string[]}
   * @memberOf GlovoOrder
   */
  bundled_orders: string[]
  /**
   * Non-sequential, non-unique 3 digit numerical code used to identify an order for pickup by the courier or customer.
   *
   * @type {string}
   * @memberOf GlovoOrder
   */
  pick_up_code: string
  /**
   * Boolean to indicate if the order will be picked up by a customer instead of by a courier
   *
   * @type {boolean}
   * @memberOf GlovoOrder
   */
  is_picked_up_by_customer: boolean
  cutlery_requested: boolean
  partner_discounts_products: number
  partner_discounted_products_total: number
  /**
   * Marketplace: Final amount to be paid in cents by customer including discounts, promotions, surcharges, fees and other adjustments
   * Normal partners: null
   *
   * @type {(number | null)}
   * @memberOf GlovoOrder
   */
  total_customer_to_pay: number | null
}

interface GlovoOrderCourier {
  name: string
  phone_number: string
}

interface GlovoCustomer {
  name: string
  phone_number: string
  hash: string
  /**
   * Object containing invoicing information. Null if the customer doesn't need invoice (Invoicing details object)
   *
   * @type {(GlovoCustomerInvoice | null)}
   * @memberOf GlovoCustomer
   */
  invoicing_details: GlovoCustomerInvoice | null
}

interface GlovoCustomerInvoice {
  company_name: string
  company_address: string
  tax_id: string
}

interface GlovoProduct {
  id: string
  quantity: number
  name?: string
  price?: number
  attributes: GlovoProductAttributes[]
  purchased_product_id: string
}

interface GlovoProductAttributes {
  id: string
  quantity: number
  name?: string
  price?: number
  purchased_product_id?: string
}

interface GlovoDeliveryAddress {
  label: string
  longitude: number
  latitude: number
}

interface GlovoOrderCancellation {
  order_id: string
  store_id: string
  cancel_reason: string
  payment_strategy: string
}

interface GlovoProductUpdate {
  skuId: string
  price?: number
  available?: boolean
  glovoStoreId: string
}

interface GlovoProductPatch {
  available?: boolean
  id?: string
  price?: number
}

interface GlovoProductBulkUpdate {
  products: GlovoProductPatch[]
}

interface GlovoBulkUpdateResponse {
  transaction_id: string
}

interface GlovoUpdatedProduct {
  purchased_product_id: string
  product: GlovoProduct
}

interface GlovoUpdateOrderStatus {
  glovoStoreId: string
  glovoOrderId: string
  status: string
}

interface GlovoModifyOrderPayload {
  glovoStoreId: string
  glovoOrderId: string
  replacements: GlovoModifyReplacement[]
  removed_purchases: Array<string | undefined>
  added_products: GlovoModifiedProduct[]
}

interface GlovoModifyReplacement {
  purchased_product_id: string
  product: GlovoModifiedProduct
}

interface GlovoModifiedProduct {
  id: string
  quantity: number
  attributes: GlovoModifiedProductAttributes[]
}

interface GlovoModifiedProductAttributes {
  id: string
  quantity: 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 glovo-integration/node/typings/global.d.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { EventContext, RecorderState, ServiceContext } from '@vtex/api'
import type { ClientProfileData, Store } from 'vtex.glovo-integration'
import type { Clients } from '../clients'

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

  interface State extends RecorderState {
    vtexAuthOrder: VTEXAuthorizedOrder
    vtexOrder: VTEXOrder | VTEXMarketplaceOrder
    glovoOrder: GlovoOrder
    glovoToken: string
    catalogUpdate: CatalogChange
    marketplace: boolean
    stores: Store[]
    storeInfo: Store
    clientProfileData: ClientProfileData
    orderSimulation: SimulationOrderForm
  }

  interface StatusChangeContext extends EventContext<Clients, State> {
    body: {
      domain: string
      orderId: string
      currentState: string
      lastState: string
      currentChangeDate: string
      lastChangeDate: 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 glovo-integration/node/typings/vtex.orders.d.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ClientProfileData } from 'vtex.glovo-integration'

declare global {
  interface VTEXOrder {
    marketplaceOrderId: string
    orderId: string
    followUpEmail: string
    items: VTEXOrderItem[]
    clientProfileData: ClientProfileData
    shippingData: {
      address: ShippingAddress
      logisticsInfo: ItemLogistics
      isFOB: boolean
      selectedAddresses: ShippingAddress[]
      trackingHints: any[]
    }
    paymentData: any
    customData: any
    orders?: any
    changesAttachment: ChangesAttachment
  }

  interface CreateOrderPayload {
    marketplaceOrderId: string
    marketplaceServicesEndpoint: string
    marketplacePaymentValue: number
    marketplaceOrderGroup: string
    isCreatedAsync: boolean
    items: VTEXOrderItem[]
    clientProfileData: ClientProfileData
    shippingData: ShippingData
    paymentData?: PaymentData
    marketingData?: MarketingData
    openTextField?: string
    savePersonalData: boolean
  }

  interface CreateMarketplaceOrderResponse {
    orderForm?: any
    transactionData: any
    orders: VTEXMarketplaceOrder[]
  }

  interface AuthorizeOrderPayload {
    marketplaceOrderId: string
  }

  interface AuthorizeMarketplaceOrderPayload {
    marketplaceOrderGroup: string
    authorizationReceipt: {
      date: string
      receipt: string
    }
  }

  interface VTEXAuthorizedOrder extends VTEXAuthorizedMarketplaceOrder {
    orderId: string
    marketplaceOrderId: string
  }

  interface OrderRecord {
    orderId: string
    glovoOrder: GlovoOrder
    invoiced: any | null
    hasChanged: boolean
    createdAt?: number
    startHandlingAt?: string
    invoicedAt?: number
  }

  interface OrderChangeBody {
    requestId: string
    reason: string
    discountValue: number
    incrementValue: number
    itemsRemoved: OrderChangeItem[]
    itemsAdded: OrderChangeItem[]
  }

  interface VTEXMarketplaceOrder {
    orderId: string
    orderGroup: string
    state: string | null
    isCheckedIn: boolean
    sellerOrderId: string
    storeId: string | null
  }

  interface VTEXAuthorizedMarketplaceOrder {
    receipt: string
    date: string
    items: [{ id: string }]
    shippingData: {
      logisticsInfo: [
        {
          itemIndex: number
          selectedSLAId: string
          selectedDeliveryChannel: string
          shippingEstimateDate: string
        }
      ]
    }
  }

  interface OrderChangeItem {
    id: string
    price: number
    quantity: number
  }

  interface VTEXOrderItem {
    id: string
    quantity: number
    seller: string
    priceTable: any
    commission: number
    freightCommission: number
    price: number
    bundleItems: any[]
    priceTags: any[]
    measurementUnit: string
    unitMultiplier: number
    isGift: boolean
    manufacturerCode: string
    catalogProvider: string
  }

  interface ShippingAddress {
    addressType: string
    receiverName: string
    addressId: string
    postalCode: string
    city: string | null
    state: string | null
    country: string
    street: string
    number: string | null
    neighborhood: string | null
    complement: string | null
    reference: string | null
    geoCoordinates: number[] | []
  }

  interface ItemLogistics {
    itemIndex: number
    selectedSla: string
    addressId?: string
    selectedDeliveryChannel: string
    name?: string
    deliveryIds?: ItemLogisticsDeliveryId[]
    lockTTL: string
    deliveryWindow: {
      startDateUtc: string
      endDateUtc: string
      price: number
      lisPrice: number
      tax: number
    }
    shippingEstimate: string
    price: number
  }

  interface ChangesAttachment {
    id: string
    changesData: ChangesData[]
  }

  interface ChangesData {
    reason: string
    discountvalue: number
    incrementValue: number
    itemsAdded: ChangesAttachmentItem[]
    itemsRemoved: ChangesAttachmentItem[]
    receipt: {
      date: string
      orderId: string
      receipt: string
    }
  }

  interface ChangesAttachmentItem {
    id: string
    name: string
    quantity: number
    price: number
    unitMultiplier: number
  }

  interface ShippingData {
    address: ShippingAddress
    logisticsInfo: ItemLogistics[]
  }

  interface ItemLogisticsDeliveryId {
    warehouseId: string
    dockId: string
    accountCarrierName: string
  }

  interface PaymentData {
    id?: 'paymentData'
    payments: [
      {
        paymentSystem: string
        paymentSystemName?: string
        value: number
        installments: number
        referenceValue: number
      }
    ]
  }

  interface MarketingData {
    utmSource: string
    utmMedium: string
    utmCampaign: string
    utmiPage: string
    utmiPart: string
    utmiCampaign: 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 glovo-integration/node/utils/requests.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
/**
 * Utility function to delay execution of your current process
 * @param milliseconds Milliseconds to delay the resolve
 */
export function delayFor(milliseconds: number) {
  return new Promise<void>((resolve) => {
    setTimeout(() => {
      resolve()
    }, milliseconds)
  })
}

/**
 * Utility function to retry the request passed.
 *
 * @param request Request to be made
 * @param retries Number of retries to be made. Defaults to 2
 * @param delay Delay in milliseconds to wait between retries. Defaults to 500 milliseconds
 * @returns request response or request error
 */
export async function requestWithRetries<T>(
  request: unknown,
  retries = 2,
  delay = 500
): Promise<T> {
  try {
    const response = (await request) as T

    return response
  } catch (error) {
    if (retries === 0) {
      throw error
    }

    await delayFor(delay)

    return requestWithRetries(request, retries - 1)
  }
}

```


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

[User] Show me the implementation of glovo-integration/node/utils/errors.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
export class ServiceError extends Error {
  constructor({ message, reason, metric, data, error }: ErrorParams) {
    super(message)
    this.reason = reason
    this.metric = metric
    this.data = data ?? 'No data provided'
    this.error = error ?? 'No error information'
  }

  public reason: string
  public metric: ErrorMetric
  public data: unknown
  public error: unknown
}

```


[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 glovo-integration/node/utils/utils.ts from the glovo-integration VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/naming-convention */
import type { OrderFormItem, PayloadItem } from '@vtex/clients'
import type { Store } from 'vtex.glovo-integration'

import { createSimulationItem } from './simulation'

export const isSkuAvailable = (item: OrderFormItem | undefined): boolean => {
  if (!item) {
    return false
  }

  return item.availability === 'available'
}

export const getStoreInfoFormGlovoStoreId = (
  id: string,
  stores: Store[]
): Store | undefined => stores.find(({ glovoStoreId }) => glovoStoreId === id)

export const getStoreInfoFromStoreId = (id: string, stores: Store[]) =>
  stores.find(({ affiliateId }) => affiliateId === id) as Store

export const convertGlovoProductToItems = (
  sellerId: string,
  glovoProducts: GlovoProduct[] = []
): PayloadItem[] => {
  const items = []
  const attributesCollection = []

  for (const product of glovoProducts) {
    const { id, quantity, attributes = [] } = product
    const item = createSimulationItem({ id, quantity, sellerId })

    items.push(item)
    attributesCollection.push(...attributes)
  }

  for (const attribute of attributesCollection) {
    const { id, quantity } = attribute
    const item = createSimulationItem({ id, quantity, sellerId })

    items.push(item)
  }

  return items
}

type ProductsToCompare = {
  id: string
  quantity: number
  purchased_product_id: string
}

export const convertGlovoProductsToCompare = (
  glovoProducts: GlovoProduct[]
) => {
  const items: ProductsToCompare[] = []
  const attributesCollection = []

  for (const product of glovoProducts) {
    const { id, quantity, attributes = [], purchased_product_id } = product
    const item = {
      id,
      quantity,
      purchased_product_id,
    }

    items.push(item)
    attributesCollection.push(...attributes)
  }

  for (const attribute of attributesCollection) {
    if (attribute.purchased_product_id) {
      const { id, quantity } = attribute

      const updatedItems = items.map((item) => {
        if (item.id === id) {
          item.quantity += quantity
        }

        return item
      })

      items.push(...updatedItems)
    }
  }

  return items
}

export const isValidAffiliateId = (
  affiliateId: string,
  stores: Store[]
): boolean => {
  if (Number(affiliateId)) {
    return false
  }

  return stores.some((store) => store.affiliateId === affiliateId)
}

```