From c40a0ae55fe35b101def424766a717ec27528bf7 Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 13 Feb 2026 02:53:00 +0100 Subject: [PATCH] . --- src/lib/cmps/BtDownload.svelte | 25 ++++---- src/lib/cmps/PoDownload.svelte | 101 +++++++++++++++++++++++++-------- src/lib/data/DataConfig.ts | 10 ++-- src/lib/data/DataIconsB64.ts | 12 ++++ 4 files changed, 110 insertions(+), 38 deletions(-) create mode 100644 src/lib/data/DataIconsB64.ts diff --git a/src/lib/cmps/BtDownload.svelte b/src/lib/cmps/BtDownload.svelte index 96596e1..59bae94 100644 --- a/src/lib/cmps/BtDownload.svelte +++ b/src/lib/cmps/BtDownload.svelte @@ -272,28 +272,33 @@ const priceWidth = priceStr ? pdfDoc.getTextWidth(priceStr) : 0; // Si label es demasiado largo, recortamos con splitTextToSize y dibujamos en varias líneas + const lineHeight = fontSize * 0.45; // controla aquí el espaciado fino + if (labelWidth + priceWidth + 6 > maxWidth) { - // dividir label en líneas que dejen espacio para precio en la última línea + const availableForLabel = maxWidth - (priceWidth ? priceWidth + 6 : 0); const labelLines = pdfDoc.splitTextToSize(label, availableForLabel); - for (let i = 0; i < labelLines.length; i++) { - const line = labelLines[i]; - const lineY = y + i * (fontSize * 0.6 + 2); - pdfDoc.text(line, x, lineY); - // si es la última línea y hay precio, pintarlo a la derecha + + labelLines.forEach((line: string, i:number) => { + const lineY = y + i * lineHeight; + pdfDoc.text(line, x + iconWidth, lineY); if (i === labelLines.length - 1 && priceStr) { if (priceColor) pdfDoc.setTextColor(priceColor.r, priceColor.g, priceColor.b); - if (priceFont && priceFontSize) pdfDoc.setFont(priceFont, "normal"), pdfDoc.setFontSize(priceFontSize); + if (priceFont && priceFontSize) { + pdfDoc.setFont(priceFont, "normal"); + pdfDoc.setFontSize(priceFontSize); + } + pdfDoc.text(priceStr, x + maxWidth - priceWidth, lineY); - // reset font/color pdfDoc.setFont(font, "normal"); pdfDoc.setFontSize(fontSize); pdfDoc.setTextColor(0, 0, 0); } - } - return y + labelLines.length * (fontSize * 0.6 + 2); + }); + + return y + labelLines.length * lineHeight; } else { // etiqueta en una línea y precio alineado a la derecha si existe pdfDoc.text(label, x+iconWidth, y); diff --git a/src/lib/cmps/PoDownload.svelte b/src/lib/cmps/PoDownload.svelte index c4b4acb..1787aca 100644 --- a/src/lib/cmps/PoDownload.svelte +++ b/src/lib/cmps/PoDownload.svelte @@ -1,5 +1,3 @@ - - {#if isVisible} @@ -46,7 +55,7 @@
@@ -61,28 +70,74 @@
- - {#if downloadState !== 'error' && downloadState !== 'idle' } + + {#if showSelector} +
+
+ + +
+ + +
+ + +
+
+ + {:else if downloadState !== 'error'}
{#if showSpin} -
{/if}
-
+
{stateText}
+ {:else} -
- ❌ Error al generar PDF +
+
+ ❌ Error al generar PDF +
+

{message}

+
-

{message}

{/if}
diff --git a/src/lib/data/DataConfig.ts b/src/lib/data/DataConfig.ts index bc0f085..982c900 100644 --- a/src/lib/data/DataConfig.ts +++ b/src/lib/data/DataConfig.ts @@ -322,7 +322,7 @@ export const dataConfig : DataConfig = { salon: { id: 'salon', name: 'Salón', - text: '', + text: 'Arquitectura que respira y se adapta a tu estilo. Disfruta de un salón bañado por la luz natural gracias a sus amplios ventanales, donde el diseño de vanguardia se une al confort absoluto del suelo radiante-refrescante y el control inteligente de tu hogar mediante domótica avanzada', help: '', options: [], hotspots: [ @@ -339,7 +339,7 @@ export const dataConfig : DataConfig = { bano1: { id: 'bano1', name: 'Baño principal', - text: '', + text: 'Un santuario privado diseñado para el relax sensorial. Con texturas que abrazan y acabados de alta gama, el baño principal incluye detalles de excelencia como su espejo retroiluminado antivaho y columna termostática, garantizando una experiencia de bienestar única cada día', help: '', options: [ // Grupo @@ -416,7 +416,7 @@ export const dataConfig : DataConfig = { bano2: { id: 'bano2', name: 'Baño secundario', - text: '', + text: 'Elegancia y versatilidad para el día a día de toda la familia. Equipado con materiales resistentes de primera calidad, bañera y mampara incluida, este espacio refleja el equilibrio ideal entre durabilidad y diseño que define a OPEN-BOX', help: '', options: [ // Grupo @@ -479,7 +479,7 @@ export const dataConfig : DataConfig = { aseo: { id: 'aseo', name: 'Aseo', - text: '', + text: 'Incluso los espacios más pequeños reflejan la identidad icónica del proyecto. Un aseo de cortesía con líneas limpias y sanitarios de cerámica vitrificada, pensado para impresionar a tus invitados con la sofisticación y el cuidado por el detalle de Ebrosa', help: '', options: [ // Grupo @@ -530,7 +530,7 @@ export const dataConfig : DataConfig = { cocina: { id: 'cocina', name: 'Cocina', - text: '', + text: 'Donde la tecnología y la estética se alían en perfecta armonía. Tu cocina se entrega totalmente equipada con electrodomésticos de última generación y elegantes encimeras porcelánicas, creando un espacio funcional y moderno diseñado para perdurar', help: '', options: [ // Grupo diff --git a/src/lib/data/DataIconsB64.ts b/src/lib/data/DataIconsB64.ts new file mode 100644 index 0000000..46e6b2d --- /dev/null +++ b/src/lib/data/DataIconsB64.ts @@ -0,0 +1,12 @@ + + + + + + +// Imágenes generadas automáticamente + +export const precaucionIconB64 = "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAByUlEQVR4nOxVu4sTQRj/fZMzuUviwXnnq7hCuUY8Ym0364OgMRGUkN5XESwNNoKoKAoBtfZP0MoiCBamswo2ATGNhYUa8n6sMbr7SUYjCftMMIVwPxh29pv5PWZ2hhVYMHYMPLHkd+Kn4+mVSFDPj/r9YfjG5tvn3/6pQTQ0uMeg7KgfCek6gJwfHvmZ1JapLQNmGUBIFRhDQ4jY3jcvP3hxfX0DA/zkr/jvWMEAm3k/XM8V1GTilAC9Vmn2b6ia+bWmngzzzHqx8GpuA5ZyqYnoOwDbo/fVZ49UvXP15njK+7Xu52NUKv1w0nDdohYi18fiKk14WbUJHGntPph103A0aMfjexh0y40MtU243ZHJjZkNjO+77gNY9zIAsPaTcHcmg7qWPArgiiVttw/u9KwE5muNk6mYnZbtRRNsPmaQZaybe+AUNABDHeUTniuoa8mLDDptq3J4UzV7sNbUEhdcDTidDhLzQ6eY4csZrFzKOA2DmfIfpZw6ZlPb0Kjq54loy0mgd+epo/gfHFpF9ByAF7YGQlCFGQMAy3Zss970MhhQQFQmC5abXJVnDwjQtpeSbQBweV+x8GUe7tz4/3+ZCzf4FQAA//8XSHr/N7SpsQAAAABJRU5ErkJggg==" + +export const advertenciaIconB64 = "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABlUlEQVR4nOyVvWtTURjGf+feEOONix9DwEkIiB/EQcE5omCIIKg4OYqDOOomCIpbof07QjukTSDQoXOXtkNKaZZOpe3WoUnTpslb7hfNx7m594ZmKPSBAznvOe/ze/Oec7gGU9Y1IFSJqBulxE0sZpxJi5/qM8eXCsDiH/Dd+90CfkVJU1E2SZksJnXghhc6xSSnCmyH5UY7A5O5PnNbSc68doUo9B9IhdfAsjNJ3XeD7V0/u6CK1CYGyAoJmqwDT+1596XrZa6+9bdskeGZekEnyGN8i5r88M1d51vuuNAj9ryDjwuQGneA32MLwOnBH1niXmwAXf4Dd0MBcBvF31gAWeQJwteRYjuHztDom5TJ6Rb0D81gVrdmbHwJKtT0rvKrUavh6qt8BN7oXCT90BkBykuFD8PBgWsqJZJYbAJZnUPv+QKIYKx9CoLskOaxytP2A4NtsHgfZG7LqI+9kbYecMQ7YF4PEBooh57Spp8chAHa9Gj0B0ZeslTJIH2PK44UdVVkf6LcSXX1P5lTB5wHAAD//0kDVOGS5cmMAAAAAElFTkSuQmCC" +