[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 product-availability/react/components/Container.tsx from the product-availability VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import type { PropsWithChildren } from 'react'
import { useIntl } from 'react-intl'

import { useContextCssHandles } from './CssHandlesContext'

function Container({ children }: PropsWithChildren<unknown>) {
  const { handles } = useContextCssHandles()
  const intl = useIntl()

  return (
    <div
      className={`${handles.container} flex pv2`}
      aria-label={intl.formatMessage({
        id: 'store/product-availability.container.aria-label',
      })}
    >
      {children}
    </div>
  )
}

export default Container

```


[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 product-availability/react/components/ShowAvailable.tsx from the product-availability VTEX app.

[Assistant]
Here's the implementation:

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

import { useContextCssHandles } from './CssHandlesContext'

interface Props {
  text: string
  availableQuantity: number
}

function ShowAvailable({ text, availableQuantity }: Props) {
  const { handles } = useContextCssHandles()
  const [before, after] = text.split('{quantity}')

  return (
    <Fragment>
      {before && (
        <span className={`${handles.showAvailableText} c-muted-2 t-body`}>
          {before}
        </span>
      )}
      {availableQuantity && (
        <span
          className={`${handles.showAvailableTextHighlight} c-muted-2 t-body b mh1`}
        >
          {availableQuantity}
        </span>
      )}
      {after && (
        <span className={`${handles.showAvailableText} c-muted-2 t-body`}>
          {after}
        </span>
      )}
    </Fragment>
  )
}

export default ShowAvailable

```


[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 product-availability/react/components/HighStock.tsx from the product-availability VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import { useContextCssHandles } from './CssHandlesContext'

interface Props {
  text: string
}

function HighStock({ text }: Props) {
  const { handles } = useContextCssHandles()

  return (
    <span className={`${handles.highStockText} c-muted-2 t-body`}>{text}</span>
  )
}

export default HighStock

```


[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 product-availability/react/components/ProductAvailability.tsx from the product-availability VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { memo } from 'react'
import type { ProductTypes } from 'vtex.product-context'

import LowStock from './LowStock'
import HighStock from './HighStock'
import ShowAvailable from './ShowAvailable'
import Container from './Container'

interface Props {
  threshold: number
  lowStockMessage?: string
  highStockMessage?: string
  showAvailability?: 'disabled' | 'stock'
  showAvailabilityMessage?: string
  availableQuantity?: ProductTypes.CommercialOffer['AvailableQuantity']
}

function ProductAvailability({
  threshold,
  lowStockMessage,
  highStockMessage,
  showAvailability = 'disabled',
  showAvailabilityMessage,
  availableQuantity,
}: Props) {
  if (!availableQuantity || availableQuantity < 1) {
    return null
  }

  const isLowStock = availableQuantity < threshold

  if (showAvailability === 'stock' && showAvailabilityMessage) {
    return (
      <Container>
        <ShowAvailable
          text={showAvailabilityMessage}
          availableQuantity={availableQuantity}
        />
      </Container>
    )
  }

  if (isLowStock && lowStockMessage) {
    return (
      <Container>
        <LowStock
          text={lowStockMessage}
          availableQuantity={availableQuantity}
        />
      </Container>
    )
  }

  if (!highStockMessage) {
    return null
  }

  return (
    <Container>
      <HighStock text={highStockMessage} />
    </Container>
  )
}

export default memo(ProductAvailability)

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.colors.title": "Favorite Color",
  "store/colorPicker.title": "Escolha sua cor favorita",
  "store/colorPicker.subtitle": "Escolha sua cor favorita e envie!"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.colors.title": "Favorite Color",
  "store/colorPicker.title": "Pick your favorite color",
  "store/colorPicker.subtitle": "Pick your favorite color and submit!"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.colors.title": "Favorite Color",
  "store/colorPicker.title": "Pick your favorite color",
  "store/colorPicker.subtitle": "Pick your favorite color and submit!"
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/editor.colors.title": "Color Favorito",
  "store/colorPicker.title": "Elegí tu color favorito",
  "store/colorPicker.subtitle": "Elegí tu color favorito y envialo!"
}

```


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

[Assistant]
Here's the implementation:

```markdown

# Service Example

A reference app implementing a VTEX IO service with HTTP route handlers.

![Service Example Architecture](https://user-images.githubusercontent.com/18706156/77381360-72489680-6d5c-11ea-9da8-f4f03b6c5f4c.jpg)

We use [**KoaJS**](https://koajs.com/) as the web framework, so you might want to get into that

We also use the [**node-vtex-api**](https://github.com/vtex/node-vtex-api), a VTEX set of utilities for Node services. You can import this package using NPM from `@vtex/api` (already imported on this project)

- Start from `node/index.ts` and follow the comments and imports :)

## Recipes

### Defining routes on _service.json_
```json
{
  "memory": 256,
  "ttl": 10,
  "timeout": 2,
  "minReplicas": 2,
  "maxReplicas": 4,
  "routes": {
    "status": {
      "path": "/_v/status/:code",
      "public": true
    }
  }
}
```

The `service.json` file that sits on the root of the `node` folder holds informations about this service, like the maximum timeout and number of replicas, what might be discontinued on the future, but also **sets its routes**.

Koa uses the [path-to-regexp](https://github.com/pillarjs/path-to-regexp) format for defining routes and, as seen on the example, we use the `:code` notation for declaring a **route param** named code, in this case. A HTTP request for `https://{{workspace}}--{{account}}.myvtex.com/_v/status/500` will match the route we've defined.

For cach _key_ on the `routes` object, there should be a **corresponding entry** on the exported Service object on `node/index.ts`, this will hook your code to a specific route.

### Access Control
You can also provide a `public` option for each route. If `true`, that resource will be reachable for everyone on the internet. If `false`, VTEX credentials will be requested as well.

Another way of controlling access to specific routes is using **ReBACs (Resource-based access)**, that supports more robust configuration. You can read more [on this document](https://docs.google.com/document/d/1ZxNHMFIXfXz3BgTN9xyrHL3V5dYz14wivYgQjRBZ6J8/edit#heading=h.z7pad3qd2qw7) (VTEX only).

#### Query String
For `?accepting=query-string`, you **don't need to declare anything**, as any query provided to the URL will already be available for you to use on the code as `ctx.query`, already parsed as an object, or `ctx.queryString`, taken directly from the URL as a string.

#### Route Params
Route Params will be available for you to use on the code as `ctx.vtex.params`, already parsed as an object.
For a path like `/_v/status/:code`, if you receive the request `/_v/status/200`, `ctx.vtex.params` will return `{ code: '200' }`

#### HTTP methods
When you define a route on the `service.json`, your NodeJS handlers for that route will be triggered  **on every HTTP method** (GET, POST, PUT...), so, if you need to handle them separately you need to implement a "sub-router". Fortunately, the _node-vtex-api_ provides a helper function `method`, exported from `@vtex/api`, to accomplish that behaviour. Instead of passing your handlers directly to the corresponding route on `index.ts`, you pass a `method` call passing **an object with the desired method as key and one handler as its corresponding value**. Check this example:
```typescript
import { method } from '@vtex/api'
...

export default new Service<Clients, State>({
  clients,
  routes: {
    status: method({
      GET: statusGetHandler,
      POST: statusPostHandler,
    }),
  },
})
```

### Throwing errors

When building a HTTP service, we should follow HTTP rules regarding data types, cache, authorization, and status code. Our example app sets a `ctx.status` value that will be used as a HTTP status code return value, but often we also want to give proper information about errors as well.

The **node-vtex-api** already exports a handful of **custom error classes** that can be used for that purpose, like the `NotFoundError`. You just need to throw them inside one of the the route handlers that the appropriate response will be sent to the server.

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

export async function validate(ctx: Context, next: () => Promise<any>) {
  const { code } = ctx.vtex.route.params
  if (isNaN(code) || code < 100 || code > 600) {
    throw new UserInputError('Code must be a number between 100 and 600')
  }
...
```

You can check all the available errors [here](https://github.com/vtex/node-vtex-api/tree/fd6139349de4e68825b1074f1959dd8d0c8f4d5b/src/errors), but some are not useful for just-HTTP services. Check the most useful ones:

|Error Class | HTTP Code |
|--|:--:|
| `UserInputError` | 400 |
| `AuthenticationError` | 401 |
| `ForbiddenError` | 403 |
| `NotFoundError` | 404 |

You can also **create your custom error**, just see how it's done above ;)

### Reading a JSON body

When writing POST or PUT handlers, for example, often you need to have access to the **request body** that comes as a JSON format, which is not provided directly by the handler function.

For this, you have to use the [co-body](https://www.npmjs.com/package/co-body) package that will parse the request into a readable JSON object, used as below:
```typescript
import { json } from 'co-body'
export async function method(ctx: Context, next: () => Promise<any>) {
    const body = await json(ctx.req)
```

### Other example apps

We use Node services across all VTEX, and there are a lot inspiring examples. If you want to dive deeper on learning about this subject, don't miss those internal apps: [builder-hub](https://github.com/vtex/builder-hub) or [store-sitemap](https://github.com/vtex-apps/store-sitemap)

## Testing

`@vtex/test-tools` and `@types/jest` should be installed on `./node` package as `devDependencies`.

Run `vtex test` and [Jest](https://jestjs.io/) will do its thing.

Check the `node/__tests__/simple.test.ts` test case and also [Jest's Documentation](https://jestjs.io/docs/en/getting-started).

## Splunk Dashboard

We have an (for now, VTEX-only, internal) Splunk dashboard to show all metrics related to your app. You can find it [here](https://splunk7.vtex.com/en-US/app/vtex_colossus/node_app_metrics).

After linking this app and making some requests, you can select `vtex.service-example` and see the metrics for your app. **Don't forget to check the box Development, as you are linking your app in a development workspace**.

For convenience, the link for the current version: https://splunk7.vtex.com/en-US/app/vtex_colossus/node_app_metrics?form.time.earliest=-30m%40m&form.time.latest=%40m&form.picked_context=false&form.picked_region=aws-us-east-*&form.picked_service=vtex.service-example

**Upcoming documentation:**

 - [Back](https://github.com/vtex-apps/favourite-colors/pull/1)
 - [Resolvers listos](https://github.com/vtex-apps/favourite-colors/pull/2)
```


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

[User] Show me the implementation of favourite-colors/graphql/schema.graphql from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```graphql
type Query {
  getAllColors: GetAllColorsResponse
}

type Mutation {
  updateColor(colorId: String): UpdateColorResponse
}
```


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

[Assistant]
Here's the implementation:

```json
{
  "memory": 256,
  "ttl": 10,
  "timeout": 2,
  "minReplicas": 2,
  "maxReplicas": 4,
  "workers": 1,
  "routes": {
    "colors": {
      "path": "/_v/colors",
      "public": 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 favourite-colors/node/package.json from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "dependencies": {
    "@vtex/clients": "^2.13.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.4",
    "@vtex/test-tools": "^1.0.0",
    "@vtex/tsconfig": "^0.5.6",
    "typescript": "3.9.7"
  },
  "scripts": {
    "lint": "tsc --noEmit --pretty"
  },
  "version": "0.0.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 favourite-colors/node/index.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```typescript
import {
  ClientsConfig,
  ServiceContext,
  RecorderState,
  LRUCache,
  method,
  Service
} from '@vtex/api'

import { Clients } from './clients'
import { readData } from './middlewares/readData'
import { saveData } from './middlewares/saveData'
import { validate } from './middlewares/validate'
import { resolvers } from './resolvers'

const TIMEOUT_MS = 800

const memoryCache = new LRUCache<string, any>({ max: 20 })

metrics.trackCache('status', memoryCache)

const clients: ClientsConfig<Clients> = {
  implementation: Clients,
  options: {
    default: {
      retries: 2,
      timeout: TIMEOUT_MS,
    },
     status: {
      memoryCache,
    },
  },
}

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

  interface BodyColor {
    color: string
    votes: number
  }

  interface State extends RecorderState {
    body: BodyColor
  }

}

export default new Service<Clients, RecorderState, Context>({
  clients,
  routes: {
    colors: method({
      GET: [readData],
      POST: [validate, readData ,saveData],
    }),
  },
  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 favourite-colors/react/package.json from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```json
{
  "sideEffects": false,
  "peerDependencies": {
    "react": "^16.0.0"
  },
  "devDependencies": {
    "@types/react": "^16.9.27",
    "@types/react-dom": "^16.9.7",
    "@vtex/prettier-config": "^0.3.1",
    "@vtex/tsconfig": "^0.5.0",
    "eslint-config-vtex-react": "^6.7.0",
    "prettier": "^2.0.5",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "^3.4.1",
    "ts-loader": "^8.0.1"
  },
  "scripts": {
    "test": "vtex-test-tools test"
  },
  "files": [
    "dist",
    "src"
  ]
}

```


[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 favourite-colors/react/FavouriteColors.tsx from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState } from 'react'
import Chart from './components/Chart'
import ColorPicker from './components/ColorPicker'
import Header from './components/Header'

const FavouriteColors = ({ image, title, colors, isActive }: FavouriteColorsProps) => {
  const [submitted, setSubmitted] = useState(false)

  return (
    isActive &&
    <>
      <Header image={image} title={title} />
      {!submitted ?
        <ColorPicker colors={colors} setSubmitted={setSubmitted} />
        :
        <Chart />
      }
    </>
  )
}

FavouriteColors.schema = {
  title: 'Favourite Colors',
  type: 'object',
  properties: {
    isActive: {
      title: 'Activar componente',
      type: 'boolean',
    },
    image: {
      title: 'Image Header',
      type: 'string',
      default: 'https://vtexarg.vtexassets.com/assets/vtex.file-manager-graphql/images/b9a84d73-c93f-4ee4-a299-0d0f4d929bc3___a24c847e9489c2d13719ce3b820f07b3.png',
      widget: {
        'ui:widget': 'image-uploader'
      }
    },
    title: {
      title: 'Title Header',
      type: 'string',
      default: 'Color Favorito'
    },
    colors: {
      title: 'Colors',
      type: 'array',
      items: {
        properties: {
          code: {
            tile: 'Color Hexadecimal',
            type: 'string'
          }
        }
      }
    }
  }
}

export default FavouriteColors

```


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

[Assistant]
Here's the implementation:

```json
{
  "favourite-colors": {
    "component": "FavouriteColors"
  }
}

```


[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 favourite-colors/graphql/types/updateColor.graphql from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```graphql
type UpdateColorResponse {
  response : String!
  status: 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 favourite-colors/graphql/types/getAllColors.graphql from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```graphql
type GetAllColorsResponse{
  colors: [Colors!]
  message: String!
}

type Colors{
  color: String!
  votes: 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 favourite-colors/node/clients/status.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

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

export default class Status extends ExternalClient {
  constructor(context: IOContext, options?: InstanceOptions) {
    super('http://httpstat.us', context, options)
  }

  public async getStatus(status: number): Promise<string> {
    return this.http.get(status.toString(), {
      metric: 'status-get',
    })
  }

  public async getStatusWithHeaders(
    status: number
  ): Promise<IOResponse<string>> {
    return this.http.getRaw(status.toString(), {
      metric: 'status-get-raw',
    })
  }
}

```


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

[Assistant]
Here's the implementation:

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

export default class MasterdataClient extends JanusClient {
  private baseUrl: string = `http://${this.context.account}.vtexcommercestable.com.br/api/dataentities`

  constructor(context: IOContext, options?: InstanceOptions) {
    super(context,
      {
        ...options,
        headers: {
          VtexIdclientAutCookie: context.authToken,
        },
      })
  }

  public async getAllColors() {
    return this.http.getRaw(`${this.baseUrl}/colors/search?_fields=id,votes&_schema=colors`)
  }
  public async getColor(colorId:string){
    return this.http.getRaw(`${this.baseUrl}/colors/documents/${colorId}?_fields=votes`)
  }
  public async updateColor(colorId:string, body: ColorBody){
    return this.http.putRaw(`${this.baseUrl}/colors/documents/${colorId}`, body)
  }
}

interface ColorBody{
  votes: 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 favourite-colors/node/clients/index.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

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

import MasterdataClient from './masterdata'

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

```


[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 favourite-colors/node/middlewares/saveData.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```typescript
export async function saveData(ctx: Context, next: () => Promise<any>) {
  const {
    clients: {
      masterdataClient
    }
  } = ctx
  try {
    // Traer el state del color y el state de la cantidad de votos
    const {color, votes} = ctx.state.body
    // y guardarlos en la base de datos
    const body = { votes: (votes + 1)}
    console.info("body",body)
    const response = await masterdataClient.updateColor(color, body)
    ctx.body = {response: response.data, message: "Voto guardado"}
    ctx.status = response.status
    await next()
  } catch (error) {
    // si hay error catch
    console.info('error', error)
    ctx.status = 500
    ctx.body = error
    await next()
  }
}

```


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

[User] Show me the implementation of favourite-colors/node/middlewares/readData.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

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

export async function readData(ctx: Context, next: () => Promise<any>) {
  const {
    clients: {
      masterdataClient
    }
  } = ctx
  try{
    if(ctx.req.method === 'GET') {
      console.log('METHOD',ctx.req.method)
      const colors = await masterdataClient.getAllColors()
      const hexColors = colors.data.map((color: { id: string, votes: number})=> {
        return {
          color: `#${color.id}`,
          votes: color.votes
        }
      })
      ctx.body = {colors: hexColors, message: 'Success!!!!!'}
      ctx.status = 200

      await next()
    } else {
      const {color} = ctx.state.body
      // Levantar el color del state y hacer un getColor() y pasar la cantidad de votos a otro state
      const responseGetColor = await masterdataClient.getColor(color)

      const {votes} = responseGetColor.data
      console.info("votes",votes)
      ctx.state.body.votes = votes
      await next()
      // y hacer next(),
    }
  } catch (error) {
    // si hay error => catch
    console.info('error', error)
    ctx.status = 500
    ctx.body = error
  }
}

```


[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 favourite-colors/node/middlewares/validate.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

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

export async function validate(ctx: Context, next: () => Promise<any>) {

  const {
    clients: {
      masterdataClient
    }
  } = ctx

  ctx.state.body = await json(ctx.req)

  try {
    // Agregar el color a un state
    let {color} = ctx.state.body
    const responseGetAllColors = await masterdataClient.getAllColors()
    const colors = responseGetAllColors.data.map((document: any) => document.id)

    if (color[0]==='#'){
      color = color.substring(1);
    }
    // Validar que el color que pasen en el post sea uno de los permitidos

    ctx.state.body.color = color

    if (colors.find((c: any) => c === color)){
      await next()
    } else {
      ctx.body = {
        message: 'Color not allowed'
      }
      ctx.status = 400
      return
    }

  } catch (error) {
    console.info('error', error)
    ctx.status = 500
     // Si hay un error hacer ctx.body error
    ctx.body = error
    return
  }
}

```


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

[Assistant]
Here's the implementation:

```typescript
import { queries as colorsQueries, mutations as colorsMutations } from './colors'

export const resolvers = {
  Query: {
    ...colorsQueries,
  },
  Mutation: {
    ...colorsMutations,
  }
}
```


[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 favourite-colors/node/__tests__/simple.test.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```typescript
// You can import your files here for testing them
//
// More info: https://github.com/sapegin/jest-cheat-sheet

describe('simpleTest', () => {
  it('one test case', async () => {
    expect(0.2 + 0.1).not.toBe(0.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 favourite-colors/node/resolvers/colors/index.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```typescript
/* eslint-disable @typescript-eslint/no-explicit-any */
export const queries = {
    getAllColors: async (_: unknown, {}:any, ctx: Context): Promise<any> => {
        const colorsResponse = await ctx.clients.masterdataClient.getAllColors()

        const hexColors = colorsResponse.data.map((color: { id: string, votes: number})=> {
            return {
              color: `#${color.id}`,
              votes: color.votes
            }
          })

        return {colors: hexColors, message: 'Success'}
    },
}

export const mutations = {
    updateColor: async (
      _: unknown,
      { colorId }: any,
      ctx: Context
    ): Promise<any> => {
        try {
            if (colorId[0]==='#'){
                colorId = colorId.substring(1);
            }
            console.log({colorId})
            const { data } = await ctx.clients.masterdataClient.getAllColors()
            console.log({data})
            const continuar = data.find((c: any) => c.id === colorId)
            console.log({continuar})
            if (continuar){
                const { data: { votes } } = await ctx.clients.masterdataClient.getColor(colorId)

                const body = {
                    votes : votes + 1
                }

                const { status } = await ctx.clients.masterdataClient.updateColor(colorId,body)

                return { response: `Color #${colorId} successfully updated with ${votes+1} votes!`, status: status}
            } else {

                return { response: 'Color not allowed', status: 404}
            }
        } catch (err) {
            console.error(err)

            return { response: err.message, status: err.status}
        }
    },
  }
```


[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 favourite-colors/react/typings/storefront.d.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FunctionComponent } from 'react'

declare global {
  interface StorefrontFunctionComponent<P = {}> extends FunctionComponent<P> {
    getSchema?(props: P): object
    schema?: object
  }

  interface StorefrontComponent<P = {}, S = {}> extends Component<P, S> {
    getSchema?(props: P): object
    schema: object
  }

  interface FavouriteColorsProps {
    isActive: boolean
    image: string
    title: string
    colors?: any
  }
  interface HeaderProps {
    image: string
    title: string
  }

  interface ColorProps {
    code: string
    selected?: string
    onClick: (code: string) => void
  }
  interface ColorPickerProps {
    colors: ColorProps[]
    onClick?: (selected: string) => void
    setSubmitted: React.Dispatch<React.SetStateAction<boolean>>
  }
  interface ColorsMetaData {
    color: string,
    votes: 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 favourite-colors/react/typings/global.d.ts from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { FunctionComponent } from 'react'

declare global {

}

```


[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 favourite-colors/react/components/Chart.tsx from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

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

import { useCssHandles } from 'vtex.css-handles'

import { Spinner, Alert } from 'vtex.styleguide'

import getAllColors from './../graphql/getAllColors.gql'

const CSS_HANDLES = [
  'chart--container',
  'chart--item'
]

const Chart = () => {
  const handles = useCssHandles(CSS_HANDLES)
  const [colors, setColors] = useState<ColorsMetaData[]>()

  const [state, setState] = useState({
    loading: false, error: ""
  })

  const { loading, error, data } = useQuery(getAllColors, {
    ssr: false,
  })

  useEffect(() => {
    if (loading) setState(prevState => ({ ...prevState, loading: true }))
    if (error) setState(prevState => ({ ...prevState, error: "Ocurrió un error, inténtelo nuevamente." }))
    if (data) setColors(data.getAllColors?.colors)
  }, [loading, error, data])

  return (
    <>
      <ul className={`ma8 pa0 ${handles['chart--container']}`}>
        {colors && colors.map((color: ColorsMetaData, index: number) =>
          <li
            key={index}
            className={`grow b--transparent pa5 mv5 br-pill list flex flex-column justify-center items-center ${handles['chart--item']}`}
            style={{ backgroundColor: color.color }}
          >
            {color.color} <span className={'b t-heading-3'}> {color.votes}</span>
          </li>
        )}
      </ul>
      {state.loading &&
        <div className='flex items-center justify-center h5'>
          <Spinner />
        </div>
      }
      {state.error &&
        <Alert type="error"> {state.error} </Alert>
      }
    </>
  )
}

export default Chart

```


[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 favourite-colors/react/components/ColorButton.tsx from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import { useCssHandles } from 'vtex.css-handles'

const CSS_HANDLES = [
  'colorButton--container',
  'colorButton--colorActive',
]

const ColorButton = ({ code, onClick, selected }: ColorProps) => {
  const handles = useCssHandles(CSS_HANDLES)

  return (
    <button
      style={{ backgroundColor: code }}
      className={`pointer b--transparent br-pill w3 h3 mr5 ${handles['colorButton--container']} ${selected === code && `${handles['colorButton--colorActive']}`}`}
      onClick={() => onClick(code)}
    >
    </button>
  )
}

export default ColorButton

```


[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 favourite-colors/react/components/Header.tsx from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'

import { useCssHandles } from 'vtex.css-handles';

const CSS_HANDLES = [
  'header--container',
  'header--title'
]

const Header: StorefrontFunctionComponent<HeaderProps> = ({ image, title }) => {
  const handles = useCssHandles(CSS_HANDLES)
  return (
    <header
      style={{ backgroundImage: `url(${image})` }}
      className={`flex items-center ${handles['header--container']}`}>
      <h1 className={`ml8 white t-heading-1 b ${handles['header--title']}`}>{title}</h1>
    </header>
  )
}

export default Header

```


[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 favourite-colors/react/components/ColorPicker.tsx from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

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

import { useCssHandles } from 'vtex.css-handles'
import { Button, Spinner, Alert } from 'vtex.styleguide'

import ColorButton from './ColorButton'
import updateColorGQL from './../graphql/updateColor.gql'

const CSS_HANDLES = [
  'colorPicker--container',
  'colorPicker--title',
  'colorPicker--subtitle'
]

const ColorPicker = ({ colors, setSubmitted }: ColorPickerProps) => {
  const handles = useCssHandles(CSS_HANDLES)
  const [selected, setSelected] = useState('')
  const [updateColor, { loading, error, data }] = useMutation(updateColorGQL)

  const [state, setState] = useState({
    loading: false, error: ""
  })

  useEffect(() => {
    if (loading) setState(prevState => ({ ...prevState, loading: true }))
    if (error) setState(prevState => ({ ...prevState, error: "Ocurrió un error, inténtelo nuevamente." }))
    if (data) data.updateColor?.status === 204 && setSubmitted(true)
  }, [loading, error, data])

  return (
    <>
      {
        !state.loading ? <section className={`${handles['colorPicker--container']} ma10`}>
          <h2 className={`${handles['colorPicker--title']} mt8 mb3 t-heading-2 fw2`}>Elegí tu color favorito</h2>
          <p className={`mb8 fw2 ${handles['colorPicker--subtitle']}`}>Elegí tu color favorito y hace click para conocer los resultados</p>
          <div className={`mv8 flex`}>
            {colors.map((item: ColorProps, index: number) =>
              <ColorButton
                code={item.code}
                key={index}
                onClick={setSelected}
                selected={selected}
              />
            )}
          </div>
          <Button onClick={() => updateColor({ variables: { colorId: selected } })}>
            Enviar
          </Button>

        </section>
          :
          <div className='flex items-center justify-center h5'>
            <Spinner />
          </div>
      }
      {state.error &&
        <Alert type="error"> {state.error} </Alert>}
    </>
  )
}

export default ColorPicker

```


[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 favourite-colors/react/graphql/getAllColors.gql from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```graphql
query getAllColorsQuery{
  getAllColors{
    colors{
      color
      votes
    }
    message
  }
}

```


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

[User] Show me the implementation of favourite-colors/react/graphql/updateColor.gql from the favourite-colors VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation updateColor($colorId: String){
    updateColor(colorId: $colorId) {
      response
      status
  }
}

```


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

[Assistant]
Here's the implementation:

```json
{
  "admin/return-app.navigation.label": "Retouren",
  "admin/navigation.labelRequests": "Aanvragen",
  "admin/return-app.settings.navigation.label": "Instellingen retouren",
  "admin/return-app.settings.max-days.label": "Max. aantal dagen:",
  "admin/return-app.settings.error.header": "Fout bij laden instellingen",
  "admin/return-app.settings.error.description": "Er is een fout opgetreden bij het laden van de applicatie-instellingen. Probeer de pagina opnieuw te laden.",
  "admin/return-app.settings.terms.label": "Algemene voorwaarden URL:",
  "admin/return-app.settings.section.payment-options.available-payment-methods.header": "Beschikbare betaalmethoden:",
  "admin/return-app.settings.section.payment-options.enable-payment-method-selection.description": "Voorkom dat de klant een andere betaalmethode kiest",
  "admin/return-app.settings.section.payment-options.enable-payment-method-selection.label.uncheck": "Hetzelfde als bestelling",
  "admin/return-app.settings.section.payment-options.enable-payment-method-selection.label.check": "Toegestaan om te kiezen",
  "admin/return-app.settings.section.payment-options.enable-payment-method-selection.error": "Ten minste één methode moet worden geselecteerd.",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.header": "Beschikbare aangepaste retouropties:",
  "admin/return-app.settings.excluded-categories.label": "Uitgesloten categorieën",
  "admin/return-app.settings.search-categories.placeholder": "Zoek categorie",
  "admin/return-app.settings.section.return-payment-options.header": "Retourbetalingopties",
  "admin/return-app.settings.section.custom-return-reasons.header": "Aangepaste retourredenen",
  "admin/return-app.settings.section.general-options.header": "Algemene opties",
  "admin/return-app.settings.section.general-options.enable-other-option-selection.label": "Sta toe dat u de optie \"Andere\" kiest",
  "admin/return-app.settings.section.general-options.enable-other-option-selection.description": "Laat gebruikers \"Andere\" kiezen en hun eigen retourreden toevoegen",
  "admin/return-app.settings.section.general-options.enable-pickup-points.label": "Afhaalpunten toestaan",
  "admin/return-app.settings.section.general-options.enable-pickup-points.description": "Sta de gebruiker toe voorwerpen af te geven bij afhaalpunten",
  "admin/return-app.settings.section.general-options.enable-proportional-shipping-value.label": "Proportionele verzending",
  "admin/return-app.settings.section.general-options.enable-proportional-shipping-value.description": "Bereken proportionele verzending voor elk item geretourneerd",
  "admin/return-app.settings.section.general-options.enable-select-item-condition.label": "Activeer de \"Item condition\" selector",
  "admin/return-app.settings.section.general-options.enable-select-item-condition.description": "Indien geactiveerd, moet de gebruiker de conditie van elk item selecteren",
  "admin/return-app.settings.section.general-options.enable-highlight-form-message.label": "Enable a customizable message in return forms",
  "admin/return-app.settings.section.general-options.enable-highlight-form-message.description": "When enabled, on top of the form that's used to fill the user personal data, a message will be displayed. Customizable via \"Messages\"",
  "admin/return-app.settings.section-excluded-categories.fetch-data-error": "Fout bij laden categorieën",
  "admin/return-app.settings.save.button": "Instellingen opslaan",
  "admin/return-app.settings.section.custom-reasons.empty-custom-reasons": "Geen opties toegevoegd",
  "admin/return-app.settings.section.custom-reasons.empty-custom-reasons.how-to": "Klik op de knop rechtsboven in de tabel om uw aangepaste retouropties toe te voegen",
  "admin/return-app.settings.section.custom-reasons.empty-custom-reasons.reasons.disclaimer": "Deze opties overschrijven de standaard opties. De hier weergegeven opties krijgen voorrang.",
  "admin/return-app.settings.section.custom-reasons.add.button": "NIEUWE TOEVOEGEN",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.label": "Aangepaste reden",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.placeholder": "Aangepaste retouroptie invoeren",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.max-days.label": "Maximale retourdagen",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.max-days.placeholder": "Voer maximale retourdagen in",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.add-new.button": "OPTIE TOEVOEGEN",
  "admin/return-app.settings.section.custom-reasons.modal.custom-reason.edit.button": "OPTIE BEWERKEN",
  "admin/return-app.settings.section.custom-reasons.modal.delete.custom-reason.confirm": "Verwijderen",
  "admin/return-app.settings.section.custom-reasons.modal.delete.custom-reason.cancel": "Annuleren",
  "admin/return-app.settings.section.custom-reasons.modal.delete.custom-reason.message": "Wilt u {reason} en de bijbehorende vertalingen verwijderen?",
  "admin/return-app.settings.section.custom-reasons.table.header.reason": "Reden",
  "admin/return-app.settings.section.custom-reasons.table.header.max-days": "Max. aantal dagen",
  "admin/return-app.settings.section.custom-reasons.modal.translations.error.header": "Fout bij laden beschikbare lokales",
  "admin/return-app.settings.section.custom-reasons.modal.translations.error.description": "Fout bij laden beschikbare lokales",
  "admin/return-app.settings.section.custom-reasons.modal.translations.confirm": "Bevestigen",
  "admin/return-app.settings.section.custom-reasons.modal.translations.cancel": "Annuleren",
  "admin/return-app.settings.section.custom-reasons.modal.translations.header.custom-reason-translation": "Aangepaste reden - Vertalingen",
  "admin/return-app.settings.section.custom-reasons.modal.translations.sub-header.custom-reason-translation": "Vertalingen voor: {reason}",
  "admin/return-app.settings.section.custom-reasons.modal.translations.table.header.custom-reason-translation.locale": "Lokaal",
  "admin/return-app.settings.section.custom-reasons.modal.translations.table.header.custom-reason-translation.translation": "Vertaling",
  "store/return-app.link": "Mijn retourzendingen",
  "store/return-app.request-return.page.header": "Nieuwe retour aanvragen",
  "store/return-app.request-return.page.header.subtitle": "Selecteer een bestelling om het retourverzoek te starten",
  "store/return-app.request-return.page.card.return-text": "Items beschikbaar voor retournering",
  "store/return-app.request-return.page.card.sequential-number": "Opeenvolgend nummer",
  "store/return-app.return-order-list.table-header.order-id": "Bestel-ID",
  "store/return-app.return-order-list.table-header.creation-date": "Aanmaakdatum",
  "store/return-app.return-order-list.table-header.items-to-return": "Beschikbare items voor retour",
  "store/return-app.return-order-list.table-header.select-order": "Kies bestelling",
  "store/return-app.return-order-list.table-empty-state-label.no-orders-available": "Geen bestellingen beschikbaar om te retouren",
  "store/return-app.return-order-list.table-pagination.text-of": "van",
  "store/return-app.return-order-details.page-header.link": "Terug naar bestellingen",
  "store/return-app.return-order-details.page-header.title": "Retouraanvraagformulier",
  "store/return-app.return-order-details.page-header.subtitle": "Selecteer de producten die u wilt terugbetalen",
  "store/return-app.return-order-details.section-products": "Producten beschikbaar voor retour",
  "store/return-app.return-order-details.section-details": "Contactgegevens",
  "store/return-app.return-order-details.section-details-highlighted-message": "Contact information customizable message",
  "store/return-app.return-order-details.section-payment": "Betaalmethode voor terugbetaling",
  "store/return-app.return-order-details.page-header.creation-date": "Aanmaakdatum",
  "store/return-app.return-order-details.table-header.product": "Artikel",
  "store/return-app.return-order-details.table-header.quantity": "Aantal artikelen",
  "store/return-app.return-order-details.table-header.available-to-return": "Beschikbaar voor retour",
  "store/return-app.return-order-details.table-header.quantity-to-return": "Retourhoeveelheid",
  "store/return-app.return-order-details.table-header.reason": "Reden",
  "store/return-app.return-order-details.table-header.condition": "Voorwaarde",
  "store/return-app.return-order-details.conditions.new-with-box": "Nieuwe met box",
  "store/return-app.return-order-details.conditions.new-without-box": "Nieuwe zonder box",
  "store/return-app.return-order-details.conditions.used-with-box": "Gebruikt met box",
  "store/return-app.return-order-details.conditions.used-without-box": "Gebruikt zonder box",
  "store/return-app.return-order-details.dropdown-conditions.placeholder.select-condition": "Selecteer voorwaarde",
  "store/return-app.return-order-details.dropdown-reasons.accidental-order": "Onbedoelde bestelling",
  "store/return-app.return-order-details.dropdown-reasons.better-price": "Betere prijs",
  "store/return-app.return-order-details.dropdown-reasons.performance": "Prestatie",
  "store/return-app.return-order-details.dropdown-reasons.incompatible": "Incompatibel",
  "store/return-app.return-order-details.dropdown-reasons.item-damaged": "Beschadigd item",
  "store/return-app.return-order-details.dropdown-reasons.missed-delivery": "Gemiste levering",
  "store/return-app.return-order-details.dropdown-reasons.missing-parts": "Ontbrekende onderdelen",
  "store/return-app.return-order-details.dropdown-reasons.box-damaged": "Beschadigde box",
  "store/return-app.return-order-details.dropdown-reasons.different-product": "Ander product",
  "store/return-app.return-order-details.dropdown-reasons.defective": "Beschadigd",
  "store/return-app.return-order-details.dropdown-reasons.arrived-in-addition": "Gearriveerd als extra",
  "store/return-app.return-order-details.dropdown-reasons.no-longer-needed": "Niet langer nodig",
  "store/return-app.return-order-details.dropdown-reasons.unauthorized-purchase": "Onbevoegde aankoop",
  "store/return-app.return-order-details.dropdown-reasons.different-from-website": "Verschillende van website",
  "store/return-app.return-order-details.dropdown-reasons.other-reason": "Andere reden",
  "store/return-app.return-order-details.dropdown-reasons.placeholder.select-reason": "Reden selecteren",
  "store/return-app.return-order-details.error.order-not-invoiced": "De bestelling is niet gefactureerd",
  "store/return-app.return-order-details.error.out-of-max-days": "De bestelling overschrijdt de maximale retourperiode",
  "store/return-app.return-order-details.error.order-not-found": "Bestelling niet gevonden",
  "store/return-app.return-order-details.error.forbidden": "U heeft geen toegang tot deze bestelling",
  "store/return-app.return-order-details.error.unknown": "Er is iets misgegaan. Probeer het opnieuw.",
  "store/return-app.return-order-details.title.contact-details": "Contactgegevens",
  "store/return-app.return-order-details.inputs.name-input": "Naam",
  "store/return-app.return-order-details.inputs.email-input": "E-mail",
  "store/return-app.return-order-details.inputs.phone-input": "Telefoon",
  "store/return-app.return-order-details.title.pickup-address": "Leveringsadres",
  "store/return-app.return-order-details.title.tooltip.pickup-address": "Selecteer het verzendadres dat u wilt voor levering of afhalen",
  "store/return-app.return-order-details.title.extra-comment": "Aanvullende opmerking",
  "store/return-app.return-order-details.inputs.address-input": "Adres",
  "store/return-app.return-order-details.inputs.city-input": "Stad",
  "store/return-app.return-order-details.inputs.state-input": "Staat",
  "store/return-app.return-order-details.inputs.zip-input": "Postcode",
  "store/return-app.return-order-details.inputs.country-input": "Land",
  "store/return-app.return-order-details.setting-provider.error.retry-action": "Opnieuw proberen",
  "store/return-app.return-order-details.setting-provider.error": "Er is een fout opgetreden bij het laden van app-instellingen.",
  "store/return-app.return-order-details.payment-options.card": "Kaart",
  "store/return-app.return-order-details.payment-options.bank": "Bank",
  "store/return-app.return-order-details.payment-options.gift-card": "Geschenkkaart",
  "store/return-app.return-order-details.payment-method.description": "Selecteer de betaalmethode waarnaar de terugbetaling zal worden uitgevoerd",
  "store/return-app.return-order-details.payment-method.default": "De terugbetaling zal worden uitgegeven aan de betaalmethode die voor deze bestelling wordt gebruikt",
  "store/return-app.return-order-details.payment-method.account-holder": "Naam rekeninghouder",
  "store/return-app.return-order-details.payment-method.iban": "IBAN",
  "store/return-app.return-order-details.terms-and-conditions.form-agree": "Ik heb de {link} gelezen en accepteer het",
  "store/return-app.return-order-details.terms-and-conditions.link": "algemene voorwaarden",
  "store/return-app.return-order-details.button.next": "Volgende",
  "store/return-app.return-order-details.page-header.order-id": "Bestel-id",
  "store/return-app.return-item-details.excluded-items.warning": "Winkel laat dit product niet retourneren",
  "store/return-app.return-item-details.dropdown-reason.error": "Reden is vereist",
  "store/return-app.return-item-details.dropdown-condition.error": "Voorwaarde is vereist",
  "store/return-app.return-payment-methods.input-payment-method.error": "Betaalmethode is vereist",
  "store/return-app.return-payment-methods.input-iban.error": "IBAN is vereist",
  "store/return-app.return-payment-methods.input-iban-invalid.error": "IBAN is not valid",
  "store/return-app.return-payment-methods.input-account-holder.error": "Rekeninghouder is vereist",
  "store/return-app.return-terms-and-conditions.checkbox.error": "Algemene voorwaarden dienen te worden geaccepteerd.",
  "store/return-app.return-items-list.no-items-selected.error": "Geen items geselecteerd",
  "store/return-app.return-address-details.address-input.error": "Adres is verplicht",
  "store/return-app.return-address-details.city-input.error": "Stad is verplicht",
  "store/return-app.return-address-details.state-input.error": "Staat is vereist",
  "store/return-app.return-address-details.zip-input.error": "Postcode is vereist",
  "store/return-app.return-address-details.country-input.error": "Land is vereist",
  "store/return-app.return-contact-details.name-input.error": "Naam is vereist",
  "store/return-app.return-contact-details.phone-input.error": "Telefoon is vereist",
  "store/return-app.confirm-and-submit.page-header.title": "Bevestig retourgegevens",
  "store/return-app.confirm-and-submit.refund-method.title": "Betaalmethode voor terugbetaling",
  "store/return-app.confirm-and-submit.alert.label": "Bekijk uw retourlijst",
  "store/return-app.confirm-and-submit.alert.error.label": "Probeer opnieuw",
  "store/return-app.confirm-and-submit.alert.success": "Het retourverzoek is aangemaakt.",
  "store/return-app.confirm-and-submit.alert.error": "Er is iets fout gegaan. Probeer het opnieuw.",
  "store/return-app.confirm-and-submit.button.back": "Terug",
  "store/return-app.confirm-and-submit.button.submit": "Verzend",
  "store/return-app.confirm-and-submit.pickup-address.title": "Leveringsadres",
  "store/return-app.confirm-and-submit.contact-details.title": "Contactgegevens",
  "store/return-app.confirm-and-submit.user-comment.title": "Opmerking",
  "store/return-app.confirm-payment-methods.refund-method.p-account-holder-name": "Naam van de ontvanger: ",
  "store/return-app.confirm-payment-methods.refund-method.p-iban": "Bankoverschrijving naar rekening: ",
  "store/return-app.confirm-payment-methods.refund-method.p-same-as-purchase": "Hetzelfde als de aankoop",
  "store/return-app.return-information-table.table-row.p-condition": "Voorwaarde:",
  "store/return-app.return-information-table.table-row.p-reason": "Reden:",
  "admin/return-app.settings.section.payment-options.available-payment-methods.card": "Kredietkaart",
  "admin/return-app.settings.section.payment-options.available-payment-methods.gift-card": "Cadeaubon",
  "admin/return-app.settings.section.payment-options.available-payment-methods.bank": "Bankoverschrijving",
  "admin/return-app.settings.section.payment-options.available-payment-methods.label": "Alle",
  "admin/return-app.settings.alert.save.success": "Instellingen opgeslagen!",
  "admin/return-app.settings.alert.save.error": "Er is een fout opgetreden bij het opslaan van de instellingen. Probeer het opnieuw.",
  "admin/return-app.return-request-details.page-header.title": "Gegevens retourverzoek",
  "admin/return-app.return-request-details.page-header.link-label": "Lijst retouraanvraag",
  "admin/return-app.return-request-details.error.title": "Fout bij laden van aanvraag",
  "admin/return-app.return-request-details.error.description": "Er is een fout opgetreden tijdens het laden van de aanvraag. Probeer het opnieuw.",
  "admin/return-app.return-request-details.update-status.title": "Status bijwerken of opmerking toevoegen",
  "admin/return-app.return-request-details.update-status.tooltip": "Status wijzigen of opmerking toevoegen. Selecteer de huidige status.",
  "admin/return-app.return-request-details.update-status.dropdown.placeholder": "Selecteer status",
  "admin/return-app.return-request-details.update-status.textarea.label": "Opmerking toevoegen",
  "admin/return-app.return-request-details.update-status.checkbox.label": "Opmerking zichtbaar voor klant",
  "admin/return-app.return-request-details.update-status.button.comment": "Opmerking toevoegen",
  "admin/return-app.return-request-details.update-status.button.update-status": "Status bijwerken",
  "admin/return-app.return-request-details.update-status.alert.success": "Status bijgewerkt",
  "admin/return-app.return-request-details.update-status.alert.error": "Fout bij het bijwerken van de status",
  "store/return-app-status.new": "Nieuw",
  "store/return-app-status.processing": "Verwerken",
  "store/return-app-status.pickedup-from-client": "Afgehaald bij klant",
  "store/return-app-status.pending-verification": "In afwachting van verificatie",
  "store/return-app-status.package-verified": "Pakket geverifieerd",
  "store/return-app-status.refunded": "Terugbetaald",
  "store/return-app-status.denied": "Geweigerd",
  "store/return-app-status.cancelled": "Geannuleerd",
  "admin/return-app.return-request-details.verify-items.button": "items verifiëren",
  "admin/return-app.return-request-details.verify-items.action.confirm": "Status bijwerken",
  "admin/return-app.return-request-details.verify-items.action.cancel": "Annuleren",
  "admin/return-app.return-request-details.verify-items.title": "Items verifiëren",
  "admin/return-app.return-request-details.verify-items.action.approve": "Goedkeuren",
  "admin/return-app.return-request-details.verify-items.action.partially-approve": "Gedeeltelijk goedgekeurd",
  "admin/return-app.return-request-details.verify-items.action.deny": "Ontken",
  "admin/return-app.return-request-details.verify-items.modal.title": "Weet u zeker dat u de status wilt bijwerken?",
  "admin/return-app.return-request-details.verify-items.modal.tooltip": "De aanvraag wordt geweigerd omdat alle items de actie \"Weigeren\" hebben",
  "admin/return-app.return-request-details.verify-items.modal.deny-message": " Deze aanvraag wordt geweigerd",
  "admin/return-app.return-request-details.verify-items.modal.button-verify": "Items verifiëren",
  "admin/return-app.return-request-details.verify-items.modal.button-deny": "Ontken",
  "admin/return-app.return-request-details.verify-items.table.header.product": "Artikel",
  "admin/return-app.return-request-details.verify-items.table.header.price": "Prijs",
  "admin/return-app.return-request-details.verify-items.table.header.tax": "Belasting",
  "admin/return-app.return-request-details.verify-items.table.header.total": "Totaal",
  "admin/return-app.return-request-details.verify-items.table.header.quantity": "Aantal artikelen",
  "admin/return-app.return-request-details.verify-items.table.header.verified": "Geverifiëerd",
  "admin/return-app.return-request-details.verify-items.table.header.restock-fee": "Herbevoorradingskosten",
  "admin/return-app.return-request-details.verify-items.table.header.refund-product-total": "Totaal terugbetalingen",
  "admin/return-app.return-request-details.verify-items.table.header.action": "Actie",
  "admin/return-app.return-request-details.verify-items.table.header.refundable-shipping": "Terugbetaalbare verzending",
  "admin/return-app.return-request-details.verify-items.table.header.shipping-to-refund": "Verzending naar terugbetaling",
  "admin/return-app.return-request-details.verify-items.table.header.total-refund-items": "Totaal aantal producten",
  "admin/return-app.return-request-details.verify-items.table.header.total-refund": "Totaal terugbetalingen",
  "admin/return-app.return-request-details.verify-items.table.title.items": "Items",
  "admin/return-app.return-request-details.verify-items.table.title.totals": "Totaal",
  "store/return-app.return-request-details.table.product-info.ref-id": "Ref ID: {refId}",
  "store/return-app.return-request-details.table.product-info.reason": "Reden: {reason}",
  "store/return-app.return-request-details.table.product-info.sold-by": "Verkocht door: {seller}",
  "store/return-app.return-request-details.table.product-info.condition": "Voorwaarde: {condition}",
  "store/return-app.return-request-details.table.verification-status.denied": "Geweigerd",
  "store/return-app.return-request-details.table.verification-status.cancelled": "Geannuleerd",
  "store/return-app.return-request-details.table.verification-status.approved": "Goedgekeurd",
  "store/return-app.return-request-details.table.verification-status.new": "Nieuw",
  "store/return-app.return-request-details.table.verification-status.partially-approved": "Gedeeltelijk goedgekeurd {quantityRefunded}/{quantity}",
  "store/return-app.return-request-details.table.header.product": "Artikel",
  "store/return-app.return-request-details.table.header.product-info": "Naam",
  "store/return-app.return-request-details.table.header.quantity": "Aantal artikelen",
  "store/return-app.return-request-details.table.header.unit-price": "Prijs per stuk",
  "store/return-app.return-request-details.table.header.tax": "Belasting",
  "store/return-app.return-request-details.table.header.total-price": "Totaalprijs",
  "store/return-app.return-request-details.table.header.verification-status": "Verificatiestatus",
  "store/return-app.return-request-details.request-total.header": "Totaal retouraanvraag",
  "store/return-app.return-request-details.request-total.item-tax": "Item (met BTW)",
  "store/return-app.return-request-details.request-total.shipping": "Verzending",
  "store/return-app.return-request-details.request-total.total": "Totaal",
  "store/return-app.return-request-details.refund-total.header-approved": "Totale terugbetaling goedgekeurd",
  "store/return-app.return-request-details.refund-total.header-refunded": "Totaal terugbetaald",
  "store/return-app.return-request-details.refund-total.item-tax": "Item (met BTW)",
  "store/return-app.return-request-details.refund-total.restock-fee": "Herbevoorradingskosten",
  "store/return-app.return-request-details.refund-total.shipping": "Verzending",
  "store/return-app.return-request-details.refund-total.total": "Totaal",
  "store/return-app.return-request-details.contact-details.title": "Contactgegevens",
  "store/return-app.return-request-details.pickup-address.title": "Leveringsadres",
  "store/return-app.return-request-details.pickup-address.pickup-type": "Type afhaling",
  "store/return-app.return-request-details.pickup-address.pickup-type.pickup-point": "Afhaalpunt",
  "store/return-app.return-request-details.pickup-address.pickup-type.customer-address": "Adres van klant",
  "store/return-app.return-request-details.payent-method.title": "Betaalmethode voor terugbetaling",
  "store/return-app.return-request-details.payent-method.refund-option.refund-method": "Terugbetalingsmethode: {refundMethod}",
  "store/return-app.return-request-details.payent-method.refund-option.gift-card": "Cadeaukaart",
  "store/return-app.return-request-details.payent-method.refund-option.gift-card-code": "Cadeaubon code: {code}",
  "store/return-app.return-request-details.payent-method.refund-option.gift-card-value": "Cadeaubon waarde: {value}",
  "store/return-app.return-request-details.payent-method.refund-option.same-as-purchase": "Hetzelfde als de aankoop",
  "store/return-app.return-request-details.payent-method.refund-option.bank": "Bankoverschrijving",
  "store/return-app.return-request-details.payent-method.refund-option.card": "Kredietkaart",
  "store/return-app.return-request-details.payent-method.refund-option.iban": "IBAN: {iban}",
  "store/return-app.return-request-details.payent-method.refund-option.account-holder": "Rekeninghouder: {accountHolderName}",
  "store/return-app.return-request-details.pickup-address.country": "Land: {country}",
  "store/return-app.return-request-details.pickup-address.locality": "Stad: {city}",
  "store/return-app.return-request-details.pickup-address.state": "Staat: {state}",
  "store/return-app.return-request-details.pickup-address.address": "Adres: {address}",
  "store/return-app.return-request-details.pickup-address.zip": "Postcode: {zipCode}",
  "store/return-app.return-request-details.contact-details.name": "Naam",
  "store/return-app.return-request-details.contact-details.email": "E-mail",
  "store/return-app.return-request-details.contact-details.phone": "Telefoon",
  "admin/return-app.return-request-details.status-timeline.comment": "{ts, date, ::yyyyMMdd} {ts, time, ::HHmmss} - {comment} - ({submittedBy})",
  "store/return-app.return-request-details.status-timeline.comment": "{ts, date, ::yyyyMMdd} {ts, time, ::HHmmss} - {comment}",
  "store/return-app.return-request-details.status-timeline.header": "Status",
  "store/return-app-status.timeline.new": "Retourformulier voltooid op {ts, date, ::yyyyMMdd} {ts, time, ::HHmmss}",
  "store/return-app-status.timeline.processing": "Verwerken",
  "store/return-app-status.timeline.pickedup-from-client": "Afgehaald bij klant",
  "store/return-app-status.timeline.pending-verification": "In afwachting van verificatie",
  "store/return-app-status.timeline.package-verified": "Pakket geverifieerd",
  "store/return-app-status.timeline.refunded": "Terugbetaald",
  "store/return-app-status.timeline.denied": "Geweigerd",
  "store/return-app-status.timeline.cancelled": "Geannuleerd",
  "admin/return-app.return-request-list.page-header.title": "Return Requests List",
  "admin/return-app.return-request-list.page-header.subTitle": "All return requests created by the store users. Click on a Request ID to see more.",
  "store/return-app.return-request-list.error.title": "Fout bij laden lijst",
  "store/return-app.return-request-list.error.description": "Er is een fout opgetreden tijdens het laden van de aanvraaglijst. Probeer het opnieuw.",
  "store/return-app.return-request-list.table.emptyState": "Geen resultaten beschikbaar",
  "store/return-app.return-request-list.table.emptyState-children": "Probeer verschillende filters voor uw zoekopdracht",
  "store/return-app.return-request-list.table-pagination.textOf": "van",
  "store/return-app.return-request-list.table-data.requestId": "Aanvraag-ID",
  "store/return-app.return-request-list.table-data.sequenceNumber": "Volgnummer",
  "store/return-app.return-request-list.table-data.orderId": "Bestel-id",
  "store/return-app.return-request-list.table-data.createdDate": "Gemaakte datum",
  "store/return-app.return-request-list.table-data.status": "Status",
  "store/return-app.return-request-list.table-filters.fromDate": "Vanaf datum",
  "store/return-app.return-request-list.table-filters.toDate": "Tot datum",
  "store/return-app.return-request-list.table-filters.apply-filters": "TOEPASSEN",
  "store/return-app.return-request-list.table-filters.clear-filters": "WISSEN",
  "store/return-app.return-request-list.table-jumpToPage.pageText": "Pagina",
  "store/return-app.return-request-list.table-jumpToPage.cta": "GA",
  "store/return-app.return-request-list.page-header.title": "Mijn retourzendingen",
  "store/return-app.return-request-list.page-header.goBack": "Ga terug",
  "store/return-app.return-request-list.page-header.cta": "Nieuwe aanvraag",
  "store/return-app.return-request-list.table.status.new": "Nieuw",
  "store/return-app.return-request-list.table.status.processing": "Verwerken",
  "store/return-app.return-request-list.table.status.pickedup-from-client": "Afgehaald bij klant",
  "store/return-app.return-request-list.table.status.pending-verification": "In afwachting van verificatie",
  "store/return-app.return-request-list.table.status.package-verified": "Pakket geverifieerd",
  "store/return-app.return-request-list.table.status.refunded": "Terugbetaald",
  "store/return-app.return-request-list.table.status.denied": "Geweigerd",
  "store/return-app.return-request-list.table.status.cancelled": "Geannuleerd",
  "store/return-app.return-request-list.table.status.allStatus": "Status",
  "store/return-app.return-request-details.table.status-history.header.created-at": "Gemaakt op",
  "store/return-app.return-request-list.table.view": "Visualisatie",
  "store/return-app.return-request-details.table.status-history.header.status": "Status",
  "store/return-app.return-request-details.table.status-history.header.submitted-by": "Ingezonden door",
  "store/return-app.return-request-details.status-history.title": "Statusgeschiedenis",
  "store/return-app.return-request-details.page-header.title": "Gegevens retourverzoek",
  "store/return-app.return-request-details.page-header.link-label": "Lijst retouraanvraag",
  "store/return-app.return-request-details.order-id.link": "Bestelling {orderId}\"",
  "store/return-app.return-request-details.current-status.request-id": "Aanvraag-ID: {id}",
  "store/return-app.return-request-details.current-status.status": "Status:",
  "admin/return-app.return-request-list.table-data.requestId.tooltip": "Klanten kunnen hun aanvraag-ID zien in de aanvraaggegevens",
  "admin/return-app.settings.modal-warning.title": "Controleer uw instellingen",
  "admin/return-app.settings.modal-warning.first-paragraph": "Het lijkt erop dat u probeert de aangepaste retouropties op te slaan, waarvan er geen alle {maxDays} bereiken. Dit is het maximum aantal dagen voor een retouraanvraag.",
  "admin/return-app.settings.modal-warning.second-paragraph": "Een winkelgebruiker kan mogelijk de stroom starten om een retourzending te maken, maar kan niet doorgaan als de besteldatum buiten een van uw aangepaste opties valt.",
  "admin/return-app.settings.modal-warning.third-paragraph": "Als u op Bewerken klikt, wordt het maximum aantal dagen voor een retour teruggebracht van {maxDays} tot {customMaxDays}. Dit zijn de maximale dagen die worden weergegeven in uw aangepaste retouropties.",
  "admin/return-app.settings.modal-warning.confirm": "Bewerken",
  "admin/return-app.settings.modal-warning.cancel": "Annuleren",
  "store/return-app.return-order-details.pickup-address.drop-off-points": "Selecteer een afleverpunt",
  "store/return-app.return-order-details.pickup-address.drop-off-points.tooltip": "U kunt je items retourneren in een van onze geselecteerde afhaalpunten",
  "store/return-app.return-order-details.pickup-address.drop-off-points.dropdown.placehoder": "Selecteer een afleverpunt",
  "store/return-app.return-order-details.pickup-address.drop-off-points.dropdown.error": "Er is een fout opgetreden bij het laden van de afhaalpunten",
  "admin/return-app.return-request-details.localized-product-name.tooltip": "Oorspronkelijke item naam van de bestelling",
  "admin/return-app.settings.section.payment-options.refund-method-strategy.checkbox.label": "Automatisch aanvragen terugbetalen",
  "admin/return-app.settings.section.payment-options.refund-method-strategy.checkbox.description": "Automatisch de retourfactuur aanmaken in de OMS voor de aanvragen",
  "store/return-app.return-request-details.payent-method.refund-option.refund-process": "Terugbetalingsproces: {automaticallyRefundPaymentMethod, select, true{Automatisch} false{Handmatig}}",
  "store/return-app.return-request-details.cancellation.cta": "Annuleer verzoek",
  "store/return-app.return-request-details.cancellation.modal.accept": "Ga verder met annuleren",
  "store/return-app.return-request-details.cancellation.modal.close": "Close",
  "store/return-app.return-request-details.cancellation.modal.adminAllow": "
Let op: De status van dit verzoek wordt ingesteld op GEANNULEERD.

Dit stelt de gebruiker via e-mail op de hoogte en stelt hem in staat een nieuwe retouraanvraag te maken met de items van het geannuleerde verzoek.

Als dat niet uw bedoeling is, stel het verzoek dan in als GEWEIGERD.
",
  "store/return-app.return-request-details.cancellation.modal.adminRefuse": "
Sorry, het is niet mogelijk om dit verzoek te annuleren vanwege de huidige status.
",
  "store/return-app.return-request-details.cancellation.modal.storeAllow": "
Als u dit verzoek annuleert, kunnen de huidige items worden gebruikt in een nieuwe retouraanvraag.

Deze actie is onomkeerbaar.
",
  "store/return-app.return-request-details.cancellation.modal.storeRefuse": "
Sorry, u moet contact opnemen met het ondersteuningsteam om dit verzoek te annuleren vanwege de huidige status.
"
}

```