Skip to content

Commit

Permalink
Merge pull request #3317 from andrzejewsky/feature/3249-refactoring-v…
Browse files Browse the repository at this point in the history
…uex-cart

Refactoring vuex cart module
  • Loading branch information
pkarw committed Aug 13, 2019
2 parents bd2d02c + 9bef021 commit 60a696a
Show file tree
Hide file tree
Showing 61 changed files with 1,578 additions and 1,006 deletions.
7 changes: 2 additions & 5 deletions core/compatibility/components/blocks/Microcart/Product.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default {
// deprecated, will be moved to theme or removed in the near future #1742
this.$bus.$on('cart-after-itemchanged', this.onProductChanged)
this.$bus.$on('notification-after-itemremoved', this.onProductRemoved)
this.updateQuantity = debounce(this.updateQuantity, 5000)
this.updateQuantity = debounce(this.updateQuantity, 1000)
},
beforeDestroy () {
// deprecated, will be moved to theme or removed in the near future #1742
Expand Down Expand Up @@ -52,8 +52,5 @@ export default {
this.removeFromCart(event.item)
}
}
},
mixins: [
MicrocartProduct
]
}
}
153 changes: 153 additions & 0 deletions core/data-resolver/CartService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { DataResolver } from './types/DataResolver'
import Task from '@vue-storefront/core/lib/sync/types/Task'
import CartItem from '@vue-storefront/core/modules/cart/types/CartItem'
import { TaskQueue } from '@vue-storefront/core/lib/sync'
import { processLocalizedURLAddress } from '@vue-storefront/core/helpers'
import config from 'config';

const setShippingInfo = async (addressInformation: any): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.shippinginfo_endpoint),
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors',
body: JSON.stringify({ addressInformation })
},
silent: true
});

const getTotals = async (): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.totals_endpoint),
payload: {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
},
silent: true
});

const getCartToken = async (guestCart: boolean = false, forceClientState: boolean = false): Promise<Task> => {
const url = processLocalizedURLAddress(guestCart
? config.cart.create_endpoint.replace('{{token}}', '')
: config.cart.create_endpoint)

return TaskQueue.execute({
url,
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
},
force_client_state: forceClientState,
silent: true
});
}

const updateItem = async (cartServerToken: string, cartItem: CartItem): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.updateitem_endpoint),
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors',
body: JSON.stringify({
cartItem: {
...cartItem,
quoteId: cartItem.quoteId || cartServerToken
}
})
}
});

const deleteItem = async (cartServerToken: string, cartItem: CartItem): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.deleteitem_endpoint),
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors',
body: JSON.stringify({
cartItem: {
...cartItem,
quoteId: cartServerToken
}
})
},
silent: true
});

const getPaymentMethods = async (): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.paymentmethods_endpoint),
payload: {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
},
silent: true
});

const getShippingMethods = async (address: any): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.shippingmethods_endpoint),
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors',
body: JSON.stringify({
address
})
},
silent: true
});

const getItems = async (): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.pull_endpoint),
payload: {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
},
silent: true
});

const applyCoupon = async (couponCode: string): Promise<Task> => {
const url = processLocalizedURLAddress(config.cart.applycoupon_endpoint.replace('{{coupon}}', couponCode))

return TaskQueue.execute({
url,
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
},
silent: false
});
}

const removeCoupon = async (): Promise<Task> =>
TaskQueue.execute({
url: processLocalizedURLAddress(config.cart.deletecoupon_endpoint),
payload: {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
},
silent: false
});

export const CartService: DataResolver.CartService = {
setShippingInfo,
getTotals,
getCartToken,
updateItem,
deleteItem,
getPaymentMethods,
getShippingMethods,
getItems,
applyCoupon,
removeCoupon
}
8 changes: 5 additions & 3 deletions core/data-resolver/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { CategoryService } from './CategoryService';
import { UserService } from './UserService';
import { CategoryService } from './CategoryService'
import { UserService } from './UserService'
import { CartService } from './CartService'

export {
CategoryService,
UserService
UserService,
CartService
}
14 changes: 14 additions & 0 deletions core/data-resolver/types/DataResolver.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Category } from 'core/modules/catalog-next/types/Category';
import { UserProfile } from 'core/modules/user/types/UserProfile'
import CartItem from '@vue-storefront/core/modules/cart/types/CartItem'
import Task from '@vue-storefront/core/lib/sync/types/Task'

declare namespace DataResolver {
Expand Down Expand Up @@ -43,4 +44,17 @@ declare namespace DataResolver {
changePassword: (passwordData: PasswordData) => Promise<Task>,
refreshToken: (refreshToken: string) => Promise<string>
}

interface CartService {
setShippingInfo: (methodsData: any /*: ShippingMethodsData */) => Promise<Task>,
getTotals: () => Promise<Task>,
getCartToken: (guestCart: boolean, forceClientState: boolean) => Promise<Task>,
updateItem: (cartServerToken: string, cartItem: CartItem) => Promise<Task>,
deleteItem: (cartServerToken: string, cartItem: CartItem) => Promise<Task>,
getPaymentMethods: () => Promise<Task>,
getShippingMethods: (address: any /*: ShippingMethodsData */) => Promise<Task>,
getItems: () => Promise<Task>,
applyCoupon: (couponCode: string) => Promise<Task>,
removeCoupon: () => Promise<Task>
}
}
2 changes: 1 addition & 1 deletion core/filters/price.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { currentStoreView } from '@vue-storefront/core/lib/multistore';
const formatValue = (value, locale) => {
const price = Math.abs(parseFloat(value));

return price.toLocaleString(locale, { maximumFractionDigits: 2 });
return price.toLocaleString(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
};

const applyCurrencySign = (formattedPrice, { currencySign, currencySignPlacement }) => {
Expand Down
5 changes: 0 additions & 5 deletions core/lib/module/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ function registerModules (modules: VueStorefrontModule[], context): void {
)()
}

function isModuleRegistered (key: string): boolean {
return registeredModules.some(m => m.key === key)
}

function extendModule (moduleConfig: VueStorefrontModuleConfig) {
moduleExtendings.push(moduleConfig)
}
Expand Down Expand Up @@ -138,6 +134,5 @@ export {
extendModule,
VueStorefrontModule,
registerModules,
isModuleRegistered,
createModule
}
6 changes: 5 additions & 1 deletion core/lib/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ function registerModule (module: StorefrontModule, config?: any) {
}
}

export { refs, injectReferences, registerModule }
function isModuleRegistered (name: string): boolean {
return registeredModules.some(m => m.name === name)
}

export { refs, injectReferences, registerModule, isModuleRegistered }
2 changes: 2 additions & 0 deletions core/modules/cart/components/AddToCart.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Product from '@vue-storefront/core/modules/catalog/types/Product'
import { Logger } from '@vue-storefront/core/lib/logger';

// @deprecated moved to store
export const AddToCart = {
name: 'AddToCart',
data () {
Expand All @@ -23,6 +24,7 @@ export const AddToCart = {
this.isAddingToCart = true
try {
const diffLog = await this.$store.dispatch('cart/addItem', { productToAdd: product })

if (diffLog) {
if (diffLog.clientNotifications && diffLog.clientNotifications.length > 0) {
diffLog.clientNotifications.forEach(notificationData => {
Expand Down
1 change: 1 addition & 0 deletions core/modules/cart/components/Microcart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import AppliedCoupon from '../types/AppliedCoupon'
import Product from '@vue-storefront/core/modules/catalog/types/Product'
import CartTotalSegments from '../types/CartTotalSegments'

// @deprecated moved to store
export const Microcart = {
name: 'Microcart',
computed: {
Expand Down
1 change: 1 addition & 0 deletions core/modules/cart/components/MicrocartButton.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

// @deprecated moved to theme
export const MicrocartButton = {
name: 'MicrocartButton',
mounted () {
Expand Down
45 changes: 4 additions & 41 deletions core/modules/cart/components/Product.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { productThumbnailPath } from '@vue-storefront/core/helpers'
import config from 'config'
import { getThumbnailForProduct, getProductConfiguration } from '@vue-storefront/core/modules/cart/helpers'

// @deprecated moved to theme
export const MicrocartProduct = {
name: 'MicrocartProduct',
props: {
Expand All @@ -11,47 +11,10 @@ export const MicrocartProduct = {
},
computed: {
thumbnail () {
const thumbnail = productThumbnailPath(this.product)
if (typeof navigator !== 'undefined' && !navigator.onLine) {
return this.getThumbnail(thumbnail, config.products.thumbnails.width, config.products.thumbnails.height) // for offline support we do need to have ProductTile version
} else return this.getThumbnail(thumbnail, config.cart.thumbnails.width, config.cart.thumbnails.height)
},
options () {
const opts = {}

if (!this.product.configurable_options) {
return null
}

this.product.configurable_options.forEach(el => {
opts[el.attribute_code] = el.values.map(obj => ({
id: obj.value_index,
label: obj.label,
attribute_code: el.attribute_code,
type: el.attribute_code
}))
})

return opts
return getThumbnailForProduct(this.product)
},
configuration () {
if (!this.options) {
return null
}

const getAttributesFields = (attributeCode) =>
this.options[attributeCode].find(c => c.id === parseInt(this.product[attributeCode]))

return {
color: {
attribute_code: 'color',
...getAttributesFields('color')
},
size: {
attribute_code: 'size',
...getAttributesFields('size')
}
}
return getProductConfiguration(this.product)
}
},
methods: {
Expand Down
41 changes: 41 additions & 0 deletions core/modules/cart/helpers/calculateTotals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import i18n from '@vue-storefront/i18n'
import sumBy from 'lodash-es/sumBy'
import ShippingMethod from '@vue-storefront/core/modules/cart/types/ShippingMethod'
import PaymentMethod from '@vue-storefront/core/modules/cart/types/PaymentMethod'
import CartItem from '@vue-storefront/core/modules/cart/types/CartItem'

const calculateTotals = (shippingMethod: ShippingMethod, paymentMethod: PaymentMethod, cartItems: CartItem[]) => {
const shippingTax = shippingMethod ? shippingMethod.price_incl_tax : 0

const totalsArray = [
{
code: 'subtotal_incl_tax',
title: i18n.t('Subtotal incl. tax'),
value: sumBy(cartItems, (p) => p.qty * p.price_incl_tax)
},
{
code: 'grand_total',
title: i18n.t('Grand total'),
value: sumBy(cartItems, (p) => p.qty * p.price_incl_tax + shippingTax)
}
]

if (paymentMethod) {
totalsArray.push({
code: 'payment',
title: i18n.t(paymentMethod.title),
value: paymentMethod.cost_incl_tax
})
}
if (shippingMethod) {
totalsArray.push({
code: 'shipping',
title: i18n.t(shippingMethod.method_title),
value: shippingMethod.price_incl_tax
})
}

return totalsArray
}

export default calculateTotals
Loading

0 comments on commit 60a696a

Please sign in to comment.