@ecomplus/storefront-app
Version:
Vue.js ecommerce app with cart, checkout and account pages
294 lines (272 loc) • 7.54 kB
JavaScript
import { i19error, i19paymentError, i19paymentErrorMsg } from '@ecomplus/i18n'
import { i18n } from '@ecomplus/utils'
import { store } from '@ecomplus/client'
import ecomCart from '@ecomplus/shopping-cart'
import ecomPassport from '@ecomplus/passport-client'
import Vue from 'vue'
import { mapGetters, mapMutations, mapActions } from 'vuex'
import { upsertCart } from './../../lib/sync-cart-to-api'
import EcCheckout from './../../components/EcCheckout.vue'
export default {
name: 'checkout',
components: {
EcCheckout
},
data () {
return {
updateInterval: null,
ecomPassport: null,
checkoutStep: 0,
skipShippingApps: []
}
},
computed: {
...mapGetters([
'amount',
'shippingService',
'shippingZipCode',
'selectedAddress'
]),
cart () {
return ecomCart.data
},
checkoutMode () {
const { mode } = this.$route.params
return mode ? mode.toLowerCase() : null
},
isLpCheckout () {
return this.checkoutMode === 'lp'
},
isGuestCheckout () {
if (this.isLpCheckout) {
if (typeof window !== 'object' || window.ecomGuestCheckout === undefined) {
return true
}
return Boolean(window.ecomGuestCheckout)
}
return this.checkoutMode === 'guest'
},
customer: {
get () {
return this.$store.getters.customer
},
set (customer) {
this.setCustomer(customer)
if (customer._id) {
const { ecomPassport } = this
if (ecomPassport && ecomPassport.checkAuthorization()) {
this.saveCustomer({ ecomPassport })
}
}
}
},
discountCoupon: {
get () {
return this.$store.getters.discountCoupon
},
set (couponCode) {
this.setDiscountCoupon(couponCode)
}
},
shippingService: {
get () {
return this.$store.getters.shippingService
},
set (service) {
this.selectShippingService(service)
}
},
paymentGateway: {
get () {
return this.$store.getters.paymentGateway
},
set (gateway) {
this.selectPaymentGateway(gateway)
}
},
notes: {
get () {
return this.$store.getters.notes
},
set (notes) {
this.setNotes(notes)
}
}
},
methods: {
...mapMutations([
'triggerLoading',
'setFluidPage',
'setDiscountCoupon',
'setDiscountRule',
'setNotes',
'selectShippingService',
'selectPaymentGateway',
'setCustomer',
'selectAddress',
'addOrder'
]),
...mapActions([
'fetchCartItems',
'fetchCustomer',
'saveCustomer',
'sendCheckout'
]),
login (ecomPassport) {
this.ecomPassport = ecomPassport
this.triggerLoading(true)
this.fetchCustomer({ ecomPassport })
.finally(() => this.triggerLoading(false))
},
checkout (transaction) {
const { customer } = this
this.triggerLoading(true)
this.sendCheckout({ customer, transaction })
.then(order => {
this.addOrder(order)
this.$router.push({
name: 'confirmation',
params: {
id: order._id,
number: order.number
}
})
})
.catch((err) => {
if (err.response) {
const { data } = err.response
if (data && data.error_code === 'CKT901') {
this.$toast({
title: i18n(i19error),
body: i18n(data.user_message),
variant: 'warning'
})
this.skipShippingApps.push(this.shippingService.app_id)
return
}
}
this.$toast({
title: i18n(i19paymentError),
body: i18n(i19paymentErrorMsg),
variant: 'danger'
})
})
.finally(() => this.triggerLoading(false))
}
},
watch: {
checkoutStep (stepNumber, lastStep) {
this.$router.push({
params: {
step: stepNumber
}
})
if (stepNumber && !lastStep) {
this.setFluidPage(true)
}
}
},
created () {
if (!this.isLpCheckout) {
const update = items => this.fetchCartItems({ removeOnError: true, items })
const fetchAddedItem = ({ item }) => {
update([item])
}
ecomCart.on('addItem', fetchAddedItem)
const checkCart = ({ data }) => {
if (!data.items.length) {
this.$router.push({
name: 'cart'
})
}
}
this.updateInterval = setInterval(update, 600000)
this.triggerLoading(true)
update()
.then(() => {
if (!ecomCart.data.flags) {
ecomCart.data.flags = []
}
if (ecomCart.data.flags.indexOf('open-checkout') === -1) {
ecomCart.data.flags.push('open-checkout')
}
const tryUpsertCart = () => {
if (ecomPassport.checkAuthorization()) {
upsertCart()
} else {
ecomPassport.once('login', tryUpsertCart)
}
}
setTimeout(tryUpsertCart, 300)
})
.finally(() => {
this.triggerLoading(false)
checkCart(ecomCart)
ecomCart.on('change', checkCart)
})
this.$once('hook:beforeDestroy', () => {
ecomCart.off('addItem', fetchAddedItem)
ecomCart.off('change', checkCart)
})
}
},
mounted () {
if (this.isLpCheckout) {
const productId = this.$route.params.product
if (productId) {
this.triggerLoading(true)
const fetchProduct = (isRetry = false) => {
store({
url: `/products/${productId}.json`,
axiosConfig: {
timeout: 6000
}
})
.then(({ data }) => {
ecomCart.clear()
let canAddToCart = false
const selectFields = ['variations', 'customizations', 'kit_composition']
for (let i = 0; i < selectFields.length; i++) {
const selectOptions = data[selectFields[i]]
if (selectOptions && selectOptions.length) {
canAddToCart = true
break
}
}
if (!canAddToCart) {
ecomCart.addProduct(data)
}
return import('#components/TheProduct.vue').then(productView => {
this.setFluidPage(true)
new Vue({
render: h => h(productView.default, {
props: {
product: data,
headingTag: 'h3',
galleryColClassName: 'col-12 order-last mt-3',
canAddToCart,
hasBuyButton: canAddToCart,
isQuickview: true
}
})
}).$mount(this.$refs.product)
})
})
.catch(err => {
console.error(err)
if (!isRetry) {
setTimeout(() => fetchProduct(true), 800)
}
})
.finally(() => this.triggerLoading(false))
}
fetchProduct()
}
}
},
destroyed () {
this.selectPaymentGateway(null)
this.setFluidPage(false)
clearInterval(this.updateInterval)
}
}