mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-23 01:00:23 +00:00
cargando carrito desde backend
This commit is contained in:
@ -20,6 +20,12 @@ databaseChangeLog:
|
||||
primaryKey: true
|
||||
primaryKeyName: pk_cart_direcciones
|
||||
|
||||
- column:
|
||||
name: cart_id
|
||||
type: BIGINT
|
||||
constraints:
|
||||
nullable: false
|
||||
|
||||
- column:
|
||||
name: direccion_id
|
||||
type: BIGINT
|
||||
@ -37,6 +43,18 @@ databaseChangeLog:
|
||||
type: INT
|
||||
constraints:
|
||||
nullable: true
|
||||
|
||||
- column:
|
||||
name: is_palets
|
||||
type: TINYINT(1)
|
||||
constraints:
|
||||
nullable: false
|
||||
defaultValue: false
|
||||
|
||||
- column:
|
||||
name: base
|
||||
type: DECIMAL(12, 2)
|
||||
|
||||
|
||||
- createIndex:
|
||||
indexName: idx_cart_dir_direccion_id
|
||||
|
||||
@ -21,7 +21,9 @@ cart.shipping.ud=ud.
|
||||
cart.shipping.uds=uds.
|
||||
cart.shipping.enter-units=Introduzca el número de unidades para esta dirección:
|
||||
cart.shipping.units-label=Número de unidades (máximo {max})
|
||||
|
||||
cart.shipping.send-in-palets=Enviar en palets
|
||||
cart.shipping.send-in-palets.info=Marque esta opción si desea que el envío se realice en palets (sólo para tiradas grandes). La entrega se realizará a pie de calle.
|
||||
cart.shipping.tipo-envio=Tipo de envío:
|
||||
|
||||
cart.shipping.errors.units-error=Por favor, introduzca un número válido entre 1 y {max}.
|
||||
cart.shipping.errors.noAddressSelected=Debe seleccionar una dirección de envío para el pedido.
|
||||
@ -34,4 +36,6 @@ cart.resumen.iva-21=IVA 21%:
|
||||
cart.resumen.total=Total cesta:
|
||||
cart.resumen.tramitar=Tramitar pedido
|
||||
|
||||
cart.resumen.fidelizacion=Si tiene descuento por fidelización, se aplicará al tramitar el pedido.
|
||||
cart.resumen.fidelizacion=Si tiene descuento por fidelización, se aplicará al tramitar el pedido.
|
||||
|
||||
cart.errors.update-cart=Error al actualizar la cesta de la compra: {0}
|
||||
@ -29,3 +29,13 @@ body {
|
||||
color: #fff;
|
||||
border-color: #92b2a7;
|
||||
}
|
||||
|
||||
/* Solo dentro del modal */
|
||||
.swal2-popup .form-switch-custom {
|
||||
font-size: 1rem; /* clave: fija el tamaño base del switch */
|
||||
line-height: 1.5;
|
||||
}
|
||||
.swal2-popup .form-switch-custom .form-check-input {
|
||||
float: none; /* por si acaso */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ $(() => {
|
||||
$(this).find('.presupuesto-id').attr('name', 'direcciones[' + i + '].presupuestoId');
|
||||
if($(this).find('.item-tirada').length > 0 && $(this).find('.item-tirada').val() !== null
|
||||
&& $(this).find('.item-tirada').val() !== "")
|
||||
$(this).find('.item-tirada').attr('name', 'direcciones[' + i + '].tirada');
|
||||
$(this).find('.item-tirada').attr('name', 'direcciones[' + i + '].unidades');
|
||||
});
|
||||
$.post(form.attr('action'), form.serialize(), (response) => {
|
||||
// handle response
|
||||
|
||||
@ -7,23 +7,23 @@ $(() => {
|
||||
|
||||
$("#onlyOneShipment").on('change', function () {
|
||||
if ($(this).is(':checked')) {
|
||||
$('.nav-product').hide();
|
||||
$('.nav-product').addClass('d-none');
|
||||
document.querySelectorAll('.card.product').forEach(card => {
|
||||
const detailsBtn = card.querySelector('.nav-link[id^="pills-details-"][id$="-tab"]');
|
||||
if (detailsBtn) new bootstrap.Tab(detailsBtn).show();
|
||||
if (detailsBtn) $(new bootstrap.Tab(detailsBtn)).removeClass('d-none');
|
||||
});
|
||||
$('#shippingAddressesContainer').empty().show();
|
||||
$('#shippingAddressesContainer').empty().removeClass('d-none');
|
||||
$('.shipping-addresses-item').toArray().forEach(element => {
|
||||
$(element).empty().hide();
|
||||
$(element).empty().addClass('d-none');
|
||||
});
|
||||
$('#addOrderAddress').show();
|
||||
$('#addOrderAddress').removeClass('d-none');
|
||||
} else {
|
||||
$('.nav-product').show();
|
||||
$('#shippingAddressesContainer').empty().hide();
|
||||
$('.nav-product').removeClass('d-none');
|
||||
$('#shippingAddressesContainer').empty().addClass('d-none');
|
||||
$('.shipping-addresses-item').toArray().forEach(element => {
|
||||
$(element).empty().show();
|
||||
$(element).empty().removeClass('d-none');
|
||||
});
|
||||
$('#addOrderAddress').hide();
|
||||
$('#addOrderAddress').addClass('d-none');
|
||||
}
|
||||
$(document).trigger('updateCart');
|
||||
});
|
||||
@ -34,7 +34,7 @@ $(() => {
|
||||
const $div = $card.parent();
|
||||
$card.remove();
|
||||
if ($div.hasClass('shipping-order-address')) {
|
||||
$('#addOrderAddress').show();
|
||||
$('#addOrderAddress').removeClass('d-none');
|
||||
}
|
||||
else {
|
||||
$div.trigger('direcciones:actualizadas');
|
||||
@ -50,19 +50,27 @@ $(() => {
|
||||
const tirada = $(this).closest('.product').find('.item-tirada').val();
|
||||
const totalTirada = container.find('.item-tirada').toArray().reduce((acc, el) => acc + parseInt($(el).val() || 0), 0);
|
||||
const remainingTirada = parseInt(tirada) - parseInt(totalTirada) + parseInt($card.find('.item-tirada').val() || 0);
|
||||
const units = getUnitsFromUser(remainingTirada);
|
||||
units.then(unidades => {
|
||||
if (unidades) {
|
||||
$card.find('.item-tirada').val(unidades);
|
||||
const data = getUnitsFromUser(remainingTirada);
|
||||
data.then(data => {
|
||||
if (data.unidades) {
|
||||
$card.find('.item-tirada').val(data.unidades);
|
||||
$card.find('#units-text').each(function () {
|
||||
if (unidades == 1) {
|
||||
$(this).text(`${unidades} ${window.languageBundle['cart.shipping.ud'] || 'unidad'}`);
|
||||
if (data.unidades == 1) {
|
||||
$(this).text(`${data.unidades} ${window.languageBundle['cart.shipping.ud'] || 'unidad'}`);
|
||||
} else {
|
||||
$(this).text(`${unidades} ${window.languageBundle['cart.shipping.uds'] || 'unidades'}`);
|
||||
$(this).text(`${data.unidades} ${window.languageBundle['cart.shipping.uds'] || 'unidades'}`);
|
||||
}
|
||||
});
|
||||
container.trigger('direcciones:actualizadas');
|
||||
$(document).trigger('updateCart');
|
||||
$card.find('.is-palets').val(data.isPalets ? 'true' : 'false');
|
||||
$card.find('.icon-shipment').each(function () {
|
||||
if (data.isPalets) {
|
||||
$(this).removeClass('la-box').addClass('la-pallet');
|
||||
} else {
|
||||
$(this).removeClass('la-pallet').addClass('la-box');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -87,7 +95,7 @@ $(() => {
|
||||
$('#addOrderAddress').on('click', async () => {
|
||||
if ($('#onlyOneShipment').is(':checked')) {
|
||||
if (await seleccionarDireccionEnvio()) {
|
||||
$('#addOrderAddress').hide();
|
||||
$('#addOrderAddress').addClass('d-none');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -210,16 +218,27 @@ $(() => {
|
||||
$('#direccionFormModalBody').html(html);
|
||||
const title = $('#direccionFormModalBody #direccionForm').data('add');
|
||||
$('#direccionFormModal .modal-title').text(title);
|
||||
modal.show();
|
||||
modal.removeClass('d-none');
|
||||
});
|
||||
}
|
||||
|
||||
let unidades = null;
|
||||
let isPalets = 0;
|
||||
if (tirada !== null && tirada >= 1 && direccionId) {
|
||||
|
||||
const unidadesValue = await getUnitsFromUser(tirada);
|
||||
if (unidadesValue) {
|
||||
unidades = parseInt(unidadesValue);
|
||||
const data = await getUnitsFromUser(tirada);
|
||||
if (data && data.unidades) {
|
||||
unidades = parseInt(data.unidades);
|
||||
isPalets = data.isPalets ? 1 : 0;
|
||||
} else {
|
||||
// Si el usuario cancela, salir de la función
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(presupuestoId == null){ // caso para todas los envios a la misma direccion
|
||||
const isPaletsValue = await getTipoEnvio();
|
||||
if (isPaletsValue !== null) {
|
||||
isPalets = isPaletsValue ? 1 : 0;
|
||||
} else {
|
||||
// Si el usuario cancela, salir de la función
|
||||
return false;
|
||||
@ -228,9 +247,9 @@ $(() => {
|
||||
if (direccionId) {
|
||||
// Obtén el objeto completo seleccionado
|
||||
showLoader();
|
||||
let uri = `/cart/get-address/${direccionId}`;
|
||||
let uri = `/cart/get-address/${direccionId}?isPalets=${isPalets}`;
|
||||
if (presupuestoId !== null) {
|
||||
uri += `?presupuestoId=${presupuestoId}`;
|
||||
uri += `&presupuestoId=${presupuestoId}`;
|
||||
if (tirada !== null) {
|
||||
uri += `&unidades=${unidades}`;
|
||||
}
|
||||
@ -255,18 +274,29 @@ $(() => {
|
||||
}
|
||||
|
||||
async function getUnitsFromUser(tirada) {
|
||||
|
||||
// Swal preguntando numero de unidades a asignar con máximo de tirada, necesito guardar el valor
|
||||
const { value: unidadesValue } = await Swal.fire({
|
||||
const { value: formValues } = await Swal.fire({
|
||||
title: window.languageBundle['cart.shipping.enter-units'] || 'Introduzca el número de unidades para esta dirección',
|
||||
input: 'number',
|
||||
inputLabel: window.languageBundle['cart.shipping.units-label']?.replace('{max}', tirada) || `Número de unidades (máximo ${tirada})`,
|
||||
inputAttributes: {
|
||||
min: 1,
|
||||
max: tirada,
|
||||
step: 1,
|
||||
},
|
||||
inputValue: tirada,
|
||||
html: `
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">
|
||||
${window.languageBundle['cart.shipping.units-label']?.replace('{max}', tirada) || `Número de unidades (máximo ${tirada})`}
|
||||
</label>
|
||||
<input id="swal-input-unidades" type="number" min="1" max="${tirada}" step="1"
|
||||
value="${tirada}" class="form-control text-center">
|
||||
</div>
|
||||
<div class="form-check form-switch form-switch-custom mb-3 d-flex align-items-center justify-content-center ps-0">
|
||||
<input type="checkbox"
|
||||
id="swal-input-palets"
|
||||
class="form-check-input ms-0 me-2 float-none">
|
||||
<label for="swal-input-palets" class="form-check-label mb-0">
|
||||
${window.languageBundle['cart.shipping.send-in-palets'] || 'Enviar en palets'}
|
||||
</label>
|
||||
</div>
|
||||
<span class="form-text text-muted">
|
||||
${window.languageBundle['cart.shipping.send-in-palets.info'] || 'En palets la entrega se realizará a pie de calle.'}
|
||||
</span>
|
||||
`,
|
||||
focusConfirm: false,
|
||||
showCancelButton: true,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
@ -275,14 +305,60 @@ $(() => {
|
||||
},
|
||||
confirmButtonText: window.languageBundle['app.aceptar'] || 'Aceptar',
|
||||
cancelButtonText: window.languageBundle['app.cancelar'] || 'Cancelar',
|
||||
inputValidator: (value) => {
|
||||
if (!value || isNaN(value) || value < 1 || value > tirada) {
|
||||
return window.languageBundle['cart.shipping.errors.units-error']?.replace('{max}', tirada) || `Por favor, introduzca un número válido entre 1 y ${tirada}.`;
|
||||
preConfirm: () => {
|
||||
const unidades = parseInt(document.getElementById('swal-input-unidades').value, 10);
|
||||
const isPalets = document.getElementById('swal-input-palets').checked;
|
||||
|
||||
if (!unidades || isNaN(unidades) || unidades < 1 || unidades > tirada) {
|
||||
Swal.showValidationMessage(
|
||||
window.languageBundle['cart.shipping.errors.units-error']?.replace('{max}', tirada)
|
||||
|| `Por favor, introduzca un número válido entre 1 y ${tirada}.`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
return { unidades, isPalets };
|
||||
}
|
||||
});
|
||||
return unidadesValue;
|
||||
|
||||
if (formValues) {
|
||||
return formValues; // { unidades: number, isPalets: boolean }
|
||||
}
|
||||
return null; // Si se cancela el Swal
|
||||
}
|
||||
|
||||
async function getTipoEnvio() {
|
||||
const { value: checkValue } = await Swal.fire({
|
||||
title: window.languageBundle['cart.shipping.tipo-envio'] || 'Tipo de envío',
|
||||
html: `
|
||||
<div class="form-check form-switch form-switch-custom my-3 d-flex align-items-center justify-content-center gap-2">
|
||||
<input type="checkbox" class="form-check-input" id="swal-input-palets">
|
||||
<label for="swal-input-palets" class="form-label mb-0">
|
||||
${window.languageBundle['cart.shipping.send-in-palets'] || 'Enviar en palets'}
|
||||
</label>
|
||||
</div>
|
||||
<span class="form-text text-muted">
|
||||
${window.languageBundle['cart.shipping.send-in-palets.info'] || 'En palets la entrega se realizará a pie de calle.'}
|
||||
</span>
|
||||
`,
|
||||
focusConfirm: false,
|
||||
showCancelButton: true,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2',
|
||||
cancelButton: 'btn btn-light',
|
||||
},
|
||||
confirmButtonText: window.languageBundle['app.aceptar'] || 'Aceptar',
|
||||
cancelButtonText: window.languageBundle['app.cancelar'] || 'Cancelar',
|
||||
preConfirm: () => {
|
||||
const isPalets = document.getElementById('swal-input-palets').checked;
|
||||
return isPalets;
|
||||
}
|
||||
});
|
||||
|
||||
if (checkValue !== undefined) {
|
||||
return checkValue; // boolean
|
||||
}
|
||||
return null; // Si se cancela el Swal
|
||||
}
|
||||
|
||||
function checkTotalUnits(container, tirada) {
|
||||
@ -294,8 +370,8 @@ $(() => {
|
||||
if (totalUnits < tirada) {
|
||||
return false;
|
||||
}
|
||||
if(container.find('.product').closest('.shipping-addresses-sample')){
|
||||
if(container.find('.direccion-card').toArray().length === 0){
|
||||
if (container.find('.product').closest('.shipping-addresses-sample')) {
|
||||
if (container.find('.direccion-card').toArray().length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -308,21 +384,21 @@ $(() => {
|
||||
const container = $(this);
|
||||
|
||||
if (!checkTotalUnits(container, tirada)) {
|
||||
container.closest('.px-2').find('.btn-add-shipping').show();
|
||||
container.closest('.px-2').find('.btn-add-shipping').removeClass('d-none');
|
||||
} else {
|
||||
container.closest('.px-2').find('.btn-add-shipping').hide();
|
||||
container.closest('.px-2').find('.btn-add-shipping').addClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('direcciones:actualizadas', '.shipping-addresses-sample', function (e) {
|
||||
|
||||
|
||||
const container = $(this);
|
||||
|
||||
if (container.find('.direccion-card').toArray().length === 0) {
|
||||
container.closest('.px-2').find('.btn-add-shipping-sample').show();
|
||||
container.closest('.px-2').find('.btn-add-shipping-sample').removeClass('d-none');
|
||||
}
|
||||
else {
|
||||
container.closest('.px-2').find('.btn-add-shipping-sample').hide();
|
||||
container.closest('.px-2').find('.btn-add-shipping-sample').addClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
@ -345,7 +421,7 @@ $(() => {
|
||||
return;
|
||||
}
|
||||
// Éxito real: cerrar y recargar tabla
|
||||
modal.hide();
|
||||
modal.addClass('d-none');
|
||||
seleccionarDireccionEnvio();
|
||||
},
|
||||
error: function (xhr) {
|
||||
|
||||
@ -10,26 +10,28 @@
|
||||
<div th:if="${items.isEmpty()}">
|
||||
<div class="alert alert-info" role="alert" th:text="#{cart.empty}"></div>
|
||||
</div>
|
||||
<div th:if="${errorMessage}" class="alert alert-danger " role="alert" th:text="${errorMessage}"></div>
|
||||
|
||||
<div class="alert alert-danger alert-shipment d-none" role="alert"
|
||||
th:text="#{cart.shipping.errors.fillAddressesItems}"></div>
|
||||
|
||||
<form id="cartForm" th:action="${'/cart/update/' + cartId}" method="POST" class="col-xl-8 col-12">
|
||||
<form id="cartForm" th:action="${'/cart/update/' + cart.id}" method="POST" class="col-xl-8 col-12">
|
||||
|
||||
<input type="hidden" name="id" th:value="${cartId}" />
|
||||
<input type="hidden" name="id" th:value="${cart.id}" />
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<p th:text="#{cart.shipping.info}"></p>
|
||||
<div
|
||||
class="form-check form-switch form-switch-custom form-switch-presupuesto mb-3 d-flex align-items-center">
|
||||
|
||||
<input type="checkbox" class="form-check-input datos-generales-data me-2" id="onlyOneShipment"
|
||||
name="only_one_shipment" checked />
|
||||
th:field="${cart.onlyOneShipment}"/>
|
||||
<label for="onlyOneShipment" class="form-label d-flex align-items-center mb-0">
|
||||
<span th:text="#{cart.shipping.onlyOneShipment}" class="me-2"></span>
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary" id="addOrderAddress"
|
||||
<button type="button" th:class="${'btn btn-secondary' + (!cart.onlyOneShipment or mainDir?.size > 0 ? ' d-none' : '')}" id="addOrderAddress"
|
||||
th:text="#{cart.shipping.add}">Añadir dirección</button>
|
||||
|
||||
<div id="shippingAddressesContainer" class="shipping-order-address d-flex flex-wrap gap-3 mt-4"></div>
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<input type="hidden" class="item-tirada" th:value="${item.tirada}" />
|
||||
|
||||
<div class="step-arrow-nav mt-n3 mx-n3 mb-3">
|
||||
<ul class="nav nav-pills nav-justified custom-nav nav-product" style="display: none;" role="tablist">
|
||||
<ul th:class="${'nav nav-pills nav-justified custom-nav nav-product' + (cart.onlyOneShipment ? ' d-none' : '')}" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link fs-15 active" th:id="${'pills-details-' + item.cartItemId + '-tab'}"
|
||||
th:data-bs-target="${'#pills-details-' + item.cartItemId}" type="button" role="tab"
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
<input type="hidden" class="direccion-cp" th:value="${direccion.cp}" />
|
||||
<input type="hidden" class="direccion-pais-code3" th:value="${direccion.pais.code3}" />
|
||||
<input type="hidden" class="item-tirada" th:value="${unidades != null ? unidades : ''}" />
|
||||
<input type="hidden" class="is-palets" th:value="${isPalets != null ? isPalets : ''}" />
|
||||
|
||||
<div class="row g-3 align-items-start flex-nowrap">
|
||||
<div class="col">
|
||||
@ -17,17 +18,24 @@
|
||||
<span class="text-muted fw-normal d-block text-break"
|
||||
th:text="#{'direcciones.telefono'} + ': ' + ${direccion.telefono}"></span>
|
||||
</div>
|
||||
<div th:if="${unidades != null}" class="col-auto ms-auto text-end">
|
||||
<span id="units-text" class="mb-2 fw-semibold d-block text-muted text-uppercase" th:if="${unidades == 1}"
|
||||
th:text="|${unidades} #{cart.shipping.ud}|"></span>
|
||||
<div class="col-auto ms-auto text-end">
|
||||
<div th:if="${unidades != null}">
|
||||
<span id="units-text" class="mb-2 fw-semibold d-block text-muted text-uppercase" th:if="${unidades == 1}"
|
||||
th:text="|${unidades} #{cart.shipping.ud}|"></span>
|
||||
|
||||
<!-- plural -->
|
||||
<span id="units-text" class="mb-2 fw-semibold d-block text-muted text-uppercase" th:unless="${unidades == 1}"
|
||||
th:text="|${unidades} #{cart.shipping.uds}|"></span>
|
||||
<!-- plural -->
|
||||
<span id="units-text" class="mb-2 fw-semibold d-block text-muted text-uppercase" th:unless="${unidades == 1}"
|
||||
th:text="|${unidades} #{cart.shipping.uds}|"></span>
|
||||
</div>
|
||||
<div th:if="${isPalets != null and isPalets==1}">
|
||||
<i class="icon-shipment las la-pallet la-3x text-muted"></i>
|
||||
</div>
|
||||
<div th:if="${isPalets == null or isPalets == 0}">
|
||||
<i class="icon-shipment las la-box la-3x text-muted"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex flex-wrap align-items-center gap-2 py-1 bg-light rounded-bottom border-top mt-auto actions-row">
|
||||
<div class="d-flex flex-wrap align-items-center gap-2 py-1 bg-light rounded-bottom border-top mt-auto actions-row">
|
||||
<a href="javascript:void(0)" class="d-block text-body p-1 px-2 btn-delete-direccion"
|
||||
data-id="${this._esc(d.id ?? '')}">
|
||||
<i class="ri-delete-bin-fill text-muted align-bottom me-1"></i>
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
<form id="tpv" th:action="${action}" method="POST">
|
||||
<input type="hidden" name="Ds_SignatureVersion" th:value="${signatureVersion}" />
|
||||
<input type="hidden" name="Ds_MerchantParameters" th:value="${merchantParameters}" />
|
||||
<input type="hidden" name="Ds_Signature" th:value="${signature}" />
|
||||
<noscript><button type="submit">Pagar</button></noscript>
|
||||
</form>
|
||||
<script>document.getElementById('tpv').submit();</script>
|
||||
Reference in New Issue
Block a user