Abo Einmalprodukte und Bestätigung abschließen
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2bdc9ada3c
commit
2269ce031f
57 changed files with 3647 additions and 371 deletions
297
public/js/iq-abo-onetime.js
Normal file
297
public/js/iq-abo-onetime.js
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
var IqAboOneTime = {
|
||||
card: "#onetime_order_card",
|
||||
holder: "#insert_show_onetime_order",
|
||||
abo_holder: "#insert_show_products_order",
|
||||
summary_card: "#combined_summary_card",
|
||||
comp_holder: "#holder_html_view_comp_product",
|
||||
modal: "#modals-load-content",
|
||||
oTable: null,
|
||||
url: null,
|
||||
|
||||
btn_modal_add: ".add-onetime-product-basket",
|
||||
btn_add: ".onetime-add-from-basket",
|
||||
btn_remove: ".onetime-remove-from-basket",
|
||||
input_change: ".onetime-input-onchange",
|
||||
remove_item: ".remove_onetime_from_cart",
|
||||
confirm_changes: ".onetime-confirm-changes",
|
||||
discard_changes: ".onetime-discard-changes",
|
||||
|
||||
summary_col: "#combined_summary_col",
|
||||
sticky_gap: 16,
|
||||
_stickyTicking: false,
|
||||
|
||||
init: function () {
|
||||
var _self = this;
|
||||
_self.url = $(_self.card).data("onetime-route");
|
||||
_self.reInitCart();
|
||||
_self.initSticky();
|
||||
return _self;
|
||||
},
|
||||
|
||||
initSticky: function () {
|
||||
var _self = this;
|
||||
var card = document.querySelector(_self.summary_card);
|
||||
var col = document.querySelector(_self.summary_col);
|
||||
if (!card || !col) {
|
||||
return;
|
||||
}
|
||||
|
||||
var onScrollOrResize = function () {
|
||||
if (_self._stickyTicking) {
|
||||
return;
|
||||
}
|
||||
_self._stickyTicking = true;
|
||||
window.requestAnimationFrame(function () {
|
||||
_self.updateSticky(card, col);
|
||||
_self._stickyTicking = false;
|
||||
});
|
||||
};
|
||||
|
||||
// Capture-Phase, damit Scroll-Events beliebiger Scroll-Container erfasst werden.
|
||||
window.addEventListener("scroll", onScrollOrResize, true);
|
||||
window.addEventListener("resize", onScrollOrResize);
|
||||
_self.updateSticky(card, col);
|
||||
},
|
||||
|
||||
resetSticky: function (card) {
|
||||
card.style.position = "";
|
||||
card.style.top = "";
|
||||
card.style.left = "";
|
||||
card.style.width = "";
|
||||
card.style.zIndex = "";
|
||||
},
|
||||
|
||||
updateSticky: function (card, col) {
|
||||
var _self = this;
|
||||
|
||||
// Nur im zweispaltigen Layout (lg+) kleben.
|
||||
if (window.innerWidth < 992) {
|
||||
_self.resetSticky(card);
|
||||
return;
|
||||
}
|
||||
|
||||
var colStyle = window.getComputedStyle(col);
|
||||
var padLeft = parseFloat(colStyle.paddingLeft) || 0;
|
||||
var padRight = parseFloat(colStyle.paddingRight) || 0;
|
||||
var colRect = col.getBoundingClientRect();
|
||||
var contentLeft = colRect.left + padLeft;
|
||||
var contentWidth = col.clientWidth - padLeft - padRight;
|
||||
var cardHeight = card.offsetHeight;
|
||||
var gap = _self.sticky_gap;
|
||||
|
||||
if (colRect.top >= gap) {
|
||||
// Noch nicht über den oberen Rand gescrollt -> normaler Fluss.
|
||||
_self.resetSticky(card);
|
||||
return;
|
||||
}
|
||||
|
||||
// Oben anheften, aber maximal bis zum Ende der Spalte.
|
||||
var topPos = gap;
|
||||
var maxTop = colRect.bottom - cardHeight;
|
||||
if (maxTop < gap) {
|
||||
topPos = maxTop;
|
||||
}
|
||||
|
||||
card.style.position = "fixed";
|
||||
card.style.top = topPos + "px";
|
||||
card.style.left = contentLeft + "px";
|
||||
card.style.width = contentWidth + "px";
|
||||
card.style.zIndex = "1020";
|
||||
},
|
||||
|
||||
setDatabase: function (oTable) {
|
||||
this.oTable = oTable;
|
||||
},
|
||||
|
||||
reInitModal: function () {
|
||||
var _self = this;
|
||||
$(_self.oTable)
|
||||
.find(_self.btn_modal_add)
|
||||
.off("click")
|
||||
.on("click", function () {
|
||||
_self.addFromModal($(this));
|
||||
});
|
||||
},
|
||||
|
||||
reInitCart: function () {
|
||||
var _self = this;
|
||||
var $holder = $(_self.holder);
|
||||
|
||||
$holder
|
||||
.find(_self.btn_add)
|
||||
.off("click")
|
||||
.on("click", function () {
|
||||
_self.changeQty($(this), 1);
|
||||
});
|
||||
$holder
|
||||
.find(_self.btn_remove)
|
||||
.off("click")
|
||||
.on("click", function () {
|
||||
_self.changeQty($(this), -1);
|
||||
});
|
||||
$holder
|
||||
.find(_self.input_change)
|
||||
.off("change")
|
||||
.on("change", function () {
|
||||
_self.updateInput($(this));
|
||||
});
|
||||
$holder
|
||||
.find(_self.remove_item)
|
||||
.off("click")
|
||||
.on("click", function (event) {
|
||||
event.preventDefault();
|
||||
_self.removeItem($(this));
|
||||
});
|
||||
$holder
|
||||
.find(_self.confirm_changes)
|
||||
.off("click")
|
||||
.on("click", function () {
|
||||
_self.confirmChanges();
|
||||
});
|
||||
$holder
|
||||
.find(_self.discard_changes)
|
||||
.off("click")
|
||||
.on("click", function () {
|
||||
_self.discardChanges();
|
||||
});
|
||||
},
|
||||
|
||||
addFromModal: function (_obj) {
|
||||
var _self = this;
|
||||
var $modal = $(_self.modal);
|
||||
$modal.one("hidden.bs.modal", function () {
|
||||
_self
|
||||
.performRequest({
|
||||
action: "add",
|
||||
product_id: _obj.data("product-id"),
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
});
|
||||
$modal.modal("hide");
|
||||
},
|
||||
|
||||
changeQty: function (_obj, delta) {
|
||||
var _self = this;
|
||||
var itemId = _obj.data("onetime-item-id");
|
||||
var input = $(_self.holder).find(
|
||||
'input[name="onetime_qty_' + itemId + '"]'
|
||||
);
|
||||
var qty = _self.checkNumber(parseInt(input.val(), 10) + delta);
|
||||
input.val(qty);
|
||||
_self
|
||||
.performRequest({
|
||||
action: "update",
|
||||
one_time_item_id: itemId,
|
||||
qty: qty,
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
},
|
||||
|
||||
updateInput: function (_obj) {
|
||||
var _self = this;
|
||||
var qty = _self.checkNumber(parseInt(_obj.val(), 10));
|
||||
_obj.val(qty);
|
||||
_self
|
||||
.performRequest({
|
||||
action: "update",
|
||||
one_time_item_id: _obj.data("onetime-item-id"),
|
||||
qty: qty,
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
},
|
||||
|
||||
removeItem: function (_obj) {
|
||||
var _self = this;
|
||||
_self
|
||||
.performRequest({
|
||||
action: "remove",
|
||||
one_time_item_id: _obj.data("onetime-item-id"),
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
},
|
||||
|
||||
confirmChanges: function () {
|
||||
var _self = this;
|
||||
_self
|
||||
.performRequest({
|
||||
action: "confirm",
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
},
|
||||
|
||||
discardChanges: function () {
|
||||
var _self = this;
|
||||
_self
|
||||
.performRequest({
|
||||
action: "discard",
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
},
|
||||
|
||||
refreshView: function (data) {
|
||||
var _self = IqAboOneTime;
|
||||
if (data.html_onetime) {
|
||||
$(_self.holder).html(data.html_onetime);
|
||||
}
|
||||
if (data.html_abo) {
|
||||
$(_self.abo_holder).html(data.html_abo);
|
||||
}
|
||||
if (data.html_summary) {
|
||||
$(_self.summary_card).html(data.html_summary);
|
||||
}
|
||||
if (data.html_comp !== undefined) {
|
||||
$(_self.comp_holder).html(data.html_comp);
|
||||
}
|
||||
$(_self.modal).modal("hide");
|
||||
_self.reInitCart();
|
||||
if (typeof iqModalCart !== "undefined" && iqModalCart.reInitCart) {
|
||||
iqModalCart.reInitCart($(_self.abo_holder));
|
||||
iqModalCart.reInitCart($(_self.comp_holder));
|
||||
}
|
||||
var card = document.querySelector(_self.summary_card);
|
||||
var col = document.querySelector(_self.summary_col);
|
||||
if (card && col) {
|
||||
_self.updateSticky(card, col);
|
||||
}
|
||||
},
|
||||
|
||||
performRequest: function (data) {
|
||||
var _self = this;
|
||||
return $.ajax({
|
||||
url: _self.url,
|
||||
data: data,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
headers: {
|
||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
|
||||
},
|
||||
}).fail(function (jqXHR) {
|
||||
var msg =
|
||||
jqXHR.responseJSON && jqXHR.responseJSON.message
|
||||
? jqXHR.responseJSON.message
|
||||
: "Error";
|
||||
var errorEl = document.getElementById("insert_onetime_error_message");
|
||||
if (!errorEl) {
|
||||
errorEl = document.createElement("div");
|
||||
errorEl.id = "insert_onetime_error_message";
|
||||
errorEl.className = "alert alert-danger mt-2";
|
||||
var holder = document.querySelector("#insert_show_onetime_order");
|
||||
if (holder) {
|
||||
holder.insertBefore(errorEl, holder.firstChild);
|
||||
}
|
||||
}
|
||||
errorEl.textContent = msg;
|
||||
});
|
||||
},
|
||||
|
||||
checkNumber: function (number) {
|
||||
if (number < 1 || isNaN(number)) {
|
||||
return 1;
|
||||
}
|
||||
if (number > 100) {
|
||||
return 100;
|
||||
}
|
||||
return number;
|
||||
},
|
||||
};
|
||||
|
|
@ -45,16 +45,66 @@ var IqModalCart = {
|
|||
}
|
||||
});
|
||||
},
|
||||
showConfirm: function(productName, productPrice, qtyInfo, callback) {
|
||||
parseCurrency: function(value) {
|
||||
if (value === undefined || value === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var normalized = String(value)
|
||||
.replace(/<[^>]*>/g, "")
|
||||
.replace(/€/g, "")
|
||||
.replace(/€/g, "")
|
||||
.replace(/\s/g, "")
|
||||
.replace(/\./g, "")
|
||||
.replace(",", ".");
|
||||
var amount = parseFloat(normalized);
|
||||
|
||||
return isNaN(amount) ? null : amount;
|
||||
},
|
||||
formatCurrency: function(value) {
|
||||
if (value === undefined || value === null || isNaN(value)) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
return (
|
||||
value.toLocaleString("de-DE", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}) + " €"
|
||||
);
|
||||
},
|
||||
showConfirm: function(productName, productPrice, qtyInfo, callback, options) {
|
||||
var _self = this;
|
||||
var $confirmModal = $(_self.confirmModal);
|
||||
var titleKey = _self.addOnlyMode ? "title-add-only" : "title-normal";
|
||||
var warningKey = _self.addOnlyMode ? "warning-add-only" : "warning-normal";
|
||||
$("#modal-confirm-add-label").text($confirmModal.data(titleKey));
|
||||
$("#confirm-add-warning-text").text($confirmModal.data(warningKey));
|
||||
var confirmOptions = options || {};
|
||||
var confirmType = confirmOptions.type || "add";
|
||||
var additionalCost = _self.parseCurrency(productPrice);
|
||||
var currentTotal = _self.parseCurrency(
|
||||
$("#value-amount").text() || $confirmModal.data("current-total"),
|
||||
);
|
||||
var newTotal =
|
||||
currentTotal !== null && additionalCost !== null
|
||||
? currentTotal + additionalCost
|
||||
: null;
|
||||
|
||||
var title = $confirmModal.data("title-" + confirmType);
|
||||
var info = $confirmModal.data("info-" + confirmType);
|
||||
$("#modal-confirm-add-label").text(title || $confirmModal.data("title-add"));
|
||||
$("#confirm-add-info-text").text(info || $confirmModal.data("info-add"));
|
||||
$("#confirm-add-product-name").text(productName || "-");
|
||||
$("#confirm-add-product-price").html(productPrice || "-");
|
||||
$("#confirm-add-product-price").html(
|
||||
additionalCost !== null
|
||||
? "+ " +
|
||||
_self.formatCurrency(additionalCost) +
|
||||
" " +
|
||||
($confirmModal.data("per-delivery") || "")
|
||||
: productPrice || "-",
|
||||
);
|
||||
$("#confirm-add-qty-info").text(qtyInfo || "");
|
||||
$("#confirm-add-new-total").text(_self.formatCurrency(newTotal));
|
||||
$("#confirm-add-next-billing-date").text(
|
||||
$confirmModal.data("next-billing-date") || "-",
|
||||
);
|
||||
_self.pendingAction = callback;
|
||||
$confirmModal.modal("show");
|
||||
},
|
||||
|
|
@ -76,15 +126,21 @@ var IqModalCart = {
|
|||
var productPrice = _obj.data("product-price") || "";
|
||||
var $modal = $(_self.modal);
|
||||
$modal.one("hidden.bs.modal", function() {
|
||||
_self.showConfirm(productName, productPrice, "1x", function() {
|
||||
_self
|
||||
.performRequest({
|
||||
product_id: _obj.data("product-id"),
|
||||
qty: 1,
|
||||
action: "addProduct",
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
});
|
||||
_self.showConfirm(
|
||||
productName,
|
||||
productPrice,
|
||||
"1x",
|
||||
function() {
|
||||
_self
|
||||
.performRequest({
|
||||
product_id: _obj.data("product-id"),
|
||||
qty: 1,
|
||||
action: "addProduct",
|
||||
})
|
||||
.done(_self.refreshView);
|
||||
},
|
||||
{ type: "add" },
|
||||
);
|
||||
});
|
||||
$modal.modal("hide");
|
||||
},
|
||||
|
|
@ -117,9 +173,11 @@ var IqModalCart = {
|
|||
_self.remove_from_cart($(this), _obj);
|
||||
});
|
||||
if (_self.is_for === "me" || _self.is_for === "abo-me") {
|
||||
$('input[name^="' + _self.comp_products + '"]').on("change", function() {
|
||||
_self.update_comp_product($(this));
|
||||
});
|
||||
$('input[name^="' + _self.comp_products + '"]')
|
||||
.off("change")
|
||||
.on("change", function() {
|
||||
_self.update_comp_product($(this));
|
||||
});
|
||||
}
|
||||
},
|
||||
update_comp_product: function(_obj) {
|
||||
|
|
@ -149,10 +207,16 @@ var IqModalCart = {
|
|||
var productPrice = _obj.data("product-price") || "";
|
||||
var qtyInfo = currentQty + " \u2192 " + qty;
|
||||
console.log(qtyInfo);
|
||||
_self.showConfirm(productName, productPrice, qtyInfo, function() {
|
||||
input.val(qty);
|
||||
_self.update_cart(_holder, _obj, qty);
|
||||
});
|
||||
_self.showConfirm(
|
||||
productName,
|
||||
productPrice,
|
||||
qtyInfo,
|
||||
function() {
|
||||
input.val(qty);
|
||||
_self.update_cart(_holder, _obj, qty);
|
||||
},
|
||||
{ type: "increase" },
|
||||
);
|
||||
},
|
||||
remove_product: function(_obj, _holder) {
|
||||
var _self = this;
|
||||
|
|
@ -200,12 +264,16 @@ var IqModalCart = {
|
|||
var obj = $(_self.cart_holder);
|
||||
obj.html(data.html_cart);
|
||||
$(_self.insert_show_total_order).html(data.html_total);
|
||||
if (data.html_summary) {
|
||||
$("#combined_summary_card").html(data.html_summary);
|
||||
}
|
||||
$(_self.modal).modal("hide");
|
||||
if ($(_self.comp_holder)) {
|
||||
if (data.html_comp !== undefined) {
|
||||
$(_self.comp_holder).html(data.html_comp);
|
||||
}
|
||||
if ($("#value-amount")) {
|
||||
$("#value-amount").html(data.amount);
|
||||
$(_self.confirmModal).data("current-total", data.amount);
|
||||
}
|
||||
_self.reInitCart(obj);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ var IqShoppingCart = {
|
|||
oTable: null,
|
||||
table_input: '.table-input-event-onchange',
|
||||
cart_input: '.cart-input-event-onchange',
|
||||
cart_add: '.cart-add-event',
|
||||
cart_remove: '.cart-remove-event',
|
||||
remove_item: '.remove_item_form_cart',
|
||||
shipping_state: '#change_shipping_state',
|
||||
comp_products: 'switchers-comp-product',
|
||||
|
|
@ -57,6 +59,12 @@ var IqShoppingCart = {
|
|||
$(_self.cart_input).on('change', function(){
|
||||
_self.update_input_cart($(this));
|
||||
});
|
||||
$(_self.cart_add).off('click').on('click', function(){
|
||||
_self.change_cart_qty($(this), 1);
|
||||
});
|
||||
$(_self.cart_remove).off('click').on('click', function(){
|
||||
_self.change_cart_qty($(this), -1);
|
||||
});
|
||||
$(_self.remove_item).on('click', function(event){
|
||||
event.preventDefault();
|
||||
_self.update_cart_database($(this).data('product-id'), 0);
|
||||
|
|
@ -88,6 +96,18 @@ var IqShoppingCart = {
|
|||
_obj.val(qty);
|
||||
_self.update_cart_database(_obj.data('product-id'), qty);
|
||||
},
|
||||
/**
|
||||
* Plus-/Minus-Buttons im Warenkorb: Menge nicht optimistisch erhöhen, sondern
|
||||
* erst nach Server-Antwort (Re-Render) anzeigen. So bleibt bei einem Stop
|
||||
* (z. B. Maximalgewicht) der Zähler stehen und es erscheint ein Inline-Hinweis.
|
||||
*/
|
||||
change_cart_qty: function (_obj, delta){
|
||||
var _self = this;
|
||||
var productId = _obj.data('product-id');
|
||||
var input = $(_self.card_holder).find('.cart-input-event-onchange[data-product-id="'+productId+'"]');
|
||||
var qty = _self.checkNumber(parseInt(input.val(), 10) + delta);
|
||||
_self.update_cart_database(productId, qty);
|
||||
},
|
||||
update_comp_product: function (_obj){
|
||||
var _self = this;
|
||||
_self.performRequest({comp_product_id: _obj.val(), comp_num: _obj.data('comp_num'), count_comp_products: $('input[name="'+_self.count_comp_products+'"]').val(), action: 'updateCompProduct'})
|
||||
|
|
@ -170,10 +190,24 @@ var IqShoppingCart = {
|
|||
}
|
||||
},
|
||||
|
||||
showCartError: function (message){
|
||||
var _self = this;
|
||||
var errorEl = document.getElementById('insert_show_error_message');
|
||||
if (!errorEl) {
|
||||
errorEl = document.createElement('div');
|
||||
errorEl.id = 'insert_show_error_message';
|
||||
errorEl.className = 'alert alert-danger mt-2';
|
||||
var cartContent = document.getElementById('cartContent');
|
||||
if (cartContent) {
|
||||
cartContent.insertBefore(errorEl, cartContent.firstChild);
|
||||
}
|
||||
}
|
||||
errorEl.textContent = message;
|
||||
},
|
||||
refreshItemsAndView: function (data){
|
||||
var _self = IqShoppingCart;
|
||||
if (data && data.response === false && data.message) {
|
||||
alert(data.message);
|
||||
_self.showCartError(data.message);
|
||||
return;
|
||||
}
|
||||
$(_self.card_holder).html(data.html_card);
|
||||
|
|
@ -185,7 +219,7 @@ var IqShoppingCart = {
|
|||
refreshDatabaseAndView: function (data) {
|
||||
var _self = IqShoppingCart;
|
||||
if (data && data.response === false && data.message) {
|
||||
alert(data.message);
|
||||
_self.showCartError(data.message);
|
||||
return;
|
||||
}
|
||||
$(_self.card_holder).html(data.html_card);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue