// global Vue.use(window.vuelidate.default); const { required, requiredIf, requiredUnless, minLength, maxLength, minValue, maxValue, between, alpha, alphaNum, numeric, integer, decimal, email, ipAddress, macAddress, sameAs, url, or, and, not, $params } = window.validators; let cartStore = new Vuex.Store({ state: { initialized: false, shippingCategories: {}, cartMessages: { total: 0, errors: [], success: [], warning: [], info: [], }, lastAddedItems: [], lastDeniedItems: [], taxPercent: 0.0, shippingState: 'All', shippingZipCode: null, // priorityShipping: 0, // saturdayDelivery: 0, // alaskaDelivery: 0, couponData: {}, couponCode: null, isGiftCertApplied: false, availableGiftCertAmount: 0.0, appliedGiftCertCode: null, appliedGiftCertAmount: 0.0, availableStoreCredit: 0.0, appliedStoreCredit: 0.0, alaskaCostForMarineLife: 0.0 }, actions: { INIT_SHIPPING_CATEGORIES: (context, payload) => { return new Promise((resolve, reject) => { context.commit('SETUP_CART_SHIPPING_CATEGORIES', payload); resolve('INIT_SHIPPING_CATEGORIES done'); }); }, INIT: function (context) { return new Promise((resolve, reject) => { if (context.state.initialized) { resolve('INIT done'); } else { $.get('/shipping-categories', payload => { context.dispatch( 'INIT_SHIPPING_CATEGORIES', { allShippingCategories: payload.shipping_categories } ).then(data => { context.commit('UPDATE_INITIALIZED', {initialized: true}); localdb.setItem('cartStore', context.state); $.post('/cart-snapshot', {cart_store: JSON.stringify(context.state)}); resolve('INIT done'); }); }); } }); }, CLEAR_LAST_ADDED_ITEMS: (context) => { context.commit('CLEAR_LAST_ADDED_ITEMS'); }, CLEAR_LAST_DENIED_ITEMS: (context) => { context.commit('CLEAR_LAST_DENIED_ITEMS'); }, ADD_LAST_ADDED_ITEMS: (context, payload) => { context.commit('ADD_LAST_ADDED_ITEMS', payload); }, ADD_LAST_DENIED_ITEMS: (context, payload) => { context.commit('ADD_LAST_DENIED_ITEMS', payload); }, SYNC_VENDOR: (context, payload) => { return new Promise((resolve, reject) => { $.post('/sync-vendor', { catalogid: payload.catalogid, vendor_session_id: Cookies.get('vendor_session_id'), qty_added_to_cart: payload.qtyAddedToCart, qty_to_add: payload.qtyToAdd }, response => { if (response.available) { resolve('available'); } else { reject('not available'); } }); }); }, SYNC_PRODUCT_QTY_DEC: (context, payload) => { return new Promise((resolve, reject) => { $.post('/sync-product-qty-dec', { catalogid: payload.catalogid, vendor_session_id: Cookies.get('vendor_session_id'), qty_added_to_cart: payload.qtyAddedToCart, qty_to_remove: 1 }, response => { if (response.available) { resolve('available'); } else { reject('not available'); } }); }); }, SYNC_PRODUCT_REMOVE_FROM_CART: (context, payload) => { return new Promise((resolve, reject) => { $.post('/sync-product-remove-form-cart', { catalogid: payload.catalogid, vendor_session_id: Cookies.get('vendor_session_id'), qty_added_to_cart: payload.qtyAddedToCart, }, response => { if (response.available) { resolve('available'); } else { reject('not available'); } }); }); }, SAVE_CART_SNAPSHOT: (context, payload) => { return new Promise((resolve, reject) => { $.post('/cart-snapshot', payload).done(response => { resolve('Saved cart snapshot into database'); }); }) }, ADD_GIFT_CERT: (context, payload) => { return new Promise((resolve, reject) => { context.commit('ADD_GIFT_CERT', payload); resolve('gift cert added'); }); }, ADD_TO_CART: (context, payload) => { return new Promise((resolve, reject) => { context.commit('ADD_TO_CART', payload); resolve('added to cart') }) }, INCREMENT_QTY: (context, payload) => { return new Promise((resolve, reject) => { let product = context.getters.cartProductByCategoryIndex(payload.shippingCategoryKey, payload.itemIndex); if (product.is_eibi || product.is_managed) { product.qtyToAdd = payload.amount; context.dispatch('SYNC_VENDOR', product).then(result => { context.commit('INCREMENT_QTY', payload); resolve('INCREMENT_QTY done'); }, error => { reject('requested qty increment not okay with available stock'); }); } else { context.commit('INCREMENT_QTY', payload); resolve('INCREMENT_QTY done'); } }); }, DECREMENT_QTY: (context, payload) => { return new Promise((resolve, reject) => { let product = context.getters.cartProductByCategoryIndex(payload.shippingCategoryKey, payload.itemIndex); if (product.is_eibi || product.is_managed) { context.dispatch('SYNC_PRODUCT_QTY_DEC', product).then(result => { context.commit('DECREMENT_QTY', payload); resolve('done'); }, error => { reject('decrement qty failed'); }); } else { context.commit('DECREMENT_QTY', payload); resolve('done'); } }); }, REMOVE_FROM_CART: (context, payload) => { return new Promise((resolve, reject) => { let product = context.getters.cartProductByCategoryIndex(payload.shippingCategoryKey, payload.itemIndex); if (product.is_eibi || product.is_managed) { context.dispatch('SYNC_PRODUCT_REMOVE_FROM_CART', product).then(result => { context.commit('REMOVE_FROM_CART', payload); resolve('REMOVE_FROM_CART done'); }, error => { reject('remove from cart failed'); }); } else { context.commit('REMOVE_FROM_CART', payload); resolve('REMOVE_FROM_CART done'); } }); }, UPDATE_PRODUCT_WITH_LATEST_DATA:({commit, getters}, payload)=> { return new Promise((resolve, reject) => { commit('UPDATE_PRODUCT_WITH_LATEST_DATA', {payload, getters}) resolve('product with latest update'); }) }, UPDATE_SHIPPING_STATE: (context, payload) => { return new Promise((resolve, reject) => { context.commit('UPDATE_SHIPPING_STATE', payload) resolve('shipping state updated'); }); }, UPDATE_SHIPPING_ZIP_CODE: (context, payload) => { return new Promise((resolve, reject) => { context.commit('UPDATE_SHIPPING_ZIP_CODE', payload) resolve('shipping ZIP CODE updated'); }); }, FETCH_CATEGORY_SHIPPING_CHARGE: (context, payload) => { let shippingCategory = context.state.shippingCategories[payload.shippingCategoryKey]; let priorityShipping = 'priorityShipping' in payload ? payload.priorityShipping : 0; let saturdayDelivery = 'saturdayDelivery' in payload ? payload.saturdayDelivery : 0; // let alaskaDelivery = 'alaskaDelivery' in payload ? payload.alaskaDelivery : 0; let subtotal = context.getters.categorySubTotal(shippingCategory.meta.internal_name); // shipping charge will be calculated after deducting store credit and coupon // Store credit can only be checked for Marine Life. Because, Only Marine Life will have Store Credit if (payload.shippingCategoryKey === 'marine_life') { if (context.getters.isStoreCreditApplied) { subtotal = subtotal - parseFloat(context.state.appliedStoreCredit); } } subtotal = subtotal - parseFloat(context.getters.categoryCouponDiscount(payload.shippingCategoryKey)); return new Promise((resolve, reject) => { requestPayload = { shipping_category_id: shippingCategory.meta.id, sub_total: subtotal, shipping_state: context.state.shippingState, priority_shipping: priorityShipping, saturday_delivery: saturdayDelivery, // alaska_delivery: alaskaDelivery }; $.get('/cart-category-charge', requestPayload, responsePayload => { responsePayload.total_items_count = context.getters.categoryTotalQuantities(shippingCategory.meta.internal_name) responsePayload.priority_shipping = priorityShipping responsePayload.saturday_delivery = saturdayDelivery context.commit('UPDATE_CATEGORY_SHIPPING_CHARGE', responsePayload); resolve('FETCH_CATEGORY_SHIPPING_CHARGE done') }); }); }, FETCH_CATEGORY_TAX: (context, payload) => { let shippingState = 'shippingState' in payload ? payload.shippingState : context.state.shippingState; let shippingZip = 'shippingZip' in payload ? payload.shippingZip : context.state.shippingZipCode; let subtotal = parseFloat(context.getters.categorySubTotal(payload.shippingCategoryKey)); // tax will be calculated after deducting store credit and coupon // Store credit can only be checked for Marine Life. Because, Only Marine Life will have Store Credit if (payload.shippingCategoryKey === 'marine_life') { if (context.getters.isStoreCreditApplied) { subtotal = subtotal - parseFloat(context.state.appliedStoreCredit); } } subtotal = subtotal - parseFloat(context.getters.categoryCouponDiscount(payload.shippingCategoryKey)); subtotal = subtotal + parseFloat(context.getters.categoryShippingCharge(payload.shippingCategoryKey)); subtotal = subtotal + parseFloat(context.state.shippingCategories[payload.shippingCategoryKey].summary.packagingCharge); return new Promise((resolve, reject) => { let requestPayload = { shipping_category_id: parseInt(context.state.shippingCategories[payload.shippingCategoryKey].meta.id), shipping_category_total: subtotal, shipping_state: shippingState, shipping_zip: shippingZip }; $.get('/cart-category-tax', requestPayload, responsePayload => { context.commit('UPDATE_CATEGORY_TAX', responsePayload); resolve('FETCH_CATEGORY_SHIPPING_CHARGE done') }); }); }, CLEAR_CART: (context, payload) => { return new Promise((resolve, reject) => { context.commit('CLEAR_CART'); resolve('cart is cleared'); }); }, APPLY_COUPON: (context, payload) => { return new Promise((resolve, reject) => { context.commit('APPLY_COUPON', payload); resolve('coupon is set'); }); }, REMOVE_COUPON: (context) => { return new Promise((resolve, reject) => { context.commit('REMOVE_COUPON'); resolve('coupon is removed'); }); }, SET_GIFT_CERT: (context, payload) => { return new Promise((resolve, reject) => { context.commit('SET_GIFT_CERT', payload); resolve('gift cert is SET'); }); }, UNSET_GIFT_CERT: (context) => { return new Promise((resolve, reject) => { context.commit('UNSET_GIFT_CERT'); resolve('gift cert UNSET'); }); }, SET_AVAILABLE_STORE_CREDIT: (context, payload) => { return new Promise((resolve, reject) => { context.commit('SET_AVAILABLE_STORE_CREDIT', payload); resolve('available store credit is set'); }); }, UNSET_AVAILABLE_STORE_CREDIT: (context) => { return new Promise((resolve, reject) => { context.commit('UNSET_AVAILABLE_STORE_CREDIT'); resolve('available store credit is unset'); }); }, SET_APPLIED_STORE_CREDIT: (context, payload) => { return new Promise((resolve, reject) => { if(redeemCouponApp.isCouponApplied){ let couponCode = context.state.couponCode; context.dispatch('REMOVE_COUPON').then(()=>{ redeemCouponApp.$data.formData.code = couponCode redeemCouponApp.submit() }) } let marineLifeSubTotal = context.getters.categorySubTotal('marine_life'); let cartSubTotal = context.getters.cartSubTotal; if (marineLifeSubTotal == 0) { reject(new Error('Store credit can only be applied on Marine Life. Please add some Marine Life items in your cart.')); } if (marineLifeSubTotal < payload.storeCreditToApply) { newPaylaod = { storeCreditToApply: marineLifeSubTotal } } else { newPaylaod = { storeCreditToApply: payload.storeCreditToApply } } context.commit('SET_APPLIED_STORE_CREDIT', newPaylaod); resolve('available store credit is set'); // if (marineLifeSubTotal < payload.storeCreditToApply) { // reject(new Error("Store credit can only be applied on Marine Life. And Marine Life subtotal needs to be higher than store credit you want to apply.")); // } else if (cartSubTotal < payload.storeCreditToApply) { // reject(new Error("To apply store credit, your cart subtotal needs to be more than amount of store credit you want to apply.")); // } else { // context.commit('SET_APPLIED_STORE_CREDIT', payload); // resolve('available store credit is set'); // } }); }, UNSET_APPLIED_STORE_CREDIT: (context, payload) => { return new Promise((resolve, reject) => { context.commit('UNSET_APPLIED_STORE_CREDIT'); resolve('available store credit is unset'); }); }, AUTO_EXPIRE_EIBI: (context, payload) => { return new Promise((resolve, reject) => { context.commit('AUTO_EXPIRE_EIBI', payload); resolve('auto expired eibi items'); }); } }, mutations: { UPDATE_SHIPPING_STATE: (state, payload) => { state.shippingState = payload.shippingState; }, UPDATE_PRODUCT_WITH_LATEST_DATA:(state, {payload, getters})=> { let hasChanges = false; let hasChangesList = []; let changed_products_messages = {}; let oos_products = []; let handler = false; const getMax = (a, b) => Math.max(a, b); Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { if(shippingCategoryKey === 'gift_certificates') { return; } if( !state.shippingCategories[shippingCategoryKey].products.length && !state.shippingCategories[shippingCategoryKey].free_products.length && !state.shippingCategories[shippingCategoryKey].discounted_products ) { return; } state.shippingCategories[shippingCategoryKey].products.forEach((product, productIndex)=>{ handler = getters.handleUpdateItem(product, productIndex, shippingCategoryKey, 'products', hasChangesList, changed_products_messages, oos_products); hasChangesList = handler[0] changed_products_messages = handler[1] oos_products = handler[2] }); state.shippingCategories[shippingCategoryKey].free_products.forEach((product, productIndex)=>{ handler = getters.handleUpdateItem(product, productIndex, shippingCategoryKey, 'free_products', hasChangesList, changed_products_messages, oos_products); hasChangesList = handler[0] changed_products_messages = handler[1] oos_products = handler[2] }); state.shippingCategories[shippingCategoryKey].discounted_products.forEach((product, productIndex)=>{ handler = getters.handleUpdateItem(product, productIndex, shippingCategoryKey, 'discounted_products', hasChangesList, changed_products_messages, oos_products); hasChangesList = handler[0] changed_products_messages = handler[1] oos_products = handler[2] }); }) if(hasChangesList.length) { hasChanges = hasChangesList.reduce(getMax) > 0; } console.log(hasChanges, hasChangesList, changed_products_messages, oos_products); // We will not send oos notification for loggedin users. Because, that will be handled by my-abandoned-cart-items if(payload.hasOwnProperty('isLoggedIn') && !payload.isLoggedIn) { if (oos_products.length) { $.ajax({ url: `notify_oss`, type: "post", data: {'oos_products': oos_products.join(',')}, async: false, }); } } if(hasChanges){ if(changed_products_messages) { let error_object = { 'warning_messages': [] } for(var i in changed_products_messages) { if(typeof changed_products_messages[i] === 'string') { error_object['warning_messages'].push(changed_products_messages[i]) } else if(typeof changed_products_messages[i] === 'object') { for(var j in changed_products_messages[i]) { error_object['warning_messages'].push(changed_products_messages[i][j]) } } } //console.log(error_object) display_cart_page_errors(error_object) } if(window.location.pathname==="/orderconfirmation"){ alert('Some items are changed. We will be redirecting you to the cart page. Please review those ' + 'and process to checkout again') const urlParams = new URLSearchParams(window.location.search); //urlParams.set("changedItem","true") if(payload.hasOwnProperty('isLoggedIn') && !payload.isLoggedIn) { if(changed_products_messages) { urlParams.set("error",Base64EncodeUrl(str_to_base64(JSON.stringify(changed_products_messages) )) ); } } window.location.href=`/viewcart?${urlParams.toString()}`; } } }, UPDATE_SHIPPING_ZIP_CODE: (state, payload) => { Vue.set(state, 'shippingZipCode', payload.shippingZipCode); }, AUTO_EXPIRE_EIBI: (state, payload) => { let currentTime = new Date().getTime(); let expireAfterSeconds = payload.expireAfterMinutes * 60; let expireAfterMiliseconds = expireAfterSeconds * 1000; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { if (state.shippingCategories[shippingCategoryKey].products.length) { state.shippingCategories[shippingCategoryKey].products.forEach((item, index) => { if (item.is_eibi) { if ( (currentTime - item.addedToCartOn) > expireAfterMiliseconds ) { state.shippingCategories[shippingCategoryKey].products.splice(index, 1); } } }); } }); }, SET_AVAILABLE_STORE_CREDIT: (state, payload) => { Vue.set(state, 'availableStoreCredit', parseFloat(payload.storeCredit)); }, UNSET_AVAILABLE_STORE_CREDIT: (state) => { Vue.set(state, 'availableStoreCredit', 0.0); }, SET_APPLIED_STORE_CREDIT: (state, payload) => { Vue.set(state, 'appliedStoreCredit', parseFloat(payload.storeCreditToApply)); }, UNSET_APPLIED_STORE_CREDIT: (state) => { Vue.set(state, 'appliedStoreCredit', 0.0); }, SET_GIFT_CERT: (state, payload) => { Vue.set(state, 'isGiftCertApplied', true); Vue.set(state, 'availableGiftCertAmount', payload.giftCertAmount); Vue.set(state, 'appliedGiftCertCode', payload.giftCertCode); Vue.set(state, 'appliedGiftCertAmount', payload.giftCertAmountToApply); }, UNSET_GIFT_CERT: (state) => { Vue.set(state, 'isGiftCertApplied', false); Vue.set(state, 'availableGiftCertAmount', 0.0); Vue.set(state, 'appliedGiftCertCode', null); Vue.set(state, 'appliedGiftCertAmount', 0.0); }, SET_SATURDAY_DELIVERY: (state) => { Vue.set(state, 'saturdayDelivery', 1); }, UNSET_SATURDAY_DELIVERY: (state) => { Vue.set(state, 'saturdayDelivery', 0); }, SET_PRIORITY_DELIVERY: (state) => { Vue.set(state, 'priorityShipping', 1); }, UNSET_PRIORITY_DELIVERY: (state) => { Vue.set(state, 'priorityShipping', 0); }, SET_ALASKA_DELIVERY: (state) => { state.alaskaDelivery = 1; }, UNSET_ALASKA_DELIVERY: (state) => { state.alaskaDelivery = 0; }, REMOVE_COUPON: (state) => { Object.keys(state.couponData).forEach(key => { Vue.delete(state.couponData, key); }); state.couponCode = null; Object.keys(state.shippingCategories).forEach(key => { if(state.shippingCategories[key].hasOwnProperty('free_products') && state.shippingCategories[key].free_products) { Vue.set(state.shippingCategories[key], 'free_products', []) } if(state.shippingCategories[key].hasOwnProperty('discounted_products') && state.shippingCategories[key].discounted_products) { Vue.set(state.shippingCategories[key], 'discounted_products', []) } // let discountedProductIndexes = []; // state.shippingCategories[key].products.forEach((product, productIndex) => { // if (product.is_discounted) { // discountedProductIndexes.push(productIndex); // } // }); // // discountedProductIndexes.reverse(); // discountedProductIndexes.forEach(removalIndex => { // state.shippingCategories[key].products.splice(removalIndex, 1); // }) }); }, APPLY_COUPON: (state, payload) => { state.couponCode = payload.code; Object.keys(payload.shipping_categories).forEach(key => { Vue.set(state.couponData, key, payload.shipping_categories[key]); }); }, CLEAR_CART: (state, payload) => { Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { state.shippingCategories[shippingCategoryKey].products.splice(0); if(state.shippingCategories[shippingCategoryKey].hasOwnProperty('free_products') && state.shippingCategories[key].free_products) { state.shippingCategories[shippingCategoryKey].free_products.splice(0); } if(state.shippingCategories[shippingCategoryKey].hasOwnProperty('discounted_products') && state.shippingCategories[key].discounted_products) { state.shippingCategories[shippingCategoryKey].discounted_products.splice(0); } }); Vue.set(state, 'couponCode', null); Vue.set(state, 'couponData', {}); Vue.set(state, 'shippingState', 'All'); Vue.set(state, 'shippingZipCode', null); Vue.set(state, 'taxPercent', 0); Vue.set(state, 'appliedGiftCertAmount', 0); Vue.set(state, 'appliedGiftCertCode', null); Vue.set(state, 'availableGiftCertAmount', 0); Vue.set(state, 'isGiftCertApplied', false); Vue.set(state, 'appliedStoreCredit', 0); Vue.set(state, 'availableStoreCredit', 0); state.lastAddedItems.splice(0); state.lastDeniedItems.splice(0); }, ADD_GIFT_CERT: (state, payload) => { let newArrayLength = state.shippingCategories[payload.shipping_category_key].products.push(payload); Vue.set(state.shippingCategories[payload.shipping_category_key].products[newArrayLength - 1], 'qtyAddedToCart', payload.qtyToAdd) }, UPDATE_CATEGORY_TAX: (state, payload) => { Vue.set(state, 'taxPercent', Number(parseFloat(payload.tax_rate).toFixed(2))) Vue.set(state.shippingCategories[payload.internal_name].summary, 'taxPercent', Number(parseFloat(payload.tax_rate).toFixed(2))) Vue.set(state.shippingCategories[payload.internal_name].summary, 'tax', Number(parseFloat(payload.tax).toFixed(2))) }, UPDATE_CATEGORY_SHIPPING_CHARGE: (state, payload) => { // If category doesn't have enough items in cart, need to reset the Shipping and Handling charge if (payload.hasOwnProperty('total_items_count')) { if(payload.total_items_count <= 0) { payload.shipping_charge = 0.00 payload.handling_charge = 0.00 } } Vue.set(state.shippingCategories[payload.internal_name].summary, 'shippingCharge', Number(parseFloat(payload.shipping_charge).toFixed(2))) Vue.set(state.shippingCategories[payload.internal_name].summary, 'packagingCharge', Number(parseFloat(payload.handling_charge).toFixed(2))) }, CLEAR_LAST_ADDED_ITEMS: (state, payload) => { state.lastAddedItems = []; }, CLEAR_LAST_DENIED_ITEMS: (state, payload) => { state.lastDeniedItems = []; }, UPDATE_INITIALIZED: (state, payload) => { state.initialized = payload.initialized; }, SETUP_CART_SHIPPING_CATEGORIES: (state, payload) => { payload.allShippingCategories.forEach(item => { Vue.set(state.shippingCategories, item.internal_name, {}); Vue.set(state.shippingCategories[item.internal_name], 'products', []); Vue.set(state.shippingCategories[item.internal_name], 'free_products', []); Vue.set(state.shippingCategories[item.internal_name], 'discounted_products', []); Vue.set(state.shippingCategories[item.internal_name], 'meta', item); Vue.set(state.shippingCategories[item.internal_name], 'summary', { packagingCharge: Number(parseFloat(item.handling_charge).toFixed(2)), shippingCharge: 0.0, taxPercent: 0.0, tax: 0.0 }); }); state.alaskaCostForMarineLife = state.shippingCategories['marine_life'].meta.alaska_delivery_charge; }, ADD_TO_CART: function (state, payload) { let itemOfLocalStore; if(!state.shippingCategories[payload.shipping_category_key].hasOwnProperty('free_products')) { state.shippingCategories[payload.shipping_category_key].free_products = [] } if(!state.shippingCategories[payload.shipping_category_key].hasOwnProperty('discounted_products')) { state.shippingCategories[payload.shipping_category_key].discounted_products = [] } if(payload.hasOwnProperty('is_free') && payload.is_free) { payload.free_key = payload.catalogid + '_' + payload.free_qty let foundFreeIndex = state.shippingCategories[payload.shipping_category_key].free_products.findIndex(item => item.free_key === payload.free_key); if (foundFreeIndex === -1) { payload.qtyAddedToCart = payload.qtyToAdd state.shippingCategories[payload.shipping_category_key].free_products.push(payload); } } else if(payload.hasOwnProperty('is_discounted') && payload.is_discounted) { payload.discount_key = payload.catalogid + '_' + payload.price let foundFreeIndex = state.shippingCategories[payload.shipping_category_key].discounted_products.findIndex(item => item.discount_key === payload.discount_key); if (foundFreeIndex === -1) { payload.qtyAddedToCart = payload.qtyToAdd state.shippingCategories[payload.shipping_category_key].discounted_products.push(payload); } } else { let foundIndex = state.shippingCategories[payload.shipping_category_key].products.findIndex(item => item.catalogid === payload.catalogid); if (foundIndex === -1) { // not found let newArrayLength = state.shippingCategories[payload.shipping_category_key].products.push(payload); itemOfLocalStore = state.shippingCategories[payload.shipping_category_key].products[newArrayLength - 1]; itemOfLocalStore.qtyAddedToCart = payload.qtyToAdd; } else { let currentQty = parseInt(state.shippingCategories[payload.shipping_category_key].products[foundIndex].qtyAddedToCart); itemOfLocalStore = state.shippingCategories[payload.shipping_category_key].products[foundIndex] itemOfLocalStore.qtyAddedToCart = currentQty + parseInt(payload.qtyToAdd); } if (!itemOfLocalStore.is_discounted && itemOfLocalStore.catalogid != 11) { $.post('/cart-item-sync', itemOfLocalStore, (response) => { }); } } }, ADD_LAST_ADDED_ITEMS: (state, payload) => { state.lastAddedItems.push(payload); }, ADD_LAST_DENIED_ITEMS: (state, payload) => { state.lastDeniedItems.push(payload); }, INCREMENT_QTY: (state, payload) => { let currentQty = parseInt(state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex].qtyAddedToCart); if (isNaN(currentQty)) { currentQty = 0; } let newQty = currentQty + payload.amount; state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex].qtyAddedToCart = newQty; let itemOfLocalStore = state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex]; if(!itemOfLocalStore.is_discounted && itemOfLocalStore.catalogid !=11){ $.post('/cart-item-sync', itemOfLocalStore, (response) => {}); } }, DECREMENT_QTY: (state, payload) => { let currentQty = parseInt(state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex].qtyAddedToCart); if (isNaN(currentQty)) { currentQty = 0; } if (currentQty > 0) { let newQty = currentQty - payload.amount; state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex].qtyAddedToCart = newQty; let itemOfLocalStore = state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex]; if(!itemOfLocalStore.is_discounted && itemOfLocalStore.catalogid !=11){ $.post('/cart-item-sync', itemOfLocalStore, (response) => {}); } } }, REMOVE_FROM_CART: (state, payload) => { let itemOfLocalStore; itemOfLocalStore = state.shippingCategories[payload.shippingCategoryKey].products[payload.itemIndex]; state.shippingCategories[payload.shippingCategoryKey].products.splice(payload.itemIndex, 1); $.post('/cart-item-delete', itemOfLocalStore, (response) => { }); }, }, getters: { isStoreCreditApplied: (state, getters) => { if (parseFloat(state.appliedStoreCredit) > 0) { return true; } return false; }, availableStoreCredit: (state, getters) => { return state.availableStoreCredit; }, appliedStoreCredit: (state, getters) => { return state.appliedStoreCredit; }, isGiftCertApplied: (state, getters) => { return state.isGiftCertApplied; }, appliedGiftCertCode: (state, getters) => { return state.appliedGiftCertCode; }, availableGiftCertAmount: (state, getters) => { return state.availableGiftCertAmount; }, appliedGiftCertAmount: (state, getters) => { return state.appliedGiftCertAmount; }, cartSubTotal: (state, getters) => { let total = 0.0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { let subtotal = parseFloat(getters.categorySubTotal(shippingCategoryKey)) total += subtotal; }); return Number(parseFloat(total).toFixed(2)); }, cartGrandTotal: (state, getters) => { let total = 0.0; let subtotal = parseFloat(getters.cartSubTotal) let shipping = parseFloat(getters.cartShippingCharge) let packaging = parseFloat(getters.cartPackagingCharge) let tax = parseFloat(getters.cartTax) let discount = parseFloat(getters.cartCouponDiscount) let giftCertificate = parseFloat(state.appliedGiftCertAmount) let storeCredit = parseFloat(state.appliedStoreCredit) total = total + subtotal + shipping + packaging + tax; total = total - discount; if (state.isGiftCertApplied) { total = total - giftCertificate; } if (getters.isStoreCreditApplied) { total = total - storeCredit; } if (parseFloat(total) < 0) { total = 0.0; } console.log('cartGrandTotal: ', subtotal, shipping, tax, total) return Number(parseFloat(total).toFixed(2)); }, cartCouponDiscount: (state, getters) => { let totalDiscount = 0.0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { if (state.shippingCategories[shippingCategoryKey].products.length) { totalDiscount += parseFloat(getters.categoryCouponDiscount(shippingCategoryKey)); } }); return Number(parseFloat(totalDiscount).toFixed(2)); }, cartShippingCharge: (state, getters) => { let totalShippingCharge = 0.0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { if(state.shippingCategories[shippingCategoryKey].products.length){ totalShippingCharge += parseFloat(getters.categoryShippingCharge(shippingCategoryKey)); } else if(state.shippingCategories[shippingCategoryKey].free_products.length) { totalShippingCharge += parseFloat(getters.categoryShippingCharge(shippingCategoryKey)); } // if (state.shippingCategories[shippingCategoryKey].products.length) { // let categorySubTotal = parseFloat(getters.categorySubTotal(shippingCategoryKey)); // if (shippingCategoryKey in state.couponData) { // let requiredSubTotal = parseFloat(state.couponData[shippingCategoryKey].required_sub_total); // if (categorySubTotal >= requiredSubTotal && state.couponData[shippingCategoryKey].give_free_shipping) { // totalShippingCharge += 0; // } else { // totalShippingCharge += parseFloat(state.shippingCategories[shippingCategoryKey].summary.shippingCharge); // } // } else { // totalShippingCharge += parseFloat(state.shippingCategories[shippingCategoryKey].summary.shippingCharge); // } // } }); return Number(parseFloat(totalShippingCharge).toFixed(2)); }, cartPackagingCharge: state => { let total = 0.0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { if (state.shippingCategories[shippingCategoryKey].products.length) { total += parseFloat(state.shippingCategories[shippingCategoryKey].summary.packagingCharge); } }); return Number(parseFloat(total).toFixed(2)); }, cartTax: state => { let total = 0.0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { if (state.shippingCategories[shippingCategoryKey].products.length) { total += parseFloat(state.shippingCategories[shippingCategoryKey].summary.tax); } }); return Number(parseFloat(total).toFixed(2)); }, cartTotalItems: state => { let count = 0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { count += parseFloat(state.shippingCategories[shippingCategoryKey].products.length); }); return count; }, cartTotalQuantities: state => { let count = 0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { state.shippingCategories[shippingCategoryKey].products.forEach(item => { count += parseInt(item.qtyAddedToCart); }) }); return count; }, categoryTotalQuantities: state => shippingCategoryKey => { let products_qty_count = 0 if(state.shippingCategories[shippingCategoryKey].products.length) { state.shippingCategories[shippingCategoryKey].products.forEach(item => { if(item.hasOwnProperty('qtyAddedToCart') && item.qtyAddedToCart) { products_qty_count += item.qtyAddedToCart } }) } return products_qty_count }, categorySubTotal: state => (shippingCategoryKey, exclude_discounted_products=false) => { let subTotal = 0.0; if (state.shippingCategories[shippingCategoryKey].products.length) { state.shippingCategories[shippingCategoryKey].products.forEach(item => { if(exclude_discounted_products && item.hasOwnProperty('is_discounted') && item.is_discounted) { return; } let itemPrice; if (item.payWithRewardPoints) { itemPrice = 0; } else { if (item.onsale) { itemPrice = parseFloat(parseFloat(item.saleprice).toFixed(2)); } else { itemPrice = parseFloat(parseFloat(item.price).toFixed(2)); } } subTotal += ( itemPrice * parseInt(item.qtyAddedToCart) ) }); } if(!exclude_discounted_products) { if(state.shippingCategories[shippingCategoryKey].hasOwnProperty('discounted_products')) { if (state.shippingCategories[shippingCategoryKey].discounted_products.length) { state.shippingCategories[shippingCategoryKey].discounted_products.forEach(item => { let itemPrice; if (item.payWithRewardPoints) { itemPrice = 0; } else { if (item.onsale) { itemPrice = parseFloat(parseFloat(item.saleprice).toFixed(2)); } else { itemPrice = parseFloat(parseFloat(item.price).toFixed(2)); } } subTotal += ( itemPrice * parseInt(item.qtyAddedToCart) ) }); } } } return Number(subTotal.toFixed(2)); }, categoryCouponDiscount: (state, getters) => shippingCategoryKey => { let finalDiscount; let subTotal = parseFloat(getters.categorySubTotal(shippingCategoryKey)); // If store credit is applied, then that should be excluded from subtotal, before applying coupon if (getters.isStoreCreditApplied) { subTotal = subTotal - parseFloat(state.appliedStoreCredit); } if (shippingCategoryKey in state.couponData) { let requiredSubTotal = parseFloat(state.couponData[shippingCategoryKey].required_sub_total); if (subTotal >= requiredSubTotal) { couponDiscount = parseFloat(state.couponData[shippingCategoryKey].discount); if (state.couponData[shippingCategoryKey].discount_type === 'fixed') { finalDiscount = couponDiscount; } else { finalDiscount = (subTotal * (couponDiscount / 100)); } } else { finalDiscount = 0.0; } } else { finalDiscount = 0.0; } return parseFloat(finalDiscount).toFixed(2); }, getIsPriorityShippingSelected: (state, getters) => shippingCategoryKey => { //console.log(shippingCategoryKey, window.location.pathname, $('#choosePriorityShipping').is(':checked')) if(shippingCategoryKey === 'marine_life') { if(window.location.pathname === '/orderconfirmation') { return $('#choosePriorityShipping').is(':checked') } } return false; }, categoryShippingCharge: (state, getters) => shippingCategoryKey => { let shippingCharge = 0.0; let subTotal = parseFloat(getters.categorySubTotal(shippingCategoryKey)); let priorityShippingApplied = 0; // shipping charge needs to be calculated after deducting store credit and coupon if(shippingCategoryKey === 'marine_life') { if (getters.isStoreCreditApplied) { subTotal = subTotal - parseFloat(state.appliedStoreCredit); } // This following lines needs to be run, because, this calls the state. // If there is any changes related to shipping, in the state and we do not capture it in this method, // the shipping price doesn't get updated. Because, this method is in `getters` and getters // doesn't get updated normally. if(state.shippingCategories[shippingCategoryKey].summary.hasOwnProperty('priorityShipping')) { if(state.shippingCategories[shippingCategoryKey].summary.priorityShipping) { priorityShippingApplied = 1; } } // This following lines, we are here checking if customer has really chosen the Priority Shipping in the Checkout page // if(getters.getIsPriorityShippingSelected(shippingCategoryKey)) { // priorityShippingApplied = 1; // } // else{ // priorityShippingApplied = 0; // } } subTotal = subTotal - parseFloat(getters.categoryCouponDiscount(shippingCategoryKey)); //console.log(subTotal); if (shippingCategoryKey in state.couponData) { let requiredSubTotal = parseFloat(state.couponData[shippingCategoryKey].required_sub_total); let couponGivesFreeShipping = state.couponData[shippingCategoryKey].give_free_shipping; if (subTotal >= requiredSubTotal && couponGivesFreeShipping) { shippingCharge = 0.0; if(priorityShippingApplied) { //shippingCharge = state.shippingCategories[shippingCategoryKey].summary.shippingCharge; shippingCharge = state.shippingCategories[shippingCategoryKey].meta.priority_shipping_charge; } } else { shippingCharge = state.shippingCategories[shippingCategoryKey].summary.shippingCharge; } } else { shippingCharge = state.shippingCategories[shippingCategoryKey].summary.shippingCharge; } return parseFloat(shippingCharge).toFixed(2); }, categoryGrandTotal: (state, getters) => shippingCategoryKey => { let total = 0.0; let subTotal = parseFloat(parseFloat(getters.categorySubTotal(shippingCategoryKey)).toFixed(2)); let shippingCharge = parseFloat(parseFloat(getters.categoryShippingCharge(shippingCategoryKey)).toFixed(2)); let appliedStoreCredit = parseFloat(parseFloat(getters.appliedStoreCredit).toFixed(2)); if (shippingCategoryKey !== 'marine_life') { appliedStoreCredit = 0.00 } subTotal -= appliedStoreCredit if (shippingCategoryKey in state.couponData) { let requiredSubTotal = parseFloat(state.couponData[shippingCategoryKey].required_sub_total); if (subTotal >= requiredSubTotal) { let couponDiscount = parseFloat(parseFloat(state.couponData[shippingCategoryKey].discount).toFixed(2)); if (state.couponData[shippingCategoryKey].discount_type === 'fixed') { subTotal -= couponDiscount; } else { subTotal = subTotal - (subTotal * (couponDiscount / 100)); } // if (state.couponData[shippingCategoryKey].give_free_shipping) { // shippingCharge = 0.0; // } } } //console.log(parseFloat(state.shippingCategories[shippingCategoryKey].summary.packagingCharge).toFixed(2)) //console.log(parseFloat(parseFloat(state.shippingCategories[shippingCategoryKey].summary.tax).toFixed(2))) total = parseFloat(parseFloat(total).toFixed(2)) total += parseFloat(parseFloat(subTotal).toFixed(2)) total += parseFloat(parseFloat(shippingCharge).toFixed(2)) total += parseFloat(parseFloat(state.shippingCategories[shippingCategoryKey].summary.packagingCharge).toFixed(2)) total += parseFloat(parseFloat(state.shippingCategories[shippingCategoryKey].summary.tax).toFixed(2)) // - appliedStoreCredit if (total < 0) { total = 0; } return Number(parseFloat(total).toFixed(2)); }, cartProductByCategoryIndex: state => (shippingCategoryKey, index) => { return state.shippingCategories[shippingCategoryKey].products[index]; }, categorySaturdayCost: (state, getters) => shippingCategoryKey => { return state.shippingCategories[shippingCategoryKey].meta.saturday_delivery_charge; }, categoryPriorityCost: (state, getters) => shippingCategoryKey => { return state.shippingCategories[shippingCategoryKey].meta.priority_shipping_charge; }, categoryAlaskaCost: (state, getters) => shippingCategoryKey => { return state.alaskaCostForMarineLife; }, totalRedeemedPoints: (state, getters) => { let total = 0; Object.keys(state.shippingCategories).forEach(shippingCategoryKey => { state.shippingCategories[shippingCategoryKey].products.forEach(product => { if (product.payWithRewardPoints) { total += parseInt(product.reward_redeem) * parseInt(product.qtyAddedToCart) } }); }); return total; }, compareProductInstances: (state, getters) => (product, latest_product, type='products') => { let changed_products = {'old_product': product, new_product: latest_product, 'messages': []} if (latest_product.stock <= 0) { let remove_message = 'Product `'+latest_product.name+'` has become out of stock. You may choose another item. Please remove this one to proceed.' if(type === 'free_products') { remove_message += ' (Free Item)'; } if(type === 'discounted_products') { remove_message += ' (Discounted Item)'; } changed_products['messages'].push(remove_message); return changed_products } /** * @TODO: If a free product is also added as a normal product, while checking the stock with vendor, * We need to be sure that vendor has (FREE_QTY + REGULAR_QTY) available. * Currently we are checking the stock separately */ if( product.qtyAddedToCart > latest_product.stock || ( product.qtyAddedToCart === 0 && (product.qtyAddedToCart < latest_product.stock) ) ){ let new_stock = latest_product.stock if(product.qtyAddedToCart === 0) { new_stock = 1 } let stock_message = 'Stock Changed by '+product.qtyAddedToCart+' --> '+new_stock+' for: `' + latest_product.name + '`' if(type === 'free_products') { stock_message += ' (Free Item)'; } if(type === 'discounted_products') { stock_message += ' (Discounted Item)'; } changed_products['messages'].push(stock_message); } let new_price = latest_product.onsale ? latest_product.saleprice : latest_product.price let old_price = product.onsale ? product.saleprice : product.price new_price = parseFloat(new_price).toFixed(2) old_price = parseFloat(old_price).toFixed(2) if(type === 'free_products') { new_price = parseFloat('0.00').toFixed(2); } if(product.is_discounted) { new_price = old_price } // if(new_price !== old_price) { // let price_message = 'Price Changed by $'+old_price+' --> $'+new_price+' for: `' + latest_product.name + '`'; // if(type === 'free_products') { // price_message += ' (Free Item)'; // } // changed_products['messages'].push(price_message) // } return changed_products }, handleUpdateItem: (state, getters) => (product, productIndex, shippingCategoryKey, type='products', hasChangesList=[], changed_products_messages={}, oos_products=[]) => { let hasChanges = 0; type = $.inArray(type, ['products', 'free_products', 'discounted_products']) ? type : 'products' // console.log(hasChangesList) if(product && product.hasOwnProperty('catalogid')) { $.ajax({ url: `products_stock/${product.catalogid}/json`, type: "get", async: false, success: (product_payload) => { const latest_product = product_payload.product let changed_product = getters.compareProductInstances(product, latest_product, type) if (changed_product && changed_product.hasOwnProperty('messages') && changed_product.messages) { if (changed_product.messages.length > 0) { let key = product.catalogid if(type === 'free_products') { key += '_free'; } if(type === 'discounted_products') { key += '_discounted'; } changed_products_messages[key] = changed_product.messages } } if (latest_product.stock <= 0) { let itemOfLocalStore; itemOfLocalStore = state.shippingCategories[shippingCategoryKey][type][productIndex]; if(itemOfLocalStore.qtyAddedToCart !== latest_product.stock || latest_product.stock === 0) { if(type === 'products') { try{ gtag("event", "add_to_cart", { currency: "USD", value: String(latest_product.price), items: [{ item_id: String(latest_product.catalogid), item_name: String(latest_product.name), item_brand: "Salt Water Fish", price: String(latest_product.price), quantity: String(product.qtyAddedToCart), }], }); } catch (e) { console.log(e.message) } try { ga('ec:addProduct', { 'id': String(latest_product.catalogid), 'name': String(latest_product.name), 'price': Number(latest_product.price), 'quantity': Number(product.qtyAddedToCart), 'category': String(latest_product.category) }); ga('ec:setAction', 'remove'); ga('send', 'event', 'Product', 'click'); } catch (err) { console.log(err.message); } } hasChanges = 1; if(itemOfLocalStore) { Vue.set(state.shippingCategories[shippingCategoryKey][type][productIndex], 'stock', latest_product.stock) Vue.set(state.shippingCategories[shippingCategoryKey][type][productIndex], 'display_stock', latest_product.display_stock) Vue.set(state.shippingCategories[shippingCategoryKey][type][productIndex], 'qtyAddedToCart', 0) oos_products.push(itemOfLocalStore.catalogid) } } //state.shippingCategories[shippingCategoryKey][type].splice(productIndex, 1); //$.post('/cart-item-delete', itemOfLocalStore, (response) => {}); } else { if (!product.is_discounted) { if (product.qtyAddedToCart > latest_product.stock) { hasChanges = 1; // if added quantity is more than stock then replace cart product quantity with max stock product.qtyAddedToCart = latest_product.stock } } else { latest_product.price = product.price; latest_product.saleprice = product.saleprice; } if(type === 'products') { if(product.qtyAddedToCart === 0) { product.qtyAddedToCart = 1 hasChanges = 1; } } if(type === 'free_products') { // From cart.views.coupon_apply.CouponApply latest_product.price = parseFloat('0.00').toFixed(2); latest_product.saleprice = parseFloat('0.00').toFixed(2); } if(product.is_discounted || type==='free_products') { latest_product.is_eibi = (latest_product.drop_shipper_sku.toUpperCase().lastIndexOf('ICF', 0) === 0); latest_product.maximumorder = (latest_product.maximumorder) ? latest_product.maximumorder : 10; latest_product.minimumorder = (latest_product.minimumorder) ? latest_product.minimumorder : 1; } const updated_product = {...product, ...latest_product} Vue.set(state.shippingCategories[shippingCategoryKey][type], productIndex, updated_product) $.post('/cart-item-sync', updated_product, (response) => {}); } if (!hasChanges) { for (let key in latest_product) { if($.inArray(key, ['stock', 'display_stock'])) { return; } // if (product.hasOwnProperty(key) && latest_product[key] != product[key]) { // //console.log(product.catalogid, key, latest_product[key], product[key]); // hasChanges = 1 // } } } }, }) } hasChangesList.push(hasChanges); //console.log(hasChangesList, changed_products_messages) return [hasChangesList, changed_products_messages, oos_products]; } }, }); cartStore.subscribeAction({ after: (action, state) => { if (action.type === 'DECREMENT_QTY' || action.type === 'REMOVE_FROM_CART') { let marineLifeSubtotal = cartStore.getters.categorySubTotal('marine_life'); let appliedStoreCredit = cartStore.getters.appliedStoreCredit; if (marineLifeSubtotal < appliedStoreCredit) { cartStore.dispatch('UNSET_APPLIED_STORE_CREDIT'); } } } }); let miniCartSummaryApp = new Vue({ el: "#miniCartSummaryApp", data: { store: cartStore }, methods: { handleMiniCart: function(cartStore) { // not syncing cart from database for guest user const isLoggedIn = !$("#header-account-dropdown").parent().hasClass("d-none") if(isLoggedIn){ let listoflocalitems = [] Object.keys(this.store.state.shippingCategories).forEach(key => { if (this.store.state.shippingCategories[key].products.length) { let shippingCategory_productsLength = this.store.state.shippingCategories[key].products.length while (shippingCategory_productsLength--) { let productIndex = shippingCategory_productsLength let product = this.store.state.shippingCategories[key].products[productIndex] // product 11 is gift certificate and we are not sending it to cart sync because it has selected price which // we cant store at database and other details like to who giftcert should apply. if(!product.is_discounted && product.catalogid !== 11){ listoflocalitems.push(product); } } } }); $.ajax({ type:'post', url: '/cart-multi-item-sync', data: {"local_items": JSON.stringify(listoflocalitems)}, async: false, }); } Object.keys(this.store.state.shippingCategories).forEach(key => { if (this.store.state.shippingCategories[key].products.length) { if(isLoggedIn){ let shippingCategory_productsLength = this.store.state.shippingCategories[key].products.length while (shippingCategory_productsLength--) { let productIndex = shippingCategory_productsLength let product = this.store.state.shippingCategories[key].products[productIndex] // product 11 is gift certificate and we are not sending it to cart sync because it has selected price which // we cant store at database and other details like to who giftcert should apply. if(!product.is_discounted && product.catalogid !== 11){ //listoflocalitems.push(product); this.store.state.shippingCategories[key].products.splice(productIndex, 1); } } } cartStore.dispatch('FETCH_CATEGORY_SHIPPING_CHARGE', {shippingCategoryKey: key}) .then(result => cartStore.dispatch('FETCH_CATEGORY_TAX', {shippingCategoryKey: key})); } }); if(isLoggedIn){ this.handleCartItemsWithServer(cartStore); } $('#miniCartSummaryApp .badge').removeClass('d-none'); }, handleCartItemsWithServer: function (cartStore) { let fromCartPage = window.location.pathname === "/viewcart" ? 1 : 0 $.ajax({ url : `/my-abandoned-cart-items`, type : "get", data: {'fromCartPage': fromCartPage}, async: false, success : (payload) => { if (payload.abandoned_cart_items.length) { let shippingCategories = [] //console.log("abandon cartitem default", payload.abandoned_cart_items); if(payload.hasOwnProperty('changed_items') && payload.changed_items.length) { if (window.location.pathname === "/orderconfirmation") { alert('Some items are changed. We will be redirecting you to the cart page. Please review those ' + 'and process to checkout again') const urlParams = new URLSearchParams(window.location.search); urlParams.set("changedItem", "true") urlParams.delete('paymentmethod') urlParams.delete('reload') window.location.href = `/viewcart?${urlParams.toString()}`; } } payload.abandoned_cart_items.forEach(AbandonCartItem => { console.log("cartitem id", AbandonCartItem.catalogid, "cartitem paid with paints? ", AbandonCartItem.paid_with_point, AbandonCartItem); if(AbandonCartItem.paid_with_point === true && parseInt(AbandonCartItem.reward_redeem) > 0){ AbandonCartItem.payWithRewardPoints = true; }else{ AbandonCartItem.payWithRewardPoints = false; } AbandonCartItem.qtyAddedToCart = 0; AbandonCartItem.addedToCartOn = new Date().getTime(); var foundIndex = cartStore.state.shippingCategories[AbandonCartItem.shipping_category_key].products.findIndex(item => item.catalogid === AbandonCartItem.catalogid); if (foundIndex === -1) { cartStore.dispatch('ADD_TO_CART', AbandonCartItem); cartStore.dispatch('ADD_LAST_ADDED_ITEMS', AbandonCartItem); shippingCategories.push(AbandonCartItem.shipping_category_key) } display_cart_page_errors(AbandonCartItem) }); if(shippingCategories.length) { shippingCategories.forEach(shippingCategoryKey => { cartStore.dispatch('FETCH_CATEGORY_SHIPPING_CHARGE', {shippingCategoryKey: shippingCategoryKey}) .then(result => cartStore.dispatch('FETCH_CATEGORY_TAX', {shippingCategoryKey: shippingCategoryKey})) .then(result => localdb.setItem('cartStore', cartStore.state)) .then(result => { // window.location.href = '/viewcart'; $.post('/cart-snapshot', {cart_store: JSON.stringify(cartStore.state)}); }); }) } if(payload.out_of_stock_items.length) { $.ajax({ url: `notify_oss`, type: "post", data: {'oos_products': payload.out_of_stock_items}, async: false, }); } } else { for(let shippingCategory in cartStore.state.shippingCategories) { if(shippingCategory !== 'gift_certificates') { Vue.set(cartStore.state.shippingCategories[shippingCategory], 'products', []); Vue.set(cartStore.state.shippingCategories[shippingCategory], 'free_products', []); } } } } }) } }, computed: { cartTotalItems: function () { return this.store.getters.cartTotalItems; }, cartTotalQuantities: function () { return this.store.getters.cartTotalQuantities; }, cartSubTotal: function () { return parseFloat(this.store.getters.cartSubTotal).toFixed(2); }, cartShippingCharge: function () { return parseFloat(this.store.getters.cartShippingCharge).toFixed(2); }, cartPackagingCharge: function () { return parseFloat(this.store.getters.cartPackagingCharge).toFixed(2); }, cartTaxPercent: function () { return parseFloat(this.store.state.taxPercent).toFixed(2); }, cartTax: function () { return parseFloat(this.store.getters.cartTax).toFixed(2); }, cartGrandTotal: function () { return parseFloat(this.store.getters.cartGrandTotal).toFixed(2); }, cartCouponDiscount: function () { return parseFloat(this.store.getters.cartCouponDiscount).toFixed(2); }, isCouponApplied: function () { if (this.store.state.couponCode) { return true; } return false; }, appliedCoupon: function () { return this.store.state.couponCode; }, isGiftCertApplied: function () { return this.store.getters.isGiftCertApplied; }, appliedGiftCertAmount: function () { return parseFloat(this.store.state.appliedGiftCertAmount).toFixed(2); }, isStoreCreditApplied: function () { return this.store.getters.isStoreCreditApplied; }, appliedStoreCredit: function () { return parseFloat(this.store.getters.appliedStoreCredit).toFixed(2); } } }); localdb.getItem('cartStore').then(guestLocalCartStore => { if (guestLocalCartStore) { cartStore.replaceState(guestLocalCartStore); } cartStore.dispatch('INIT').then(result => { miniCartSummaryApp.handleMiniCart(cartStore) }); }); let loginForms = ['#loginForm', '#headerLoginForm', '#cartPageLoginForm', '#checkoutLoginForm']; loginForms.forEach(function (loginFormId) { let loginForm; if ($(loginFormId).length) { loginForm = new Vue({ el: loginFormId, data: function () { return { store: cartStore, isSubmitting: false, showAjaxMessage: false, ajaxMessage: null, ajaxMessageClass: {}, formData: { email: null, password: null, next: null }, isLoggedIn: false, storeCreditToApply: null, applyingStoreCredit: false }; }, validations: { formData: { email: { required, email }, password: { required, } } }, mounted: function() { if (loginFormId === '#loginForm') { this.formData.next = '/myaccount'; } if (loginFormId === '#headerLoginForm') { this.formData.next = '/myaccount'; } if (loginFormId === '#cartPageLoginForm') { this.formData.next = null; } if (loginFormId === '#checkoutLoginForm') { this.formData.next = '/orderconfirmation'; } if ($('input[name="next"]').length) { this.formData.next = $('input[name="next"]').first().val() } $.get('/loggedin-customer-data', response => { if (response.success) { this.store.dispatch('SET_AVAILABLE_STORE_CREDIT', {storeCredit: response.store_credit}); this.isLoggedIn = true; } else { this.isLoggedIn = false; } }); }, methods: { redirectTo: function (url) { window.location.href = url; }, reApplyGiftCertificate: function () { if(this.store.state.isGiftCertApplied){ // console.log("Applied") // total gift certificate amount let giftCertAmount = this.store.state.availableGiftCertAmount; let giftCertCode = this.store.state.appliedGiftCertCode; // this is the amount they have applied let giftCertAmountToApply = this.store.state.appliedGiftCertAmount; let total = 0.0; total = total + parseFloat(this.store.getters.cartSubTotal) + parseFloat(this.store.getters.cartShippingCharge) + parseFloat(this.store.getters.cartPackagingCharge) + parseFloat(this.store.getters.cartTax); total = total - parseFloat(this.store.getters.cartCouponDiscount); // if (state.isGiftCertApplied) { // total = total - parseFloat(state.appliedGiftCertAmount); // } if (this.store.getters.isStoreCreditApplied) { total = total - parseFloat(this.store.state.appliedStoreCredit); } if (parseFloat(total) < 0) { total = 0.0; } let grandTotal = Number(parseFloat(total).toFixed(2)); if (giftCertAmount > grandTotal) { giftCertAmountToApply = grandTotal; } else { giftCertAmountToApply = giftCertAmount; } if(giftCertAmount && giftCertCode && giftCertAmountToApply){ // console.log("giftCertAmount",giftCertAmount,"giftCertCode",giftCertCode,"giftCertAmountToApply",giftCertAmountToApply,"grandTotal",grandTotal) // removing gift certificate amount this.store.dispatch('UNSET_GIFT_CERT') .then( // applying gift certificate amount this.store.dispatch('SET_GIFT_CERT', { giftCertAmount: giftCertAmount, giftCertCode: giftCertCode, giftCertAmountToApply: giftCertAmountToApply }) ) .then(result => localdb.setItem('cartStore', this.store.state)) .then(result => this.store.dispatch('SAVE_CART_SNAPSHOT', {cart_store: JSON.stringify(this.store.state)})) .catch(error => { }); } } else{ // console.log("NOT APLE") } }, applyStoreCredit: function () { $('#checkoutInitApp').hide(); console.log("we have applying store credit"); this.applyingStoreCredit = true; setTimeout(() => { let enteredStoreCredit = parseFloat(this.storeCreditToApply); if (isNaN(enteredStoreCredit)) { this.storeCreditToApply = ''; $('#alertModal .modal-body').html('Please enter number in store credit input field.'); $('#alertModal').modal('show'); } else if (enteredStoreCredit <= 0) { this.storeCreditToApply = ''; $('#alertModal .modal-body').html('Please enter positive number in store credit input field.'); $('#alertModal').modal('show'); } else if (enteredStoreCredit > parseFloat(this.availableStoreCredit)) { this.storeCreditToApply = ''; $('#alertModal .modal-body').html('You cannot exceed more than what is available in your store credit.'); $('#alertModal').modal('show'); } else { this.store.dispatch('SET_APPLIED_STORE_CREDIT', {storeCreditToApply: enteredStoreCredit}) .then(result => this.store.dispatch('SAVE_CART_SNAPSHOT', {cart_store: JSON.stringify(this.store.state)})) .then(result => this.store.dispatch( 'FETCH_CATEGORY_SHIPPING_CHARGE', { shippingCategoryKey: 'marine_life', shippingState: this.store.state.shippingState, shippingZip: this.store.state.shippingZipCode, } )) .then(result => this.store.dispatch( 'FETCH_CATEGORY_TAX', { shippingCategoryKey: 'marine_life', shippingState: this.store.state.shippingState, shippingZip: this.store.state.shippingZipCode, } )) .then(result => { setTimeout(() => { this.reApplyGiftCertificate() },1200) }) .then(result => localdb.setItem('cartStore', this.store.state)) .then(result => this.store.dispatch('SAVE_CART_SNAPSHOT', {cart_store: JSON.stringify(this.store.state)})) .catch(error => { $('#alertModal .modal-body').html(error.message); $('#alertModal').modal('show'); }) } this.applyingStoreCredit = false; $('#checkoutInitApp').show(); }, 1000); }, removeStoreCredit: function() { let confirmed = confirm('Are you sure you want to remove store credit?'); if (confirmed) { $('#checkoutInitApp').hide(); this.store.dispatch('UNSET_APPLIED_STORE_CREDIT') .then(result => this.store.dispatch('SAVE_CART_SNAPSHOT', {cart_store: JSON.stringify(this.store.state)})) .then(result => this.store.dispatch( 'FETCH_CATEGORY_SHIPPING_CHARGE', { shippingCategoryKey: 'marine_life', shippingState: this.store.state.shippingState, shippingZip: this.store.state.shippingZipCode, } )) .then(result => this.store.dispatch( 'FETCH_CATEGORY_TAX', { shippingCategoryKey: 'marine_life', shippingState: this.store.state.shippingState, shippingZip: this.store.state.shippingZipCode, } )) .then(result => { setTimeout(() => { this.reApplyGiftCertificate() },1200) }) .then(result => localdb.setItem('cartStore', this.store.state)) .then(result => this.store.dispatch('SAVE_CART_SNAPSHOT', {cart_store: JSON.stringify(this.store.state)})) .catch(error => { $('#alertModal .modal-body').html(error.message); $('#alertModal').modal('show'); }) $('#checkoutInitApp').show(); } }, submit: function () { this.showAjaxMessage = false; this.$v.$touch(); if (!this.$v.$invalid) { this.isSubmitting = true; setTimeout(() => { $.ajax({ type: 'POST', url: '/login', data: this.$data.formData, error: (jqXHR, textStatus, errorThrown) => { this.isSubmitting = false; this.ajaxMessageClass = { 'alert': true, 'alert-brand-color-accent-primary': true } this.ajaxMessage = 'Something went wrong.'; this.showAjaxMessage = true; }, success: (data, textStatus, jqXHR) => { this.isSubmitting = false; if (data.success) { this.ajaxMessageClass = { 'alert': true, 'alert-brand-color-accent-secondary': true } } else { this.ajaxMessageClass = { 'alert': true, 'alert-brand-color-accent-primary': true } } if (data.message) { this.ajaxMessage = data.message; this.showAjaxMessage = true; } if (data.success) { $('.customer-only').removeClass('d-none'); $('.guest-only').addClass('d-none'); this.isLoggedIn = true; let customerData = { email: data.email, firstName: data.firstName, lastName: data.lastName, availableRewardPoints: data.availableRewardPoints }; this.storeCreditToApply = data.store_credit; this.store.dispatch('SET_AVAILABLE_STORE_CREDIT', {storeCredit: data.store_credit}) .then(result => this.store.dispatch('UPDATE_SHIPPING_STATE', {shippingState: data.state})) .then(result => this.store.dispatch('UPDATE_SHIPPING_ZIP_CODE', {shippingZipCode: data.zip})) .then(result => localdb.removeItem('guestData')) .then(result => localdb.setItem('customerData', customerData)) .then(result => { Object.keys(this.store.state.shippingCategories).forEach(key => { if (this.store.state.shippingCategories[key].products.length) { this.store.dispatch('FETCH_CATEGORY_SHIPPING_CHARGE', {shippingCategoryKey: key}) } }); }) .then(result => { Object.keys(this.store.state.shippingCategories).forEach(key => { if (this.store.state.shippingCategories[key].products.length) { this.store.dispatch('FETCH_CATEGORY_TAX', {shippingCategoryKey: key}) } }); }) .then(result => localdb.setItem('cartStore', this.store.state)) //.then(result => this.store.dispatch('SAVE_CART_SNAPSHOT', {cart_store: JSON.stringify(this.store.state)})) .then(result => { if (loginFormId === '#cartPageLoginForm'){ window.location.reload() }else{ if (data.redirectTo) { const urlParams = new URLSearchParams(window.location.search).toString(); if(urlParams){ this.redirectTo(data.redirectTo+'?'+urlParams); } else{ this.redirectTo(data.redirectTo); } } } }); } } }); }, 1000); } } }, computed: { cartTotalItems: function () { return this.store.getters.cartTotalItems; }, cartTotalQuantities: function () { return this.store.getters.cartTotalQuantities; }, availableStoreCredit: function () { return parseFloat(this.store.getters.availableStoreCredit).toFixed(2); }, appliedStoreCredit: function () { return parseFloat(this.store.getters.appliedStoreCredit).toFixed(2); }, isStoreCreditApplied: function () { if (parseFloat(this.store.getters.appliedStoreCredit) > 0) { return true; } return false; } } }); } }); let searchSuggestionApp = new Vue({ el: '#searchSuggestionApp', data: { searchTerm: '', products: [], filteredProducts: [], fuse: null, showSuggestions: false }, mounted: function () { }, methods: { getData: function(e) { if (this.products.length < 1) { $.get(`/search-suggestions`, (payload) => { this.products = payload.products this.fuse = new Fuse(this.products, { includeScore: true, keys: ['name', 'url'] }); $('#searchSuggestionApp .search-suggestions').removeClass('d-none'); }); } }, handleKeyDown: function(e) { if (e.key === 'Escape' || e.keyCode === 27) { this.showSuggestions = false; this.searchTerm = ''; setTimeout(() => { this.$refs.searchInput.focus(); }, 0); } else if (e.keyCode === 13) { e.preventDefault(); let activeFocusIndex = $('.search-suggestions').find('.active').index(); if (activeFocusIndex != -1) { let activeFocusUrl = $('.search-suggestions a').eq(activeFocusIndex).attr('href'); window.location.href = activeFocusUrl; } else { $('#searchSuggestionApp').trigger('submit'); } } else { let currentFocus = $('.search-suggestions').find('.active').index(); let totalSearchResult = $('.search-suggestions').find('a').length; let maxFocus = totalSearchResult - 1; let newFocus; if (e.keyCode === 38) { newFocus = currentFocus - 1; if (newFocus < 0) { newFocus = maxFocus; } } if (e.keyCode === 40) { newFocus = currentFocus + 1; if (newFocus > maxFocus) { newFocus = 0; } } $('.search-suggestions a').removeClass('active'); $('.search-suggestions a').eq(newFocus).addClass('active'); } }, getSuggestions: function (e) { let term = this.searchTerm; if (term.length) { this.filteredProducts = this.fuse.search(term); this.showSuggestions = true; } else { this.showSuggestions = false; } }, resetSearch: function(e) { this.searchTerm = ''; this.showSuggestions = false; setTimeout(() => { this.$refs.searchInput.focus(); }, 0); } }, computed: { filteredProductsSliced: function () { return this.filteredProducts.slice(0, 7) } } }); let newsletterForms = ['#footerNewsletterForm', '#modalNewsletterForm']; newsletterForms.forEach(function(newsletterFormId) { let newsletterForm; if ($(newsletterFormId).length) { newsletterForm = new Vue({ el: newsletterFormId, data: { isSubmitting: false, showAjaxMessage: false, ajaxMessage: null, ajaxMessageClass: {}, formData: { email: null, elementId: newsletterFormId, }, }, validations: { formData: { email: { required, email } } }, mounted: function() { }, methods: { submit: function() { this.showAjaxMessage = false; this.$v.$touch(); if (!this.$v.$invalid) { this.isSubmitting = true; setTimeout(() => { $.post('newsletter-subscribers/create', this.$data.formData, response => { this.isSubmitting = false; this.$v.$reset(); if (newsletterFormId == '#footerNewsletterForm') { if (response.success) { this.formData.email = ''; $('#alertModal .modal-title').html('Success'); } $('#alertModal .modal-body').html(response.message); $('#alertModal').modal('show'); } if (newsletterFormId == '#modalNewsletterForm') { if (response.success) { this.formData.email = ''; this.ajaxMessageClass = { 'alert': true, 'alert-brand-color-accent-secondary': true } } else { this.ajaxMessageClass = { 'alert': true, 'alert-brand-color-accent-primary': true } } if (response.message) { this.ajaxMessage = response.message; this.showAjaxMessage = true; } } }); }, 2000) } else { if (newsletterFormId == '#footerNewsletterForm') { $('#alertModal .modal-body').html('Please enter a valid email address.'); $('#alertModal').modal('show'); } } } } }); } }); function display_cart_page_errors(error_object) { if(typeof error_object !== 'object') { return; } if(error_object.hasOwnProperty('info_messages') && error_object.info_messages.length) { if(typeof error_object.info_messages === 'object') { $('#myCartListingApp .js_messages').removeClass('d-none') $('#myCartListingApp .js_messages .alert-info') .removeClass('d-none') for (var i in error_object.info_messages) { let message = error_object.info_messages[i] $('#myCartListingApp .js_messages .alert-info ul').append('
  • '+message+'
  • ') } } } if(error_object.hasOwnProperty('warning_messages') && error_object.warning_messages.length) { if(typeof error_object.warning_messages === 'object') { $('#myCartListingApp .js_messages').removeClass('d-none') $('#myCartListingApp .js_messages .alert-warning') .removeClass('d-none') for (var i in error_object.warning_messages) { let message = error_object.warning_messages[i] $('#myCartListingApp .js_messages .alert-warning ul').append('
  • '+message+'
  • ') } } } if(error_object.hasOwnProperty('error_messages') && error_object.error_messages.length) { if(typeof error_object.error_messages === 'object') { $('#myCartListingApp .js_messages').removeClass('d-none') $('#myCartListingApp .js_messages .alert-danger') .removeClass('d-none') for (var i in error_object.error_messages) { let message = error_object.error_messages[i] $('#myCartListingApp .js_messages .alert-danger ul').append('
  • '+message+'
  • ') } } } } function str_to_base64(str) { try { return btoa(unescape(encodeURIComponent(str))); } catch (e) { return '' } } function base64_to_str(b64) { try { return decodeURIComponent(escape(window.atob(b64))); } catch (e) { return '' } } /** * use this to make a Base64 encoded string URL friendly, * i.e. '+' and '/' are replaced with '-' and '_' also any trailing '=' * characters are removed * * @param {String} str the encoded string * @returns {String} the URL friendly encoded String */ function Base64EncodeUrl(str){ return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''); } /** * Use this to recreate a Base64 encoded string that was made URL friendly * using Base64EncodeurlFriendly. * '-' and '_' are replaced with '+' and '/' and also it is padded with '+' * * @param {String} str the encoded string * @returns {String} the URL friendly encoded String */ function Base64DecodeUrl(str){ str = (str + '===').slice(0, str.length + (str.length % 4)); return str.replace(/-/g, '+').replace(/_/g, '/'); } setInterval(() => { cartStore.dispatch('AUTO_EXPIRE_EIBI', {expireAfterMinutes: 45}).then(result => { //localdb.setItem('cartStore', cartStore.state); //$.post('/cart-snapshot', {cart_store: JSON.stringify(cartStore.state)}); }); }, 30000); var newsletter_hidden = Cookies.get('subscribeHidden'); $('#newsletterModal').on('hidden.bs.modal', function (e) { Cookies.set('subscribeHidden', "true", {expires: 7}); if ($('#canvasOverlay').hasClass('reOpenCanvas')) { openPushMenu(); $('#canvasOverlay').removeClass('reOpenCanvas'); } }); setTimeout(function() { if (newsletter_hidden !== 'true') { if ($('#canvasOverlay').hasClass('showCanvasOverlay')) { closePushMenu(); $('#canvasOverlay').addClass('reOpenCanvas') } $("#newsletterModal").modal("show"); } }, 10000);