npm package: @nacelle/nacelle-wishlist-nuxt-module
Description: Integrates Wishlist into your Nacelle Nuxt project
Latest version: 0.0.6

# nacelle-wishlist-nuxt-module

Adds Vue.js components for integrating [Wishlist](https://github.com/getnacelle/nacelle-wishlist-graphql) - customer shopping lists in your [Nacelle](https://getnacelle.com/) Nuxt project.

## Requirements

* A Nacelle project set up locally. See https://docs.getnacelle.com for getting started.

## Setup

### Add Module to Nacelle

Once you have Nacelle set up you can install this module in your project from `npm`:

```
npm install @nacelle/nacelle-wishlist-nuxt-module --save
```

After the package has installed, open `nuxt.config.js`. Under `modules` add `@nacelle/nacelle-wishlist-nuxt-module` to the array. It should look something like this:

```
modules: [
  '@nuxtjs/pwa',
  '@nuxtjs/dotenv',
  '@nacelle/nacelle-nuxt-module',
  '@nuxtjs/sitemap',
  '@nacelle/nacelle-wishlist-nuxt-module'
],
```

### Add the components to your Nacelle Storefront

There are two components you can add to your Nacelle site: `<add-to-wishlist />`, `<main-nav-wishlist />`.

**AddToWishlist**

This component is meant to appear on Product Cards and allows for an svg element to be slotted under the **icon** namespace.

We need to pass the **variant** and **product** objects as props.

```js
  <add-to-wishlist
    class="circle-button is-primary"
    :variant="currentVariant"
    :product="product"
  >
    <template v-slot:icon>
      <svg width="120%" height="100%" viewBox="-42 0 592 469" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
        <path d="M471.383,55.578c-26.504,-28.746 -62.871,-44.578 -102.41,-44.578c-29.555,0 -56.621,9.344 -80.45,27.77c-12.023,9.3 -22.918,20.679 -32.523,33.96c-9.602,-13.277 -20.5,-24.66 -32.527,-33.96c-23.825,-18.426 -50.891,-27.77 -80.446,-27.77c-39.539,0 -75.91,15.832 -102.414,44.578c-26.187,28.41 -40.613,67.223 -40.613,109.293c0,43.301 16.137,82.938 50.781,124.742c30.992,37.395 75.535,75.356 127.117,119.313c17.614,15.012 37.579,32.027 58.309,50.152c5.477,4.797 12.504,7.438 19.793,7.438c7.285,0 14.316,-2.641 19.785,-7.43c20.731,-18.129 40.707,-35.152 58.328,-50.172c51.574,-43.949 96.117,-81.906 127.11,-119.305c34.644,-41.8 50.777,-81.437 50.777,-124.742c0,-42.066 -14.426,-80.879 -40.617,-109.289Z" style="fill-rule:nonzero;"/>
      </svg>
    </template>
  </add-to-wishlist>
```

**MainNavWishlist**

This component is meant to appear in the Global Header and allows for an svg element to be slotted under the **icon** namespace.

The **path** prop defaults to `'/wishlist'`, but a custom path to wishlist can be added.

```js
  <main-nav-wishlist
    path="/wishlist"
  >
    <template v-slot:icon>
      <svg class="icon" width="100%" height="100%" viewBox="0 0 512 469" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
        <path d="M471.383,55.578c-26.504,-28.746 -62.871,-44.578 -102.41,-44.578c-29.555,0 -56.621,9.344 -80.45,27.77c-12.023,9.3 -22.918,20.679 -32.523,33.96c-9.602,-13.277 -20.5,-24.66 -32.527,-33.96c-23.825,-18.426 -50.891,-27.77 -80.446,-27.77c-39.539,0 -75.91,15.832 -102.414,44.578c-26.187,28.41 -40.613,67.223 -40.613,109.293c0,43.301 16.137,82.938 50.781,124.742c30.992,37.395 75.535,75.356 127.117,119.313c17.614,15.012 37.579,32.027 58.309,50.152c5.477,4.797 12.504,7.438 19.793,7.438c7.285,0 14.316,-2.641 19.785,-7.43c20.731,-18.129 40.707,-35.152 58.328,-50.172c51.574,-43.949 96.117,-81.906 127.11,-119.305c34.644,-41.8 50.777,-81.437 50.777,-124.742c0,-42.066 -14.426,-80.879 -40.617,-109.289Z" style="fill-rule:nonzero;"/>
      </svg>
    </template>
  </main-nav-wishlist>
```
### Load wishlist

Once the module is installed we have access to the `wishlist` store's actions, which can be dispatched across the application.

**getWishlists**
`dispatch('wishlist/getWishlists', null, { root: true })`
* Will need to be manually implemented

**addToWishlist**
`dispatch('wishlist/addToWishlist', null, { root: true })`
* implemented by <add-to-wishlist /> component

**removeFromWishlist**
`dispatch('wishlist/removeFromWishlist', null, { root: true })`
* implemented by <add-to-wishlist /> component

**resetWishlist**
`dispatch('wishlist/resetWishlist', null, { root: true })`
* Will need to be manually implemented


### Load Anonymous Customer's wishlist from Browser Storage

We utilize the `localforage` package, just like for our cart, to persist wishlists for those who are not logged in. To implement this feature we need to dispatch a wishlist action when we check for a customer's logged in state. This could vary across builds, but here is a basic example:

```js
// The readCustomerAccessToken action is dispatched on the 'created' hook on our default layout
// Thus, it runs on page load.
async readCustomerAccessToken ({ dispatch, commit }, { accessToken }) {
  if (accessToken) { 
    commit('setCustomerAccessToken', { accessToken, expiresAt: null })
    await dispatch('renewCustomerAccessToken', accessToken)
  } else {
    // Get wishlist for anonymous customers
    dispatch('wishlist/getWishlists', null, { root: true })
  }
},
```

### Load Logged-in Customer's wishlist from Nacelle Wishlist Service

If the customer is logged in, we can pull their wishlist data from our service and load it into memory. We run a merge on variant id, if there is anonymous data already present. This action is dependent on `customer` data being present in the `account` store. Here is how we can implement this feature whenever we fetchCustomer data (ie. login, page load):

```js
// The fetchCustomer action is dispatched on Customer login, and on page load if customerAccessToken is present.
async fetchCustomer ({ state, commit, dispatch }) {
  try {
    const variables = { customerAccessToken: state.customerAccessToken.accessToken }
    const query = GET_CUSTOMER
    const response = await accountClient.post(null, { query, variables })
    const { customer, userErrors } = response.data.data
    if (customer) {
      commit('setCustomer', customer)
      // Get wishlist for logged in customers
      dispatch('wishlist/getWishlists', null, { root: true })
    }
    commit('setErrors', userErrors)
  } catch (error) {
    throw error
  }
},
```

### Reset wishlist on Logout

We probably want to reset the wishlist when a customer logs out:

```js
async logout ({ state, dispatch, commit, rootState }) {
  const accessToken = (state.customerAccessToken && state.customerAccessToken.accessToken) || getCookie('customerAccessToken')
  const variables = { customerAccessToken: accessToken }
  const query = CUSTOMER_ACCESS_TOKEN_DELETE
  const response = await accountClient.post(null, { query, variables })
  const { deletedAccessToken, deletedCustomerAccessTokenId, userErrors } = response.data.data.customerAccessTokenDelete
  if (deletedAccessToken) {
    dispatch('removeCustomerAccessToken')
    // Reset Wishlist 
    dispatch('wishlist/resetWishlist', null, { root: true })
  }
  commit('setErrors', userErrors)
},
```