mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-21 16:20:22 +00:00
guardando presupuestos anonimos
This commit is contained in:
@ -33,11 +33,9 @@ safekat.api.password=Safekat2024
|
||||
#
|
||||
# Debug JPA / Hibernate
|
||||
#
|
||||
#spring.jpa.show-sql=true
|
||||
#logging.level.org.hibernate.SQL=DEBUG
|
||||
#logging.level.org.hibernate.orm.jdbc.bind=TRACE
|
||||
#spring.jpa.properties.hibernate.format_sql=true
|
||||
|
||||
logging.level.org.hibernate.SQL=DEBUG
|
||||
logging.level.org.hibernate.orm.jdbc.bind=TRACE
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
|
||||
#
|
||||
# Resource chain
|
||||
|
||||
@ -10,6 +10,7 @@ presupuesto.resumen=Resumen
|
||||
presupuesto.add-to-presupuesto=Añadir al presupuesto
|
||||
presupuesto.calcular=Calcular
|
||||
presupuesto.add=Añadir presupuesto
|
||||
presupuesto.guardar=Guardar
|
||||
|
||||
presupuesto.nav.presupuestos-cliente=Presupuestos cliente
|
||||
presupuesto.nav.presupuestos-anonimos=Presupuestos anónimos
|
||||
@ -278,6 +279,19 @@ presupuesto.error.delete-permission-denied=No se puede eliminar: permiso denegad
|
||||
presupuesto.error.delete-not-found=No se puede eliminar: presupuesto no encontrado.
|
||||
presupuesto.error.delete-not-draft=Solo se pueden eliminar presupuestos en estado Borrador.
|
||||
|
||||
# Añadir presupuesto
|
||||
presupuesto.add.tipo=Tipo de presupuesto
|
||||
presupuesto.add.anonimo=Anónimo
|
||||
presupuesto.add.cliente=De cliente
|
||||
presupuesto.add.next=Siguiente
|
||||
presupuesto.add.cancel=Cancelar
|
||||
presupuesto.add.select-client=Seleccione cliente
|
||||
presupuesto.add.error.options=Debe seleccionar una opción
|
||||
presupuesto.add.error.options-client=Debe seleccionar un cliente
|
||||
presupuesto.error.save-internal-error=No se puede guardar: error interno.
|
||||
presupuesto.exito.guardado=Presupuesto guardado con éxito.
|
||||
presupuesto.exito.guardado-actualizado=Presupuesto actualizado con éxito.
|
||||
|
||||
# Errores
|
||||
presupuesto.errores-title=Corrija los siguientes errores:
|
||||
presupuesto.errores.titulo=El título es obligatorio
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import PresupuestoWizard from './wizard.js';
|
||||
|
||||
const app = new PresupuestoWizard({
|
||||
mode: 'public',
|
||||
readonly: false,
|
||||
canSave: true,
|
||||
useSessionCache: false,
|
||||
});
|
||||
app.init();
|
||||
@ -1,7 +1,7 @@
|
||||
import PresupuestoWizard from './wizard.js';
|
||||
|
||||
const app = new PresupuestoWizard({
|
||||
mode: 'view',
|
||||
mode: 'public',
|
||||
readonly: true,
|
||||
canSave: false,
|
||||
useSessionCache: false,
|
||||
|
||||
@ -22,15 +22,15 @@ export default class PresupuestoWizard {
|
||||
titulo: '',
|
||||
autor: '',
|
||||
isbn: '',
|
||||
tirada1: '',
|
||||
tirada1: 10,
|
||||
tirada2: '',
|
||||
tirada3: '',
|
||||
tirada4: '',
|
||||
ancho: '',
|
||||
alto: '',
|
||||
ancho: 148,
|
||||
alto: 218,
|
||||
formatoPersonalizado: false,
|
||||
paginasNegro: '',
|
||||
paginasColor: '',
|
||||
paginasNegro: 0,
|
||||
paginasColor: 32,
|
||||
posicionPaginasColor: '',
|
||||
tipoEncuadernacion: 'fresado',
|
||||
},
|
||||
@ -99,7 +99,7 @@ export default class PresupuestoWizard {
|
||||
}
|
||||
}
|
||||
},
|
||||
selectedTirada: null,
|
||||
selectedTirada: 10,
|
||||
}
|
||||
|
||||
// pestaña datos generales
|
||||
@ -180,12 +180,20 @@ export default class PresupuestoWizard {
|
||||
|
||||
async init() {
|
||||
|
||||
$.ajaxSetup({
|
||||
beforeSend: function (xhr) {
|
||||
const token = document.querySelector('meta[name="_csrf"]')?.content;
|
||||
const header = document.querySelector('meta[name="_csrf_header"]')?.content;
|
||||
if (token && header) xhr.setRequestHeader(header, token);
|
||||
}
|
||||
});
|
||||
|
||||
const root = document.getElementById('presupuesto-app');
|
||||
const mode = root?.dataset.mode || 'public';
|
||||
const presupuestoId = root?.dataset.id || null;
|
||||
|
||||
let stored = null;
|
||||
if(this.opts.useSessionCache) {
|
||||
if (this.opts.useSessionCache) {
|
||||
stored = sessionStorage.getItem("formData");
|
||||
}
|
||||
|
||||
@ -238,29 +246,75 @@ export default class PresupuestoWizard {
|
||||
|
||||
if (this.opts.canSave) {
|
||||
$('#btn-guardar').on('click', async () => {
|
||||
// compón el payload con lo que ya tienes:
|
||||
|
||||
const alert = $('#form-errors');
|
||||
const servicios = [];
|
||||
$('.service-checkbox:checked').each(function () {
|
||||
const $servicio = $(this);
|
||||
servicios.push({
|
||||
id: $servicio.attr('id') ?? $(`label[for="${$servicio.attr('id')}"] .service-title`).text().trim(),
|
||||
label: $(`label[for="${$servicio.attr('id')}"] .service-title`).text().trim(),
|
||||
units: $servicio.attr('id') === 'marcapaginas' ? self.formData.servicios.datosMarcapaginas.marcapaginas_tirada : 1,
|
||||
price: $servicio.data('price') ?? $(`label[for="${$servicio.attr('id')}"] .service-price`).text().trim().replace(" " + self.divExtras.data('currency'), ''),
|
||||
});
|
||||
});
|
||||
const payload = {
|
||||
id: this.opts.presupuestoId,
|
||||
mode: this.opts.mode,
|
||||
presupuesto: this.#getPresupuestoData(),
|
||||
servicios: servicios,
|
||||
};
|
||||
try {
|
||||
const res = await fetch(this.opts.endpoints.save, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
}).then(r => r.json());
|
||||
alert.addClass('d-none').find('ul').empty();
|
||||
$.ajax({
|
||||
url: '/presupuesto/save',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(payload)
|
||||
}).then((data) => {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: window.languageBundle?.get('common.guardado') || 'Guardado',
|
||||
timer: 1800,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
showConfirmButton: false
|
||||
});
|
||||
// opcional: actualizar window.PRESUPUESTO_ID/resumen con el id devuelto
|
||||
if (data.id) this.opts.presupuestoId = data.id;
|
||||
}).catch((xhr, status, error) => {
|
||||
|
||||
// feedback
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: window.languageBundle?.get('common.guardado') || 'Guardado',
|
||||
timer: 1800,
|
||||
showConfirmButton: false
|
||||
const errors = xhr.responseJSON;
|
||||
if (errors && typeof errors === 'object') {
|
||||
if (!this.DEBUG && xhr.responseJSON.error && xhr.responseJSON.error == 'Internal Server Error') {
|
||||
console.error("Error al validar los datos generales. Internal Server Error");
|
||||
return;
|
||||
}
|
||||
Object.values(errors).forEach(errorMsg => {
|
||||
alert.find('ul').append(`<li>${errorMsg}</li>`);
|
||||
});
|
||||
alert.removeClass('d-none');
|
||||
} else {
|
||||
alert.find('ul').append('<li>Error desconocido. Por favor, inténtelo de nuevo más tarde.</li>');
|
||||
$(window).scrollTop(0);
|
||||
alert.removeClass('d-none');
|
||||
}
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
});
|
||||
// opcional: actualizar window.PRESUPUESTO_ID/resumen con el id devuelto
|
||||
if (res.id) window.PRESUPUESTO_ID = res.id;
|
||||
} catch (e) {
|
||||
Swal.fire({ icon: 'error', title: 'Error al guardar', text: e?.message || '' });
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error al guardar',
|
||||
text: e?.message || '',
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -381,7 +435,7 @@ export default class PresupuestoWizard {
|
||||
$(document).on('change', 'input[name="tipoEncuadernacion"]', (e) => {
|
||||
|
||||
if ($(e.target).is(':checked')) {
|
||||
|
||||
|
||||
Summary.updateEncuadernacion();
|
||||
}
|
||||
});
|
||||
@ -507,7 +561,7 @@ export default class PresupuestoWizard {
|
||||
this.tirada4.val(this.formData.datosGenerales.tirada4);
|
||||
|
||||
this.paginasNegro.val(this.formData.datosGenerales.paginasNegro);
|
||||
this.paginasColor.val(this.formData.datosGenerales.paginasColor);;
|
||||
this.paginasColor.val(this.formData.datosGenerales.paginasColor);;
|
||||
|
||||
this.posicionPaginasColor.val(this.formData.datosGenerales.posicionPaginasColor);
|
||||
|
||||
@ -589,7 +643,7 @@ export default class PresupuestoWizard {
|
||||
}
|
||||
|
||||
if (!(selectedTipo && $('.tipo-libro#' + selectedTipo).length > 0 && !$('.tipo-libro#' + selectedTipo).hasClass('d-none'))) {
|
||||
|
||||
|
||||
let firstVisible = $('.tipo-libro').not('.d-none').first();
|
||||
|
||||
if (firstVisible.length) {
|
||||
@ -626,7 +680,7 @@ export default class PresupuestoWizard {
|
||||
$(document).on('change', 'input[name="tipoImpresion"]', (e) => {
|
||||
if (!$(e.target).is(':checked'))
|
||||
return;
|
||||
|
||||
|
||||
const data = this.#getPresupuestoData();
|
||||
Summary.updateTipoImpresion();
|
||||
|
||||
@ -849,7 +903,7 @@ export default class PresupuestoWizard {
|
||||
for (let i = 0; i < opciones_papel_interior.length; i++) {
|
||||
const opcion = opciones_papel_interior[i];
|
||||
const item = new imagen_presupuesto(opcion);
|
||||
item.group = 'papelInterior';
|
||||
item.group = 'papelInterior';
|
||||
item.extraClass = 'interior-data papel-interior';
|
||||
if (this.formData.interior.papelInteriorId == '' && i === 0 ||
|
||||
this.formData.interior.papelInteriorId == opcion.extra_data["sk-id"]) {
|
||||
@ -934,7 +988,12 @@ export default class PresupuestoWizard {
|
||||
`,
|
||||
confirmButtonClass: 'btn btn-primary w-xs mt-2',
|
||||
showConfirmButton: false,
|
||||
showCloseButton: true
|
||||
showCloseButton: true,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -946,7 +1005,12 @@ export default class PresupuestoWizard {
|
||||
html: window.languageBundle.get('presupuesto.impresion-cubierta-help'),
|
||||
confirmButtonClass: 'btn btn-primary w-xs mt-2',
|
||||
showConfirmButton: false,
|
||||
showCloseButton: true
|
||||
showCloseButton: true,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -955,7 +1019,7 @@ export default class PresupuestoWizard {
|
||||
if (!$(e.target).is(':checked'))
|
||||
return;
|
||||
|
||||
if(this._hydrating)
|
||||
if (this._hydrating)
|
||||
return;
|
||||
|
||||
$('.tapa-dura-options').eq(0).removeClass('animate-fadeInUpBounce');
|
||||
@ -995,7 +1059,7 @@ export default class PresupuestoWizard {
|
||||
Summary.updateTapaCubierta();
|
||||
});
|
||||
|
||||
|
||||
|
||||
$(document).on('change', 'input[name="papel-cubierta"]', (e) => {
|
||||
|
||||
const data = this.#getPresupuestoData();
|
||||
@ -1036,7 +1100,7 @@ export default class PresupuestoWizard {
|
||||
|
||||
$(document).on('change', '.datos-cubierta', (e) => {
|
||||
|
||||
if(this._hydrating)
|
||||
if (this._hydrating)
|
||||
return;
|
||||
|
||||
const dataToStore = this.#getCubiertaData();
|
||||
@ -1178,12 +1242,12 @@ export default class PresupuestoWizard {
|
||||
if (item.extraData["sk-id"] == this.formData.cubierta.papelCubiertaId) {
|
||||
item.setSelected(true);
|
||||
}
|
||||
item.group='papel-cubierta';
|
||||
item.group = 'papel-cubierta';
|
||||
this.divPapelCubierta.append(item.render());
|
||||
}
|
||||
|
||||
if (this.divPapelCubierta.find('input[name="papel-cubierta"]:checked').length === 0) {
|
||||
|
||||
|
||||
this.divPapelCubierta.find('input[name="papel-cubierta"]').first().prop('checked', true).trigger('change');
|
||||
}
|
||||
|
||||
@ -1493,6 +1557,8 @@ export default class PresupuestoWizard {
|
||||
|
||||
const body = {
|
||||
presupuesto: this.#getPresupuestoData(),
|
||||
save: !this.opts.canSave,
|
||||
mode: this.opts.mode,
|
||||
servicios: servicios
|
||||
};
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { preguntarTipoPresupuesto } from './presupuesto-utils.js';
|
||||
|
||||
(() => {
|
||||
// si jQuery está cargado, añade CSRF a AJAX
|
||||
const csrfToken = document.querySelector('meta[name="_csrf"]')?.getAttribute('content');
|
||||
@ -67,7 +69,7 @@
|
||||
});
|
||||
|
||||
$('#presupuestos-anonimos-datatable').on('click', '.btn-edit-anonimo', function (e) {
|
||||
|
||||
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
if (id) {
|
||||
@ -76,7 +78,7 @@
|
||||
});
|
||||
|
||||
$('#presupuestos-anonimos-datatable').on('click', '.btn-delete-anonimo', function (e) {
|
||||
|
||||
|
||||
e.preventDefault();
|
||||
const id = $(this).data('id');
|
||||
|
||||
@ -113,10 +115,34 @@
|
||||
// usa el mensaje del backend; fallback genérico por si no llega JSON
|
||||
const msg = (xhr.responseJSON && xhr.responseJSON.message)
|
||||
|| 'Error al eliminar el presupuesto.';
|
||||
Swal.fire({ icon: 'error', title: 'No se pudo eliminar', text: msg });
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'No se pudo eliminar',
|
||||
text: msg,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('#addPresupuestoButton').on('click', async function (e) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const res = await preguntarTipoPresupuesto();
|
||||
if (!res) return;
|
||||
|
||||
if (res.tipo === 'anonimo') {
|
||||
console.log('Crear presupuesto ANÓNIMO');
|
||||
} else {
|
||||
console.log('Crear presupuesto de CLIENTE:', res.clienteId, res.clienteText);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Pregunta el tipo de presupuesto y (si aplica) selecciona cliente.
|
||||
* Devuelve una promesa con { tipo: 'anonimo'|'cliente', clienteId?: string }
|
||||
*/
|
||||
export async function preguntarTipoPresupuesto() {
|
||||
const { value: tipo } = await Swal.fire({
|
||||
title: window.languageBundle.get(['presupuesto.add.tipo']) || 'Selecciona tipo de presupuesto',
|
||||
input: 'radio',
|
||||
inputOptions: {
|
||||
anonimo: window.languageBundle.get(['presupuesto.add.anonimo']) || 'Anónimo',
|
||||
cliente: window.languageBundle.get(['presupuesto.add.cliente']) || 'De cliente'
|
||||
},
|
||||
inputValidator: (value) => {
|
||||
if (!value) {
|
||||
return window.languageBundle.get(['presupuesto.add.error.options']) || 'Debes seleccionar una opción.';
|
||||
}
|
||||
},
|
||||
confirmButtonText: window.languageBundle.get(['presupuesto.add.next']) || 'Siguiente',
|
||||
showCancelButton: true,
|
||||
cancelButtonText: window.languageBundle.get(['presupuesto.add.cancel']) || 'Cancelar',
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
});
|
||||
|
||||
if (!tipo) return null; // Cancelado
|
||||
|
||||
if (tipo === 'anonimo') {
|
||||
return { tipo };
|
||||
}
|
||||
|
||||
// Si es de cliente, mostrar otro paso con Select2
|
||||
return Swal.fire({
|
||||
title: window.languageBundle.get(['presupuesto.add.select-client']) || 'Selecciona cliente',
|
||||
html: `
|
||||
<select id="selectCliente" class="form-select select2" style="width:100%"></select>
|
||||
`,
|
||||
focusConfirm: false,
|
||||
buttonsStyling: false,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: window.languageBundle.get(['presupuesto.add.next']) || 'Aceptar',
|
||||
cancelButtonText: window.languageBundle.get(['presupuesto.add.cancel']) || 'Cancelar',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
didOpen: () => {
|
||||
const $select = $('#selectCliente');
|
||||
// Configura Select2 (AJAX o lista estática)
|
||||
$select.select2({
|
||||
dropdownParent: $('.swal2-container'),
|
||||
ajax: {
|
||||
url: 'users/api/get-users', // ajusta a tu endpoint
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
data: (params) => ({ q: params.term }),
|
||||
processResults: data => ({
|
||||
results: data.results,
|
||||
pagination: data.pagination
|
||||
}),
|
||||
cache: true
|
||||
}
|
||||
});
|
||||
},
|
||||
preConfirm: () => {
|
||||
const clienteId = $('#selectCliente').val();
|
||||
const clienteText = $('#selectCliente option:selected').text();
|
||||
if (!clienteId) {
|
||||
Swal.showValidationMessage(window.languageBundle.get(['presupuesto.add.error.select-client']) || 'Debes seleccionar un cliente.');
|
||||
return false;
|
||||
}
|
||||
return { tipo, clienteId, clienteText };
|
||||
}
|
||||
}).then((r) => (r.isConfirmed ? r.value : null));
|
||||
}
|
||||
@ -132,7 +132,16 @@ $(() => {
|
||||
// usa el mensaje del backend; fallback genérico por si no llega JSON
|
||||
const msg = (xhr.responseJSON && xhr.responseJSON.message)
|
||||
|| 'Error al eliminar el usuario.';
|
||||
Swal.fire({ icon: 'error', title: 'No se pudo eliminar', text: msg });
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'No se pudo eliminar',
|
||||
text: msg,
|
||||
buttonsStyling: false,
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-secondary me-2', // clases para el botón confirmar
|
||||
cancelButton: 'btn btn-light' // clases para cancelar
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
<!-- templates/fragments/common.html -->
|
||||
<div th:fragment="buttons(appMode)"
|
||||
th:if="${appMode == 'add' or appMode == 'edit'}"
|
||||
class="order-3 order-md-2 mx-md-auto d-flex">
|
||||
<button id="btn-guardar" type="button"
|
||||
class="btn btn-success d-flex align-items-center">
|
||||
<i class="ri-save-3-line me-2"></i>
|
||||
<span th:text="#{presupuesto.guardar}">Guardar</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -21,7 +21,8 @@
|
||||
|
||||
<div class="ribbon-content mt-4">
|
||||
<div class="row justify-content-center imagen-container-group mt-3">
|
||||
<label id="tapaBlanda" class="tapa-cubierta image-container imagen-selector" th:attr="data-summary-text=#{presupuesto.tapa-blanda}">
|
||||
<label id="tapaBlanda" class="tapa-cubierta image-container imagen-selector"
|
||||
th:attr="data-summary-text=#{presupuesto.tapa-blanda}">
|
||||
<input type="radio" name="tipoCubierta" value="tapaBlanda" hidden>
|
||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/tapa-blanda.png"
|
||||
alt="">
|
||||
@ -30,7 +31,8 @@
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label id="tapaDura" class="tapa-cubierta image-container imagen-selector" th:attr="data-summary-text=#{presupuesto.tapa-dura}">
|
||||
<label id="tapaDura" class="tapa-cubierta image-container imagen-selector"
|
||||
th:attr="data-summary-text=#{presupuesto.tapa-dura}">
|
||||
<input type="radio" name="tipoCubierta" value="tapaDura" hidden>
|
||||
<img class="image-presupuesto"
|
||||
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-recto.png" alt="">
|
||||
@ -39,7 +41,8 @@
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label id="tapaDuraLomoRedondo" class="tapa-cubierta image-container imagen-selector" th:attr="data-summary-text=#{presupuesto.tapa-dura-lomo-redondo}">
|
||||
<label id="tapaDuraLomoRedondo" class="tapa-cubierta image-container imagen-selector"
|
||||
th:attr="data-summary-text=#{presupuesto.tapa-dura-lomo-redondo}">
|
||||
<input type="radio" name="tipoCubierta" value="tapaDuraLomoRedondo" hidden>
|
||||
<img class="image-presupuesto"
|
||||
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-redondo.png" alt="">
|
||||
@ -56,7 +59,8 @@
|
||||
|
||||
<!-- Bloque de solapas -->
|
||||
<div class="d-flex gap-3">
|
||||
<label id="sin-solapas" class="image-container imagen-selector solapas-cubierta" th:attr="data-summary-text=#{app.no}">
|
||||
<label id="sin-solapas" class="image-container imagen-selector solapas-cubierta"
|
||||
th:attr="data-summary-text=#{app.no}">
|
||||
<input type="radio" name="solapasCubierta" value="sinSolapas" checked hidden>
|
||||
<img class="image-presupuesto"
|
||||
src="/assets/images/imprimelibros/presupuestador/sinSolapasCubierta.png" alt="">
|
||||
@ -65,7 +69,8 @@
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label id="con-solapas" class="image-container imagen-selector solapas-cubierta" th:attr="data-summary-text=#{app.yes}">
|
||||
<label id="con-solapas" class="image-container imagen-selector solapas-cubierta"
|
||||
th:attr="data-summary-text=#{app.yes}">
|
||||
<input type="radio" name="solapasCubierta" value="conSolapas" hidden>
|
||||
<img class="image-presupuesto"
|
||||
src="/assets/images/imprimelibros/presupuestador/conSolapasCubierta.png" alt="">
|
||||
@ -82,7 +87,8 @@
|
||||
<label for="impresion-cubierta" class="form-label"
|
||||
th:text="#{presupuesto.impresion-cubierta}">Impresión de cubierta</label>
|
||||
<div class="input-group input-group-sm">
|
||||
<select class="form-select select2 datos-cubierta tapa-cubierta-summary" id="impresion-cubierta">
|
||||
<select class="form-select select2 datos-cubierta tapa-cubierta-summary"
|
||||
id="impresion-cubierta">
|
||||
<option value="2" th:text="#{presupuesto.una-cara}">Una cara</option>
|
||||
<option value="4" th:text="#{presupuesto.dos-caras}">Dos caras</option>
|
||||
</select>
|
||||
@ -276,7 +282,8 @@
|
||||
<div class="d-flex flex-column me-2">
|
||||
<label for="papel-sobrecubierta" class="form-label"
|
||||
th:text="#{presupuesto.sobrecubierta-papel}">Papel</label>
|
||||
<select class="form-select select2 datos-cubierta sobrecubierta-item w-auto" id="papel-sobrecubierta">
|
||||
<select class="form-select select2 datos-cubierta sobrecubierta-item w-auto"
|
||||
id="papel-sobrecubierta">
|
||||
<optgroup th:label="#{presupuesto.estucado}">
|
||||
<option selected value="2" data-papel-id="2" data-gramaje="170"
|
||||
th:text="#{presupuesto.estucado-mate} + ' 170 gr'">Estucado mate 170 gr
|
||||
@ -284,14 +291,16 @@
|
||||
</optgroup>
|
||||
<optgroup th:label="#{presupuesto.verjurado}">
|
||||
<option value="1" data-papel-id="18" data-gramaje="160"
|
||||
th:text="#{presupuesto.verjurado-blanco-natural} + ' 160 gr'">Verjurado blanco natural 160 gr
|
||||
th:text="#{presupuesto.verjurado-blanco-natural} + ' 160 gr'">Verjurado
|
||||
blanco natural 160 gr
|
||||
170 gr
|
||||
</option>
|
||||
<option value="2" data-papel-id="9" data-gramaje="160"
|
||||
th:text="#{presupuesto.verjurado-ahuesado} + ' 160 gr'">Verjurado ahuesado 160 gr
|
||||
th:text="#{presupuesto.verjurado-ahuesado} + ' 160 gr'">Verjurado ahuesado
|
||||
160 gr
|
||||
</option>
|
||||
</optgroup>
|
||||
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@ -309,7 +318,8 @@
|
||||
<div class="d-flex flex-column me-2">
|
||||
<label for="sobrecubierta-acabado" class="form-label"
|
||||
th:text="#{presupuesto.acabado}">Acabado</label>
|
||||
<select class="form-select select2 datos-cubierta sobrecubierta-item w-auto" id="sobrecubierta-acabado">
|
||||
<select class="form-select select2 datos-cubierta sobrecubierta-item w-auto"
|
||||
id="sobrecubierta-acabado">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -346,22 +356,24 @@
|
||||
</optgroup>
|
||||
<optgroup th:label="#{presupuesto.verjurado}">
|
||||
<option value="1" data-papel-id="18" data-gramaje="160"
|
||||
th:text="#{presupuesto.verjurado-blanco-natural} + ' 160 gr'">Verjurado blanco natural 160 gr
|
||||
th:text="#{presupuesto.verjurado-blanco-natural} + ' 160 gr'">Verjurado
|
||||
blanco natural 160 gr
|
||||
170 gr
|
||||
</option>
|
||||
<option value="2" data-papel-id="9" data-gramaje="160"
|
||||
th:text="#{presupuesto.verjurado-ahuesado} + ' 160 gr'">Verjurado ahuesado 160 gr
|
||||
th:text="#{presupuesto.verjurado-ahuesado} + ' 160 gr'">Verjurado ahuesado
|
||||
160 gr
|
||||
</option>
|
||||
</optgroup>
|
||||
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column me-2">
|
||||
<label for="alto-faja" class="form-label"
|
||||
th:text="#{presupuesto.faja-alto}">Alto faja</label>
|
||||
<input type="number" class="form-control datos-cubierta faja-item w-auto"
|
||||
id="alto-faja" min="50" max="120" value="80" step="1">
|
||||
<label for="alto-faja" class="form-label" th:text="#{presupuesto.faja-alto}">Alto
|
||||
faja</label>
|
||||
<input type="number" class="form-control datos-cubierta faja-item w-auto" id="alto-faja"
|
||||
min="50" max="120" value="80" step="1">
|
||||
<div class="form-text">
|
||||
<p class="mb-0">min: 50 mm</p>
|
||||
<p class="alto-faja-max">max: 120 mm</p>
|
||||
@ -397,12 +409,15 @@
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<button id="btn-prev-cubierta" type="button"
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-cubierta">
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-cubierta order-1">
|
||||
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||
<span th:text="#{presupuesto.volver-interior}">Volver a interior</span>
|
||||
</button>
|
||||
|
||||
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_buttons :: buttons(${appMode})}"></div>
|
||||
|
||||
<button id="btn-next-cubierta" type="button"
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-cubierta">
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-cubierta order-2 order-md-3">
|
||||
<span th:text="#{presupuesto.continuar-seleccion-tirada}">Continuar a selección de tirada</span>
|
||||
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||
</button>
|
||||
|
||||
@ -252,7 +252,10 @@
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-center gap-3 mt-3">
|
||||
<button type="button" id="next-datos-generales" class="btn btn-secondary d-flex align-items-center ms-auto">
|
||||
|
||||
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_buttons :: buttons(${appMode})}"></div>
|
||||
|
||||
<button type="button" id="next-datos-generales" class="btn btn-secondary d-flex align-items-center ms-auto order-2 order-md-3">
|
||||
<span th:text="#{presupuesto.continuar-interior}">Continuar a diseño interior</span>
|
||||
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||
</button>
|
||||
|
||||
@ -18,12 +18,15 @@
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<button id="btn-prev-extras" type="button"
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-extras">
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-extras order-1">
|
||||
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||
<span th:text="#{presupuesto.volver-seleccion-tirada}">Volver a selección de tirada</span>
|
||||
</button>
|
||||
|
||||
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_buttons :: buttons(${appMode})}"></div>
|
||||
|
||||
<button id="btn-next-extras" type="button"
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-extras">
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-extras order-2 order-md-3">
|
||||
<span><b th:text="#{presupuesto.resumen}">Resumen</b></span>
|
||||
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||
</button>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
</div>
|
||||
|
||||
<div id="div-opciones-color" class="row justify-content-center imagen-container-group">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -35,7 +35,7 @@
|
||||
<div class="ribbon-content mt-4">
|
||||
|
||||
<div id="div-papel-interior" class="row justify-content-center imagen-container-group">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -52,17 +52,22 @@
|
||||
|
||||
<div class="ribbon-content mt-4">
|
||||
<div id="div-gramaje-interior" class="hstack gap-2 justify-content-center flex-wrap">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<button id="btn-prev-interior" type="button" class="btn btn-change-tab-interior btn-light d-flex align-items-center">
|
||||
<button id="btn-prev-interior" type="button"
|
||||
class="btn btn-change-tab-interior btn-light d-flex align-items-center order-1">
|
||||
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||
<span th:text="#{presupuesto.volver-datos-generales}">Volver a datos generales</span>
|
||||
</button>
|
||||
<button id="btn-next-interior" type="button" class="btn btn-change-tab-interior btn-secondary d-flex align-items-center">
|
||||
|
||||
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_buttons :: buttons(${appMode})}"></div>
|
||||
|
||||
<button id="btn-next-interior" type="button"
|
||||
class="btn btn-change-tab-interior btn-secondary d-flex align-items-center order-2 order-md-3">
|
||||
<span th:text="#{presupuesto.continuar-cubierta}">Continuar a diseño cubierta</span>
|
||||
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||
</button>
|
||||
|
||||
@ -47,21 +47,24 @@
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<button id="btn-prev-resumen" type="button"
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-resumen">
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-resumen order-1">
|
||||
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||
<span th:text="#{presupuesto.volver-extras}">Volver a extras</span>
|
||||
</button>
|
||||
|
||||
|
||||
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_buttons :: buttons(${appMode})}"></div>
|
||||
|
||||
<div th:unless="${#authorization.expression('isAuthenticated()')}">
|
||||
<button id="btn-add-cart" type="button"
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-resumen">
|
||||
class="btn btn-secondary d-flex align-items-center order-2 order-md-3">
|
||||
<i class="mdi mdi-login label-icon align-middle fs-16 me-2"></i>
|
||||
<span th:text="#{presupuesto.resumen.inicie-sesion}">Inicie sesión para continuar</span>
|
||||
</button>
|
||||
</div>
|
||||
<div th:if="${#authorization.expression('isAuthenticated()')}">
|
||||
<button id="btn-add-cart" type="button"
|
||||
class="btn btn-secondary d-flex align-items-center">
|
||||
class="btn btn-secondary d-flex align-items-center order-2 order-md-3">
|
||||
<span th:text="#{presupuesto.resumen.agregar-cesta}">Agregar a la cesta</span>
|
||||
<i class="ri-shopping-cart-2-line fs-16 ms-2"></i>
|
||||
</button>
|
||||
|
||||
@ -28,12 +28,15 @@
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<button id="btn-prev-seleccion-tirada" type="button"
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-seleccion-tirada">
|
||||
class="btn btn-light d-flex align-items-center btn-change-tab-seleccion-tirada order-1">
|
||||
<i class=" ri-arrow-left-circle-line label-icon align-middle fs-16 me-2"></i>
|
||||
<span th:text="#{presupuesto.volver-cubierta}">Volver a diseño de cubierta</span>
|
||||
</button>
|
||||
|
||||
<div th:replace="~{imprimelibros/presupuestos/presupuestador-items/_buttons :: buttons(${appMode})}"></div>
|
||||
|
||||
<button id="btn-next-seleccion-tirada" type="button"
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-seleccion-tirada">
|
||||
class="btn btn-secondary d-flex align-items-center btn-change-tab-seleccion-tirada order-2 order-md-3">
|
||||
<span><b th:text="#{presupuesto.continuar-extras-libro}">Continuar a extras del libro</b></span>
|
||||
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||
</button>
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
<div id="presupuesto-app"
|
||||
th:data-mode="${appMode} ?: 'public'"
|
||||
th:data-id="${id} ?: ''"
|
||||
th:fragment="presupuestador">
|
||||
|
||||
<div id="presupuesto-app" th:data-mode="${appMode} ?: 'public'" th:data-id="${id} ?: ''" th:fragment="presupuestador">
|
||||
|
||||
<!-- Modales-->
|
||||
<div
|
||||
th:replace="imprimelibros/partials/modal-form :: modal('maquetacionModal', 'presupuesto.maquetacion', 'modal-md', 'maquetacionModalBody')">
|
||||
@ -18,6 +15,14 @@
|
||||
|
||||
<form action="#">
|
||||
<input type="hidden" id="cliente_id" th:value="${cliente_id} ?: null" />
|
||||
|
||||
<div id="form-errors" class="alert alert-danger d-none" role="alert">
|
||||
<i class="ri-error-warning-line label-icon"></i>
|
||||
<strong th:text="#{presupuesto.errores-title}">Corrija los siguientes errores:</strong>
|
||||
<ul class="mb-0" id="form-errors-alert-list">
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="step-arrow-nav mt-n3 mx-n3 mb-3">
|
||||
|
||||
<ul class="nav nav-pills nav-justified custom-nav" role="tablist">
|
||||
@ -123,7 +128,9 @@
|
||||
<div class="tab-pane fade" id="pills-resumen" role="tabpanel"
|
||||
aria-labelledby="pills-resumen-tab">
|
||||
|
||||
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_resumen_final.html}"></div>
|
||||
<div
|
||||
th:include="~{imprimelibros/presupuestos/presupuestador-items/_resumen_final.html}">
|
||||
</div>
|
||||
</div>
|
||||
<!-- end tab pane -->
|
||||
|
||||
|
||||
@ -58,6 +58,9 @@
|
||||
<div th:if="${appMode} == 'view'">
|
||||
<script type="module" th:src="@{/assets/js/pages/imprimelibros/presupuestador/wizard-publicos.js}"></script>
|
||||
</div>
|
||||
<div th:if="${appMode} == 'add'">
|
||||
<script type="module" th:src="@{/assets/js/pages/imprimelibros/presupuestador/wizard-publicos-add.js}"></script>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
<script th:src="@{/assets/libs/datatables/buttons.print.min.js}"></script>
|
||||
<script th:src="@{/assets/libs/datatables/buttons.colVis.min.js}"></script>
|
||||
|
||||
<script th:src="@{/assets/js/pages/imprimelibros/presupuestos/list.js}"></script>
|
||||
<script type="module" th:src="@{/assets/js/pages/imprimelibros/presupuestos/list.js}"></script>
|
||||
</th:block>
|
||||
</body>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user