<|start_filename|>_/Chapter09/js/app.js<|end_filename|>
Vue.use(ShopifyProducts);

const store = new Vuex.Store({
	state: {
		products: {},
		categories: {},

		categoryHome: {
			title: 'Welcome to the Shop',
			handle: 'home',
			products: [
				'adjustable-stem',
				'fizik-saddle-pak',
				'kenda-tube',
				'colorful-fixie-lima',
				'oury-grip-set',
				'pure-fix-pedals-with-cages'
			]
		}
	},

	mutations: {
		products(state, payload) {
			let products = {};

			Object.keys(payload).forEach(key => {
				let product = payload[key];

				let prices = [];
				for(let variation of product.variationProducts) {
					if(!prices.includes(variation.price)) {
						prices.push(variation.price);
					}
				}

				product.price = Math.min(...prices);
				product.hasManyPrices = prices.length > 1;

				products[key] = product;
			});

			state.products = products;
		}
	}
});


const router = new VueRouter({
	routes: [
		{
			path: '/product/:slug',
			name: 'Product',
			component: ProductPage
		},

		{
			path: '/404',
			alias: '*',
			component: PageNotFound
		}
	]
});

new Vue({
	el: '#app',

	store,
	router,

	created() {
		CSV.fetch({url: './data/csv-files/bicycles.csv'}).then(data => {
			this.$store.commit('products', this.$formatProducts(data));
		});
	}
});

<|start_filename|>_/Chapter11/js/views/OrderConfirmation.js<|end_filename|>
const OrderConfirmation = {
  name: 'OrderConfirmation',

  template: `<div>
    <h1>Order Complete!</h1>
    <p>Thanks for shopping with us - you can expect your products within 2 - 3 working days</p>
    <list-purchases />
  </div>`,

  components: {
    ListPurchases
  }
};

<|start_filename|>_/Chapter11/js/views/ProductPage.js<|end_filename|>
const ProductPage = {
  name: 'ProductPage',

  template: `<div>
    <div v-if="product">
      <div class="images" v-if="image">
        <div class="main">
          <img 
            :src="image.source" 
            :alt="image.alt || product.title">
        </div>

        <div class="thumbnails" v-if="product.images.length > 1">
          <template v-for="img in product.images">
            <img 
              :src="img.source" 
              :alt="img.alt || product.title" 
              width="100" 
              @click="updateImage(img)">
          </template>
        </div>
      </div> 

      <h1>{{ product.title }} - \${{ variation.price }}</h1>

      <div class="meta">
        <span v-if="product.vendor">
          Manufacturer: <strong>{{ product.vendor.title }}</strong>
        </span>
        <span v-if="product.type">
          Category: <strong>{{ product.type.title }}</strong>
        </span>
        <span>
          Quantity: <strong>{{ variation.quantity }}</strong>
        </span>
      </div>

      <div class="variations">
        <select v-model="variation" v-if="product.variationProducts.length > 1">
          <option 
            v-for="variation in product.variationProducts" 
            :key="variation.barcode" 
            :value="variation"
            v-html="variantTitle(variation) + ((!variation.quantity) ? ' - out of stock' : '')"
          ></option>
        </select>

        <button 
          @click="addToBasket()" 
          :class="(addedToBasket) ? 'isAdded' : ''" 
          :disabled="!variation.quantity"
        >
          {{ 
            (variation.quantity) ? 
            ((addedToBasket) ? 'Added to your basket' : 'Add to basket') : 
            'Out of stock'
          }}
        </button>
      </div>

      <div v-html="product.body"></div>

    </div>
    <page-not-found v-if="productNotFound"></page-not-found>
  </div>`,

  components: {
    PageNotFound
  },
  
  data() {
    return {
      slug: this.$route.params.slug,
      productNotFound: false,
      image: false,
      variation: false,
      addedToBasket: false
    }
  },

  computed: {
    product() {
      let product;

      if(Object.keys(this.$store.state.products).length) {

        product = this.$store.state.products[this.slug];

        this.image = (product.images.length) ? product.images[0] : false;
        this.variation = product.variationProducts[0];

        if(!product) {
          this.productNotFound = true;
        }
      }

      return product;
    }
  },

  watch: {
    variation(v) {
      if(v.hasOwnProperty('image')) {
        this.updateImage(v.image);
      }
      
      this.addedToBasket = false;
    },

    '$route'(to) {
      this.slug = to.params.slug;
      this.addedToBasket = false;
    }
  },

  methods: {
    updateImage(img) {
      this.image = img;
    },

    variantTitle(variation) {
      let variants = variation.variant,
        output = [];

      for(let a in variants) {
        output.push(`${variants[a].name}: ${variants[a].value}`);
      }

      return output.join(' / ');
    },

    addToBasket() {
      this.$store.commit('addToBasket', this);

      this.addedToBasket = true;
      setTimeout(() => this.addedToBasket = false, 2000);
    }
  }
};

<|start_filename|>_/Chapter11/js/components/ProductFiltering.js<|end_filename|>
const ProductFiltering = {
  name: 'ProductFiltering',

  template: `<div>
    <div class="filters">
      <div class="filterGroup" v-for="filter in filters">
        <h3>{{ filter.title }}</h3>

        <label class="filter" v-for="value in filter.values">
          <input type="checkbox" :value="value.handle" v-model="filter.checked" @click="updateFilters">
          {{ value.title }} ({{ value.count.length }})
        </label>
      </div> 
    </div>

    <list-categories />
  </div>`,

  components: {
    ListCategories
  },

  props: {
    slug: String
  },

  data() {
    return {
      topics: this.defaultTopics()
    }
  },

  computed: {
    ...Vuex.mapGetters([
      'categoriesExist',
      'categoryProducts'
    ]),

    filters() {
      if(this.categoriesExist) {

        let category = this.categoryProducts(this.slug);

        for(let product of category.productDetails) {

          if(product.hasOwnProperty('vendor')) {
            this.addTopic(this.topics.vendor, product.vendor, product.handle);
          }

          if(product.hasOwnProperty('tags')) {
            for(let tag of product.tags) {
              this.addTopic(this.topics.tags, tag, product.handle);
            }
          }

          Object.keys(product.variationTypes).forEach(vkey => {
            let variation = product.variationTypes[vkey];

            if(variation.handle == 'title') {
              return;
            }

            if(!this.topics.hasOwnProperty(variation.handle)) {
              this.topics[variation.handle] = {
                ...variation,
                checked: [],
                values: {}
              }
            }

            Object.keys(product.variationProducts).forEach(pkey => {
              let variationProduct = product.variationProducts[pkey];
              this.addTopic(
                this.topics[variation.handle],
                variationProduct.variant[variation.handle],
                product.handle
              );
            });

          });

        }

        Object.keys(this.$route.query).forEach(key => {
          if(Object.keys(this.topics).includes(key)) {
            let query = this.$route.query[key];
            this.topics[key].checked = Array.isArray(query) ? query : [query];
          }
        });
      }


      return this.topics;
    }
  },

  watch: {
    slug() {
      this.topics = this.defaultTopics();
    }
  },

  methods: {
    defaultTopics() {
      return {
        vendor: {
          title: 'Manufacturer',
          handle: 'vendor',
          checked: [],
          values: {}
        },
        tags: {
          title: 'Tags',
          handle: 'tags',
          checked: [],
          values: {}
        }
      }
    },

    addTopic(category, item, handle) {
      if(item.handle) {

        if(category.values[item.handle]) {
          if(!category.values[item.handle].count.includes(handle)) {
            category.values[item.handle].count.push(handle);
          }

        } else {

          if(item.hasOwnProperty('value')) {
            item.title = item.value;
          }

          category.values[item.handle] = {
            ...item,
            count: [handle]
          }
        }
      }
    },

    updateFilters() {
      let filters = {};

      Object.keys(this.topics).forEach(key => {
        let topic = this.topics[key];
        if(topic.checked.length) {
          filters[key] = topic.checked;
        }
      });

      this.$router.push({query: filters});
    }
  }
}

<|start_filename|>_/Chapter11/js/views/OrderBasket.js<|end_filename|>
const OrderBasket = {
  name: 'OrderBasket',

  template: `<div>
    <h1>Basket</h1>
    <list-purchases :editable="true" />
    <router-link :to="{name: 'Checkout'}">Proceed to Checkout</router-link>
  </div>`,

  components: {
    ListPurchases
  }
};

<|start_filename|>_/Chapter11/js/app.js<|end_filename|>
Vue.use(ShopifyProducts);

const store = new Vuex.Store({
  state: {
    products: {},
    categories: {},

    categoryHome: {
      title: 'Welcome to the Shop',
      handle: 'home',
      products: [
        'adjustable-stem',
        'fizik-saddle-pak',
        'kenda-tube',
        'colorful-fixie-lima',
        'oury-grip-set',
        'pure-fix-pedals-with-cages'
      ]
    },

    basket: []


  },

  mutations: {
    products(state, payload) {
      let products = {};

      Object.keys(payload).forEach(key => {
        let product = payload[key];

        let prices = [];
        for(let variation of product.variationProducts) {
          if(!prices.includes(variation.price)) {
            prices.push(variation.price);
          }
        }

        product.price = Math.min(...prices);
        product.hasManyPrices = prices.length > 1;

        products[key] = product;
      });

      state.products = products;
    },

    categories(state, payload) {
      let categories = {},
        other = {
          title: 'Other',
          handle: 'other'
        };

      Object.keys(payload).forEach(key => {
        let product = payload[key],
          type = product.hasOwnProperty('type') ? product.type : other;

        if(!categories.hasOwnProperty(type.handle)) {
          categories[type.handle] = {
            title: type.title,
            handle: type.handle,
            products: []
          }
        }

        categories[type.handle].products.push(product.handle);
      });

      Object.keys(categories).forEach(key => {
        let category = categories[key];

        if(category.products.length < 3) {
          categories.other.products = categories.other.products.concat(category.products);
          delete categories[key];
        }
      });

      let categoriesSorted = {}
      Object.keys(categories).sort().forEach(key => {
          categoriesSorted[key] = categories[key]
      });
      state.categories = categories;
    },

    addToBasket(state, item) {
      let product = state.basket.find(p => {
        if(p.sku == item.variation.sku) {
          p.quantity++;

          return p;
        }
      });

      if(!product) {
        state.basket.push({
          sku: item.variation.sku,
          title: item.product.title,
          handle: item.slug,
          image: item.image,
          variationTitle: item.variantTitle(item.variation),
          variation: item.variation,
          quantity: 1
        });
      }
    },

    updatePurchases(state, payload) {
      state.basket = payload;
    }
  },

  actions: {
    initialiseShop({commit}, products) {
      commit('products', products);
      commit('categories', products);
    }
  },

  getters: {
    categoriesExist: (state) => {
      return Object.keys(state.categories).length;
    },

    categoryProducts: (state, getters) => (slug) => {
      if(getters.categoriesExist) {
        let category = false,
          products = [];

        if(slug) {
          category = state.categories[slug];
        } else {
          category = state.categoryHome;
        }

        if(category) {
          for(let featured of category.products) {
            products.push(state.products[featured]);
          }

          category.productDetails = products;
        }
        return category;
      }
    },

    cartQuantity: (state) => {
      let quantity = 0;
      for(let item of state.basket) {
        quantity += item.quantity;
      }
      return quantity;
    }
  }
});


const router = new VueRouter({
  routes: [
    {
      path: '/',
      name: 'Home',
      components: {
        default: CategoryPage,
        sidebar: ListCategories
      },
      props: {
        default: true,
        sidebar: true
      }
    },
    {
      path: '/category',
      redirect: {name: 'Home'}
    },
    {
      path: '/category/:slug',
      name: 'Category',
      components: {
        default: CategoryPage,
        sidebar: ProductFiltering
      },
      props: {
        default: true,
        sidebar: true
      }
    },
    {
      path: '/product',
      redirect: {name: 'Home'}
    },
    {
      path: '/product/:slug',
      name: 'Product',
      component: ProductPage
    },
    {
      path: '/basket',
      name: 'Basket',
      component: OrderBasket
    },
    {
      path: '/checkout',
      name: 'Checkout',
      component: OrderCheckout
    },
    {
      path: '/complete',
      name: 'Confirmation',
      component: OrderConfirmation
    },

    {
      path: '/404',
      alias: '*',
      component: PageNotFound
    }
  ]
});

new Vue({
  el: '#app',

  store,
  router,

  computed: {
    cartQuantity() {
      let quantity = this.$store.getters.cartQuantity;
      return quantity ? '(' + quantity + ')' : '';
    }
  },

  created() {
    CSV.fetch({url: './data/csv-files/bicycles.csv'}).then(data => {
      this.$store.dispatch('initialiseShop', this.$formatProducts(data));
    });
  }
});

<|start_filename|>_/Chapter11/js/components/ListPurchases.js<|end_filename|>
const ListPurchases = {
  name: 'ListPurchases',

  template: `<table>
    <thead>
      <tr>
        <th></th>
        <th>Title</th>
        <th>Unit price</th>
        <th>Quantity</th>
        <th>Price</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="product in products">
        <td>
          <img 
            :src="product.image.source" 
            :alt="product.image.alt || product.variationTitle"
            width="80"
          >
        </td>
        <td>
          <router-link :to="{name: 'Product', params: {slug: product.handle}}">
            {{ product.title }}
          </router-link><br>
          {{ product.variationTitle }}
        </td>
        <td>{{ product.variation.price | currency }}</td>
        <td v-if="!editable">{{ product.quantity }}</td>
        <td v-if="editable"><input 
          type="text"
          :value="product.quantity" 
          @blur="updateQuantity($event, product.sku)"
        ></td>
        <td>{{ product.variation.price * product.quantity | currency }}</td>
        <td v-if="editable">
          <button @click="removeItem(product.sku)">Remove item</button>
        </td>
      </tr>
    </tbody>
    <tfoot>
      <td colspan="4" align="right">
        <strong>Total:</strong>
      </td>
      <td>{{ totalPrice | currency }}</td>
    </tfoot>
  </table>`,

  filters: {
    currency(val) {
      return '$' + val.toFixed(2);
    }
  },

  props: {
    editable: {
      type: Boolean,
      default: false
    }
  },

  computed: {
    products() {
      return this.$store.state.basket;
    },

    totalPrice() {
      let total = 0;

      for(let p of this.products) {
        total += (p.variation.price * p.quantity);
      }

      return total;
    }
  },

  methods: {
    updateQuantity(e, sku) {
      if(!parseInt(e.target.value)) {
        this.removeItem(sku);
      } else {
        let products = this.products.map(p => {
          if(p.sku == sku) {
            p.quantity = parseInt(e.target.value);
          }
          return p;
        });

        this.$store.commit('updatePurchases', products);
      }
    },

    removeItem(sku) {
      let products = this.products.filter(p => {
        if(p.sku != sku) {
          return p;
        }
      });

      this.$store.commit('updatePurchases', products);
    }
  }
};

<|start_filename|>_/Chapter11/js/views/CategoryPage.js<|end_filename|>
const CategoryPage = {
  name: 'CategoryPage',

  template: `<div>
    <div v-if="category">
      <h1>{{ category.title }}</h1>
      <list-products :products="category.productDetails"></list-products>
    </div>
    <page-not-found v-if="categoryNotFound"></page-not-found>
  </div>`,

  components: {
    PageNotFound
  },

  props: {
    slug: String
  },
  
  data() {
    return {
      categoryNotFound: false
    }
  },

  computed: {
    ...Vuex.mapGetters([
      'categoriesExist',
      'categoryProducts'
    ]),

    category() {
      if(this.categoriesExist) {
        let category = this.categoryProducts(this.slug),
          filters = Object.assign({}, this.$route.query);

        if(Object.keys(filters).length && filters.hasProperty('page')) {
          delete filters.page;
        }    

        if(Object.keys(filters).length) {
          category.productDetails = category.productDetails.filter(
            p => this.filtering(p, filters)
          );
        }

        if(!category) {
          this.categoryNotFound = true;
        }
        return category;
      }
    }
  },

  methods: {
    filtering(product, query) {
      let display = false,
        hasProperty = {};

        Object.keys(query).forEach(key => {
          let filter = Array.isArray(query[key]) ? query[key] : [query[key]];

          for(attribute of filter) {
            if(key == 'vendor') {

              hasProperty.vendor = false;
              if(product.vendor.handle == attribute) {
                hasProperty.vendor = true;
              }

            } else  if(key == 'tags') {
              hasProperty.tags = false;

              product[key].map(key => {
                if(key.handle == attribute) {
                  hasProperty.tags = true;
                }
              });

            } else {
              hasProperty[key] = false;

              let variant = product.variationProducts.map(v => {
                if(v.variant[key] && v.variant[key].handle == attribute) {
                  hasProperty[key] = true;
                }
              });
            }
          }

          if(Object.keys(hasProperty).every(key => hasProperty[key])) {
            display = true;
          }

        });

      return display;
    }
  }
};

<|start_filename|>_/Chapter11/js/views/PageNotFound.js<|end_filename|>
const PageNotFound = {
  name: 'PageNotFound',
  template: `<div>
    <h1>404 Page Not Found</h1>
    <p>Head back to the <router-link to="/">home page</router-link> and start again.</p>
  </div>`
};

<|start_filename|>_/Chapter11/js/components/ListProducts.js<|end_filename|>
Vue.component('list-products', {
  template: `<div v-if="products">
    <p v-if="pagination.totalPages > 1">
      Page {{ currentPage }} out of {{ pagination.totalPages }}
    </p>

    <div v-if="pagination.totalProducts > 12">
      Products per page: 
      <select v-model="perPage">
        <option>12</option>
        <option>24</option>
        <option v-if="pagination.totalProducts > 24">48</option>
        <option v-if="pagination.totalProducts > 48">60</option>
      </select>
    </div>

    <button 
      @click="toPage(currentPage - 1)" 
      :disabled="currentPage == 1" 
      v-if="pagination.totalPages > 1"
    >
      Previous page
    </button>
    <button 
      @click="toPage(currentPage + 1)" 
      :disabled="currentPage == pagination.totalPages" 
      v-if="pagination.totalPages > 1"
    >
      Next page
    </button>

    <div class="ordering">
      <select v-model="ordering">
        <option value="">Order products</option>
        <option value="title-asc">Title - ascending (A - Z)</option>
        <option value="title-desc">Title - descending (Z - A)</option>
        <option value="price-asc">Price - ascending ($1 - $999)</option>
        <option value="price-desc">Price - descending ($999 - $1)</option>
      </select>
    </div>

    <ol :start="pagination.range.from + 1">
      <li v-for="product in paginate()" :key="product.handle">
        <router-link :to="{name: 'Product', params: {slug: product.handle}}">
          <img v-if="product.images[0]" :src="product.images[0].source" :alt="product.title" width="120">
        </router-link>
        <h3>
          <router-link :to="{name: 'Product', params: {slug: product.handle}}">
            {{ product.title }}
          </router-link>
        </h3>
        <p>Made by: {{ product.vendor.title }}</p>
        <p>Price {{ productPrice(product) }}</p>
      </li>
    </ol>

    <nav v-if="pagination.totalPages > pageLinksCount">
      <ul>
        <li v-for="page in pageLinks">
          <button @click="toPage(page)">{{ page }}</button>
        </li>
      </ul>
    </nav>
  </div>`,

  props: {
    products: Array
  },

  data() {
    return {
      perPage: 12, 
      currentPage: 1,
      pageLinksCount: 3,

      ordering: ''
    }
  },

  computed: {
    pagination() {
      if(this.products) {
        let totalProducts = this.products.length,
          pageFrom = (this.currentPage * this.perPage) - this.perPage,
          totalPages = Math.ceil(totalProducts / this.perPage);

        return {
          totalProducts: totalProducts,
          totalPages: Math.ceil(totalProducts / this.perPage),
          range: {
            from: pageFrom,
            to: pageFrom + this.perPage
          }
        }
      }
    },

    pageLinks() {
      if(this.products.length) {
        let negativePoint = this.currentPage - this.pageLinksCount,
          positivePoint = this.currentPage + this.pageLinksCount,
          pages = [];


        if(negativePoint < 1) {
          negativePoint = 1;
        }

        if(positivePoint > this.pagination.totalPages) {
          positivePoint = this.pagination.totalPages;
        }

        for (var i = negativePoint; i <= positivePoint; i++) {
          pages.push(i)
        }

        return pages;
      }
    },

    orderProducts() {
      let output;

      if(this.ordering.length) {
        let orders = this.ordering.split('-');
        output = this.products.sort(function(a, b) {
          if(typeof a[orders[0]] == 'string') {
            return a[orders[0]].localeCompare(b[orders[0]]);
          } else {
            return a[orders[0]] - b[orders[0]];
          }
        });

        if(orders[1] == 'desc') {
          output.reverse();
        }
      } else {
        output = this.products;
      }
      return output;
    }
  },

  watch: {
    '$route'(to) {
      this.currentPage = parseInt(to.query.page) || 1;
    },

    perPage() {
      if(this.currentPage > this.pagination.totalPages) {
        this.$router.push({
          query: Object.assign({}, this.$route.query, {
            page: this.pagination.totalPages
          })
        })
      }
    }
  },

  created() {
    if(this.$route.query.page) {
      this.currentPage = parseInt(this.$route.query.page);
    }
  },

  methods: {
    toPage(page) {
      this.$router.push({
        query: Object.assign({}, this.$route.query, {
          page
        })
      });
      this.currentPage = page;
    },

    paginate() {
      return this.orderProducts.slice(
        this.pagination.range.from, 
        this.pagination.range.to
      );
    },

    productPrice(product) {
      let price = '$' + product.price;

      if(product.hasManyPrices) {
        price = 'From: ' + price;
      }

      return price;
    }
  }
});

<|start_filename|>_/Chapter11/js/components/ListCategories.js<|end_filename|>
const ListCategories = {
  name: 'ListCategories',

  template: `<div v-if="categories">
    <ul>
      <li v-for="category in categories">
        <router-link :to="{name: 'Category', params: {slug: category.handle}}">
          {{ category.title }} ({{ category.products.length }})
        </router-link>
      </li>
    </ul>
  </div>`,

  computed: {
    categories() {
      return this.$store.state.categories;
    }
  }  
};

<|start_filename|>_/Chapter11/js/views/HomePage.js<|end_filename|>
const HomePage = {
  name: 'HomePage',

  template: `<div>
    <list-products :products="products"></list-products>
  </div>`,

  data() {
    return {
      selectedProducts: [
        'adjustable-stem',
        'fizik-saddle-pak',
        'kenda-tube',
        'colorful-fixie-lima',
        'oury-grip-set',
        'pure-fix-pedals-with-cages'
      ]
    }
  },

  computed: {
    products() {
      let products = this.$store.state.products,
        output = [];

      if(Object.keys(products).length) {
        for(let featured of this.selectedProducts) {
          output.push(products[featured]);
        }
        return output;
      }
    }
  }
};

<|start_filename|>_/Chapter11/js/views/OrderCheckout.js<|end_filename|>
const OrderCheckout = {
  name: 'OrderCheckout',

  template: `<div>
    <h1>Order Confirmation</h1>
    <p>Please check the items below and fill in your details to complete your order</p>
    <list-purchases />

    <form @submit="submitForm()">
      <fieldset>
        <h2>Billing Details</h2>
        <label for="billingName">Name:</label>
        <input type="text" id="billingName" v-model="billing.name">
        <label for="billingAddress">Address:</label>
        <input type="text" id="billingAddress" v-model="billing.address">
        <label for="billingZipcode">Post code/Zip code:</label>
        <input type="text" id="billingZipcode" v-model="billing.zipcode">
      </fieldset>

      <label for="sameAddress">
        <input type="checkbox" id="sameAddress" v-model ="sameAddress">
        Delivery address is the same as billing
      </label>

      <fieldset>
        <h2>Delivery Details</h2>
        <label for="deliveryName">Name:</label>
        <input type="text" id="deliveryName" v-model="delivery.name" :disabled="sameAddress">
        <label for="deliveryAddress">Address:</label>
        <input type="text" id="deliveryAddress" v-model="delivery.address" :disabled="sameAddress">
        <label for="deliveryZipcode">Post code/Zip code:</label>
        <input type="text" id="deliveryZipcode" v-model="delivery.zipcode" :disabled="sameAddress">
      </fieldset>

      <input type="submit" value="Purchase items">
    </form>
  </div>`,

  components: {
    ListPurchases
  },

  data() {
    return {
      sameAddress: false,

      billing: {
        name: '',
        address: '',
        zipcode: ''
      },
      delivery: {
        name: '',
        address: '',
        zipcode: ''
      }
    }
  },

  watch: {
    sameAddress() {
      if(this.sameAddress) {
        this.delivery = this.billing;
      } else {
        this.delivery = Object.assign({}, this.billing);
      }
    }
  },

  methods: {
    submitForm() {
      // this.billing = billing details
      // this.delivery = delivery details
      
      this.$router.push({name: 'Confirmation'});
    }
  }
};