var app = new Vue({ el: '#app-order-order', data() { return Object.assign({ order: null, timerAjaxInfosProducts: false, xhr: false, loading: false, loadingProducts: false, loadingInit: true, cancelTokenSource: null, step: null, producer: null, user: null, date: null, dateFormat: null, distributions: [], distribution: null, pointsSale: [], pointSaleActive: null, pointSaleActiveId: null, pointsSaleCodes: [], products: [], categories: [], categoryCurrent: null, comment: '', creditCheckbox: false, paymentMethod: 'onsite', useCredit: false, errors: [], disableConfirmButton: false, delivery: false, deliveryAddress: null, urlLogin: '#', producerOptionOrderEntryPoint: null, calendar: { columns: this.isMobile() ? 1 : 2, mode: 'single', attrs: [], availableDates: [], themeStyles: { wrapper: { background: '#F7F7F7', color: '#333', border: 'solid 1px #e0e0e0' }, header: { padding: '10px 10px', }, headerHorizontalDivider: { borderTop: 'solid rgba(255, 255, 255, 0.2) 1px', width: '80%', }, weekdays: { color: 'gray', fontWeight: '600', padding: '10px 10px', fontSize: '2rem' }, weeks: { padding: '0 15px 15px 15px', }, dayContent: function (object) { var style = { fontSize: '1.4rem', padding: app.isMobile() ? '18px' : '20px', }; return style; }, }, masks: { //dayPopover: 'DD/MM/YYYY' dayPopover: '' } } }, window.appInitValues); }, mounted: function() { this.initDate(); this.init('first', false); }, methods: { initDate: function() { var dateDefined = $('#order-distribution-date').size() || $('#distribution-date').size() ; if(dateDefined && (this.producerOptionOrderEntryPoint != 'point-sale' || this.pointSaleActiveId)) { if($('#order-distribution-date').size()) { this.date = new Date($('#order-distribution-date').html()) ; } else { this.date = new Date($('#distribution-date').html()) ; } this.dateFormat = ('0' + this.date.getDate()).slice(-2)+ '/' + ('0' + (this.date.getMonth() +1)).slice(-2) + '/' + this.date.getFullYear() ; } }, getDate: function() { return this.formatDate(this.date) ; }, formatDate: function(date) { if(date) { return date.getFullYear() + '-' + ('0' + (date.getMonth() +1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2) ; } return false ; }, formatPrice: formatPrice, getPointSale: function(idPointSale) { for(var key in this.pointsSale) { if(this.pointsSale[key].id == idPointSale) { return this.pointsSale[key] ; } } }, getPointSaleKey: function(idPointSale) { for(var key in this.pointsSale) { if(this.pointsSale[key].id == idPointSale) { return key ; } } }, getProduct: function(idProduct) { for(var key in this.products) { if(this.products[key].id == idProduct) { return this.products[key] ; } } }, init: function(type, loadingProducts) { var app = this ; if(loadingProducts) { if (app.timerAjaxInfosProducts) { clearTimeout(app.timerAjaxInfosProducts); } app.timerAjaxInfosProducts = setTimeout(function(app) { app.loadingProducts = true ; if(app.xhr) { app.xhr.abort(); } app.xhr = $.get('ajax-infos', { date : app.getDate(), pointSaleId: app.pointSaleActiveId ? app.pointSaleActiveId : (app.pointSaleActive ? app.pointSaleActive.id : 0), productsJson: JSON.stringify(app.getProductsArray()), loadingProducts: loadingProducts }, function(response) { app.products = response.products; app.loadingProducts = false; }, 'json'); }.bind(this, app), 500); return; } else { this.loading = true ; } if(app.isChangeState('date', 'date', 'point-sale')) { app.pointSaleActive = null ; app.products = [] ; } //app.cancelTokenSource = axios.CancelToken.source(); axios.get("ajax-infos",{ //cancelToken: app.cancelTokenSource.token, params: { date : this.getDate(), pointSaleId: this.pointSaleActiveId ? this.pointSaleActiveId : (this.pointSaleActive ? this.pointSaleActive.id : 0), productsJson: this.getProductsArray(), loadingProducts: loadingProducts }}) .catch(function (thrown) { if (axios.isCancel(thrown)) { } }) .then(function(response) { if(response) { app.calendar.attrs = []; app.calendar.availableDates = []; var distributions = response.data.distributions; app.distributions = distributions; if (distributions.length) { var arrayDate; var highlightStyle = { style: { background: 'white', border: 'solid 2px #198754' }, contentStyle: { color: '#198754' } }; for (var i = 0; i < distributions.length; i++) { app.calendar.attrs.push({ highlight: highlightStyle, dates: distributions[i].date }); arrayDate = distributions[i].date.split('-'); app.calendar.availableDates.push({ highlight: highlightStyle, start: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]), end: new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]) }); } } if (response.data.leave_period) { leavePeriodStartDateArray = response.data.leave_period.start.split('-'); leavePeriodEndDateArray = response.data.leave_period.end.split('-'); app.calendar.attrs.push({ highlight: { style: { //background: '#E09F3E' background: 'gray' }, contentStyle: { color: 'white' } }, dates: { start: new Date(leavePeriodStartDateArray[0], leavePeriodStartDateArray[1] - 1, leavePeriodStartDateArray[2]), end: new Date(leavePeriodEndDateArray[0], leavePeriodEndDateArray[1] - 1, leavePeriodEndDateArray[2]) }, popover: { label: 'En congé', hideIndicator: true, isInteractive: true }, }); } if (response.data.distribution) { app.distribution = response.data.distribution; } var orders = []; if (response.data.orders) { orders = response.data.orders; } if (orders.length) { for (var i = 0; i < orders.length; i++) { arrayDate = orders[i].date_distribution.split('-'); var dateOrder = new Date(arrayDate[0], arrayDate[1] - 1, arrayDate[2]); if (app.isAvailableDate(dateOrder)) { app.calendar.attrs.push({ highlight: { style: { background: '#198754' }, contentStyle: { color: 'white' } }, popover: { label: orders[i].pointSale.name + ' (' + app.formatPrice(orders[i].amount_total) + ')', hideIndicator: true, isInteractive: true }, dates: orders[i].date_distribution }); } } } app.producer = response.data.producer; app.user = response.data.user; app.useCredit = response.data.producer.use_credit_checked_default; if (response.data.points_sale) { app.pointsSale = []; var orderPointSale = 0; for (var key in response.data.points_sale) { response.data.points_sale[key].order = orderPointSale++; app.pointsSale[response.data.points_sale[key].id] = response.data.points_sale[key]; if (!app.pointsSaleCodes[response.data.points_sale[key].id]) { app.pointsSaleCodes[response.data.points_sale[key].id] = ''; Vue.set(app.pointsSaleCodes, response.data.points_sale[key].id, ''); } } } if (app.pointSaleActiveId) { app.pointSaleActive = app.getPointSale(app.pointSaleActiveId); } if (app.pointSaleActive) { if (app.producer.credit && app.pointSaleActive.payment_method_credit && (app.pointSaleActive.credit_functioning == 'mandatory' || (app.pointSaleActive.credit_functioning == 'user' && app.user.credit_active) || (app.pointSaleActive.credit_functioning == 'optional' && response.data.producer.use_credit_checked_default))) { app.paymentMethod = 'credit'; } else if (app.pointSaleActive.payment_method_onsite) { app.paymentMethod = 'onsite'; } else if (app.pointSaleActive.payment_method_online) { app.paymentMethod = 'online'; } } if (app.isChangeState('point-sale', 'point-sale', 'date')) { app.date = null; app.dateFormat = null; } // update order var updateOrder = false; if (app.isChangeState('date', 'point-sale', 'products') || app.isChangeState('date', 'date', 'point-sale') || app.isChangeState('point-sale', 'date', 'products') || app.isChangeState('point-sale', 'point-sale', 'date')) { updateOrder = true; } if (updateOrder) { app.updateOrder(response); } if (type == 'first') { if (app.getDate() && app.pointSaleActive) { app.step = 'products'; if (response.data.products) { app.products = response.data.products; } app.updateOrder(response); } else if (app.producer.option_order_entry_point == 'point-sale') { app.step = 'point-sale'; } else if (app.getDate() && app.producer && app.producer.option_order_entry_point == 'date') { app.step = 'point-sale'; } else { app.step = 'date'; } } if (response.data.categories) { app.categories = response.data.categories; for (keyCategory in response.data.categories) { var category = response.data.categories[keyCategory]; if (category.id && app.countProductsByCategory(category)) { app.setCategoryCurrent(category, true); break; } } } setTimeout(function () { app.responsive(); opendistrib_products(); }, 500); app.loading = false; app.loadingProducts = false; app.loadingInit = false; } }); }, updateOrder: function(response) { var app = this; if(response.data.products) { app.products = response.data.products; } app.order = null ; if(response.data.order) { app.order = response.data.order ; app.comment = app.order.comment ; if(app.order.delivery_address && app.order.delivery_address.length > 0) { app.deliveryAddress = app.order.delivery_address ; } app.pointSaleActive = app.getPointSale(response.data.order.id_point_sale) ; } else { app.comment = null ; app.deliveryAddress = null ; if(app.user.address && app.user.address.length > 0) { app.deliveryAddress = app.user.address ; } } }, isMobile: function() { var width_window = parseInt($(window).width()); return width_window <= 768; }, responsive: function() { var app = this; app.responsiveApply(); $(window).resize(function() { app.responsiveApply(); }); }, responsiveApply: function() { var $td_summary = $('#products tr.total td.summary'); if(this.isMobile()) { $td_summary.attr('colspan', 3); } else { $td_summary.attr('colspan', 4); } }, isChangeState: function(entryPoint, oldStep, newStep) { return this.producer && entryPoint == this.producer.option_order_entry_point && oldStep == this.oldStep && newStep == this.step ; }, nextStep: function() { this.errors = [] ; var oldStep = this.step ; var nextStep = null ; // par point de vente if(this.producer && this.producer.option_order_entry_point == 'point-sale') { if(oldStep == 'point-sale') { nextStep = 'date' ; } else if(oldStep == 'date') { nextStep = 'products' ; } } // par date else { if(oldStep == 'date') { nextStep = 'point-sale' ; } else if(oldStep == 'point-sale') { nextStep = 'products' ; } } if(nextStep) { this.changeStep(nextStep) ; } }, changeStep: function(step) { this.errors = [] ; var oldStep = this.step ; this.oldStep = oldStep ; if(oldStep == 'products' && step == 'payment') { this.checkProducts() ; } if(!this.errors.length) { this.step = step ; this.init('basic', false) ; } }, dayClickList: function(event) { var dateStr = event.currentTarget.getAttribute('data-distribution-date') ; var dateObject = new Date(dateStr.replace(/-/g, "/")) ; if(this.isAvailableDate(dateObject)) { this.dayClickEvent(dateObject) ; } }, dayClick: function(day) { if(this.isAvailableDate(day.date)) { this.dayClickEvent(day.date) ; } }, dayClickEvent: function(date) { this.date = date ; this.dateFormat = ('0' + this.date.getDate()).slice(-2)+ '/' + ('0' + (this.date.getMonth() +1)).slice(-2) + '/' + this.date.getFullYear() ; this.nextStep() ; }, isAvailableDate: function(date) { for(var key in this.calendar.availableDates) { if(date.getTime() == this.calendar.availableDates[key].start.getTime()) { return true ; } } return false ; }, pointSaleClick: function(event) { var app = this ; var idPointSale = event.currentTarget.getAttribute('data-id-point-sale') ; var hasCode = event.currentTarget.getAttribute('data-code') ; if(hasCode) { axios.get('ajax-validate-code-point-sale',{params: { idPointSale: idPointSale, code: this.pointsSaleCodes[idPointSale] }}).then(function(response) { if(response.data) { app.pointsSale[app.getPointSaleKey(idPointSale)].invalid_code = false ; app.validatePointSale(idPointSale) ; } else { app.pointsSale[app.getPointSaleKey(idPointSale)].invalid_code = true ; Vue.set(app.pointsSaleCodes, idPointSale, ''); } }) ; } else { this.validatePointSale(idPointSale) ; } }, validatePointSale: function(idPointSale) { this.pointSaleActive = this.getPointSale(idPointSale) ; if(this.pointSaleActive.credit_functioning == 'mandatory' || (this.pointSaleActive.credit_functioning == 'user' && this.user.credit_active)) { this.useCredit = true ; } this.nextStep() ; }, productQuantityClick: function(product, quantity) { if(this.products[product.index].quantity_form + quantity >= 0 && (this.products[product.index].quantity_max == null || this.products[product.index].quantity_form + quantity <= this.products[product.index].quantity_max * this.products[product.index].coefficient_unit) && (this.products[product.index].quantity_remaining == null || (quantity <= (this.products[product.index].quantity_remaining * this.products[product.index].coefficient_unit))) ) { var theQuantity = parseFloat(this.products[product.index].quantity_form) + parseFloat(quantity); this.products[product.index].quantity_form = parseFloat(theQuantity.toFixed(2)) ; if(this.producer.feature_product_accessory_enabled) { this.init('first', true); } } }, oneProductOrdered: function() { for(var key in this.products) { if(this.isProductAvailable(this.products[key]) && this.products[key].quantity_form > 0) { return true ; } } return false ; }, countProductOrdered: function() { var count = 0 ; for(var key in this.products) { if(this.isProductAvailable(this.products[key]) && this.products[key].quantity_form > 0) { if(this.products[key].unit != 'piece') { count ++ ; } else { count += this.products[key].quantity_form ; } } } return count ; }, priceTotal: function(format) { var price = 0 ; for(var key in this.products) { var quantity = this.products[key].quantity_form; if(this.isProductAvailable(this.products[key]) && quantity > 0) { price += (quantity / this.products[key].unit_coefficient) * this.getBestProductPrice(this.products[key].id, this.products[key].quantity_form); } } if(format) { return this.formatPrice(price) ; } else { return numberDecimals(price, 2) ; } }, productHasPrice: function(product) { return product.prices && product.prices.length > 0; }, productHasPriceWithFromQuantity: function(product) { if(this.productHasPrice(product)) { for(var i = 0; i < product.prices.length; i++) { if(product.prices[i].from_quantity > 0) { return true; } } } return false; }, getBestProductPrice: function(idProduct, theQuantity) { var thePriceWithTax = 9999; var product = this.getProduct(idProduct); var pricesArray = product.prices; var unitCoefficient = product.unit_coefficient; if(theQuantity) { theQuantity = theQuantity / unitCoefficient; } for(var i = 0; i < pricesArray.length ; i++) { var priceWithTax = pricesArray[i].price_with_tax; var fromQuantity = pricesArray[i].from_quantity; if(priceWithTax < thePriceWithTax && fromQuantity <= theQuantity) { thePriceWithTax = priceWithTax; } } if(thePriceWithTax == 9999) { return 0; } else { return thePriceWithTax; } }, isPaymentMethodOnsiteActive: function() { return this.pointSaleActive && this.pointSaleActive.payment_method_onsite && !this.isPaymentMethodCreditActiveFunctioningUser(true) && !this.isPaymentMethodCreditActiveFunctioningMandatory(); }, isPaymentMethodCreditActive: function() { return this.isPaymentMethodCreditActiveFunctioningOptional() || this.isPaymentMethodCreditActiveFunctioningMandatory() || this.isPaymentMethodCreditActiveFunctioningUser(true); }, isPaymentMethodCreditActiveCheckBase: function() { return this.producer && this.producer.credit && this.pointSaleActive && this.pointSaleActive.payment_method_credit; }, isPaymentMethodCreditActiveFunctioningUser: function(userCreditActive) { return this.isPaymentMethodCreditActiveCheckBase() && this.pointSaleActive.credit_functioning == 'user' && this.user && this.user.credit_active == userCreditActive; }, isPaymentMethodCreditActiveFunctioningMandatory: function() { return this.isPaymentMethodCreditActiveCheckBase() && this.pointSaleActive.credit_functioning == 'mandatory'; }, isPaymentMethodCreditActiveFunctioningOptional: function() { return this.isPaymentMethodCreditActiveCheckBase() && this.pointSaleActive.credit_functioning == 'optional'; }, isPaymentMethodOnlineActive: function() { return this.producer && this.producer.online_payment && this.pointSaleActive && this.pointSaleActive.payment_method_online && !this.isPaymentMethodCreditActiveFunctioningUser(true) && !this.isPaymentMethodCreditActiveFunctioningMandatory() }, errorCreditMandatoryAndLimit: function() { return this.user && this.pointSaleActive && this.pointSaleActive.payment_method_credit && (this.pointSaleActive.credit_functioning == 'mandatory' || (this.pointSaleActive.credit_functioning == 'user' && this.user.credit_active)) && !this.checkCreditLimit(this.order); }, confirmClick: function() { var app = this ; // delivery if(app.pointSaleActive.is_home_delivery && !app.deliveryAddress) { this.errors = [] ; this.errors.push('Veuillez saisir une adresse de livraison.') ; opendistrib_scroll('page-title'); return false ; } // montant minimum de commande if(app.pointSaleActive.minimum_order_amount > 0 && app.priceTotal() < app.pointSaleActive.minimum_order_amount) { this.errors = [] ; this.errors.push('Le montant minimum de commande est de '+app.formatPrice(app.pointSaleActive.minimum_order_amount)+' pour ce point de vente.') ; opendistrib_scroll('page-title'); return false ; } // guest form var $signupGuestForm = $('#signup-guest form') ; if($signupGuestForm.length > 0 && !$signupGuestForm.valid()) { $signupGuestForm.submit() ; return false ; } var user = false ; if(this.producer.option_allow_order_guest && !this.user) { user = { email: $('#signupguest-email').val(), password: $('#signupguest-password').val(), firstname: $('#signupguest-firstname').val(), lastname: $('#signupguest-lastname').val(), phone: $('#signupguest-phone').val(), } ; } // products var productsArray = this.getProductsArray(); app.disableConfirmButton = true ; axios.post('ajax-process', { Order: { id_distribution : this.distribution.id, id_point_sale: this.pointSaleActive.id, comment: this.comment, delivery_home: this.pointSaleActive.is_home_delivery, delivery_address: this.deliveryAddress }, code_point_sale: this.pointsSaleCodes[this.pointSaleActive.id], products: productsArray, payment_method: this.paymentMethod, user: user }).then(function(response) { if(response.data.status == 'success') { app.errors = [] ; if(response.data.redirect && response.data.redirect.length > 0) { window.location.href = response.data.redirect ; } else { window.location.href = opendistrib_base_url(true)+'order/confirm?idOrder='+response.data.idOrder ; } } else { app.errors = response.data.errors ; window.scroll(0, $('#page-title').offset().top) ; app.disableConfirmButton = false ; } }); }, getProductsArray: function() { var productsArray = {} ; for(var key in this.products) { if( this.isProductAvailable(this.products[key]) && this.products[key].quantity_form != null && this.products[key].quantity_form > 0) { productsArray[this.products[key].id] = this.products[key].quantity_form ; } } return productsArray; }, checkProducts: function() { if(!this.oneProductOrdered()) { this.errors.push('Veuillez sélectionner au moins un produit.') ; } }, checkCreditLimit: function(order) { var total = this.priceTotal() ; if(order != null) { total = this.priceTotal() - order.amount_paid ; } return this.producer.credit_limit == null || (this.producer.credit_limit != null && (this.user.credit - total >= this.producer.credit_limit)) ; }, isProductAvailable: function(product) { return product.productDistribution && product.productDistribution[0] && product.productDistribution[0].active == 1; }, countProductsByCategory: function(category) { var count = 0 ; for(var i = 0 ; i < this.products.length ; i++) { if(this.products[i].id_product_category == category.id && this.isProductAvailable(this.products[i])) { count ++ ; } } return count ; }, countSelectedProductsByCategory: function(category) { var count = 0 ; for(var key in this.products) { if(this.products[key].quantity_form > 0 && this.products[key].id_product_category == category.id) { count ++ ; } } return count ; }, setCategoryCurrent: function(category, first) { var idScroll = false; if(this.categoryCurrent && this.categoryCurrent.id == category.id && !first) { this.categoryCurrent = null ; } else { this.categoryCurrent = category ; if(!first) { idScroll = 'category'+this.categoryCurrent.id; } } setTimeout(function() { opendistrib_products(); }, 500); if(idScroll) { setTimeout(opendistrib_scroll, 250, idScroll); } } }, computed : { orderedPointsSale: function() { var orderedPointsSaleArray = this.pointsSale.sort(function(a, b) { if(a.position > b.position) { return 1 ; } else { return -1 ; } }) ; return orderedPointsSaleArray ; } }, updated: function () { var app = this; this.$nextTick(function () { if(app.step == 'products' && !app.user && app.producer.option_allow_order_guest) { $("#signup-guest form").validate({ rules: { 'SignupForm[email]': { 'email': true, 'required': true, 'minlength': 8, 'maxlength': 255 }, 'SignupForm[password]': { 'required': true, 'minlength': 8, "maxlength": 255 }, 'SignupForm[firstname]': { 'required': true, 'minlength': 2, "maxlength": 255 }, 'SignupForm[lastname]': { 'required': true, 'minlength': 2, "maxlength": 255 }, 'SignupForm[phone]': { 'required': true, 'minlength': 2, "maxlength": 255 }, }, messages: { 'SignupForm[email]' : { 'required': 'Ce champs est requis.', 'email' : 'Email invalide.' }, 'SignupForm[password]' : { 'required': 'Ce champs est requis.', }, 'SignupForm[firstname]' : { 'required': 'Ce champs est requis.', }, 'SignupForm[lastname]' : { 'required': 'Ce champs est requis.', }, 'SignupForm[phone]' : { 'required': 'Ce champs est requis.', }, } }) ; } }); } }); Vue.component('step-date',{ props: [ 'step', 'pointSaleActive', 'dateFormat', 'changeStep', 'producer', 'first', ], data: function() { return { } ; }, template: '#template-step-date', methods: { } }) ; Vue.component('step-point-sale',{ props: [ 'step', 'pointSaleActive', 'changeStep', 'producer', 'first', ], data: function() { return { } ; }, template: '#template-step-point-sale', methods: { } }) ;