Compare commits
3 Commits
14f6633b83
...
29dbd21693
| Author | SHA1 | Date | |
|---|---|---|---|
| 29dbd21693 | |||
| eb0b5610d8 | |||
| 8b34d6dca9 |
25
docker-compose.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
imprimelibros-db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: imprimelibros-db
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: NrXz6DK6UoN
|
||||||
|
MYSQL_DATABASE: imprimelibros
|
||||||
|
MYSQL_USER: imprimelibros_user
|
||||||
|
MYSQL_PASSWORD: om91irrDctd
|
||||||
|
ports:
|
||||||
|
- "3306:3306"
|
||||||
|
volumes:
|
||||||
|
- db_data:/var/lib/mysql
|
||||||
|
networks:
|
||||||
|
- imprimelibros-network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
imprimelibros-network:
|
||||||
|
driver: bridge
|
||||||
17
pom.xml
@ -39,6 +39,10 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>nz.net.ultraq.thymeleaf</groupId>
|
<groupId>nz.net.ultraq.thymeleaf</groupId>
|
||||||
<artifactId>thymeleaf-layout-dialect</artifactId>
|
<artifactId>thymeleaf-layout-dialect</artifactId>
|
||||||
@ -47,18 +51,25 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.validation</groupId>
|
||||||
|
<artifactId>jakarta.validation-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thymeleaf.extras</groupId>
|
<groupId>org.thymeleaf.extras</groupId>
|
||||||
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
|
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-devtools</artifactId>
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
@ -68,7 +79,7 @@
|
|||||||
<artifactId>mysql-connector-j</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
-->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
package com.imprimelibros.erp.config.Presupuestador;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ImagenPresupuesto {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String imagen;
|
||||||
|
private String alt;
|
||||||
|
private String texto;
|
||||||
|
private boolean selected;
|
||||||
|
private Map<String, String> extra_data;
|
||||||
|
|
||||||
|
// Constructores
|
||||||
|
public ImagenPresupuesto() {}
|
||||||
|
|
||||||
|
|
||||||
|
public ImagenPresupuesto(String id, String imagen, String alt, String texto, boolean selected) {
|
||||||
|
this.id = id;
|
||||||
|
this.imagen = imagen;
|
||||||
|
this.alt = alt;
|
||||||
|
this.texto = texto;
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ImagenPresupuesto(String id, String imagen, String alt, String texto, Map<String, String> extra_data,boolean selected) {
|
||||||
|
this.id = id;
|
||||||
|
this.imagen = imagen;
|
||||||
|
this.alt = alt;
|
||||||
|
this.texto = texto;
|
||||||
|
this.selected = selected;
|
||||||
|
this.extra_data = extra_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImagen() {
|
||||||
|
return imagen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImagen(String imagen) {
|
||||||
|
this.imagen = imagen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlt() {
|
||||||
|
return alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlt(String alt) {
|
||||||
|
this.alt = alt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTexto() {
|
||||||
|
return texto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexto(String texto) {
|
||||||
|
this.texto = texto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(boolean selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getExtra_data() {
|
||||||
|
return extra_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtra_data(Map<String, String> extra_data) {
|
||||||
|
this.extra_data = extra_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
package com.imprimelibros.erp.config.Presupuestador;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class PresupuestadorItems {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageSource messageSource;
|
||||||
|
|
||||||
|
public ImagenPresupuesto getImpresionNegro(Locale locale) {
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"negro",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/blancoYnegro.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.blanco-negro", null, locale),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getImpresionNegroPremium(Locale locale) {
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"negrohq",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/negroFoto.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.blanco-negro-premium", null, locale),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getImpresionColor(Locale locale) {
|
||||||
|
|
||||||
|
String clave = "presupuesto.color"; // ✅
|
||||||
|
String texto = messageSource.getMessage(clave, null, locale);
|
||||||
|
System.out.println("Clave: " + clave + " => Texto: " + texto);
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"color",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/color.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.color", null, locale),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getImpresionColorPremium(Locale locale) {
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"colorhq",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/colorFoto.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.color-premium", null, locale),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getPapelOffsetBlanco(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"offset-blanco",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/offset-blanco.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.offset-blanco", null, locale),
|
||||||
|
Map.of("sk-id", "3"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getPapelOffsetAhuesado(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"offset-ahuesado",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/offset-ahuesado.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.offset-ahuesado", null, locale),
|
||||||
|
Map.of("sk-id", "4"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getPapelOffsetAhuesadoVolumen(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"offset-ahuesado-volumen",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/offset-ahuesado-volumen.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.offset-ahuesado-volumen", null, locale),
|
||||||
|
Map.of("sk-id", "6"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getPapelEstucadoMate(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"estucado-mate",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/estucado-mate.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.estucado-mate", null, locale),
|
||||||
|
Map.of("sk-id", "2"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getCartulinaGraficaCubierta(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"cartulina-grafica-cubierta",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/cartulina-grafica.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.cartulina-grafica-cubierta", null, locale),
|
||||||
|
Map.of("sk-id", "3"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImagenPresupuesto getEstucadoMateCubierta(Locale locale) {
|
||||||
|
|
||||||
|
return new ImagenPresupuesto(
|
||||||
|
"estucado-mate-cubierta",
|
||||||
|
"/assets/images/imprimelibros/presupuestador/estucado-mate-cubierta.png",
|
||||||
|
"",
|
||||||
|
messageSource.getMessage("presupuesto.estucado-mate-cubierta", null, locale),
|
||||||
|
Map.of("sk-id", "2"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SecurityConfig {
|
public class SecurityConfig {
|
||||||
@ -11,15 +12,24 @@ public class SecurityConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers("/", "/assets/**", "/css/**", "/js/**", "/images/**", "/public/**").permitAll()
|
.requestMatchers(
|
||||||
.anyRequest().authenticated()
|
"/",
|
||||||
)
|
"/assets/**",
|
||||||
.formLogin(login -> login
|
"/css/**",
|
||||||
//.loginPage("/login") añadir cuando se tenga login personalizado
|
"/js/**",
|
||||||
.permitAll()
|
"/images/**",
|
||||||
)
|
"/public/**",
|
||||||
.logout(logout -> logout.permitAll());
|
"/error",
|
||||||
|
"/presupuesto/public/**")
|
||||||
|
.permitAll()
|
||||||
|
.anyRequest().authenticated())
|
||||||
|
.csrf(csrf -> csrf
|
||||||
|
.ignoringRequestMatchers("/presupuesto/public/**"))
|
||||||
|
.formLogin(login -> login
|
||||||
|
// .loginPage("/login") añadir cuando se tenga login personalizado
|
||||||
|
.permitAll())
|
||||||
|
.logout(logout -> logout.permitAll());
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Constraint(validatedBy = ConsistentTiradasValidator.class)
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface ConsistentTiradas {
|
||||||
|
String message() default "Las tiradas deben ser todas mayores o todas menores al valor POD";
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.entity.Presupuesto;
|
||||||
|
import com.imprimelibros.erp.service.VariableService;
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
|
||||||
|
public class ConsistentTiradasValidator implements ConstraintValidator<ConsistentTiradas, Presupuesto> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VariableService variableService;
|
||||||
|
@Autowired
|
||||||
|
private MessageSource messageSource;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Presupuesto presupuesto, ConstraintValidatorContext context) {
|
||||||
|
if (presupuesto == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Integer[] tiradas = presupuesto.getTiradas();
|
||||||
|
Integer podValue = variableService.getValorEntero("POD");
|
||||||
|
|
||||||
|
boolean allAbove = true;
|
||||||
|
boolean allBelow = true;
|
||||||
|
|
||||||
|
for (Integer t : tiradas) {
|
||||||
|
if (t == null)
|
||||||
|
continue;
|
||||||
|
if (t <= podValue)
|
||||||
|
allAbove = false;
|
||||||
|
else // (t > podValue)
|
||||||
|
allBelow = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(allAbove || allBelow)) {
|
||||||
|
|
||||||
|
String mensajeInterpolado = messageSource.getMessage(
|
||||||
|
"presupuesto.errores.tiradas.consistentes", // clave del mensaje
|
||||||
|
new Object[] { podValue }, // parámetros para {0}
|
||||||
|
LocaleContextHolder.getLocale() // respeta el idioma actual
|
||||||
|
);
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
context.buildConstraintViolationWithTemplate(mensajeInterpolado)
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Constraint(validatedBy = ParValidator.class)
|
||||||
|
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Par {
|
||||||
|
String message() default "El valor debe ser un número par";
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class ParValidator implements ConstraintValidator<Par, Integer> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Integer value, ConstraintValidatorContext context) {
|
||||||
|
if (value == null) return true; // se permite null, usa @NotNull aparte si lo necesitas
|
||||||
|
return value % 2 == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
public class PresupuestoValidationGroups {
|
||||||
|
|
||||||
|
public interface DatosGenerales {}
|
||||||
|
public interface Interior {}
|
||||||
|
public interface Cubierta {}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Constraint(validatedBy = TamanioValidator.class)
|
||||||
|
@Target({ ElementType.TYPE })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Tamanio {
|
||||||
|
|
||||||
|
String message() default "{presupuesto.errores.tamanio.invalido}";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.imprimelibros.erp.config.validation;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.entity.Presupuesto;
|
||||||
|
import com.imprimelibros.erp.service.VariableService;
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
|
||||||
|
public class TamanioValidator implements ConstraintValidator<Tamanio, Presupuesto>{
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VariableService variableService;
|
||||||
|
@Autowired
|
||||||
|
private MessageSource messageSource;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(Presupuesto presupuesto, ConstraintValidatorContext context) {
|
||||||
|
|
||||||
|
if (presupuesto == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Integer min = variableService.getValorEntero("ancho_alto_min");
|
||||||
|
Integer max = variableService.getValorEntero("ancho_alto_max");
|
||||||
|
|
||||||
|
|
||||||
|
if (presupuesto.getAncho() <= min || presupuesto.getAncho() >= max) {
|
||||||
|
|
||||||
|
String mensajeInterpolado = messageSource.getMessage(
|
||||||
|
"presupuesto.errores.ancho.min_max", // clave del mensaje
|
||||||
|
new Object[] { min, max }, // parámetros para {0}
|
||||||
|
LocaleContextHolder.getLocale() // respeta el idioma actual
|
||||||
|
);
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
context.buildConstraintViolationWithTemplate(mensajeInterpolado)
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (presupuesto.getAlto() <= min || presupuesto.getAlto() >= max) {
|
||||||
|
|
||||||
|
String mensajeInterpolado = messageSource.getMessage(
|
||||||
|
"presupuesto.errores.alto.min_max", // clave del mensaje
|
||||||
|
new Object[] { min, max }, // parámetros para {0}
|
||||||
|
LocaleContextHolder.getLocale() // respeta el idioma actual
|
||||||
|
);
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
context.buildConstraintViolationWithTemplate(mensajeInterpolado)
|
||||||
|
.addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,24 +1,48 @@
|
|||||||
package com.imprimelibros.erp.controller;
|
package com.imprimelibros.erp.controller;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.i18n.TranslationService;
|
||||||
|
import com.imprimelibros.erp.service.VariableService;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class HomeController {
|
public class HomeController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MessageSource messageSource;
|
private TranslationService translationService;
|
||||||
|
@Autowired
|
||||||
|
private VariableService variableService;
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public String index(Model model, Locale locale) {
|
public String index(Model model, Authentication authentication, Locale locale) {
|
||||||
//model.addAttribute("title", messageSource.getMessage("t-home", null, locale));
|
|
||||||
model.addAttribute("title", "Inicio");
|
boolean isAuthenticated = authentication != null && authentication.isAuthenticated()
|
||||||
|
&& !(authentication instanceof AnonymousAuthenticationToken);
|
||||||
|
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
|
||||||
|
List<String> keys = List.of(
|
||||||
|
"presupuesto.plantilla-cubierta",
|
||||||
|
"presupuesto.plantilla-cubierta-text",
|
||||||
|
"presupuesto.impresion-cubierta",
|
||||||
|
"presupuesto.impresion-cubierta-help");
|
||||||
|
|
||||||
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
||||||
|
model.addAttribute("languageBundle", translations);
|
||||||
|
model.addAttribute("pod", variableService.getValorEntero("POD"));
|
||||||
|
model.addAttribute("ancho_alto_min", variableService.getValorEntero("ancho_alto_min"));
|
||||||
|
model.addAttribute("ancho_alto_max", variableService.getValorEntero("ancho_alto_max"));
|
||||||
|
}
|
||||||
return "imprimelibros/home";
|
return "imprimelibros/home";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,108 @@
|
|||||||
|
package com.imprimelibros.erp.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.service.PresupuestoService;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.config.validation.PresupuestoValidationGroups;
|
||||||
|
import com.imprimelibros.erp.entity.Presupuesto;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/presupuesto")
|
||||||
|
public class PresupuestoController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected PresupuestoService presupuestoService;
|
||||||
|
|
||||||
|
@PostMapping("/public/validar/datos-generales")
|
||||||
|
public ResponseEntity<?> validarDatosGenerales(
|
||||||
|
@Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
// opciones color
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesColor(presupuesto, locale);
|
||||||
|
|
||||||
|
// opciones papel interior
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesPapelInterior(presupuesto, locale));
|
||||||
|
|
||||||
|
// opciones gramaje interior
|
||||||
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeInterior(presupuesto));
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/public/validar/interior")
|
||||||
|
public ResponseEntity<?> validarInterior(
|
||||||
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
// errores globales (@ConsistentTiradas...)
|
||||||
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(Collections.singletonMap("success", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/public/get-gramaje-interior")
|
||||||
|
public ResponseEntity<?> getGramajeInterior(
|
||||||
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
||||||
|
BindingResult result) {
|
||||||
|
|
||||||
|
Map<String, String> errores = new HashMap<>();
|
||||||
|
|
||||||
|
// errores de campos individuales
|
||||||
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||||
|
|
||||||
|
if (!errores.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().body(errores);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesGramajeInterior(presupuesto);
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/public/get-papel-cubierta")
|
||||||
|
public ResponseEntity<?> getPapelCubierta(
|
||||||
|
Presupuesto presupuesto,
|
||||||
|
BindingResult result, Locale locale) {
|
||||||
|
|
||||||
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesPapelCubierta(presupuesto, locale);
|
||||||
|
return ResponseEntity.ok(resultado);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
375
src/main/java/com/imprimelibros/erp/entity/Presupuesto.java
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
package com.imprimelibros.erp.entity;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.config.validation.PresupuestoValidationGroups;
|
||||||
|
import com.imprimelibros.erp.config.validation.Tamanio;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.config.validation.ConsistentTiradas;
|
||||||
|
import com.imprimelibros.erp.config.validation.Par;
|
||||||
|
|
||||||
|
|
||||||
|
@ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Tamanio(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Entity
|
||||||
|
@Table(name = "presupuesto")
|
||||||
|
public class Presupuesto {
|
||||||
|
|
||||||
|
public enum TipoEncuadernacion {
|
||||||
|
fresado, cosido, grapado, espiral, wireo
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TipoImpresion {
|
||||||
|
negro, negrohq, color, colorhq
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TipoCubierta{
|
||||||
|
tapaBlanda, tapaDuraLomoRecto, tapaDuraLomoRedondo
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.tipo-encuadernacion}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "tipo_encuadernacion")
|
||||||
|
private TipoEncuadernacion tipoEncuadernacion = TipoEncuadernacion.fresado;
|
||||||
|
|
||||||
|
@NotBlank(message = "{presupuesto.errores.titulo}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "titulo")
|
||||||
|
private String titulo;
|
||||||
|
|
||||||
|
@Column(name = "autor")
|
||||||
|
private String autor;
|
||||||
|
|
||||||
|
@Column(name = "isbn")
|
||||||
|
private String isbn;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.tirada1}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "tirada1")
|
||||||
|
private Integer tirada1;
|
||||||
|
|
||||||
|
@Column(name = "tirada2")
|
||||||
|
private Integer tirada2;
|
||||||
|
|
||||||
|
@Column(name = "tirada3")
|
||||||
|
private Integer tirada3;
|
||||||
|
|
||||||
|
@Column(name = "tirada4")
|
||||||
|
private Integer tirada4;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.ancho}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "ancho")
|
||||||
|
private Integer ancho;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.alto}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "alto")
|
||||||
|
private Integer alto;
|
||||||
|
|
||||||
|
@Column(name = "formatoPersonalizado")
|
||||||
|
private Boolean formatoPersonalizado;
|
||||||
|
|
||||||
|
@Par(message = "{presupuesto.errores.paginasNegro.par}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@NotNull(message = "{presupuesto.errores.paginasNegro.required}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "paginas_negro")
|
||||||
|
private Integer paginasNegro;
|
||||||
|
|
||||||
|
@Par(message = "{presupuesto.errores.paginasColor.par}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@NotNull(message = "{presupuesto.errores.paginasColor.required}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||||
|
@Column(name = "paginas_color")
|
||||||
|
private Integer paginasColor;
|
||||||
|
|
||||||
|
@Column(name = "posicion_paginas_color")
|
||||||
|
private String posicionPaginasColor;
|
||||||
|
|
||||||
|
@Column(name = "paginas_color_total")
|
||||||
|
private Integer paginasColorTotal;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.tipo-impresion}", groups = PresupuestoValidationGroups.Interior.class)
|
||||||
|
@Column(name = "tipo_impresion")
|
||||||
|
private TipoImpresion tipoImpresion = TipoImpresion.negro;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.papel-interior}", groups = PresupuestoValidationGroups.Interior.class)
|
||||||
|
@Column(name = "papel_interior_id")
|
||||||
|
private Integer papelInteriorId;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.gramaje-interior}", groups = PresupuestoValidationGroups.Interior.class)
|
||||||
|
@Column(name = "gramaje_interior")
|
||||||
|
private Integer gramejeInterior;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.tipo-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
|
||||||
|
@Column(name = "tipo_cubierta")
|
||||||
|
private TipoCubierta tipoCubierta = TipoCubierta.tapaBlanda;
|
||||||
|
|
||||||
|
@Column(name = "solapas_cubierta")
|
||||||
|
private Boolean solapasCubierta = false;
|
||||||
|
|
||||||
|
@Column(name = "tamanio_solapas_cubierta")
|
||||||
|
private Integer tamanioSolapasCubierta;
|
||||||
|
|
||||||
|
@Column(name = "cubierta_caras")
|
||||||
|
private Integer cubiertaCaras;
|
||||||
|
|
||||||
|
@Column(name = "papel_guardas_id")
|
||||||
|
private Integer papelGuardasId;
|
||||||
|
|
||||||
|
@Column(name = "gramaje_guardas")
|
||||||
|
private Integer gramajeGuardas;
|
||||||
|
|
||||||
|
@Column(name = "guardas_impresas")
|
||||||
|
private Boolean guardasImpresas;
|
||||||
|
|
||||||
|
@Column(name = "cabezada")
|
||||||
|
private String cabezada;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.papel-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
|
||||||
|
@Column(name = "papel_cubierta_id")
|
||||||
|
private Integer papelCubiertaId = 2;
|
||||||
|
|
||||||
|
@NotNull(message = "{presupuesto.errores.gramaje-cubierta}", groups = PresupuestoValidationGroups.Cubierta.class)
|
||||||
|
@Column(name = "gramaje_cubierta")
|
||||||
|
private Integer gramajeCubierta = 240;
|
||||||
|
|
||||||
|
// Getters y Setters
|
||||||
|
|
||||||
|
public String getAutor() {
|
||||||
|
return autor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutor(String autor) {
|
||||||
|
this.autor = autor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsbn() {
|
||||||
|
return isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn(String isbn) {
|
||||||
|
this.isbn = isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTirada1() {
|
||||||
|
return tirada1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTirada1(Integer tirada1) {
|
||||||
|
this.tirada1 = tirada1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTirada2() {
|
||||||
|
return tirada2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTirada2(Integer tirada2) {
|
||||||
|
this.tirada2 = tirada2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTirada3() {
|
||||||
|
return tirada3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTirada3(Integer tirada3) {
|
||||||
|
this.tirada3 = tirada3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTirada4() {
|
||||||
|
return tirada4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer[] getTiradas() {
|
||||||
|
return new Integer[]{tirada1, tirada2, tirada3, tirada4};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTirada4(Integer tirada4) {
|
||||||
|
this.tirada4 = tirada4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAncho() {
|
||||||
|
return ancho;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAncho(Integer ancho) {
|
||||||
|
this.ancho = ancho;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAlto() {
|
||||||
|
return alto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlto(Integer alto) {
|
||||||
|
this.alto = alto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getFormatoPersonalizado() {
|
||||||
|
return formatoPersonalizado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormatoPersonalizado(Boolean formatoPersonalizado) {
|
||||||
|
this.formatoPersonalizado = formatoPersonalizado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitulo() {
|
||||||
|
return titulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitulo(String titulo) {
|
||||||
|
this.titulo = titulo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPaginasNegro() {
|
||||||
|
return paginasNegro;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaginasNegro(Integer paginasNegro) {
|
||||||
|
this.paginasNegro = paginasNegro;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPaginasColor() {
|
||||||
|
return paginasColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaginasColor(Integer paginasColor) {
|
||||||
|
this.paginasColor = paginasColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TipoEncuadernacion getTipoEncuadernacion() {
|
||||||
|
return tipoEncuadernacion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTipoEncuadernacion(TipoEncuadernacion tipoEncuadernacion) {
|
||||||
|
this.tipoEncuadernacion = tipoEncuadernacion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPosicionPaginasColor() {
|
||||||
|
return posicionPaginasColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosicionPaginasColor(String posicionPaginasColor) {
|
||||||
|
this.posicionPaginasColor = posicionPaginasColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPaginasColorTotal() {
|
||||||
|
return paginasColorTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaginasColorTotal(Integer paginasColorTotal) {
|
||||||
|
this.paginasColorTotal = paginasColorTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TipoImpresion getTipoImpresion() {
|
||||||
|
return tipoImpresion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTipoImpresion(TipoImpresion tipoImpresion) {
|
||||||
|
this.tipoImpresion = tipoImpresion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPapelInteriorId() {
|
||||||
|
return papelInteriorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPapelInteriorId(Integer papelInteriorId) {
|
||||||
|
this.papelInteriorId = papelInteriorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGramejeInterior() {
|
||||||
|
return gramejeInterior;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGramejeInterior(Integer gramejeInterior) {
|
||||||
|
this.gramejeInterior = gramejeInterior;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TipoCubierta getTipoCubierta() {
|
||||||
|
return tipoCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTipoCubierta(TipoCubierta tipoCubierta) {
|
||||||
|
this.tipoCubierta = tipoCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getSolapasCubierta() {
|
||||||
|
return solapasCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSolapasCubierta(Boolean solapasCubierta) {
|
||||||
|
this.solapasCubierta = solapasCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTamanioSolapasCubierta() {
|
||||||
|
return tamanioSolapasCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTamanioSolapasCubierta(Integer tamanioSolapasCubierta) {
|
||||||
|
this.tamanioSolapasCubierta = tamanioSolapasCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCubiertaCaras() {
|
||||||
|
return cubiertaCaras;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCubiertaCaras(Integer cubiertaCaras) {
|
||||||
|
this.cubiertaCaras = cubiertaCaras;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPapelGuardasId() {
|
||||||
|
return papelGuardasId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPapelGuardasId(Integer papelGuardasId) {
|
||||||
|
this.papelGuardasId = papelGuardasId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGramajeGuardas() {
|
||||||
|
return gramajeGuardas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGramajeGuardas(Integer gramajeGuardas) {
|
||||||
|
this.gramajeGuardas = gramajeGuardas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getGuardasImpresas() {
|
||||||
|
return guardasImpresas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGuardasImpresas(Boolean guardasImpresas) {
|
||||||
|
this.guardasImpresas = guardasImpresas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCabezada() {
|
||||||
|
return cabezada;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCabezada(String cabezada) {
|
||||||
|
this.cabezada = cabezada;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPapelCubiertaId() {
|
||||||
|
return papelCubiertaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPapelCubiertaId(Integer papelCubiertaId) {
|
||||||
|
this.papelCubiertaId = papelCubiertaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGramajeCubierta() {
|
||||||
|
return gramajeCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGramajeCubierta(Integer gramajeCubierta) {
|
||||||
|
this.gramajeCubierta = gramajeCubierta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
30
src/main/java/com/imprimelibros/erp/entity/Variable.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package com.imprimelibros.erp.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "variables")
|
||||||
|
public class Variable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String clave;
|
||||||
|
|
||||||
|
private String valor;
|
||||||
|
|
||||||
|
// Getters y setters
|
||||||
|
|
||||||
|
public Long getId() { return id; }
|
||||||
|
|
||||||
|
public void setId(Long id) { this.id = id; }
|
||||||
|
|
||||||
|
public String getClave() { return clave; }
|
||||||
|
|
||||||
|
public void setClave(String clave) { this.clave = clave; }
|
||||||
|
|
||||||
|
public String getValor() { return valor; }
|
||||||
|
|
||||||
|
public void setValor(String valor) { this.valor = valor; }
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.imprimelibros.erp.i18n;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TranslationService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageSource messageSource;
|
||||||
|
|
||||||
|
public Map<String, String> getTranslations(Locale locale, List<String> keys) {
|
||||||
|
Map<String, String> translations = new HashMap<>();
|
||||||
|
for (String key : keys) {
|
||||||
|
translations.put(key, messageSource.getMessage(key, null, locale));
|
||||||
|
}
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.imprimelibros.erp.repository;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.entity.Variable;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface VariableRepository extends JpaRepository<Variable, Long> {
|
||||||
|
Optional<Variable> findByClave(String clave);
|
||||||
|
}
|
||||||
@ -0,0 +1,210 @@
|
|||||||
|
package com.imprimelibros.erp.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.config.Presupuestador.ImagenPresupuesto;
|
||||||
|
import com.imprimelibros.erp.config.Presupuestador.PresupuestadorItems;
|
||||||
|
import com.imprimelibros.erp.entity.Presupuesto;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PresupuestoService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected VariableService variableService;
|
||||||
|
|
||||||
|
private final PresupuestadorItems presupuestadorItems;
|
||||||
|
|
||||||
|
public PresupuestoService(PresupuestadorItems presupuestadorItems) {
|
||||||
|
this.presupuestadorItems = presupuestadorItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateDatosGenerales(int[] tiradas) {
|
||||||
|
|
||||||
|
for (int tirada : tiradas) {
|
||||||
|
if (tirada <= 0) {
|
||||||
|
return false; // Invalid tirada found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isPOD(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
int pod_value = variableService.getValorEntero("POD");
|
||||||
|
return (presupuesto.getTirada1() != null && presupuesto.getTirada1() <= pod_value) ||
|
||||||
|
(presupuesto.getTirada2() != null && presupuesto.getTirada2() <= pod_value) ||
|
||||||
|
(presupuesto.getTirada3() != null && presupuesto.getTirada3() <= pod_value) ||
|
||||||
|
(presupuesto.getTirada4() != null && presupuesto.getTirada4() <= pod_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesColor(Presupuesto presupuesto, Locale locale) {
|
||||||
|
|
||||||
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
ImagenPresupuesto opcion;
|
||||||
|
|
||||||
|
if (presupuesto.getPaginasColor() > 0) {
|
||||||
|
if (!this.isPOD(presupuesto)) {
|
||||||
|
// POD solo color foto
|
||||||
|
opcion = this.presupuestadorItems.getImpresionColor(locale);
|
||||||
|
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color);
|
||||||
|
opciones.add(opcion);
|
||||||
|
}
|
||||||
|
opcion = this.presupuestadorItems.getImpresionColorPremium(locale);
|
||||||
|
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq);
|
||||||
|
opciones.add(opcion);
|
||||||
|
} else {
|
||||||
|
opcion = this.presupuestadorItems.getImpresionNegro(locale);
|
||||||
|
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro);
|
||||||
|
opciones.add(opcion);
|
||||||
|
opcion = this.presupuestadorItems.getImpresionNegroPremium(locale);
|
||||||
|
opcion.setSelected(presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq);
|
||||||
|
opciones.add(opcion);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean opcionSeleccionada = opciones.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(op -> {
|
||||||
|
op.setSelected(true);
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.orElse(false);
|
||||||
|
if (!opcionSeleccionada) {
|
||||||
|
opciones.get(0).setSelected(true);
|
||||||
|
presupuesto.setPapelInteriorId(Integer.parseInt(opciones.get(0).getExtra_data().get("sk-id")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_color", opciones);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesPapelInterior(Presupuesto presupuesto, Locale locale) {
|
||||||
|
|
||||||
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetBlanco(locale));
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesado(locale));
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesadoVolumen(locale));
|
||||||
|
opciones.add(this.presupuestadorItems.getPapelEstucadoMate(locale));
|
||||||
|
|
||||||
|
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
||||||
|
imagenPresupuesto.setSelected(
|
||||||
|
presupuesto.getPapelInteriorId() != null
|
||||||
|
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
||||||
|
String.valueOf(presupuesto.getPapelInteriorId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean opcionSeleccionada = opciones.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(opcion -> {
|
||||||
|
opcion.setSelected(true);
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.orElse(false);
|
||||||
|
if (!opcionSeleccionada) {
|
||||||
|
opciones.get(0).setSelected(true);
|
||||||
|
presupuesto.setPapelInteriorId(Integer.parseInt(opciones.get(0).getExtra_data().get("sk-id")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_papel_interior", opciones);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesGramajeInterior(Presupuesto presupuesto) {
|
||||||
|
|
||||||
|
List<String> gramajes = new ArrayList<>();
|
||||||
|
|
||||||
|
final int BLANCO_OFFSET_ID = 3;
|
||||||
|
final int AHUESADO_OFFSET_ID = 4;
|
||||||
|
final int AHUESADO_OFFSET_VOLUMEN_ID = 6;
|
||||||
|
final int ESTUCADO_MATE_ID = 2;
|
||||||
|
|
||||||
|
if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == BLANCO_OFFSET_ID) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("80");
|
||||||
|
}
|
||||||
|
gramajes.add("90");
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_ID) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("80");
|
||||||
|
}
|
||||||
|
gramajes.add("150");
|
||||||
|
gramajes.add("170");
|
||||||
|
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null
|
||||||
|
&& presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_VOLUMEN_ID) {
|
||||||
|
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
||||||
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("70");
|
||||||
|
}
|
||||||
|
gramajes.add("90");
|
||||||
|
gramajes.add("100");
|
||||||
|
gramajes.add("150");
|
||||||
|
gramajes.add("170");
|
||||||
|
|
||||||
|
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == ESTUCADO_MATE_ID) {
|
||||||
|
|
||||||
|
gramajes.add("90");
|
||||||
|
gramajes.add("100");
|
||||||
|
gramajes.add("115");
|
||||||
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
||||||
|
gramajes.add("120");
|
||||||
|
}
|
||||||
|
gramajes.add("135");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_gramaje_interior", gramajes);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> obtenerOpcionesPapelCubierta(Presupuesto presupuesto, Locale locale) {
|
||||||
|
|
||||||
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
||||||
|
|
||||||
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) {
|
||||||
|
opciones.add(this.presupuestadorItems.getCartulinaGraficaCubierta(locale));
|
||||||
|
}
|
||||||
|
opciones.add(this.presupuestadorItems.getEstucadoMateCubierta(locale));
|
||||||
|
|
||||||
|
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
||||||
|
imagenPresupuesto.setSelected(
|
||||||
|
presupuesto.getPapelCubiertaId() != null
|
||||||
|
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
||||||
|
String.valueOf(presupuesto.getPapelCubiertaId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean opcionSeleccionada = opciones.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(opcion -> {
|
||||||
|
opcion.setSelected(true);
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.orElse(false);
|
||||||
|
if (!opcionSeleccionada) {
|
||||||
|
opciones.get(0).setSelected(true);
|
||||||
|
presupuesto.setPapelInteriorId(Integer.parseInt(opciones.get(0).getExtra_data().get("sk-id")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("opciones_papel_cubierta", opciones);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.imprimelibros.erp.service;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.repository.VariableRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class VariableService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private VariableRepository variableRepository;
|
||||||
|
|
||||||
|
public Integer getValorEntero(String clave) {
|
||||||
|
return variableRepository.findByClave(clave)
|
||||||
|
.<Integer>map(v -> Integer.parseInt(v.getValor()))
|
||||||
|
.orElseThrow(
|
||||||
|
() -> new IllegalArgumentException("No se encontró la variable con clave '" + clave + "'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,2 +1,13 @@
|
|||||||
spring.application.name=erp
|
spring.application.name=erp
|
||||||
logging.level.org.springframework.security=DEBUG
|
logging.level.org.springframework.security=DEBUG
|
||||||
|
|
||||||
|
logging.level.root=WARN
|
||||||
|
logging.level.org.springframework=ERROR
|
||||||
|
|
||||||
|
spring.datasource.url=jdbc:mysql://localhost:3306/imprimelibros
|
||||||
|
spring.datasource.username=imprimelibros_user
|
||||||
|
spring.datasource.password=om91irrDctd
|
||||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.show-sql=true
|
||||||
@ -1,7 +1,7 @@
|
|||||||
presupuesto.datos-generales=Datos Generales
|
presupuesto.datos-generales=Datos Generales
|
||||||
presupuesto.interior=Interior
|
presupuesto.interior=Interior
|
||||||
presupuesto.cubierta=Cubierta
|
presupuesto.cubierta=Cubierta
|
||||||
presupuesto.envio=Envío
|
presupuesto.extras=Extras
|
||||||
|
|
||||||
# Pestaña datos generales de presupuesto
|
# Pestaña datos generales de presupuesto
|
||||||
presupuesto.informacion-libro=Información del libro
|
presupuesto.informacion-libro=Información del libro
|
||||||
@ -13,18 +13,98 @@ presupuesto.tirada1=Tirada 1*
|
|||||||
presupuesto.tirada2=Tirada 2
|
presupuesto.tirada2=Tirada 2
|
||||||
presupuesto.tirada3=Tirada 3
|
presupuesto.tirada3=Tirada 3
|
||||||
presupuesto.tirada4=Tirada 4
|
presupuesto.tirada4=Tirada 4
|
||||||
presupuesto.tiradasPODnoPOD=No puede mezclar tiradas menores de 30 unidades con mayores de 30 unidades
|
presupuesto.tiradasPODnoPOD=No puede mezclar tiradas menores de {0} unidades con mayores de {0} unidades
|
||||||
presupuesto.formato=Formato
|
presupuesto.formato=Formato
|
||||||
presupuesto.orientacion.vertical=Vertical
|
presupuesto.orientacion.vertical=Vertical
|
||||||
presupuesto.orientacion.apaisado=Apaisado
|
presupuesto.orientacion.apaisado=Apaisado
|
||||||
presupuesto.orientacion.cuadrado=Cuadrado
|
presupuesto.orientacion.cuadrado=Cuadrado
|
||||||
presupuesto.formato-personalizado=Formato personalizado
|
presupuesto.formato-personalizado=Formato personalizado
|
||||||
presupuesto.ancho=Ancho
|
presupuesto.ancho=Ancho (mm)*
|
||||||
presupuesto.alto=Alto
|
presupuesto.alto=Alto (mm)*
|
||||||
presupuesto.paginas-total=Total Páginas
|
presupuesto.paginas-total=Total Páginas
|
||||||
presupuesto.paginas-negro=Páginas Negro
|
presupuesto.paginas-negro=Páginas Negro
|
||||||
presupuesto.paginas-color=Páginas Color
|
presupuesto.paginas-color=Páginas Color
|
||||||
|
presupuesto.paginas-posicion=Posición páginas color
|
||||||
|
presupuesto.paginas-posicion-descripcion=Intruzca la posición separada por comas. Ej: 3,5,7 ó 4-10,20,155
|
||||||
presupuesto.siempre-pares=Siempre deben ser pares
|
presupuesto.siempre-pares=Siempre deben ser pares
|
||||||
presupuesto.encuadernacion=Encuadernación
|
presupuesto.encuadernacion=Encuadernación
|
||||||
|
presupuesto.fresado-descripcion=Fresado (a partir de 32 páginas)
|
||||||
|
presupuesto.cosido-descripcion=Cosido (a partir de 32 páginas)
|
||||||
|
presupuesto.grapado-descripcion=Grapado (entre 12 y 40 páginas)
|
||||||
|
presupuesto.espiral-descripcion=Espiral (a partir de 20 páginas)
|
||||||
|
presupuesto.wire-o-descripcion=Wire-O (a partir de 20 páginas)
|
||||||
presupuesto.encuadernacion-descripcion=Seleccione la encuadernación del libro
|
presupuesto.encuadernacion-descripcion=Seleccione la encuadernación del libro
|
||||||
presupuesto.siguiente=Siguiente
|
presupuesto.continuar-interior=Continuar a diseño interior
|
||||||
|
|
||||||
|
# Pestaña interior de presupuesto
|
||||||
|
presupuesto.tipo-encuadernacion=Tipo de impresión
|
||||||
|
presupuesto.tipo-encuadernacion-descripcion=Seleccione entre calidad estándar o premium
|
||||||
|
presupuesto.papel-interior=Papel interior
|
||||||
|
presupuesto.papel-interior-descripcion=Seleccione el papel para el interior
|
||||||
|
presupuesto.gramaje-interior=Gramaje interior
|
||||||
|
presupuesto.gramaje-interior-descripcion=Seleccione el gramaje para el interior
|
||||||
|
presupuesto.blanco-negro=Blanco y negro
|
||||||
|
presupuesto.blanco-negro-premium= Blanco y negro Premium
|
||||||
|
presupuesto.color=Color
|
||||||
|
presupuesto.color-premium=Color Premium
|
||||||
|
presupuesto.offset-blanco=Offset Blanco
|
||||||
|
presupuesto.offset-ahuesado=Offset Ahuesado
|
||||||
|
presupuesto.offset-ahuesado-volumen=Offset Ahuesado Volumen
|
||||||
|
presupuesto.estucado-mate=Estucado Mate
|
||||||
|
presupuesto.volver-datos-generales=Volver a datos generales
|
||||||
|
presupuesto.continuar-cubierta=Continuar a diseño cubierta
|
||||||
|
|
||||||
|
# Pestaña cubierta
|
||||||
|
presupuesto.plantilla-cubierta=Plantilla de cubierta
|
||||||
|
presupuesto.plantilla-cubierta-text=Recuerde que la cubierta es el conjunto formado por la portada, contraportada, lomo y solapas, en caso de que las lleve.<br/><br/><br/>Si tiene dudas de las medidas puede solicitarnos una plantilla cuando haga el pedido.
|
||||||
|
presupuesto.tipo-cubierta=Tipo de cubierta
|
||||||
|
presupuesto.tipo-cubierta-descripcion=Seleccione el tipo de cubierta y sus opciones
|
||||||
|
presupuesto.tapa-blanda=Tapa blanda
|
||||||
|
presupuesto.tapa-dura=Tapa dura
|
||||||
|
presupuesto.tapa-dura-lomo-redondo=Tapa dura lomo redondo
|
||||||
|
presupuesto.sin-solapas=Sin solapas
|
||||||
|
presupuesto.con-solapas=Con solapas
|
||||||
|
presupuesto.impresion-cubierta=Impresión de cubierta
|
||||||
|
presupuesto.impresion-cubierta-help=La cubierta se puede imprimir por anverso y reverso, como en el caso de las revistas, pero para un libro normal con portada y contraportada, la impresión de cubierta es a una cara.
|
||||||
|
presupuesto.una-cara=Una cara
|
||||||
|
presupuesto.dos-caras=Dos caras
|
||||||
|
presupuesto.tamanio-solapa=Tamaño solapa
|
||||||
|
presupuesto.papel-guardas=Papel de guardas
|
||||||
|
presupuesto.guardas-impresas=Guardas impresas
|
||||||
|
presupuesto.no=No
|
||||||
|
presupuesto.cabezada=Cabezada
|
||||||
|
presupuesto.cabezada-blanca=Blanca
|
||||||
|
presupuesto.cabezada-verde=Verde
|
||||||
|
presupuesto.cabezada-azul=Azul
|
||||||
|
presupuesto.cabezada-roja-amarilla=Roja-Amarilla
|
||||||
|
presupuesto.papel-cubierta=Papel cubierta
|
||||||
|
presupuesto.papel-cubierta-descripcion=Seleccione el papel para la cubierta
|
||||||
|
presupuesto.cartulina-grafica-cubierta=Cartulina gráfica estucada a una cara
|
||||||
|
presupuesto.estucado-mate-cubierta=Estucado mate
|
||||||
|
presupuesto.gramaje-cubierta=Gramaje cubierta
|
||||||
|
presupuesto.gramaje-cubierta-descripcion=Seleccione el gramaje para la cubierta
|
||||||
|
presupuesto.volver-interior=Volver a diseño interior
|
||||||
|
presupuesto.continuar-extras-libro=Continuar a extras del libro
|
||||||
|
|
||||||
|
|
||||||
|
# Errores
|
||||||
|
presupuesto.errores-title=Corrija los siguientes errores:
|
||||||
|
presupuesto.errores.titulo=El título es obligatorio
|
||||||
|
presupuesto.errores.tirada1=La tirada 1 es obligatoria
|
||||||
|
presupuesto.errores.tiradas.consistentes=Las tiradas deben ser consistentes (no mezclar tiradas menores de {0} unidades con mayores de {0} unidades)
|
||||||
|
presupuesto.errores.paginasNegro.required=El número de páginas en negro es obligatorio
|
||||||
|
presupuesto.errores.paginasNegro.par=El número de páginas en negro debe ser par
|
||||||
|
presupuesto.errores.paginasColor.required=El número de páginas en color es obligatorio
|
||||||
|
presupuesto.errores.paginasColor.par=El número de páginas en color debe ser par
|
||||||
|
presupuesto.errores.tipo-encuadernacion=Seleccione el tipo de libro
|
||||||
|
presupuesto.errores.ancho=El ancho no puede estar vacío
|
||||||
|
presupuesto.errores.ancho.min_max=El ancho tiene que estar en el rango [{0}, {1}] mm;
|
||||||
|
presupuesto.errores.alto=El alto no puede estar vacío
|
||||||
|
presupuesto.errores.alto.min_max=El alto tiene que estar en el rango [{0}, {1}] mm
|
||||||
|
presupuesto.errores.tipo-impresion=Seleccione el tipo de impresion
|
||||||
|
presupuesto.errores.papel-interior=Seleccione el tipo de papel para el interior
|
||||||
|
presupuesto.errores.gramaje-interior=Seleccione el gramaje del papel para el interior
|
||||||
|
presupuesto.errores.tipo-cubierta=Seleccione el tipo de cubierta
|
||||||
|
presupuesto.errores.solapas-cubierta=Seleccione si desea o no solapas en la cubierta
|
||||||
|
presupuesto.errores.papel-cubierta=Seleccione el tipo de papel para la cubierta
|
||||||
|
presupuesto.errores.gramaje-cubierta=Seleccione el gramaje del papel para la cubierta
|
||||||
@ -7,8 +7,98 @@ Website: https://themesbrand.com/
|
|||||||
Contact: support@themesbrand.com
|
Contact: support@themesbrand.com
|
||||||
File: Main Css File
|
File: Main Css File
|
||||||
*/
|
*/
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap");
|
/* poppins-300 - latin */
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap");
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Poppins';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
src: url('../fonts/poppins/poppins-v23-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poppins-regular - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Poppins';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url('../fonts/poppins/poppins-v23-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poppins-500 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Poppins';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
src: url('../fonts/poppins/poppins-v23-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poppins-600 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Poppins';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
src: url('../fonts/poppins/poppins-v23-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poppins-700 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Poppins';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: url('../fonts/poppins/poppins-v23-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* public-sans-300 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Public Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
src: url('../fonts/public-sans/public-sans-v20-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public-sans-regular - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Public Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url('../fonts/public-sans/public-sans-v20-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public-sans-500 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Public Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
src: url('../fonts/public-sans/public-sans-v20-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public-sans-600 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Public Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
src: url('../fonts/public-sans/public-sans-v20-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public-sans-700 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||||
|
font-family: 'Public Sans';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: url('../fonts/public-sans/public-sans-v20-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "hkgrotesk";
|
font-family: "hkgrotesk";
|
||||||
src: url("../fonts/hkgrotesk-light.eot");
|
src: url("../fonts/hkgrotesk-light.eot");
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
|
margin-inline: 5px;
|
||||||
|
|
||||||
transition: border 0.3s ease;
|
transition: border 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,3 +60,36 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gramaje-radio{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 70px; /* Ancho mínimo */
|
||||||
|
min-height: 70px; /* Alto mínimo */
|
||||||
|
max-width: 70px; /* Ancho máximo */
|
||||||
|
max-height: 70px; /* Alto máximo */
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInUpBounce {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translateY(5px);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fadeInUpBounce {
|
||||||
|
animation: fadeInUpBounce 0.6s ease-out both;
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 153 KiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 233 KiB |
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 531 KiB |
|
After Width: | Height: | Size: 484 KiB |
|
After Width: | Height: | Size: 481 KiB |
@ -0,0 +1,7 @@
|
|||||||
|
window.languageBundle.get = function (key, ...params) {
|
||||||
|
let text = this[key] || key;
|
||||||
|
params.forEach((val, i) => {
|
||||||
|
text = text.replace(`{${i}}`, val);
|
||||||
|
});
|
||||||
|
return text;
|
||||||
|
};
|
||||||
@ -1,23 +1,65 @@
|
|||||||
$(() => {
|
class imagen_presupuesto {
|
||||||
$('.imagen-container-group').on('click', '.imagen-selector', function () {
|
|
||||||
const clicked = $(this);
|
|
||||||
const group = clicked.closest('.imagen-container-group');
|
|
||||||
|
|
||||||
// Limpiar selección anterior
|
constructor(data) {
|
||||||
group.find('.imagen-selector').removeClass('selected preselected')
|
this.id = data.id;
|
||||||
.find('.image-presupuesto').removeClass('selected');
|
this.imagen = data.imagen;
|
||||||
|
this.alt = data.alt || "";
|
||||||
|
this.group = data.group || ""; // Grupo al que pertenece el radio
|
||||||
|
this.texto = data.texto || ""; // Texto de la etiqueta
|
||||||
|
this.selected = data.selected || false;
|
||||||
|
this.extraClass = (data.extraClass && !(data.extraClass===undefined))? (data.extraClass + ' ') : '';
|
||||||
|
this.extraData = data.extra_data || {}; // Datos extra opcionales
|
||||||
|
}
|
||||||
|
|
||||||
// Marcar nuevo seleccionado
|
render() {
|
||||||
clicked.addClass('selected');
|
const contenedor = $('<div>', {
|
||||||
const img = clicked.find('.image-presupuesto');
|
id: this.id,
|
||||||
img.addClass('selected');
|
class: `${this.extraClass + ' '}image-container imagen-selector${this.selected ? ' selected' : ''}`
|
||||||
|
});
|
||||||
|
// Añadir atributos extra al contenedor
|
||||||
|
for (const [key, value] of Object.entries(this.extraData)) {
|
||||||
|
contenedor.attr(`data-${key}`, value);
|
||||||
|
}
|
||||||
|
|
||||||
// Aplicar animación (reset antes para que se repita)
|
const input = $('<input>', {
|
||||||
img.removeClass('zoom-anim');
|
type: 'radio',
|
||||||
void img[0].offsetWidth; // "reflow" para reiniciar animación
|
name: this.group,
|
||||||
img.addClass('zoom-anim');
|
value: this.id,
|
||||||
|
hidden: true
|
||||||
|
});
|
||||||
|
|
||||||
// Guardar ID en hidden si lo necesitas
|
|
||||||
$('#tipoEncuadernacionSeleccionada').val(clicked.attr('id'));
|
const imagen = $('<img>', {
|
||||||
});
|
class: 'image-presupuesto',
|
||||||
});
|
id: this.id + '-img',
|
||||||
|
src: this.imagen,
|
||||||
|
alt: this.alt
|
||||||
|
});
|
||||||
|
|
||||||
|
const etiqueta = $('<label>', {
|
||||||
|
for: this.id + '-img',
|
||||||
|
class: 'form-label',
|
||||||
|
text: this.texto
|
||||||
|
});
|
||||||
|
|
||||||
|
contenedor.append(imagen, etiqueta);
|
||||||
|
return contenedor;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelected(selected) {
|
||||||
|
|
||||||
|
this.selected = selected;
|
||||||
|
const contenedor = $(`#${this.id}`);
|
||||||
|
const radio = contenedor.find('input[type="radio"]');
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
|
contenedor.addClass('selected');
|
||||||
|
radio.prop('checked', true).trigger('change'); // <-- esto actualiza el input y lanza evento
|
||||||
|
} else {
|
||||||
|
contenedor.removeClass('selected');
|
||||||
|
radio.prop('checked', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default imagen_presupuesto;
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
$('.imagen-container-group').on('click', '.image-container', function () {
|
||||||
|
const clicked = $(this);
|
||||||
|
const group = clicked.closest('.imagen-container-group');
|
||||||
|
|
||||||
|
// Limpiar selección anterior
|
||||||
|
group.find('.image-container').removeClass('selected')
|
||||||
|
.find('.image-presupuesto').removeClass('zoom-anim');
|
||||||
|
|
||||||
|
// Marcar nuevo seleccionado
|
||||||
|
clicked.addClass('selected');
|
||||||
|
|
||||||
|
// Aplicar animación de zoom
|
||||||
|
const img = clicked.find('.image-presupuesto');
|
||||||
|
void img[0].offsetWidth; // Forzar reflow
|
||||||
|
img.addClass('zoom-anim');
|
||||||
|
|
||||||
|
|
||||||
|
clicked.find('input[type="radio"]').prop('checked', true).trigger('change');
|
||||||
|
});
|
||||||
@ -0,0 +1,692 @@
|
|||||||
|
import imagen_presupuesto from "./imagen-presupuesto.js";
|
||||||
|
|
||||||
|
class PresupuestoCliente {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
this.DEBUG = true; // Activar o desactivar el modo de depuración
|
||||||
|
|
||||||
|
this.formData = {
|
||||||
|
datosGenerales: {
|
||||||
|
titulo: '',
|
||||||
|
autor: '',
|
||||||
|
isbn: '',
|
||||||
|
tirada1: '',
|
||||||
|
tirada2: '',
|
||||||
|
tirada3: '',
|
||||||
|
tirada4: '',
|
||||||
|
ancho: '',
|
||||||
|
alto: '',
|
||||||
|
formatoPersonalizado: false,
|
||||||
|
paginasNegro: '',
|
||||||
|
paginasColor: '',
|
||||||
|
posicionPaginasColor: '',
|
||||||
|
tipoEncuadernacion: 'fresado',
|
||||||
|
},
|
||||||
|
interior: {
|
||||||
|
tipoImpresion: 'negro',
|
||||||
|
papelInteriorId: 3,
|
||||||
|
gramajeInterior: 9,
|
||||||
|
},
|
||||||
|
cubierta: {
|
||||||
|
tipoCubierta: 'tapaBlanda',
|
||||||
|
solapasCubierta: 0,
|
||||||
|
tamanioSolapasCubierta: '80',
|
||||||
|
cubiertaCaras: 2,
|
||||||
|
papelGuardasId: 3,
|
||||||
|
gramajeGuardas: 170,
|
||||||
|
guardasImpresas: 0,
|
||||||
|
cabezada: 'WHI',
|
||||||
|
papelCubiertaId: 3,
|
||||||
|
gramajeCubierta: 170,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pestaña datos generales
|
||||||
|
this.divContentDatosGenerales = $('#content-datos-generales');
|
||||||
|
this.titulo = $('#titulo');
|
||||||
|
this.autor = $('#autor');
|
||||||
|
this.isbn = $('#isbn');
|
||||||
|
this.tirada1 = $('#tirada1');
|
||||||
|
this.tirada2 = $('#tirada2');
|
||||||
|
this.tirada3 = $('#tirada3');
|
||||||
|
this.tirada4 = $('#tirada4');
|
||||||
|
this.formatoPersonalizado = $('#formato-personalizado');
|
||||||
|
this.divFormato = $('.div-formato');
|
||||||
|
this.divFormatoPersonalizado = $('.div-formato-personalizado');
|
||||||
|
this.formato = $('#formato');
|
||||||
|
this.ancho = $('#ancho');
|
||||||
|
this.alto = $('#alto');
|
||||||
|
this.paginasNegro = $('#paginas-negro');
|
||||||
|
this.paginasColor = $('#paginas-color');
|
||||||
|
this.divPosicionPaginasColor = $('#div-posicion-paginas-color');
|
||||||
|
this.posicionPaginasColor = $('#posicionPaginasColor');
|
||||||
|
this.paginas = $('#paginas');
|
||||||
|
this.btn_next_datos_generales = $('#next-datos-generales');
|
||||||
|
this.datos_generales_alert = $('#datos-generales-alert');
|
||||||
|
|
||||||
|
// pestaña interior
|
||||||
|
this.divContentInterior = $('#content-interior');
|
||||||
|
this.divOpcionesColor = $('#div-opciones-color');
|
||||||
|
this.divPapelInterior = $('#div-papel-interior');
|
||||||
|
this.divGramajeInterior = $("#div-gramaje-interior");
|
||||||
|
this.interior_alert = $('#interior-alert');
|
||||||
|
|
||||||
|
// pestaña cubierta
|
||||||
|
this.divSolapasCubierta = $('#div-solapas-cubierta');
|
||||||
|
this.divPapelCubierta = $('#div-papel-cubierta');
|
||||||
|
this.divGramajeCubierta = $("#div-gramaje-cubierta");
|
||||||
|
this.btn_plantilla_cubierta = $('#btn-plantilla-cubierta');
|
||||||
|
this.btn_impresion_cubierta_help = $('#impresion-cubierta-help');
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
|
||||||
|
this.#initDatosGenerales();
|
||||||
|
this.#initInterior();
|
||||||
|
this.#initCubierta();
|
||||||
|
|
||||||
|
const stored = sessionStorage.getItem("formData");
|
||||||
|
if (stored) {
|
||||||
|
this.formData = JSON.parse(stored);
|
||||||
|
this.#loadDatosGeneralesData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cacheFormData() {
|
||||||
|
sessionStorage.setItem("formData", JSON.stringify(this.formData));
|
||||||
|
}
|
||||||
|
|
||||||
|
#changeTab(idContenidoTab) {
|
||||||
|
const tabButton = document.querySelector(`[data-bs-target="#${idContenidoTab}"]`);
|
||||||
|
if (tabButton) {
|
||||||
|
const tab = new bootstrap.Tab(tabButton);
|
||||||
|
tab.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#getPresupuestoData() {
|
||||||
|
return {
|
||||||
|
...this.#getDatosGeneralesData(),
|
||||||
|
...this.#getInteriorData(),
|
||||||
|
...this.#getCubiertaData()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#addGramaje(contenedor, gramaje, name) {
|
||||||
|
const id = `gramaje-${gramaje}`;
|
||||||
|
|
||||||
|
// Crear input
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
input.className = 'btn-check';
|
||||||
|
input.dataset.gramaje = gramaje;
|
||||||
|
input.id = id;
|
||||||
|
input.name = name;
|
||||||
|
|
||||||
|
// Crear label
|
||||||
|
const label = document.createElement('label');
|
||||||
|
label.className = 'btn btn-outline-primary material-shadow gramaje-radio';
|
||||||
|
label.setAttribute('for', id);
|
||||||
|
label.textContent = gramaje;
|
||||||
|
|
||||||
|
// Añadir al contenedor
|
||||||
|
contenedor.append(input);
|
||||||
|
contenedor.append(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* END OF DATOS GENERALES
|
||||||
|
******************************/
|
||||||
|
#initDatosGenerales() {
|
||||||
|
|
||||||
|
$('.datos-generales-data').on('change', () => {
|
||||||
|
const dataToStore = this.#getDatosGeneralesData();
|
||||||
|
this.#updateDatosGeneralesData(dataToStore);
|
||||||
|
this.#cacheFormData();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.paginas').on('change', () => {
|
||||||
|
this.paginas.val(parseInt(this.paginasNegro.val()) + parseInt(this.paginasColor.val()));
|
||||||
|
if (parseInt(this.paginasColor.val()) == 0) {
|
||||||
|
this.divPosicionPaginasColor.addClass('d-none');
|
||||||
|
this.posicionPaginasColor.val("");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.divPosicionPaginasColor.removeClass('d-none');
|
||||||
|
}
|
||||||
|
this.#updateTipoEncuadernacion();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.formatoPersonalizado.on('change', () => {
|
||||||
|
if (this.formatoPersonalizado.is(':checked')) {
|
||||||
|
this.divFormato.addClass('d-none');
|
||||||
|
this.divFormatoPersonalizado.removeClass('d-none');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.divFormatoPersonalizado.addClass('d-none');
|
||||||
|
this.divFormato.removeClass('d-none');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.btn_next_datos_generales.on('click', () => {
|
||||||
|
this.#nextDatosGenerales();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#nextDatosGenerales() {
|
||||||
|
|
||||||
|
let data = this.#getPresupuestoData();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/presupuesto/public/validar/datos-generales',
|
||||||
|
type: 'POST',
|
||||||
|
data: data,
|
||||||
|
success: (data) => {
|
||||||
|
this.#processDatosGenerales(data);
|
||||||
|
},
|
||||||
|
error: (xhr, status, error) => {
|
||||||
|
|
||||||
|
this.datos_generales_alert.removeClass('d-none');
|
||||||
|
this.datos_generales_alert.find('#datos-generales-alert-list').empty();
|
||||||
|
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 => {
|
||||||
|
this.datos_generales_alert.find('#datos-generales-alert-list').append(`<li>${errorMsg}</li>`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.datos_generales_alert.find('#datos-generales-alert-list').append('<li>Error desconocido. Por favor, inténtelo de nuevo más tarde.</li>');
|
||||||
|
}
|
||||||
|
$(window).scrollTop(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#processDatosGenerales(data) {
|
||||||
|
|
||||||
|
this.datos_generales_alert.addClass('d-none');
|
||||||
|
|
||||||
|
this.#loadInteriorData(data);
|
||||||
|
|
||||||
|
const interiorData = this.#getInteriorData();
|
||||||
|
this.#updateInteriorData(interiorData);
|
||||||
|
|
||||||
|
this.#changeTab('pills-inside');
|
||||||
|
|
||||||
|
this.divContentInterior.addClass('animate-fadeInUpBounce');
|
||||||
|
}
|
||||||
|
|
||||||
|
#getDatosGeneralesData() {
|
||||||
|
|
||||||
|
const tamanio = this.#getTamanio();
|
||||||
|
|
||||||
|
return {
|
||||||
|
titulo: this.titulo.val(),
|
||||||
|
autor: this.autor.val(),
|
||||||
|
isbn: this.isbn.val(),
|
||||||
|
tirada1: this.tirada1.val(),
|
||||||
|
tirada2: this.tirada2.val(),
|
||||||
|
tirada3: this.tirada3.val(),
|
||||||
|
tirada4: this.tirada4.val(),
|
||||||
|
formatoPersonalizado: this.formatoPersonalizado.is(':checked'),
|
||||||
|
ancho: parseInt(tamanio.ancho),
|
||||||
|
alto: parseInt(tamanio.alto),
|
||||||
|
paginasNegro: this.paginasNegro.val(),
|
||||||
|
paginasColor: this.paginasColor.val(),
|
||||||
|
posicionPaginasColor: this.posicionPaginasColor.val(),
|
||||||
|
tipoEncuadernacion: ($('.tipo-libro.selected').length > 0) ? $('.tipo-libro.selected').attr('id') : 'fresado',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateDatosGeneralesData(data) {
|
||||||
|
|
||||||
|
this.formData.datosGenerales = {
|
||||||
|
titulo: data.titulo,
|
||||||
|
autor: data.autor,
|
||||||
|
isbn: data.isbn,
|
||||||
|
tirada1: data.tirada1,
|
||||||
|
tirada2: data.tirada2,
|
||||||
|
tirada3: data.tirada3,
|
||||||
|
tirada4: data.tirada4,
|
||||||
|
formatoPersonalizado: data.formatoPersonalizado,
|
||||||
|
ancho: parseInt(data.ancho),
|
||||||
|
alto: parseInt(data.alto),
|
||||||
|
paginasNegro: data.paginasNegro,
|
||||||
|
paginasColor: data.paginasColor,
|
||||||
|
posicionPaginasColor: data.posicionPaginasColor,
|
||||||
|
tipoEncuadernacion: data.tipoEncuadernacion,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadDatosGeneralesData() {
|
||||||
|
|
||||||
|
this.titulo.val(this.formData.datosGenerales.titulo);
|
||||||
|
this.autor.val(this.formData.datosGenerales.autor);
|
||||||
|
this.isbn.val(this.formData.datosGenerales.isbn);
|
||||||
|
this.tirada1.val(this.formData.datosGenerales.tirada1);
|
||||||
|
this.tirada2.val(this.formData.datosGenerales.tirada2);
|
||||||
|
this.tirada3.val(this.formData.datosGenerales.tirada3);
|
||||||
|
this.tirada4.val(this.formData.datosGenerales.tirada4);
|
||||||
|
|
||||||
|
this.paginasNegro.val(this.formData.datosGenerales.paginasNegro);
|
||||||
|
this.paginasColor.val(this.formData.datosGenerales.paginasColor);
|
||||||
|
|
||||||
|
this.posicionPaginasColor.val(this.formData.datosGenerales.posicionPaginasColor);
|
||||||
|
|
||||||
|
$('.tipo-libro').removeClass('selected');
|
||||||
|
$('.image-container#' + this.formData.datosGenerales.tipoEncuadernacion).trigger('click');
|
||||||
|
this.#updateTipoEncuadernacion();
|
||||||
|
|
||||||
|
this.formatoPersonalizado.prop('checked', this.formData.datosGenerales.formatoPersonalizado).trigger('change');
|
||||||
|
|
||||||
|
$('.paginas').trigger('change');
|
||||||
|
|
||||||
|
if (this.formatoPersonalizado.is(':checked')) {
|
||||||
|
this.ancho.val(this.formData.datosGenerales.ancho);
|
||||||
|
this.alto.val(this.formData.datosGenerales.alto);
|
||||||
|
} else {
|
||||||
|
const option = this.formato.find('option').filter(() => {
|
||||||
|
return $(this).data('ancho') == this.formData.datosGenerales.ancho &&
|
||||||
|
$(this).data('alto') == this.formData.datosGenerales.alto;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (option.length) {
|
||||||
|
this.formato.val(option.val()).trigger('change');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTamanio() {
|
||||||
|
|
||||||
|
if (this.formatoPersonalizado.is(':checked')) {
|
||||||
|
return {
|
||||||
|
ancho: this.ancho.val(),
|
||||||
|
alto: this.alto.val()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const opcionSeleccionada = $('#formato option:selected');
|
||||||
|
const ancho = opcionSeleccionada.data('ancho');
|
||||||
|
const alto = opcionSeleccionada.data('alto');
|
||||||
|
return {
|
||||||
|
ancho: ancho,
|
||||||
|
alto: alto
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateTipoEncuadernacion() {
|
||||||
|
|
||||||
|
const paginas = parseInt(this.paginas.val());
|
||||||
|
const selectedTipo = $('.tipo-libro.selected').attr('id');
|
||||||
|
$('.tipo-libro').removeClass('selected');
|
||||||
|
|
||||||
|
if (paginas < 32) {
|
||||||
|
$('.tipo-libro#fresado').addClass('d-none');
|
||||||
|
$('.tipo-libro#cosido').addClass('d-none');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.tipo-libro#fresado').removeClass('d-none');
|
||||||
|
$('.tipo-libro#cosido').removeClass('d-none');
|
||||||
|
}
|
||||||
|
if (paginas < 20) {
|
||||||
|
$('.tipo-libro#espiral').addClass('d-none');
|
||||||
|
$('.tipo-libro#wireo').addClass('d-none');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.tipo-libro#espiral').removeClass('d-none');
|
||||||
|
$('.tipo-libro#wireo').removeClass('d-none');
|
||||||
|
}
|
||||||
|
if (paginas < 12 || paginas > 40) {
|
||||||
|
$('.tipo-libro#grapado').addClass('d-none');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.tipo-libro#grapado').removeClass('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedTipo && $('.tipo-libro#' + selectedTipo).length > 0 && !$('.tipo-libro#' + selectedTipo).hasClass('d-none')) {
|
||||||
|
$('.tipo-libro#' + selectedTipo).addClass('selected');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let firstVisible = $('.tipo-libro').not('.d-none').first();
|
||||||
|
|
||||||
|
if (firstVisible.length) {
|
||||||
|
firstVisible.addClass('selected');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($('.tipo-libro.selected').length > 0) {
|
||||||
|
this.formData.datosGenerales.tipoEncuadernacion = $('.tipo-libro.selected').attr('id');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.formData.datosGenerales.tipoEncuadernacion = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/******************************
|
||||||
|
* END OF DATOS GENERALES
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* INTERIOR
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
#initInterior() {
|
||||||
|
|
||||||
|
$(document).on('click', '.interior-data', (e) => {
|
||||||
|
const dataToStore = this.#getInteriorData();
|
||||||
|
this.#updateInteriorData(dataToStore);
|
||||||
|
this.#cacheFormData();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.papel-interior', (e) => {
|
||||||
|
|
||||||
|
this.divGramajeInterior.removeClass('animate-fadeInUpBounce');
|
||||||
|
|
||||||
|
const data = this.#getPresupuestoData();
|
||||||
|
$.ajax({
|
||||||
|
url: '/presupuesto/public/get-gramaje-interior',
|
||||||
|
type: 'POST',
|
||||||
|
data: data,
|
||||||
|
}).done((data) => {
|
||||||
|
|
||||||
|
this.divGramajeInterior.empty();
|
||||||
|
const gramajes = data.opciones_gramaje_interior;
|
||||||
|
this.#addGramajesInterior(gramajes);
|
||||||
|
this.divGramajeInterior.addClass('animate-fadeInUpBounce');
|
||||||
|
|
||||||
|
const dataInterior = this.#getInteriorData();
|
||||||
|
this.#updateInteriorData(dataInterior);
|
||||||
|
this.#cacheFormData();
|
||||||
|
|
||||||
|
}).fail((xhr, status, error) => {
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.btn-change-tab-interior').on('click', (e) => {
|
||||||
|
|
||||||
|
let data = this.#getPresupuestoData();
|
||||||
|
const id = e.currentTarget.id;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/presupuesto/public/validar/interior',
|
||||||
|
type: 'POST',
|
||||||
|
data: data,
|
||||||
|
success: (data) => {
|
||||||
|
if( id === 'btn-prev-interior') {
|
||||||
|
|
||||||
|
this.#changeTab('pills-general-data');
|
||||||
|
} else {
|
||||||
|
$('.tapa-cubierta.selected').trigger('click');
|
||||||
|
this.#changeTab('pills-cover');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: (xhr, status, error) => {
|
||||||
|
|
||||||
|
this.interior_alert.removeClass('d-none');
|
||||||
|
this.interior_alert.find('#inside-alert-list').empty();
|
||||||
|
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 => {
|
||||||
|
this.interior_alert.find('#inside-alert-list').append(`<li>${errorMsg}</li>`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.interior_alert.find('#inside-alert-list').append('<li>Error desconocido. Por favor, inténtelo de nuevo más tarde.</li>');
|
||||||
|
}
|
||||||
|
$(window).scrollTop(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadInteriorData(data) {
|
||||||
|
|
||||||
|
this.divOpcionesColor.empty();
|
||||||
|
this.divPapelInterior.empty();
|
||||||
|
this.divGramajeInterior.empty();
|
||||||
|
|
||||||
|
const opciones_color = data.opciones_color;
|
||||||
|
|
||||||
|
for (let i = 0; i < opciones_color.length; i++) {
|
||||||
|
const opcion = opciones_color[i];
|
||||||
|
const item = new imagen_presupuesto(opcion);
|
||||||
|
item.extraClass = 'interior-data';
|
||||||
|
if ((this.formData.interior.color === '' && i === 0) ||
|
||||||
|
this.formData.interior.color === opcion.id) {
|
||||||
|
item.setSelected(true);
|
||||||
|
}
|
||||||
|
this.divOpcionesColor.append(item.render());
|
||||||
|
}
|
||||||
|
|
||||||
|
const opciones_papel_interior = data.opciones_papel_interior;
|
||||||
|
for (let i = 0; i < opciones_papel_interior.length; i++) {
|
||||||
|
const opcion = opciones_papel_interior[i];
|
||||||
|
const item = new imagen_presupuesto(opcion);
|
||||||
|
item.extraClass = 'interior-data papel-interior';
|
||||||
|
|
||||||
|
this.divPapelInterior.append(item.render());
|
||||||
|
}
|
||||||
|
|
||||||
|
const gramajes = data.opciones_gramaje_interior;
|
||||||
|
this.#addGramajesInterior(gramajes);
|
||||||
|
|
||||||
|
const dataInterior = this.#getInteriorData();
|
||||||
|
this.#updateInteriorData(dataInterior);
|
||||||
|
this.#cacheFormData();
|
||||||
|
}
|
||||||
|
|
||||||
|
#addGramajesInterior(gramajes) {
|
||||||
|
|
||||||
|
for (let i = 0; i < gramajes.length; i++) {
|
||||||
|
const gramaje = gramajes[i];
|
||||||
|
this.#addGramaje(this.divGramajeInterior, gramaje, 'gramaje-interior');
|
||||||
|
|
||||||
|
// Seleccionar el gramaje por defecto
|
||||||
|
if (this.formData.interior.gramaje === '' && i === 0) {
|
||||||
|
$(`#gramaje-${gramaje}`).prop('checked', true);
|
||||||
|
} else if (this.formData.interior.gramaje === gramaje) {
|
||||||
|
$(`#gramaje-${gramaje}`).prop('checked', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.divGramajeInterior.find('input[type="radio"]:checked').length === 0) {
|
||||||
|
// If not, select the first one by default
|
||||||
|
this.divGramajeInterior.find('input[type="radio"]').first().prop('checked', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#getInteriorData() {
|
||||||
|
|
||||||
|
const tipoImpresion = $('#div-opciones-color .image-container.selected').attr('id') || 'negro';
|
||||||
|
const papelInteriorId = $('#div-papel-interior .image-container.selected').data('sk-id') || 3;
|
||||||
|
const gramejeInterior = $('input[name="gramaje-interior"]:checked').data('gramaje') || 90;
|
||||||
|
return {
|
||||||
|
tipoImpresion: tipoImpresion,
|
||||||
|
papelInteriorId: papelInteriorId,
|
||||||
|
gramejeInterior: gramejeInterior
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateInteriorData(data) {
|
||||||
|
|
||||||
|
this.formData.interior.tipoImpresion = data.tipoImpresion;
|
||||||
|
this.formData.interior.papelInteriorId = data.papelInteriorId;
|
||||||
|
this.formData.interior.gramejeInterior = data.gramejeInterior;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* END INTERIOR
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* CUBIERTA
|
||||||
|
******************************/
|
||||||
|
#initCubierta() {
|
||||||
|
|
||||||
|
this.btn_plantilla_cubierta.on('click', () => {
|
||||||
|
Swal.fire({
|
||||||
|
position: 'top-end',
|
||||||
|
icon: 'info',
|
||||||
|
title: window.languageBundle.get('presupuesto.plantilla-cubierta'),
|
||||||
|
html: `
|
||||||
|
<div class="text-center p-4">
|
||||||
|
<img src="/assets/images/imprimelibros/presupuestador/plantilla-cubierta.png" class="img-fluid" alt="" />
|
||||||
|
</div>
|
||||||
|
<div class="acitivity-timeline p-4">
|
||||||
|
${window.languageBundle.get('presupuesto.plantilla-cubierta-text')}
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
confirmButtonClass: 'btn btn-primary w-xs mt-2',
|
||||||
|
showConfirmButton: false,
|
||||||
|
showCloseButton: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.btn_impresion_cubierta_help.on('click', () => {
|
||||||
|
Swal.fire({
|
||||||
|
position: 'top-end',
|
||||||
|
icon: 'info',
|
||||||
|
title: window.languageBundle.get('presupuesto.impresion-cubierta'),
|
||||||
|
html: window.languageBundle.get('presupuesto.impresion-cubierta-help'),
|
||||||
|
confirmButtonClass: 'btn btn-primary w-xs mt-2',
|
||||||
|
showConfirmButton: false,
|
||||||
|
showCloseButton: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.tapa-cubierta', (e) => {
|
||||||
|
|
||||||
|
$('.tapa-dura-options').eq(0).removeClass('animate-fadeInUpBounce');
|
||||||
|
$('.tapa-blanda-options').eq(0).removeClass('animate-fadeInUpBounce');
|
||||||
|
|
||||||
|
if(e.currentTarget.id === 'tapaBlanda') {
|
||||||
|
$('.tapa-dura-options').addClass('d-none');
|
||||||
|
$('.tapa-blanda-options').removeClass('d-none');
|
||||||
|
$('.tapa-blanda-options').eq(0).addClass('animate-fadeInUpBounce');
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$('.tapa-blanda-options').addClass('d-none');
|
||||||
|
$('.tapa-dura-options').removeClass('d-none');
|
||||||
|
$('.tapa-dura-options').eq(0).addClass('animate-fadeInUpBounce');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#getPapelesCubierta(e.currentTarget.id);
|
||||||
|
|
||||||
|
const dataToStore = this.#getCubiertaData();
|
||||||
|
this.#updateCubiertaData(dataToStore);
|
||||||
|
this.#cacheFormData();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.solapas-cubierta', (e) => {
|
||||||
|
|
||||||
|
if(e.currentTarget.id === 'sin-solapas') {
|
||||||
|
this.divSolapasCubierta.addClass('d-none');
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.divSolapasCubierta.removeClass('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataToStore = this.#getCubiertaData();
|
||||||
|
this.#updateCubiertaData(dataToStore);
|
||||||
|
this.#cacheFormData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#getPapelesCubierta(tapa_id) {
|
||||||
|
|
||||||
|
this.divPapelCubierta.removeClass('animate-fadeInUpBounce');
|
||||||
|
|
||||||
|
return $.ajax({
|
||||||
|
url: '/presupuesto/public/get-papel-cubierta',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
tipoCubierta: tapa_id,
|
||||||
|
papelCubiertaId: this.formData.cubierta.papelCubiertaId,
|
||||||
|
gramajeCubierta: this.formData.cubierta.gramajeCubierta,
|
||||||
|
},
|
||||||
|
success: (data) => {
|
||||||
|
|
||||||
|
this.divPapelCubierta.empty();
|
||||||
|
this.divGramajeCubierta.empty();
|
||||||
|
|
||||||
|
const papelesCubierta = data.opciones_papel_cubierta;
|
||||||
|
for (let i = 0; i < papelesCubierta.length; i++) {
|
||||||
|
const papel = papelesCubierta[i];
|
||||||
|
const item = new imagen_presupuesto(papel);
|
||||||
|
item.extraClass = 'cubierta-data papel-cubierta';
|
||||||
|
if (papel.id === this.formData.cubierta.papelCubiertaId) {
|
||||||
|
item.setSelected(true);
|
||||||
|
}
|
||||||
|
this.divPapelCubierta.append(item.render());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.divPapelCubierta.addClass('animate-fadeInUpBounce');
|
||||||
|
},
|
||||||
|
error: (xhr, status, error) => {
|
||||||
|
|
||||||
|
console.error("Error al obtener los papeles de cubierta: ", xhr.responseText);
|
||||||
|
$(window).scrollTop(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#getCubiertaData() {
|
||||||
|
|
||||||
|
const tipoCubierta = $('.cubierta-data.tapa.selected').attr('id') || 'tapaBlanda';
|
||||||
|
const solapas = parseInt($('#div-solapas-cubierta input[type="radio"]:checked').val()) || 0;
|
||||||
|
const tamanioSolapas = $('#tamanio-solapas-cubierta').val() || '80';
|
||||||
|
const cubiertaCaras = parseInt($('#cubierta-caras').val()) || 2;
|
||||||
|
const guardasPapel = parseInt($('#guardas-papel').val()) || 3;
|
||||||
|
const guardasGramaje = parseInt($('#guardas-gramaje').val()) || 170;
|
||||||
|
const guardasImpresas = parseInt($('#guardas-impresas').val()) || 0;
|
||||||
|
const cabezada = $('#cabezada').val() || 'WHI';
|
||||||
|
const papelCubiertaId = $('#papel-cubierta-id').val() || 3;
|
||||||
|
const gramajeCubierta = $('#gramaje-cubierta').val() || 170;
|
||||||
|
|
||||||
|
return {
|
||||||
|
tipoCubierta: tipoCubierta,
|
||||||
|
solapas: solapas,
|
||||||
|
tamanioSolapas: tamanioSolapas,
|
||||||
|
cubiertaCaras: cubiertaCaras,
|
||||||
|
guardasPapel: guardasPapel,
|
||||||
|
guardasGramaje: guardasGramaje,
|
||||||
|
guardasImpresas: guardasImpresas,
|
||||||
|
cabezada: cabezada,
|
||||||
|
papelCubiertaId: papelCubiertaId,
|
||||||
|
gramajeCubierta: gramajeCubierta
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateCubiertaData(data) {
|
||||||
|
|
||||||
|
this.formData.cubierta.tipoCubierta = data.tipoCubierta;
|
||||||
|
this.formData.cubierta.solapas = data.solapas;
|
||||||
|
this.formData.cubierta.tamanioSolapas = data.tamanioSolapas;
|
||||||
|
this.formData.cubierta.cubiertaCaras = data.cubiertaCaras;
|
||||||
|
this.formData.cubierta.guardasPapel = data.guardasPapel;
|
||||||
|
this.formData.cubierta.guardasGramaje = data.guardasGramaje;
|
||||||
|
this.formData.cubierta.guardasImpresas = data.guardasImpresas;
|
||||||
|
this.formData.cubierta.cabezada = data.cabezada;
|
||||||
|
this.formData.cubierta.papelCubiertaId = data.papelCubiertaId;
|
||||||
|
this.formData.cubierta.gramajeCubierta = data.gramajeCubierta;
|
||||||
|
}
|
||||||
|
/******************************
|
||||||
|
* END CUBIERTA
|
||||||
|
******************************/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const presupuestoCliente = new PresupuestoCliente();
|
||||||
|
presupuestoCliente.init();
|
||||||
|
});
|
||||||
@ -247,7 +247,6 @@ if (document.getElementById("sa-position"))
|
|||||||
icon: 'success',
|
icon: 'success',
|
||||||
title: 'Your work has been saved',
|
title: 'Your work has been saved',
|
||||||
showConfirmButton: false,
|
showConfirmButton: false,
|
||||||
timer: 1500,
|
|
||||||
showCloseButton: true
|
showCloseButton: true
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
const head = document.head || document.getElementsByTagName("head")[0];
|
const head = document.head || document.getElementsByTagName("head")[0];
|
||||||
|
|
||||||
const scripts = [
|
const scripts = [
|
||||||
"https://cdn.jsdelivr.net/npm/toastify-js",
|
"/assets/libs/toastify-js/src/toastify.js",
|
||||||
"/assets/libs/choices.js/public/assets/scripts/choices.min.js",
|
"/assets/libs/choices.js/public/assets/scripts/choices.min.js",
|
||||||
"/assets/libs/flatpickr/flatpickr.min.js",
|
"/assets/libs/flatpickr/flatpickr.min.js",
|
||||||
"/assets/libs/feather-icons/feather.min.js" // <- AÑADIMOS feather aquí
|
"/assets/libs/feather-icons/feather.min.js" // <- AÑADIMOS feather aquí
|
||||||
|
|||||||
2
src/main/resources/static/assets/libs/jquery/jquery-3.6.0.min.js
vendored
Normal file
1
src/main/resources/static/assets/libs/select2/select2.min.css
vendored
Normal file
2
src/main/resources/static/assets/libs/select2/select2.min.js
vendored
Normal file
@ -34,8 +34,12 @@
|
|||||||
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
|
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
|
||||||
<th:block layout:fragment="pagejs">
|
<th:block layout:fragment="pagejs">
|
||||||
<div th:unless="${#authorization.expression('isAuthenticated()')}">
|
<div th:unless="${#authorization.expression('isAuthenticated()')}">
|
||||||
<script th:src="@{/assets/js/pages/imprimelibros/presupuestador/imagen-presupuesto.js}"></script>
|
<script th:src="@{/assets/js/pages/imprimelibros/presupuestador/imagen-selector.js}"></script>
|
||||||
|
<script type="module" th:src="@{/assets/js/pages/imprimelibros/presupuestador/presupuestador.js}"></script>
|
||||||
</div>
|
</div>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
window.languageBundle = /*[[${languageBundle}]]*/ {};
|
||||||
|
</script>
|
||||||
</th:block>
|
</th:block>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,13 @@
|
|||||||
<html th:lang="${#locale.language}"
|
<html th:lang="${#locale.language}" th:with="isAuth=${#authorization.expression('isAuthenticated()')}"
|
||||||
th:with="isAuth=${#authorization.expression('isAuthenticated()')}"
|
th:attrappend="data-layout=${isAuth} ? 'semibox' : 'horizontal'" data-sidebar-visibility="show" data-topbar="light"
|
||||||
th:attrappend="data-layout=${isAuth} ? 'semibox' : 'horizontal'"
|
data-sidebar="light" data-sidebar-size="lg" data-sidebar-image="none" data-preloader="disable"
|
||||||
data-sidebar-visibility="show"
|
xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||||
data-topbar="light"
|
|
||||||
data-sidebar="light"
|
|
||||||
data-sidebar-size="lg"
|
|
||||||
data-sidebar-image="none"
|
|
||||||
data-preloader="disable"
|
|
||||||
xmlns:th="http://www.thymeleaf.org"
|
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<th:block layout:fragment="pagetitle" />
|
<th:block layout:fragment="pagetitle" />
|
||||||
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
|
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
|
||||||
|
<link href="/assets/libs/sweetalert2/sweetalert2.min.css" rel="stylesheet" type="text/css" />
|
||||||
|
<link href="/assets/libs/select2/select2.min.css" rel="stylesheet" />
|
||||||
<th:block layout:fragment="pagecss" />
|
<th:block layout:fragment="pagecss" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -32,11 +27,13 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<th:block layout:fragment="modal" />
|
<th:block layout:fragment="modal" />
|
||||||
<!-- de momento comenta vendor-scripts si no lo usas -->
|
|
||||||
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
|
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="/assets/libs/jquery/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="/assets/libs/sweetalert2/sweetalert2.min.js"></script>
|
||||||
|
<script src="/assets/libs/select2/select2.min.js"></script>
|
||||||
<th:block layout:fragment="pagejs" />
|
<th:block layout:fragment="pagejs" />
|
||||||
<script th:src="@{/assets/js/app.js}"></script>
|
<script th:src="@{/assets/js/app.js}"></script>
|
||||||
|
<script th:src="@{/assets/js/pages/imprimelibros/languageBundle.js}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -0,0 +1,204 @@
|
|||||||
|
<div class="animate-fadeInUpBounce">
|
||||||
|
<div class="row justify-content-center mb-3">
|
||||||
|
<div class="col-auto">
|
||||||
|
<button type="button" id="btn-plantilla-cubierta" class="btn btn-outline-primary btn-border">
|
||||||
|
<i class="ri-questionnaire-line label-icon align-middle fs-16 me-2"></i>
|
||||||
|
<span th:text="#{presupuesto.plantilla-cubierta}">
|
||||||
|
Plantilla de cubierta
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<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="#{presupuesto.tipo-cubierta}">Tipo cubierta
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.tipo-cubierta-descripcion}">Seleccione el tipo de cubierta
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div class="row justify-content-center imagen-container-group mt-3">
|
||||||
|
<div id="tapaBlanda" class="tapa-cubierta image-container imagen-selector selected">
|
||||||
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/tapa-blanda.png"
|
||||||
|
alt="">
|
||||||
|
<label for="titulo" class="form-label" th:text="#{presupuesto.tapa-blanda}">
|
||||||
|
Tapa blanda
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="tapaDuraLomoRecto" class="tapa-cubierta image-container imagen-selector">
|
||||||
|
<img class="image-presupuesto"
|
||||||
|
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-recto.png" alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.tapa-dura}">
|
||||||
|
Tapa dura
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="tapaDuraLomoRedondo" class="tapa-cubierta image-container imagen-selector">
|
||||||
|
<img class="image-presupuesto"
|
||||||
|
src="/assets/images/imprimelibros/presupuestador/tapa-dura-lomo-redondo.png" alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.tapa-dura-lomo-redondo}">
|
||||||
|
Tapa dura lomo redondo
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center align-items-center mt-3 imagen-container-group tapa-blanda-options">
|
||||||
|
|
||||||
|
<div id="sin-solapas" class="image-container imagen-selector solapas-cubierta selected">
|
||||||
|
<img class="image-presupuesto"
|
||||||
|
src="/assets/images/imprimelibros/presupuestador/sinSolapasCubierta.png" alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.sin-solapas}">
|
||||||
|
Sin solapas
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="con-solapas" class="image-container imagen-selector solapas-cubierta">
|
||||||
|
<img class="image-presupuesto"
|
||||||
|
src="/assets/images/imprimelibros/presupuestador/conSolapasCubierta.png" alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.con-solapas}">
|
||||||
|
Con solapas
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-auto mb-3">
|
||||||
|
<label for="impresion-cubierta" class="form-label"
|
||||||
|
th:text="#{presupuesto.impresion-cubierta}">Impresión de cubierta</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<select class="form-select select2" id="impresion-cubierta">
|
||||||
|
<option value="2" th:text="#{presupuesto.una-cara}">Una cara</option>
|
||||||
|
<option value="4" th:text="#{presupuesto.dos-caras}">Dos cara</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-outline-primary btn-icon waves-effect waves-light material-shadow-none"
|
||||||
|
type="button" id="impresion-cubierta-help">
|
||||||
|
<i class="ri-questionnaire-line"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="div-solapas-cubierta" class="col-auto mb-3 d-none">
|
||||||
|
<label for="tamanio-solapas-cubierta" class="form-label"
|
||||||
|
th:text="#{presupuesto.tamanio-solapa}">Tamaño solapa</label>
|
||||||
|
<input type="number" class="form-control" id="tamanio-solapas-cubierta" value="80" step="1">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center align-items-center mt-3 imagen-container-group tapa-dura-options d-none">
|
||||||
|
|
||||||
|
<div class="col-auto mb-3">
|
||||||
|
<label for="papel-guardas" class="form-label" th:text="#{presupuesto.papel-guardas}">Papel de
|
||||||
|
guardas</label>
|
||||||
|
<select class="form-select select2" id="papel-guardas">
|
||||||
|
<option value="1" data-papel-id="3" data-gramaje="170"
|
||||||
|
th:text="#{presupuesto.offset-blanco} + ' 170 gr'" selected>Offset blanco 170 gr</option>
|
||||||
|
<option value="2" data-papel-id="4" data-gramaje="170"
|
||||||
|
th:text="#{presupuesto.offset-ahuesado} + ' 170 gr'">Offset ahuesado 170 gr</option>
|
||||||
|
<option value="3" data-papel-id="2" data-gramaje="170"
|
||||||
|
th:text="#{presupuesto.estucado-mate} + ' 170 gr'">Estucado mate 170 gr</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto mb-3">
|
||||||
|
<label for="guardas-impresas" class="form-label" th:text="#{presupuesto.guardas-impresas}">Guardas
|
||||||
|
impresas</label>
|
||||||
|
<select class="form-select select2" id="guardas-impresas">
|
||||||
|
<option value="0" th:text="#{presupuesto.no}" selected>No</option>
|
||||||
|
<option value="4" th:text="#{presupuesto.una-cara}">Una cara</option>
|
||||||
|
<option value="8" th:text="#{presupuesto.dos-caras}">Dos caras</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto mb-3">
|
||||||
|
<label for="cabezada" class="form-label" th:text="#{presupuesto.cabezada}">Cabezada</label>
|
||||||
|
<select class="form-select select2" id="guardas-impresas">
|
||||||
|
<option value="WHI" th:text="#{presupuesto.cabezada-blanca}" selected>Blanca</option>
|
||||||
|
<option value="GRE" th:text="#{presupuesto.cabezada-verde}">Verde</option>
|
||||||
|
<option value="BLUE" th:text="#{presupuesto.cabezada-azul}">Azul</option>
|
||||||
|
<option value="REDYEL" th:text="#{presupuesto.cabezada-roja-amarilla}">Roja-Amarilla</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.papel-cubierta}">Papel cubierta</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.papel-cubierta-descripcion}">
|
||||||
|
Seleccione el papel para la cubierta</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
|
<div id="div-papel-cubierta" class="row justify-content-center imagen-container-group">a
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.gramaje-cubierta}">Gramaje cubierta
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.gramaje-cubierta-descripcion}">
|
||||||
|
Gramaje del interior</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div id="div-gramaje-cubierta" class="hstack gap-2 justify-content-center flex-wrap">
|
||||||
|
<input type="radio" class="btn-check" id="gramaje-cubierta-240" name="gramaje-cubierta"
|
||||||
|
data-gramaje="240">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-cubierta-240">
|
||||||
|
240
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" id="gramaje-cubierta-250" name="gramaje-cubierta"
|
||||||
|
data-gramaje="250">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-cubierta-250">
|
||||||
|
250
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" id="gramaje-cubierta-270" name="gramaje-cubierta"
|
||||||
|
data-gramaje="270">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-cubierta-270">
|
||||||
|
270
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" id="gramaje-cubierta-300" name="gramaje-cubierta"
|
||||||
|
data-gramaje="300" checked>
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-cubierta-300">
|
||||||
|
<span class="invisible small">_</span>
|
||||||
|
300
|
||||||
|
<span class="text-warning small fw-bold">⭐</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" id="gramaje-cubierta-350" name="gramaje-cubierta"
|
||||||
|
data-gramaje="350">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-cubierta-350">
|
||||||
|
350
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||||
|
<button type="button" class="btn btn-light d-flex align-items-center">
|
||||||
|
<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>
|
||||||
|
<button type="button" class="btn btn-primary d-flex align-items-center">
|
||||||
|
<span th:text="#{presupuesto.continuar-extras-libro}">Continuar a extras del libro</span>
|
||||||
|
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<div>
|
<div id="content-datos-generales" class="animate-fadeInUpBounce">
|
||||||
<!-- Ribbon Shape -->
|
<!-- Ribbon Shape -->
|
||||||
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -9,13 +9,21 @@
|
|||||||
|
|
||||||
<div class="ribbon-content mt-4">
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
|
<div class="alert alert-danger alert-dismissible alert-label-icon rounded-label fade show material-shadow d-none"
|
||||||
|
role="alert" id="datos-generales-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="datos-generales-alert-list">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="px-2">
|
<div class="px-2">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="titulo" class="form-label" th:text="#{presupuesto.titulo}">
|
<label for="titulo" class="form-label" th:text="#{presupuesto.titulo}">
|
||||||
>Título*</label>
|
>Título*</label>
|
||||||
<input type="text" class="form-control" id="titulo" placeholder="" value="">
|
<input type="text" class="form-control datos-generales-data" id="titulo" placeholder="" value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -24,13 +32,13 @@
|
|||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="autor" class="form-label" th:text="#{presupuesto.autor}">Autor</label>
|
<label for="autor" class="form-label" th:text="#{presupuesto.autor}">Autor</label>
|
||||||
<input type="text" class="form-control" id="autor" value="">
|
<input type="text" class="form-control datos-generales-data" id="autor" value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="isbn" class="form-label" th:text="#{presupuesto.isbn}">ISBN</label>
|
<label for="isbn" class="form-label" th:text="#{presupuesto.isbn}">ISBN</label>
|
||||||
<input type="text" class="form-control" id="isbn" value="">
|
<input type="text" class="form-control datos-generales-data" id="isbn" value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -38,67 +46,87 @@
|
|||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada" class="form-label" th:text="#{presupuesto.tirada1}">Tirada 1*</label>
|
<label for="tirada1" class="form-label" th:text="#{presupuesto.tirada1}">Tirada 1*</label>
|
||||||
<input type="number" class="form-control" id="tirada" placeholder="" value="10">
|
<input type="number" class="form-control datos-generales-data" id="tirada1" placeholder="" value="10">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada2" class="form-label" th:text="#{presupuesto.tirada2}">Tirada 2</label>
|
<label for="tirada2" class="form-label" th:text="#{presupuesto.tirada2}">Tirada 2</label>
|
||||||
<input type="number" class="form-control" id="tirada" placeholder="" value="">
|
<input type="number" class="form-control datos-generales-data" id="tirada2" placeholder="" value="">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada3" class="form-label" th:text="#{presupuesto.tirada3}">Tirada 3</label>
|
<label for="tirada3" class="form-label" th:text="#{presupuesto.tirada3}">Tirada 3</label>
|
||||||
<input type="number" class="form-control" id="tirada" placeholder="" value="">
|
<input type="number" class="form-control datos-generales-data" id="tirada3" placeholder="" value="">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 mb-1">
|
<div class="col-sm-3 mb-1">
|
||||||
<label for="tirada4" class="form-label" th:text="#{presupuesto.tirada4}">Tirada 4</label>
|
<label for="tirada4" class="form-label" th:text="#{presupuesto.tirada4}">Tirada 4</label>
|
||||||
<input type="number" class="form-control" id="tirada" placeholder="" value="">
|
<input type="number" class="form-control datos-generales-data" id="tirada4" placeholder="" value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted" th:text="#{presupuesto.tiradasPODnoPOD}">
|
<p class="text-muted" th:text="#{presupuesto.tiradasPODnoPOD(${pod})}">
|
||||||
No puede mezclar tiradas menores de 30 unidades con mayores de 30
|
No puede mezclar tiradas menores de 30 unidades con mayores de 30
|
||||||
unidades</p>
|
unidades</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-8">
|
||||||
<div class="mb-3">
|
|
||||||
<label for="formato" class="form-label" th:text="#{presupuesto.formato}">Formato</label>
|
|
||||||
<select class="form-control select2" id="formato">
|
|
||||||
<optgroup th:label="#{presupuesto.orientacion.vertical}">
|
|
||||||
<option value="148x210">148x210 (A5)</option>
|
|
||||||
<option value="115x170">115x170</option>
|
|
||||||
<option value="210x297">210x297 (A4)</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup th:label="#{presupuesto.orientacion.cuadrado}">
|
|
||||||
<option value="210x210">210x210</option>
|
|
||||||
<option value="230x230">230x230</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup th:label="#{presupuesto.orientacion.apaisado}">
|
|
||||||
<option value="210x148">210x148 (A5)</option>
|
|
||||||
<option value="240x170">240x170</option>
|
|
||||||
<option value="297x210">297x210 (A4)</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</div>
|
<div class="row justify-content-center">
|
||||||
<div class="mb-3">
|
<div class="col-sm-4 mb-3 div-formato">
|
||||||
<div class="form-check form-switch form-switch-left form-switch-md">
|
<label for="formato" class="form-label" th:text="#{presupuesto.formato}">Formato</label>
|
||||||
<input type="checkbox" class="form-check-input" id="checkbox-button">
|
<select class="form-select select2 datos-generales-data" id="formato">
|
||||||
<label for="checkbox-button" class="form-label"
|
<optgroup th:label="#{presupuesto.orientacion.vertical}">
|
||||||
th:text="#{presupuesto.formato-personalizado}">Formato
|
<option data-ancho="148" data-alto="210" value="148x210">148x210 (A5)</option>
|
||||||
Personalizado</label>
|
<option data-ancho="120" data-alto="170" value="120x170">120x170</option>
|
||||||
|
<option data-ancho="210" data-alto="297" value="210x297">210x297 (A4)</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup th:label="#{presupuesto.orientacion.cuadrado}">
|
||||||
|
<option data-ancho="210" data-alto="210" value="210x210">210x210</option>
|
||||||
|
<option data-ancho="230" data-alto="230" value="230x230">230x230</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup th:label="#{presupuesto.orientacion.apaisado}">
|
||||||
|
<option data-ancho="210" data-alto="148" value="210x148">210x148 (A5)</option>
|
||||||
|
<option data-ancho="240" data-alto="170" value="240x170">240x170</option>
|
||||||
|
<option data-ancho="297" data-alto="210" value="297x210">297x210 (A4)</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center div-formato-personalizado d-none">
|
||||||
|
<div class="col-3 col-sm-3 mb-1">
|
||||||
|
<label for="ancho" class="form-label" th:text="#{presupuesto.ancho}">Ancho (mm)</label>
|
||||||
|
<input type="number" class="form-control datos-generales-data" id="ancho" name="ancho" value="210"
|
||||||
|
th:attr="min=${ancho_alto_min}, max=${ancho_alto_max}">
|
||||||
|
</div>
|
||||||
|
<div class="col-3 col-sm-3 mb-1">
|
||||||
|
<label for="alto" class="form-label" th:text="#{presupuesto.alto}">Alto (mm)</label>
|
||||||
|
<input type="number" class="form-control datos-generales-data" id="alto" name="alto" value="297"
|
||||||
|
th:attr="min=${ancho_alto_min}, max=${ancho_alto_max}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center mb-3">
|
||||||
|
<div class="col-sm-4 d-flex justify-content-center">
|
||||||
|
<div class="form-check form-switch form-switch-custom form-switch-primary mb-3">
|
||||||
|
<input type="checkbox" class="form-check-input form-switch-custom-primary datos-generales-data"
|
||||||
|
id="formato-personalizado" name="formato-personalizado">
|
||||||
|
<label for="formato-personalizado" class="form-label"
|
||||||
|
th:text="#{presupuesto.formato-personalizado}">
|
||||||
|
Formato Personalizado
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="row justify-content-center mb-2">
|
<div class="row justify-content-center mb-2">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<label for="paginas-negro" class="form-label" th:text="#{presupuesto.paginas-negro}">Páginas
|
<label for="paginas-negro" class="form-label" th:text="#{presupuesto.paginas-negro}">Páginas
|
||||||
Negro</label>
|
Negro</label>
|
||||||
<input type="number" step="2" class="form-control" id="paginas-negro" name="paginas-negro"
|
<input type="number" step="2" class="form-control paginas datos-generales-data" id="paginas-negro"
|
||||||
value="0">
|
name="paginas-negro" value="0">
|
||||||
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
||||||
Siempre deben ser pares</div>
|
Siempre deben ser pares</div>
|
||||||
</div>
|
</div>
|
||||||
@ -110,8 +138,8 @@
|
|||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<label for="paginas-color" class="form-label" th:text="#{presupuesto.paginas-color}">Páginas
|
<label for="paginas-color" class="form-label" th:text="#{presupuesto.paginas-color}">Páginas
|
||||||
Color</label>
|
Color</label>
|
||||||
<input type="number" step="2" class="form-control" id="paginas-color" name="paginas-color"
|
<input type="number" step="2" class="form-control paginas datos-generales-data" id="paginas-color"
|
||||||
value="32">
|
name="paginas-color" value="32">
|
||||||
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
<div class="form-text" th:text="#{presupuesto.siempre-pares}">
|
||||||
Siempre deben ser pares</div>
|
Siempre deben ser pares</div>
|
||||||
</div>
|
</div>
|
||||||
@ -126,6 +154,21 @@
|
|||||||
<input disabled class="form-control" id="paginas" name="paginas" value="32">
|
<input disabled class="form-control" id="paginas" name="paginas" value="32">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="div-posicion-paginas-color" class="row justify-content-center">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<label for="posicionPaginasColor" class="form-label" th:text="#{presupuesto.paginas-posicion}">
|
||||||
|
Posición páginas color
|
||||||
|
</label>
|
||||||
|
<input class="form-control datos-generales-data" id="posicionPaginasColor" value="">
|
||||||
|
<div class="form-text">
|
||||||
|
<p th:text="#{presupuesto.paginas-posicion-descripcion}">
|
||||||
|
Intruzca la posición separada por comas. Ej: 3,5,7 ó 4-10,20,155
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -143,61 +186,64 @@
|
|||||||
<div class="ribbon-content mt-4">
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
<div class="px-2">
|
<div class="px-2">
|
||||||
<div class="row justify-content-center imagen-container-group">
|
<div class="d-flex flex-wrap justify-content-center gap-3 imagen-container-group">
|
||||||
|
|
||||||
<!-- Opción: Fresado -->
|
<!-- Opción: Fresado -->
|
||||||
<div class="col-12 col-sm-6 col-md-4 d-flex justify-content-center mb-4 selected">
|
<div class="tipo-libro image-container imagen-selector selected datos-generales-data" id="fresado">
|
||||||
<div class="image-container imagen-selector" id="fresado">
|
<input type="radio" name="tipoEncuadernacion" value="fresado" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/fresado.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/fresado.png"
|
||||||
alt="Fresado" />
|
alt="Fresado" />
|
||||||
<div class="form-text text-center">Fresado (a partir de 32 páginas)</div>
|
<div class="form-text text-center" th:text="#{presupuesto.fresado-descripcion}">
|
||||||
</div>
|
Fresado (a partir de 32 páginas)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Opción: Cosido -->
|
<!-- Opción: Cosido -->
|
||||||
<div class="col-12 col-sm-6 col-md-4 d-flex justify-content-center mb-4">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="cosido">
|
||||||
<div class="image-container imagen-selector" id="cosido">
|
<input type="radio" name="tipoEncuadernacion" value="cosido" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/cosido.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/cosido.png"
|
||||||
alt="Cosido" />
|
alt="Cosido" />
|
||||||
<div class="form-text text-center">Cosido (a partir de 32 páginas)</div>
|
<div class="form-text text-center" th:text="#{presupuesto.cosido-descripcion}">
|
||||||
</div>
|
Cosido (a partir de 32 páginas)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Opción: Grapado -->
|
<!-- Opción: Grapado -->
|
||||||
<div class="col-12 col-sm-6 col-md-4 d-flex justify-content-center mb-4">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="grapado">
|
||||||
<div class="image-container imagen-selector" id="grapado">
|
<input type="radio" name="tipoEncuadernacion" value="grapado" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/grapado.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/grapado.png"
|
||||||
alt="Grapado" />
|
alt="Grapado" />
|
||||||
<div class="form-text text-center">Grapado (entre 12 y 40 páginas)</div>
|
<div class="form-text text-center" th:text="#{presupuesto.grapado-descripcion}">
|
||||||
</div>
|
Grapado (entre 12 y 40 páginas)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Opción: Espiral -->
|
<!-- Opción: Espiral -->
|
||||||
<div class="col-12 col-sm-6 col-md-4 d-flex justify-content-center mb-4">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="espiral">
|
||||||
<div class="image-container imagen-selector" id="espiral">
|
<input type="radio" name="tipoEncuadernacion" value="espiral" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/espiral.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/espiral.png"
|
||||||
alt="Espiral" />
|
alt="Espiral" />
|
||||||
<div class="form-text text-center">Espiral (a partir de 20 páginas)</div>
|
<div class="form-text text-center" th:text="#{presupuesto.espiral-descripcion}">
|
||||||
</div>
|
Espiral (a partir de 20 páginas)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Opción: Wire-O -->
|
<!-- Opción: Wire-O -->
|
||||||
<div class="col-12 col-sm-6 col-md-4 d-flex justify-content-center mb-4">
|
<div class="tipo-libro image-container imagen-selector datos-generales-data" id="wireo">
|
||||||
<div class="image-container imagen-selector" id="wireo">
|
<input type="radio" name="tipoEncuadernacion" value="wireo" hidden>
|
||||||
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/wire-o.png"
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/wire-o.png"
|
||||||
alt="Wire-O" />
|
alt="Wire-O" />
|
||||||
<div class="form-text text-center">Wire-O (a partir de 20 páginas)</div>
|
<div class="form-text text-center" th:text="#{presupuesto.wire-o-descripcion}">
|
||||||
</div>
|
Wire-O (a partir de 20 páginas)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="d-flex align-items-start gap-3 mt-3">
|
<div class="d-flex align-items-center justify-content-center gap-3 mt-3">
|
||||||
<button type="button" id="next-datos-generales" class="btn btn-primary btn-label right ms-auto">
|
<button type="button" id="next-datos-generales" class="btn btn-primary d-flex align-items-center ms-auto">
|
||||||
<i class="ri-arrow-right-circle-line align-middle fs-16 ms-2"></i>
|
<span th:text="#{presupuesto.continuar-interior}">Continuar a diseño interior</span>
|
||||||
<label th:text="#{presupuesto.siguiente}">Siguiente</label>
|
<i class="ri-arrow-right-circle-line fs-16 ms-2"></i>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
<div id="content-interior" class="animate-fadeInUpBounce">
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<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="#{presupuesto.tipo-encuadernacion}">Tipo de impresión
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.tipo-encuadernacion-descripcion}">Elija entre calidad estándar
|
||||||
|
o premium</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div class="alert alert-danger alert-dismissible alert-label-icon rounded-label fade show material-shadow d-none"
|
||||||
|
role="alert" id="inside-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="inside-alert-list">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="div-opciones-color" class="row justify-content-center imagen-container-group">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- End Ribbon Shape -->
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.papel-interior}">Papel interior</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.papel-interior-descripcion}">
|
||||||
|
Papel y gramaje del interior</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
|
||||||
|
<div id="div-papel-interior" class="row justify-content-center imagen-container-group">
|
||||||
|
|
||||||
|
<div id="offset-blanco" data-sk-id="3" class="image-container imagen-selector selected">
|
||||||
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/offset-blanco.png"
|
||||||
|
alt="">
|
||||||
|
<label for="titulo" class="form-label" th:text="#{presupuesto.offset-blanco}">
|
||||||
|
Offset Blanco
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="offset-ahuesado" data-sk-id="4" class="image-container imagen-selector">
|
||||||
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/offset-ahuesado.png"
|
||||||
|
alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.offset-ahuesado}">
|
||||||
|
Offset Ahuesado
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="offset-ahuesado-volumen" data-sk-id="6" class="image-container imagen-selector">
|
||||||
|
<img class="image-presupuesto"
|
||||||
|
src="/assets/images/imprimelibros/presupuestador/offset-ahuesado-volumen.png" alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.offset-ahuesado-volumen}">
|
||||||
|
Offset Ahuesado Volumen
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="estucado-mate" data-sk-id="2" class="image-container imagen-selector">
|
||||||
|
<img class="image-presupuesto" src="/assets/images/imprimelibros/presupuestador/estucado-mate.png"
|
||||||
|
alt="">
|
||||||
|
<label class="form-label" th:text="#{presupuesto.estucado-mate}">
|
||||||
|
Estucado Mate
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Ribbon Shape -->
|
||||||
|
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow mt-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.gramaje-interior}">Gramaje interior
|
||||||
|
</div>
|
||||||
|
<h5 class="fs-14 text-end" th:text="#{presupuesto.gramaje-interior-descripcion}">
|
||||||
|
Gramaje del interior</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ribbon-content mt-4">
|
||||||
|
<div id="div-gramaje-interior" class="hstack gap-2 justify-content-center flex-wrap">
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="70" id="gramaje-70" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-70">70</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="80" id="gramaje-80" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-80">80</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="90" id="gramaje-90" checked name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-90">90</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="100" id="gramaje-100" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-100">100</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="115" id="gramaje-115" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-115">115</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="120" id="gramaje-120" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-120">120</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="135" id="gramaje-135" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-135">135</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="150" id="gramaje-150" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-150">150</label>
|
||||||
|
|
||||||
|
<input type="radio" class="btn-check" data-gramaje="170" id="gramaje-170" name="gramaje-interior">
|
||||||
|
<label class="btn btn-outline-primary material-shadow gramaje-radio" for="gramaje-170">170</label>
|
||||||
|
</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">
|
||||||
|
<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-primary d-flex align-items-center">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
data-bs-toggle="pill" data-bs-target="#pills-general-data" type="button"
|
data-bs-toggle="pill" data-bs-target="#pills-general-data" type="button"
|
||||||
role="tab" aria-controls="pills-general-data" aria-selected="true">
|
role="tab" aria-controls="pills-general-data" aria-selected="true">
|
||||||
<i
|
<i
|
||||||
class="ri-information-fill fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
class="ri-information-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
<label th:text="#{presupuesto.datos-generales}">Datos Generales</label>
|
<label th:text="#{presupuesto.datos-generales}">Datos Generales</label>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
@ -40,8 +40,8 @@
|
|||||||
data-bs-target="#pills-shipping" type="button" role="tab"
|
data-bs-target="#pills-shipping" type="button" role="tab"
|
||||||
aria-controls="pills-shipping" aria-selected="false">
|
aria-controls="pills-shipping" aria-selected="false">
|
||||||
<i
|
<i
|
||||||
class="ri-truck-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
class="ri-add-box-line fs-16 p-2 bg-soft-primary text-primary rounded-circle align-middle me-2"></i>
|
||||||
<label th:text="#{presupuesto.envio}">Envío</label>
|
<label th:text="#{presupuesto.extras}">Extras</label>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -52,262 +52,24 @@
|
|||||||
aria-labelledby="pills-general-data-tab">
|
aria-labelledby="pills-general-data-tab">
|
||||||
|
|
||||||
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_datos-generales.html}"></div>
|
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_datos-generales.html}"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab pane -->
|
<!-- end tab pane -->
|
||||||
|
|
||||||
<div class="tab-pane fade" id="pills-bill-address" role="tabpanel"
|
<div class="tab-pane fade" id="pills-inside" role="tabpanel"
|
||||||
aria-labelledby="pills-bill-address-tab">
|
aria-labelledby="pills-inside-tab">
|
||||||
<div>
|
|
||||||
<h5 class="mb-1">Shipping Information</h5>
|
|
||||||
<p class="text-muted mb-4">Please fill all information below</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4">
|
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_interior.html}"></div>
|
||||||
<div class="d-flex align-items-center mb-2">
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<h5 class="fs-14 mb-0">Saved Address</h5>
|
|
||||||
</div>
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<!-- Button trigger modal -->
|
|
||||||
<button type="button" class="btn btn-sm btn-info mb-3"
|
|
||||||
data-bs-toggle="modal" data-bs-target="#addAddressModal">
|
|
||||||
Add Address
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row gy-3">
|
|
||||||
<div class="col-lg-4 col-sm-6">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="shippingAddress01" name="shippingAddress" type="radio"
|
|
||||||
class="form-check-input" checked>
|
|
||||||
<label class="form-check-label" for="shippingAddress01">
|
|
||||||
<span
|
|
||||||
class="mb-4 fw-semibold d-block text-muted text-uppercase">Home
|
|
||||||
Address</span>
|
|
||||||
|
|
||||||
<span class="fs-14 mb-2 d-block">Marcus Alfaro</span>
|
|
||||||
<span class="text-muted fw-normal text-wrap mb-1 d-block">4739
|
|
||||||
Bubby Drive Austin, TX 78729</span>
|
|
||||||
<span class="text-muted fw-normal d-block">Mo.
|
|
||||||
012-345-6789</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex flex-wrap p-2 py-1 bg-light rounded-bottom border mt-n1">
|
|
||||||
<div>
|
|
||||||
<a href="#" class="d-block text-body p-1 px-2"
|
|
||||||
data-bs-toggle="modal" data-bs-target="#addAddressModal"><i
|
|
||||||
class="ri-pencil-fill text-muted align-bottom me-1"></i>
|
|
||||||
Edit</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="#" class="d-block text-body p-1 px-2"
|
|
||||||
data-bs-toggle="modal" data-bs-target="#removeItemModal"><i
|
|
||||||
class="ri-delete-bin-fill text-muted align-bottom me-1"></i>
|
|
||||||
Remove</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4 col-sm-6">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="shippingAddress02" name="shippingAddress" type="radio"
|
|
||||||
class="form-check-input">
|
|
||||||
<label class="form-check-label" for="shippingAddress02">
|
|
||||||
<span
|
|
||||||
class="mb-4 fw-semibold d-block text-muted text-uppercase">Office
|
|
||||||
Address</span>
|
|
||||||
|
|
||||||
<span class="fs-14 mb-2 d-block">James Honda</span>
|
|
||||||
<span class="text-muted fw-normal text-wrap mb-1 d-block">1246
|
|
||||||
Virgil Street Pensacola, FL 32501</span>
|
|
||||||
<span class="text-muted fw-normal d-block">Mo.
|
|
||||||
012-345-6789</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex flex-wrap p-2 py-1 bg-light rounded-bottom border mt-n1">
|
|
||||||
<div>
|
|
||||||
<a href="#" class="d-block text-body p-1 px-2"
|
|
||||||
data-bs-toggle="modal" data-bs-target="#addAddressModal"><i
|
|
||||||
class="ri-pencil-fill text-muted align-bottom me-1"></i>
|
|
||||||
Edit</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="#" class="d-block text-body p-1 px-2"
|
|
||||||
data-bs-toggle="modal" data-bs-target="#removeItemModal"><i
|
|
||||||
class="ri-delete-bin-fill text-muted align-bottom me-1"></i>
|
|
||||||
Remove</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4">
|
|
||||||
<h5 class="fs-14 mb-3">Shipping Method</h5>
|
|
||||||
|
|
||||||
<div class="row g-4">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="shippingMethod01" name="shippingMethod" type="radio"
|
|
||||||
class="form-check-input" checked>
|
|
||||||
<label class="form-check-label" for="shippingMethod01">
|
|
||||||
<span
|
|
||||||
class="fs-20 float-end mt-2 text-wrap d-block fw-semibold">Free</span>
|
|
||||||
<span class="fs-14 mb-1 text-wrap d-block">Free
|
|
||||||
Delivery</span>
|
|
||||||
<span class="text-muted fw-normal text-wrap d-block">Expected
|
|
||||||
Delivery 3 to 5 Days</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="shippingMethod02" name="shippingMethod" type="radio"
|
|
||||||
class="form-check-input" checked>
|
|
||||||
<label class="form-check-label" for="shippingMethod02">
|
|
||||||
<span
|
|
||||||
class="fs-20 float-end mt-2 text-wrap d-block fw-semibold">$24.99</span>
|
|
||||||
<span class="fs-14 mb-1 text-wrap d-block">Express
|
|
||||||
Delivery</span>
|
|
||||||
<span class="text-muted fw-normal text-wrap d-block">Delivery
|
|
||||||
within 24hrs.</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-flex align-items-start gap-3 mt-4">
|
|
||||||
<button type="button" class="btn btn-light btn-label previestab"
|
|
||||||
data-previous="pills-bill-info-tab"><i
|
|
||||||
class="ri-arrow-left-line label-icon align-middle fs-16 me-2"></i>Back
|
|
||||||
to Personal Info</button>
|
|
||||||
<button type="button" class="btn btn-primary btn-label right ms-auto nexttab"
|
|
||||||
data-nexttab="pills-payment-tab"><i
|
|
||||||
class="ri-bank-card-line label-icon align-middle fs-16 ms-2"></i>Continue
|
|
||||||
to Payment</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab pane -->
|
<!-- end tab pane -->
|
||||||
|
|
||||||
<div class="tab-pane fade" id="pills-payment" role="tabpanel"
|
<div class="tab-pane fade" id="pills-cover" role="tabpanel"
|
||||||
aria-labelledby="pills-payment-tab">
|
aria-labelledby="pills-cover-tab">
|
||||||
<div>
|
|
||||||
<h5 class="mb-1">Payment Selection</h5>
|
|
||||||
<p class="text-muted mb-4">Please select and enter your billing information</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row g-4">
|
<div th:include="~{imprimelibros/presupuestos/presupuestador-items/_cubierta.html}"></div>
|
||||||
<div class="col-lg-4 col-sm-6">
|
|
||||||
<div data-bs-toggle="collapse" data-bs-target="#paymentmethodCollapse.show"
|
|
||||||
aria-expanded="false" aria-controls="paymentmethodCollapse">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="paymentMethod01" name="paymentMethod" type="radio"
|
|
||||||
class="form-check-input">
|
|
||||||
<label class="form-check-label" for="paymentMethod01">
|
|
||||||
<span class="fs-16 text-muted me-2"><i
|
|
||||||
class="ri-paypal-fill align-bottom"></i></span>
|
|
||||||
<span class="fs-14 text-wrap">Paypal</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4 col-sm-6">
|
|
||||||
<div data-bs-toggle="collapse" data-bs-target="#paymentmethodCollapse"
|
|
||||||
aria-expanded="true" aria-controls="paymentmethodCollapse">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="paymentMethod02" name="paymentMethod" type="radio"
|
|
||||||
class="form-check-input" checked>
|
|
||||||
<label class="form-check-label" for="paymentMethod02">
|
|
||||||
<span class="fs-16 text-muted me-2"><i
|
|
||||||
class="ri-bank-card-fill align-bottom"></i></span>
|
|
||||||
<span class="fs-14 text-wrap">Credit / Debit Card</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-4 col-sm-6">
|
|
||||||
<div data-bs-toggle="collapse" data-bs-target="#paymentmethodCollapse.show"
|
|
||||||
aria-expanded="false" aria-controls="paymentmethodCollapse">
|
|
||||||
<div class="form-check card-radio">
|
|
||||||
<input id="paymentMethod03" name="paymentMethod" type="radio"
|
|
||||||
class="form-check-input">
|
|
||||||
<label class="form-check-label" for="paymentMethod03">
|
|
||||||
<span class="fs-16 text-muted me-2"><i
|
|
||||||
class="ri-money-dollar-box-fill align-bottom"></i></span>
|
|
||||||
<span class="fs-14 text-wrap">Cash on Delivery</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="collapse show" id="paymentmethodCollapse">
|
|
||||||
<div class="card p-4 border shadow-none mb-0 mt-4">
|
|
||||||
<div class="row gy-3">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<label for="cc-name" class="form-label">Name on card</label>
|
|
||||||
<input type="text" class="form-control" id="cc-name"
|
|
||||||
placeholder="Enter name">
|
|
||||||
<small class="text-muted">Full name as displayed on card</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label for="cc-number" class="form-label">Credit card number</label>
|
|
||||||
<input type="text" class="form-control" id="cc-number"
|
|
||||||
placeholder="xxxx xxxx xxxx xxxx">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label for="cc-expiration" class="form-label">Expiration</label>
|
|
||||||
<input type="text" class="form-control" id="cc-expiration"
|
|
||||||
placeholder="MM/YY">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-3">
|
|
||||||
<label for="cc-cvv" class="form-label">CVV</label>
|
|
||||||
<input type="text" class="form-control" id="cc-cvv" placeholder="xxx">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="text-muted mt-2 fst-italic">
|
|
||||||
<i data-feather="lock" class="text-muted icon-xs"></i> Your transaction is
|
|
||||||
secured with SSL encryption
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-flex align-items-start gap-3 mt-4">
|
|
||||||
<button type="button" class="btn btn-light btn-label previestab"
|
|
||||||
data-previous="pills-bill-address-tab"><i
|
|
||||||
class="ri-arrow-left-line label-icon align-middle fs-16 me-2"></i>Back
|
|
||||||
to Shipping</button>
|
|
||||||
<button type="button" class="btn btn-secondary btn-label right ms-auto nexttab"
|
|
||||||
data-nexttab="pills-finish-tab"><i
|
|
||||||
class="ri-shopping-basket-line label-icon align-middle fs-16 ms-2"></i>Complete
|
|
||||||
Order</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab pane -->
|
<!-- end tab pane -->
|
||||||
|
|
||||||
<div class="tab-pane fade" id="pills-finish" role="tabpanel"
|
|
||||||
aria-labelledby="pills-finish-tab">
|
|
||||||
<div class="text-center py-5">
|
|
||||||
|
|
||||||
<div class="mb-4">
|
|
||||||
<lord-icon src="https://cdn.lordicon.com/lupuorrc.json" trigger="loop"
|
|
||||||
colors="primary:#0ab39c,secondary:#405189"
|
|
||||||
style="width:120px;height:120px"></lord-icon>
|
|
||||||
</div>
|
|
||||||
<h5>Thank you ! Your Order is Completed !</h5>
|
|
||||||
<p class="text-muted">You will receive an order confirmation email with details
|
|
||||||
of your order.</p>
|
|
||||||
|
|
||||||
<h5 class="fw-semibold">Order ID: <a href="/apps-ecommerce-order-details"
|
|
||||||
class="text-decoration-underline">VZ2451</a></h5>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- end tab pane -->
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end tab content -->
|
<!-- end tab content -->
|
||||||
</form>
|
</form>
|
||||||
@ -318,6 +80,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- end col -->
|
<!-- end col -->
|
||||||
|
|
||||||
|
<!-- Order Summary -->
|
||||||
<div class="col-xl-4">
|
<div class="col-xl-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
|||||||