mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-23 01:00:23 +00:00
trabajando en envios dentro del presupuesto
This commit is contained in:
@ -29,7 +29,8 @@ public class CartController {
|
|||||||
protected MessageSource messageSource;
|
protected MessageSource messageSource;
|
||||||
protected TranslationService translationService;
|
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.service = service;
|
||||||
this.direccionService = direccionService;
|
this.direccionService = direccionService;
|
||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
@ -55,6 +56,7 @@ public class CartController {
|
|||||||
|
|
||||||
var items = service.listItems(Utils.currentUserId(principal), locale);
|
var items = service.listItems(Utils.currentUserId(principal), locale);
|
||||||
model.addAttribute("items", items);
|
model.addAttribute("items", items);
|
||||||
|
|
||||||
model.addAttribute("cartId", service.getOrCreateActiveCart(Utils.currentUserId(principal)));
|
model.addAttribute("cartId", service.getOrCreateActiveCart(Utils.currentUserId(principal)));
|
||||||
return "imprimelibros/cart/cart"; // crea esta vista si quieres (tabla simple)
|
return "imprimelibros/cart/cart"; // crea esta vista si quieres (tabla simple)
|
||||||
}
|
}
|
||||||
@ -111,11 +113,15 @@ public class CartController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-address/{id}")
|
@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)
|
Direccion dir = direccionService.findById(id)
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
||||||
model.addAttribute("pais", messageSource.getMessage("paises." + dir.getPais().getKeyword(), null,
|
model.addAttribute("pais", messageSource.getMessage("paises." + dir.getPais().getKeyword(), null,
|
||||||
dir.getPais().getKeyword(), locale));
|
dir.getPais().getKeyword(), locale));
|
||||||
|
model.addAttribute("presupuestoId", presupuestoId);
|
||||||
|
model.addAttribute("unidades", unidades);
|
||||||
model.addAttribute("direccion", dir);
|
model.addAttribute("direccion", dir);
|
||||||
|
|
||||||
return "imprimelibros/direcciones/direccionCard :: direccionCard(direccion=${direccion})";
|
return "imprimelibros/direcciones/direccionCard :: direccionCard(direccion=${direccion})";
|
||||||
|
|||||||
@ -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.order=Envío del pedido
|
||||||
cart.shipping.samples=Envío de pruebas
|
cart.shipping.samples=Envío de pruebas
|
||||||
cart.shipping.onlyOneShipping=Todo el pedido se envía a una única dirección.
|
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.
|
cart.shipping.errors.noAddressSelected=Debe seleccionar una dirección de envío para el pedido.
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,31 @@
|
|||||||
import { formateaMoneda } from '../../imprimelibros/utils.js';
|
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();
|
updateTotal();
|
||||||
|
|
||||||
function updateTotal() {
|
function updateTotal() {
|
||||||
@ -55,7 +79,7 @@ $(() => {
|
|||||||
console.error('Error al eliminar. Status:', res.status);
|
console.error('Error al eliminar. Status:', res.status);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
card?.remove();
|
card?.remove();
|
||||||
updateTotal();
|
updateTotal();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
|
import { showLoader, hideLoader } from '../loader.js';
|
||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
|
|
||||||
|
// Si usas jQuery AJAX:
|
||||||
|
$(document).ajaxStart(showLoader).ajaxStop(hideLoader);
|
||||||
|
|
||||||
$("#onlyOneShipping").on('change', function () {
|
$("#onlyOneShipping").on('change', function () {
|
||||||
if ($(this).is(':checked')) {
|
if ($(this).is(':checked')) {
|
||||||
$('.nav-product').hide();
|
$('.nav-product').hide();
|
||||||
@ -8,21 +13,29 @@ $(() => {
|
|||||||
if (detailsBtn) new bootstrap.Tab(detailsBtn).show();
|
if (detailsBtn) new bootstrap.Tab(detailsBtn).show();
|
||||||
});
|
});
|
||||||
$('#shippingAddressesContainer').empty().show();
|
$('#shippingAddressesContainer').empty().show();
|
||||||
$('.div-shipping-product').show();
|
$('.div-shipping-product').toArray().forEach(element => {
|
||||||
|
$(element).empty().hide();
|
||||||
|
});
|
||||||
$('#addOrderAddress').show();
|
$('#addOrderAddress').show();
|
||||||
} else {
|
} else {
|
||||||
$('.nav-product').show();
|
$('.nav-product').show();
|
||||||
$('#shippingAddressesContainer').hide();
|
$('#shippingAddressesContainer').empty().hide();
|
||||||
$('.div-shipping-product').empty().hide();
|
$('.div-shipping-product').toArray().forEach(element => {
|
||||||
|
$(element).empty().show();
|
||||||
|
});
|
||||||
|
$('.div-shipping-product').empty().show();
|
||||||
$('#addOrderAddress').hide();
|
$('#addOrderAddress').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#shippingAddressesContainer').on('click', '.btn-delete-direccion', function (e) {
|
$(document).on('click', '.btn-delete-direccion', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const $card = $(this).closest('.direccion-card');
|
const $card = $(this).closest('.direccion-card');
|
||||||
|
const $div = $card.parent();
|
||||||
$card.remove();
|
$card.remove();
|
||||||
$('#addOrderAddress').show();
|
if($div.hasClass('shipping-order-address')){
|
||||||
|
$('#addOrderAddress').show();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const language = document.documentElement.lang || 'es-ES';
|
const language = document.documentElement.lang || 'es-ES';
|
||||||
@ -41,17 +54,24 @@ $(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#addOrderAddress').on('click', () => {
|
$('#addOrderAddress').on('click', async () => {
|
||||||
if ($('#onlyOneShipping').is(':checked')) {
|
if ($('#onlyOneShipping').is(':checked')) {
|
||||||
if(seleccionarDireccionEnvio()){
|
if(await seleccionarDireccionEnvio()){
|
||||||
$('#addOrderAddress').hide();
|
$('#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({
|
const { value: direccionId, isDenied } = await Swal.fire({
|
||||||
title: window.languageBundle['cart.shipping.add.title'] || 'Seleccione una dirección',
|
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) {
|
if (direccionId) {
|
||||||
// Obtén el objeto completo seleccionado
|
// 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) {
|
if (response.ok) {
|
||||||
const html = await response.text();
|
const html = await response.text();
|
||||||
$('#shippingAddressesContainer').append(html);
|
if(presupuestoId !== null){
|
||||||
|
container.append(html);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$('#shippingAddressesContainer').append(html);
|
||||||
|
}
|
||||||
|
$(document).trigger('updateCart');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
hideLoader();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
hideLoader();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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');
|
||||||
|
}
|
||||||
@ -3,96 +3,102 @@
|
|||||||
data-iva-21=${item.iva21},
|
data-iva-21=${item.iva21},
|
||||||
data-base=${item.base}">
|
data-base=${item.base}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
|
<input type="hidden" class="item-presupuesto-id" th:value="${item.cartItemId}" />
|
||||||
|
<input type="hidden" class="item-tirada" th:value="${item.tirada}" />
|
||||||
|
|
||||||
<div class="step-arrow-nav mt-n3 mx-n3 mb-3">
|
<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 class="nav nav-pills nav-justified custom-nav nav-product" style="display: none;" role="tablist">
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link fs-15 active" th:id="${'pills-details-' + item.cartItemId + '-tab'}"
|
<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"
|
th:data-bs-target="${'#pills-details-' + item.cartItemId}" type="button" role="tab"
|
||||||
th:aria-controls="${'#pills-details-' + item.cartItemId}" aria-selected="true" data-bs-toggle="tab">
|
th:aria-controls="${'#pills-details-' + item.cartItemId}" aria-selected="true"
|
||||||
<i class="ri-truck-line fs-5 p-1 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
data-bs-toggle="tab">
|
||||||
<label class="fs-13 my-2" th:text="#{cart.tabs.details}">Detalles</label>
|
<i
|
||||||
</button>
|
class="ri-truck-line fs-5 p-1 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
</li>
|
<label class="fs-13 my-2" th:text="#{cart.tabs.details}">Detalles</label>
|
||||||
<li class="nav-item" role="presentation">
|
</button>
|
||||||
<button class="nav-link fs-15" th:id="${'pills-shipping-' + item.cartItemId + '-tab'}"
|
</li>
|
||||||
th:data-bs-target="${'#pills-shipping-' + item.cartItemId}" type="button" role="tab"
|
<li class="nav-item" role="presentation">
|
||||||
th:aria-controls="${'#pills-shipping-' + item.cartItemId}" aria-selected="false" data-bs-toggle="tab">
|
<button class="nav-link fs-15" th:id="${'pills-shipping-' + item.cartItemId + '-tab'}"
|
||||||
<i class="ri-truck-line fs-5 p-1 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
th:data-bs-target="${'#pills-shipping-' + item.cartItemId}" type="button" role="tab"
|
||||||
<label class="fs-13 my-2" th:text="#{cart.tabs.envio}">Envío</label>
|
th:aria-controls="${'#pills-shipping-' + item.cartItemId}" aria-selected="false"
|
||||||
</button>
|
data-bs-toggle="tab">
|
||||||
</li>
|
<i
|
||||||
</ul>
|
class="ri-truck-line fs-5 p-1 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
|
<label class="fs-13 my-2" th:text="#{cart.tabs.envio}">Envío</label>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content row gy-3">
|
<div class="tab-content">
|
||||||
<div class="tab-pane fade show tab-pane-details active" th:id="${'pills-details-' + item.cartItemId}" role="tabpanel"
|
<div class="tab-pane fade show active tab-pane-details" th:id="${'pills-details-' + item.cartItemId}"
|
||||||
th:aria-labelledby="${'pills-details-' + item.cartItemId + '-tab'}">
|
role="tabpanel" th:aria-labelledby="${'pills-details-' + item.cartItemId + '-tab'}">
|
||||||
<div class="col-sm-auto">
|
|
||||||
<div class="avatar-lg bg-light rounded p-1">
|
|
||||||
<img th:src="${item.imagen != null ? item.imagen : '/assets/images/products/placeholder.png'}"
|
|
||||||
alt="portada" class="img-fluid d-block rounded">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Detalles -->
|
<div class="row g-3 align-items-start">
|
||||||
<div class="col-sm">
|
<!-- Col 1: imagen -->
|
||||||
<!-- Título / enlace -->
|
<div class="col-auto">
|
||||||
<h5 class="fs-18 text-truncate mb-1">
|
<div class="avatar-lg bg-light rounded p-1">
|
||||||
<a th:href="@{|presupuesto/edit/${item.presupuestoId}|}" class="text-dark"
|
<img th:src="${item.imagen != null ? item.imagen : '/assets/images/products/placeholder.png'}"
|
||||||
th:text="${item.titulo != null ? item.titulo : 'Presupuesto #'}">
|
alt="portada" class="img-fluid d-block rounded">
|
||||||
Presupuesto
|
|
||||||
</a>
|
|
||||||
</h5>
|
|
||||||
<h5 class="fs-14 text-truncate mb-1">
|
|
||||||
<span th:text="#{cart.item.presupuesto-numero}">Presupuesto #</span>
|
|
||||||
<span th:text="${item.presupuestoId != null ? item.presupuestoId : ''}">#</span>
|
|
||||||
</h5>
|
|
||||||
|
|
||||||
<!-- Detalles opcionales (ej: cliente, fecha, etc.) -->
|
|
||||||
<ul class="list-inline text-muted mb-1">
|
|
||||||
<div th:each="linea : ${item.resumen.lineas}">
|
|
||||||
<li class="list-inline-item me-3">
|
|
||||||
<div th:utext="${linea['descripcion']}"></div>
|
|
||||||
</li>
|
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
|
|
||||||
<ul class="list-inline text-muted mb-1" th:if="${item.resumen.servicios != null}">
|
<!-- Col 2: detalles -->
|
||||||
<span th:utext="#{pdf.servicios-adicionales}">Servicios adicionales</span>
|
<div class="col">
|
||||||
<span class="spec-label" th:text="${item.resumen.servicios}"></span>
|
<h5 class="fs-18 text-truncate mb-1">
|
||||||
</ul>
|
<a th:href="@{|presupuesto/edit/${item.presupuestoId}|}" class="text-dark"
|
||||||
|
th:text="${item.titulo != null ? item.titulo : 'Presupuesto #'}">Presupuesto</a>
|
||||||
|
</h5>
|
||||||
|
<h5 class="fs-14 text-truncate mb-1">
|
||||||
|
<span th:text="#{cart.item.presupuesto-numero}">Presupuesto #</span>
|
||||||
|
<span th:text="${item.presupuestoId != null ? item.presupuestoId : ''}">#</span>
|
||||||
|
</h5>
|
||||||
|
|
||||||
<ul class="list-inline text-muted mb-1" th:if="${item.resumen != null
|
<ul class="list-unstyled text-muted mb-1 ps-0">
|
||||||
and #maps.containsKey(item.resumen, 'datosMaquetacion')
|
<li th:each="linea : ${item.resumen.lineas}" class="mb-1">
|
||||||
and item.resumen['datosMaquetacion'] != null}">
|
<span th:utext="${linea['descripcion']}"></span>
|
||||||
<li class="list-inline-item spec-row mb-1">
|
</li>
|
||||||
<span th:text="#{pdf.datos-maquetacion}">Datos de maquetación:</span>
|
</ul>
|
||||||
<span th:utext="${item.resumen.datosMaquetacion}"></span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul class="list-inline text-muted mb-1" th:if="${item.resumen != null
|
<ul class="list-unstyled text-muted mb-1" th:if="${item.resumen.servicios != null}">
|
||||||
and #maps.containsKey(item.resumen, 'datosMarcapaginas')
|
<li>
|
||||||
and item.resumen['datosMarcapaginas'] != null}">
|
<span th:utext="#{pdf.servicios-adicionales}">Servicios adicionales:</span>
|
||||||
<li class="list-inline-item spec-row mb-1">
|
<span class="spec-label" th:text="${item.resumen.servicios}"></span>
|
||||||
<span th:text="#{pdf.datos-marcapaginas}">Datos de marcapáginas:</span>
|
</li>
|
||||||
<span th:utext="${item.resumen.datosMarcapaginas}"></span>
|
</ul>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
<ul class="list-unstyled text-muted mb-1"
|
||||||
|
th:if="${item.resumen != null and #maps.containsKey(item.resumen,'datosMaquetacion') and item.resumen['datosMaquetacion'] != null}">
|
||||||
|
<li class="spec-row mb-1">
|
||||||
|
<span th:text="#{pdf.datos-maquetacion}">Datos de maquetación:</span>
|
||||||
|
<span th:utext="${item.resumen.datosMaquetacion}"></span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<!-- Precio o totales (si los tienes) -->
|
<ul class="list-unstyled text-muted mb-1"
|
||||||
<div class="col-sm-auto text-end">
|
th:if="${item.resumen != null and #maps.containsKey(item.resumen,'datosMarcapaginas') and item.resumen['datosMarcapaginas'] != null}">
|
||||||
<p class="text-muted mb-1" th:text="#{cart.precio}">Precio</p>
|
<li class="spec-row mb-1">
|
||||||
<h5 class="fs-14 mb-0">
|
<span th:text="#{pdf.datos-marcapaginas}">Datos de marcapáginas:</span>
|
||||||
<span th:text="${item.baseTotal != null ? item.baseTotal : '-'}">0,00</span>
|
<span th:utext="${item.resumen.datosMarcapaginas}"></span>
|
||||||
</h5>
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Col 3: precio -->
|
||||||
|
<div class="col-auto ms-auto text-end">
|
||||||
|
<p class="text-muted mb-1" th:text="#{cart.precio}">Precio</p>
|
||||||
|
<h5 class="fs-14 mb-0">
|
||||||
|
<span th:text="${item.baseTotal != null ? item.baseTotal : '-'}">0,00</span>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane fade show tab-pane-shipping" th:id="${'pills-shipping-' + item.cartItemId}" role="tabpanel"
|
<div class="tab-pane fade show tab-pane-shipping" th:id="${'pills-shipping-' + item.cartItemId}"
|
||||||
th:aria-labelledby="${'pills-shipping-' + item.cartItemId + '-tab'}">
|
role="tabpanel" th:aria-labelledby="${'pills-shipping-' + item.cartItemId + '-tab'}">
|
||||||
|
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<!-- Título / enlace -->
|
<!-- Título / enlace -->
|
||||||
@ -106,6 +112,40 @@
|
|||||||
<span th:text="#{cart.item.presupuesto-numero}">Presupuesto #</span>
|
<span th:text="#{cart.item.presupuesto-numero}">Presupuesto #</span>
|
||||||
<span th:text="${item.presupuestoId != null ? item.presupuestoId : ''}">#</span>
|
<span th:text="${item.presupuestoId != null ? item.presupuestoId : ''}">#</span>
|
||||||
</h5>
|
</h5>
|
||||||
|
<h5 class="fs-14 text-truncate mb-1">
|
||||||
|
<span
|
||||||
|
th:text="#{cart.shipping.tirada} + ' ' + (${item.tirada} != null ? ${item.tirada} : '') + ' ' + #{cart.shipping.unidades} ">
|
||||||
|
</span>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{checkout.shipping.order}">Envio
|
||||||
|
del pedido
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div class="px-2 mb-2">
|
||||||
|
<button type="button" class="btn btn-secondary btn-add-shipping"
|
||||||
|
th:text="#{cart.shipping.add}">Añadir dirección</button>
|
||||||
|
|
||||||
|
<div class="shipping-addresses-item d-flex flex-wrap gap-3 mt-4"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4"
|
||||||
|
th:if="${item.hasSample}">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{cart.shipping.samples}">Envio
|
||||||
|
de pruebas
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-auto div-shipping-product">
|
<div class="col-sm-auto div-shipping-product">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -37,6 +37,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container-fluid row gy-4">
|
<div class="container-fluid row gy-4">
|
||||||
|
|
||||||
|
<div id="sectionLoader" class="position-absolute top-0 start-0 w-100 h-100 d-none justify-content-center align-items-center
|
||||||
|
bg-body bg-opacity-75" style="z-index:10;">
|
||||||
|
<div class="spinner-border" role="status" style="width:2.5rem;height:2.5rem;">
|
||||||
|
<span class="visually-hidden">Cargando…</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div th:if="${items.isEmpty()}">
|
<div th:if="${items.isEmpty()}">
|
||||||
<div class="alert alert-info" role="alert" th:text="#{cart.empty}"></div>
|
<div class="alert alert-info" role="alert" th:text="#{cart.empty}"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -59,7 +67,7 @@
|
|||||||
<button type="button" class="btn btn-secondary" id="addOrderAddress"
|
<button type="button" class="btn btn-secondary" id="addOrderAddress"
|
||||||
th:text="#{cart.shipping.add}">Añadir dirección</button>
|
th:text="#{cart.shipping.add}">Añadir dirección</button>
|
||||||
|
|
||||||
<div id="shippingAddressesContainer" class="d-flex flex-wrap gap-3 mt-4"></div>
|
<div id="shippingAddressesContainer" class="shipping-order-address d-flex flex-wrap gap-3 mt-4"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,19 +1,35 @@
|
|||||||
<div th:fragment="direccionCard(direccion)" class="card card border mb-3 direccion-card bg-light w-100 mx-2" th:attr="data-id=${direccion.id},
|
<div th:fragment="direccionCard(direccion)" name="direccion"
|
||||||
data-cp=${direccion.cp},
|
class="card card border mb-3 direccion-card bg-light w-100 mx-2">
|
||||||
data-pais-code3=${direccion.pais.code3}" >
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
<div class="p-2 mx-3">
|
<input type="hidden" class="presupuesto-id" th:value="${presupuestoId}" />
|
||||||
<span class="mb-2 fw-semibold d-block text-muted text-uppercase" th:text="${direccion.alias}"></span>
|
<input type="hidden" class="direccion-id" th:value="${direccion.id}" />
|
||||||
<span class="fs-14 mb-1 d-block" th:text="${direccion.att}"></span>
|
<input type="hidden" class="direccion-cp" th:value="${direccion.cp}" />
|
||||||
<span class="text-muted fw-normal text-wrap mb-1 d-block" th:text="${direccion.direccion}"></span>
|
<input type="hidden" class="direccion-pais-code3" th:value="${direccion.pais.code3}" />
|
||||||
<span class="text-muted fw-normal d-block" th:text="${pais}"></span>
|
<input type="hidden" class="item-tirada" th:value="${unidades != null ? unidades : ''}" />
|
||||||
<span class="text-muted fw-normal d-block"
|
|
||||||
th:text="#{'direcciones.telefono'} + ': ' + ${direccion.telefono}"></span>
|
<div class="row g-3 align-items-start">
|
||||||
|
<div class="col">
|
||||||
|
<span class="mb-2 fw-semibold d-block text-muted text-uppercase" th:text="${direccion.alias}"></span>
|
||||||
|
<span class="fs-14 mb-1 d-block" th:text="${direccion.att}"></span>
|
||||||
|
<span class="text-muted fw-normal text-wrap mb-1 d-block" th:text="${direccion.direccion}"></span>
|
||||||
|
<span class="text-muted fw-normal d-block" th:text="${pais}"></span>
|
||||||
|
<span class="text-muted fw-normal d-block"
|
||||||
|
th:text="#{'direcciones.telefono'} + ': ' + ${direccion.telefono}"></span>
|
||||||
|
</div>
|
||||||
|
<div th:if="${unidades != null}" class="col-auto ms-auto text-end">
|
||||||
|
<span class="mb-2 fw-semibold d-block text-muted text-uppercase" th:if="${unidades == 1}"
|
||||||
|
th:text="|${unidades} #{cart.shipping.ud}|"></span>
|
||||||
|
|
||||||
|
<!-- plural -->
|
||||||
|
<span class="mb-2 fw-semibold d-block text-muted text-uppercase" th:unless="${unidades == 1}"
|
||||||
|
th:text="|${unidades} #{cart.shipping.uds}|"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="d-flex flex-wrap align-items-center gap-2 px-2 py-1 bg-light rounded-bottom border-top mt-auto actions-row">
|
class="d-flex flex-wrap align-items-center gap-2 px-2 py-1 bg-light rounded-bottom border-top mt-auto actions-row">
|
||||||
<a href="#" class="d-block text-body p-1 px-2 btn-delete-direccion" data-id="${this._esc(d.id ?? '')}">
|
<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>
|
<i class="ri-delete-bin-fill text-muted align-bottom me-1"></i>
|
||||||
<span th:text="#{'direcciones.btn.delete'}">Eliminar</span>
|
<span th:text="#{'direcciones.btn.delete'}">Eliminar</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user