terminado

This commit is contained in:
Jaime Jiménez
2025-09-21 14:16:00 +02:00
parent b5275f89f7
commit 42fa347829
14 changed files with 177 additions and 44 deletions

View File

@ -70,7 +70,7 @@ class PresupuestoCliente {
acabado_marcapaginas: 'ninguno',
resultado: {
precio_unitario: 0,
precio_total: 0
precio: 0
}
},
datosMaquetacion: {
@ -184,6 +184,7 @@ class PresupuestoCliente {
this.#initInterior();
this.#initSeleccionTirada();
this.#initExtras();
this.#initResumen();
$(document).on('change', 'input[min][max]', function () {
const $input = $(this);
@ -1387,14 +1388,25 @@ class PresupuestoCliente {
this.#changeTab('pills-seleccion-tirada');
this.summaryTableExtras.addClass('d-none');
} else {
//this.#changeTab('pills-finalizar');
this.#changeTab('pills-resumen');
}
});
// Eventos para el resumen
$(document).on('change', '.service-checkbox', (e) => {
Summary.updateExtras();
const $target = $(e.currentTarget);
if ($target.prop('checked')) {
this.formData.servicios.servicios.push($target.val());
} else {
const index = this.formData.servicios.servicios.indexOf($target.val());
if (index > -1) {
this.formData.servicios.servicios.splice(index, 1);
}
}
Summary.updateExtras();
this.#cacheFormData();
});
}
@ -1406,14 +1418,44 @@ class PresupuestoCliente {
this.divExtras.addClass('animate-fadeInUpBounce');
for (const extra of servicios) {
if (this.formData.servicios.servicios.includes(extra.id) && !extra.checked) {
extra.checked = true;
if (extra.id === "marcapaginas" || extra.id === "maquetacion") {
extra.price = extra.id === "marcapaginas" ?
this.formData.servicios.datosMarcapaginas.resultado.precio :
this.formData.servicios.datosMaquetacion.resultado.precio;
extra.priceUnit = this.divExtras.data('currency');
}
}
const item = new ServiceOptionCard(extra);
this.divExtras.append(item.render());
if (item.checked) {
if (!this.formData.servicios.servicios.includes(extra.id)) {
this.formData.servicios.servicios.push(extra.id);
}
}
}
this.#cacheFormData();
Summary.updateExtras();
}
/******************************
* END EXTRAS
******************************/
/******************************
* EXTRAS
******************************/
#initResumen() {
$(document).on('click', '.btn-change-tab-resumen', (e) => {
const id = e.currentTarget.id;
if (id === 'btn-prev-resumen') {
this.#changeTab('pills-extras');
}
});
}
/******************************
* END EXTRAS
******************************/

View File

@ -113,9 +113,11 @@ $(document).on("submit", "#maquetacionForm", function (e) {
$(document).on('hidden.bs.modal', '#maquetacionModal', function () {
const calcularStr = $('#div-extras').data('language-calcular');
$('#maquetacion').prop('checked', false);
$('#maquetacion').data('price', calcularStr);
$('label[for="maquetacion"] .service-price').text(calcularStr);
$('#maquetacion').prop('checked', false).trigger('change');
Summary.updateExtras();
});
@ -138,6 +140,8 @@ function loadMaquetacionData() {
$('#texto-mecanografiado').prop('checked', stored.texto_mecanografiado);
$('#disenio-portada').prop('checked', stored.disenio_portada);
$('#epub').prop('checked', stored.epub);
Summary.updateExtras();
}

View File

@ -1,5 +1,5 @@
import * as Summary from "./summary.js";
import { formateaMoneda, formateaMoneda6Decimales } from "../utils.js";
import { formateaMoneda } from "../utils.js";
$(document).on('change', '#marcapaginas', function (e) {
e.preventDefault();
@ -10,7 +10,7 @@ $(document).on('change', '#marcapaginas', function (e) {
loadMarcapaginasData();
// init marcapaginas form
filtrarAcabados();
filtrarAcabados();
$("#marcapaginasModal").modal("show");
});
@ -42,7 +42,7 @@ $(document).on("submit", "#marcapaginasForm", function (e) {
const resumenHtml = `
<div class="text-start">
<p>${json.language.precio_unidad || 'Precio por unidad'}: ${formateaMoneda6Decimales(json.precio_unitario) || "-"}</p>
<p>${json.language.precio_unidad || 'Precio por unidad'}: ${formateaMoneda(json.precio_unitario, 6) || "-"}</p>
<h3 class="mb-0">${json.language.precio_total || 'Precio total'}: ${formateaMoneda(json.precio_total) || "-"}</h3>
</div>
`;
@ -72,7 +72,7 @@ $(document).on("submit", "#marcapaginasForm", function (e) {
// guardamos los datos del formulario en sessionStorage
const stored = JSON.parse(sessionStorage.getItem("formData"));
stored.servicios.datosMarcapaginas.resultado.precio_unitario = json.precio_unitario;
stored.servicios.datosMarcapaginas.resultado.precio_total = json.precio_total;
stored.servicios.datosMarcapaginas.resultado.precio = json.precio_total;
sessionStorage.setItem("formData", JSON.stringify(stored));
}
else {
@ -117,9 +117,10 @@ $(document).on("change", "#caras-impresion", function (e) {
$(document).on('hidden.bs.modal', '#marcapaginasModal', function () {
const calcularStr = $('#div-extras').data('language-calcular');
$('#marcapaginas').prop('checked', false);
$('#marcapaginas').data('price', calcularStr);
$('label[for="marcapaginas"] .service-price').text(calcularStr);
$('#marcapaginas').prop('checked', false).trigger('change');
Summary.updateExtras();
});

View File

@ -1,3 +1,5 @@
import {formateaMoneda, isNumber} from '../utils.js';
class ServiceOptionCard {
constructor({ id, title, description = '', price = '', priceUnit = '', checked = false, allowChange = true, ribbonText }) {
@ -23,7 +25,7 @@ class ServiceOptionCard {
${ribbonHtml}
<h5 class="service-title mb-1">${this.title}</h5>
<p class="service-desc mb-1 small">${this.description}</p>
<h4 class="service-price fw-semibold mt-2 h4 mb-0">${this.price} ${this.priceUnit}</h4>
<h4 class="service-price fw-semibold mt-2 h4 mb-0">${isNumber(this.price) ? formateaMoneda(this.price, 2, this.locale) : this.price}</h4>
</label>
</div>
`);

View File

@ -1,6 +1,8 @@
import { formateaMoneda, formateaNumero } from "../utils.js";
// ===== Clase =====
class TiradaCard {
constructor({ id, titulo, unidades, precioUnidad, precioTotal, selected = false, moneda = '€', name = 'tirada',
constructor({ id, titulo, unidades, precioUnidad, precioTotal, selected = false, name = 'tirada',
labels = {}, locale = (document.documentElement.lang || navigator.language || 'es-ES')
}) {
this.id = id;
@ -9,7 +11,6 @@ class TiradaCard {
this.precioUnidad = precioUnidad;
this.precioTotal = precioTotal;
this.selected = selected;
this.moneda = moneda;
this.name = name;
this.locale = locale;
this.labels = Object.assign({
@ -22,16 +23,10 @@ class TiradaCard {
this.$container = null; // se establece al renderizar
}
#formatMoneyES(value, decimals = 2) {
return new Intl.NumberFormat(this.locale, {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals
}).format(Number(value));
}
#title() {
if (this.titulo) return this.titulo;
if (this.unidades != null) return `${this.unidades} ${this.labels.units}`;
if (this.unidades != null) return `${formateaNumero({valor: this.unidades, locale: this.locale, digits: 0})} ${this.labels.units}`;
return '';
}
@ -46,11 +41,11 @@ class TiradaCard {
<div class="title">${this.#title()}</div>
<div class="per muted">${this.labels.perUnit}</div>
<div class="price-big">${this.#formatMoneyES(this.precioUnidad, 4)} ${this.moneda}</div>
<div class="price-big">${formateaMoneda(this.precioUnidad, 4, this.locale)}</div>
<div class="price-row">
<div class="muted">${this.labels.total}</div>
<div class="price-total fw-bold">${this.#formatMoneyES(this.precioTotal, 2)} ${this.moneda}</div>
<div class="price-total fw-bold">${formateaMoneda(this.precioTotal, 2, this.locale)}</div>
</div>
<button type="button" class="btn btn-select-tirada">${this.labels.select}</button>

View File

@ -1,26 +1,40 @@
function formateaMoneda(valor) {
function formateaMoneda(valor, digits = 2, locale = 'es-ES', currency = 'EUR') {
try {
return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR' }).format(valor);
return new Intl.NumberFormat(locale, { style: 'currency', currency, minimumFractionDigits: digits, useGrouping: true }).format(valor);
} catch {
return valor;
}
}
export { formateaMoneda };
function formateaMoneda4Decimales(valor) {
try {
return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 4 }).format(valor);
} catch {
return valor;
}
}
export { formateaMoneda4Decimales };
function formateaMoneda6Decimales(valor) {
try {
return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 6 }).format(valor);
} catch {
return valor;
function formateaNumero({
valor,
digits = 2,
style = 'decimal',
locale = 'es-ES',
currency = 'EUR'
}) {
const n = Number(valor);
if (!Number.isFinite(n)) return valor;
const opts = {
useGrouping: true,
minimumFractionDigits: digits,
maximumFractionDigits: digits,
};
if (style === 'currency') {
opts.style = 'currency';
opts.currency = currency;
}
return new Intl.NumberFormat(locale, opts).format(n);
}
export { formateaMoneda6Decimales };
export { formateaNumero };
function isNumber(value) {
return !isNaN(Number(value)) && value.trim() !== '';
}
export { isNumber };