diff --git a/src/main/java/com/imprimelibros/erp/cart/CartController.java b/src/main/java/com/imprimelibros/erp/cart/CartController.java index 6ffd926..9c6b8bb 100644 --- a/src/main/java/com/imprimelibros/erp/cart/CartController.java +++ b/src/main/java/com/imprimelibros/erp/cart/CartController.java @@ -29,7 +29,8 @@ public class CartController { protected MessageSource messageSource; protected TranslationService translationService; - public CartController(CartService service, DireccionService direccionService, MessageSource messageSource, TranslationService translationService) { + public CartController(CartService service, DireccionService direccionService, MessageSource messageSource, + TranslationService translationService) { this.service = service; this.direccionService = direccionService; this.messageSource = messageSource; @@ -55,6 +56,7 @@ public class CartController { var items = service.listItems(Utils.currentUserId(principal), locale); model.addAttribute("items", items); + model.addAttribute("cartId", service.getOrCreateActiveCart(Utils.currentUserId(principal))); return "imprimelibros/cart/cart"; // crea esta vista si quieres (tabla simple) } @@ -111,11 +113,15 @@ public class CartController { } @GetMapping("/get-address/{id}") - public String getDireccionCard(@PathVariable Long id, Model model, Locale locale) { + public String getDireccionCard(@PathVariable Long id, @RequestParam(required = false) Long presupuestoId, + @RequestParam(required = false) Integer unidades, + Model model, Locale locale) { Direccion dir = direccionService.findById(id) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); model.addAttribute("pais", messageSource.getMessage("paises." + dir.getPais().getKeyword(), null, dir.getPais().getKeyword(), locale)); + model.addAttribute("presupuestoId", presupuestoId); + model.addAttribute("unidades", unidades); model.addAttribute("direccion", dir); return "imprimelibros/direcciones/direccionCard :: direccionCard(direccion=${direccion})"; diff --git a/src/main/resources/i18n/cart_es.properties b/src/main/resources/i18n/cart_es.properties index d8b52b3..dcc9297 100644 --- a/src/main/resources/i18n/cart_es.properties +++ b/src/main/resources/i18n/cart_es.properties @@ -15,6 +15,10 @@ cart.shipping.info=Todos los pedidos incluyen un envío gratuito a la Península cart.shipping.order=Envío del pedido cart.shipping.samples=Envío de pruebas cart.shipping.onlyOneShipping=Todo el pedido se envía a una única dirección. +cart.shipping.tirada=Tirada: +cart.shipping.unidades=unidades +cart.shipping.ud=ud. +cart.shipping.uds=uds. cart.shipping.errors.noAddressSelected=Debe seleccionar una dirección de envío para el pedido. diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/cart/cart.js b/src/main/resources/static/assets/js/pages/imprimelibros/cart/cart.js index 707a93a..5d9a0cd 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/cart/cart.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/cart/cart.js @@ -1,7 +1,31 @@ import { formateaMoneda } from '../../imprimelibros/utils.js'; +import { showLoader, hideLoader } from '../loader.js'; $(() => { + $(document).ajaxStart(showLoader).ajaxStop(hideLoader); + + $(document).on('updateCart', () => { + // get form and submit + const form = $('#cartForm'); + const container = $("#onlyOneShipping").is(':checked') ? $('#shippingAddressesContainer') : $('.product'); + // remove name from container . direccion-card + container.find('.direccion-card input[type="hidden"]').removeAttr('name'); + + container.find('.direccion-card').each(function (i) { + $(this).find('.direccion-id').attr('name', 'direcciones[' + i + '].id'); + $(this).find('.direccion-cp').attr('name', 'direcciones[' + i + '].cp'); + $(this).find('.direccion-pais-code3').attr('name', 'direcciones[' + i + '].pais.code3'); + // añade aquí más campos si quieres que viajen + }); + $.post(form.attr('action'), form.serialize(), (response) => { + // handle response + }).always(() => { + hideLoader(); + }); + updateTotal(); + }); + updateTotal(); function updateTotal() { @@ -55,7 +79,7 @@ $(() => { console.error('Error al eliminar. Status:', res.status); return; } - else{ + else { card?.remove(); updateTotal(); } diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/cart/shipping-cart.js b/src/main/resources/static/assets/js/pages/imprimelibros/cart/shipping-cart.js index 52a8d1a..2c2fc9d 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/cart/shipping-cart.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/cart/shipping-cart.js @@ -1,5 +1,10 @@ +import { showLoader, hideLoader } from '../loader.js'; + $(() => { + // Si usas jQuery AJAX: + $(document).ajaxStart(showLoader).ajaxStop(hideLoader); + $("#onlyOneShipping").on('change', function () { if ($(this).is(':checked')) { $('.nav-product').hide(); @@ -8,21 +13,29 @@ $(() => { if (detailsBtn) new bootstrap.Tab(detailsBtn).show(); }); $('#shippingAddressesContainer').empty().show(); - $('.div-shipping-product').show(); + $('.div-shipping-product').toArray().forEach(element => { + $(element).empty().hide(); + }); $('#addOrderAddress').show(); } else { $('.nav-product').show(); - $('#shippingAddressesContainer').hide(); - $('.div-shipping-product').empty().hide(); + $('#shippingAddressesContainer').empty().hide(); + $('.div-shipping-product').toArray().forEach(element => { + $(element).empty().show(); + }); + $('.div-shipping-product').empty().show(); $('#addOrderAddress').hide(); } }); - $('#shippingAddressesContainer').on('click', '.btn-delete-direccion', function (e) { + $(document).on('click', '.btn-delete-direccion', function (e) { e.preventDefault(); const $card = $(this).closest('.direccion-card'); + const $div = $card.parent(); $card.remove(); - $('#addOrderAddress').show(); + if($div.hasClass('shipping-order-address')){ + $('#addOrderAddress').show(); + } }); const language = document.documentElement.lang || 'es-ES'; @@ -41,17 +54,24 @@ $(() => { } }); - $('#addOrderAddress').on('click', () => { + $('#addOrderAddress').on('click', async () => { if ($('#onlyOneShipping').is(':checked')) { - if(seleccionarDireccionEnvio()){ + if(await seleccionarDireccionEnvio()){ $('#addOrderAddress').hide(); } - } else { - // Add address to multiple shipping addresses container } }); - async function seleccionarDireccionEnvio() { + $(document).on('click', '.btn-add-shipping', function () { + const presupuestoId = $(this).closest('.product').find('.item-presupuesto-id').val(); + const container = $(this).closest('.product').find('.shipping-addresses-item'); + 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); + seleccionarDireccionEnvio(presupuestoId, remainingTirada, container); + }); + + async function seleccionarDireccionEnvio(presupuestoId = null, tirada = null, container = null) { const { value: direccionId, isDenied } = await Swal.fire({ title: window.languageBundle['cart.shipping.add.title'] || 'Seleccione una dirección', @@ -161,16 +181,60 @@ $(() => { }); } + let unidades = null; + if(tirada !== null && tirada >= 1 && direccionId){ + // Swal preguntando numero de unidades a asignar con máximo de tirada, necesito guardar el valor + const { value: unidadesValue } = 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, + value: tirada + }, + inputValue: 1, + showCancelButton: true, + confirmButtonText: window.languageBundle['app.ok'] || 'Aceptar', + cancelButtonText: window.languageBundle['app.cancel'] || 'Cancelar', + inputValidator: (value) => { + if (!value || isNaN(value) || value < 1 || value > tirada) { + return window.languageBundle['cart.shipping.units-error']?.replace('{max}', tirada) || `Por favor, introduzca un número válido entre 1 y ${tirada}.`; + } + return null; + } + }); + if (unidadesValue) { + unidades = parseInt(unidadesValue); + } else { + // Si el usuario cancela, salir de la función + return false; + } + } if (direccionId) { // Obtén el objeto completo seleccionado - const response = await fetch(`/cart/get-address/${direccionId}`); + showLoader(); + let uri = `/cart/get-address/${direccionId}`; + if (presupuestoId !== null && unidades !== null) { + uri += `?presupuestoId=${presupuestoId}&unidades=${unidades}`; + } + const response = await fetch(uri); if (response.ok) { const html = await response.text(); - $('#shippingAddressesContainer').append(html); + if(presupuestoId !== null){ + container.append(html); + } + else{ + $('#shippingAddressesContainer').append(html); + } + $(document).trigger('updateCart'); return true; } + hideLoader(); return false; } + hideLoader(); return false; } diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/loader.js b/src/main/resources/static/assets/js/pages/imprimelibros/loader.js new file mode 100644 index 0000000..11152b3 --- /dev/null +++ b/src/main/resources/static/assets/js/pages/imprimelibros/loader.js @@ -0,0 +1,11 @@ +export function showLoader() { + const el = document.getElementById('sectionLoader'); + el.classList.remove('d-none'); + el.classList.add('d-flex'); +} + +export function hideLoader() { + const el = document.getElementById('sectionLoader'); + el.classList.remove('d-flex'); + el.classList.add('d-none'); +} \ No newline at end of file diff --git a/src/main/resources/templates/imprimelibros/cart/_cartItem.html b/src/main/resources/templates/imprimelibros/cart/_cartItem.html index 209e36a..2d33338 100644 --- a/src/main/resources/templates/imprimelibros/cart/_cartItem.html +++ b/src/main/resources/templates/imprimelibros/cart/_cartItem.html @@ -3,96 +3,102 @@ data-iva-21=${item.iva21}, data-base=${item.base}">
Precio
-Precio
+