+ import { fade, scale } from 'svelte/transition';
+ import type {DownloadState} from "../data/DownloadTypes";
+ import {cubicOut} from "svelte/easing";
+
+ let {
+ downloadState,
+ isVisible ,
+ message,
+ logoProject,
+ logoCompany,
+ text,
+ } = $props< {
+ downloadState: DownloadState;
+ isVisible : boolean;
+ message : string ;
+ logoProject : string ;
+ logoCompany? : string ;
+ text : string
+ }> ();
+
+
+ let stateText = $derived (
+ downloadState === 'creating' ? 'Creando documento PDF' :
+ downloadState === 'downloading' ? 'Descargando documento' :
+ downloadState === 'success' ? '✅ PDF Generado correctamente' :
+ ''
+ );
+
+ let showSpin = $derived (
+ downloadState === 'creating' || downloadState === 'downloading'
+ );
+
+
+
+
+
+{#if isVisible}
+
+
+
+
+
+
+ {#if logoCompany}
+

+ {/if}
+
+

+
+
+ {text}
+
+
+
+
+ {#if downloadState !== 'error' && downloadState !== 'idle' }
+
+
+
+
+ {#if showSpin}
+
+ {/if}
+
+
+
+ {stateText}
+
+
+
+ {:else}
+
+ ❌ Error al generar PDF
+
+
{message}
+ {/if}
+
+
+{/if}
\ No newline at end of file
diff --git a/src/lib/cmps/pnView.svelte b/src/lib/cmps/pnView.svelte
new file mode 100644
index 0000000..e029bcf
--- /dev/null
+++ b/src/lib/cmps/pnView.svelte
@@ -0,0 +1,170 @@
+
+
+
e.key === 'Enter' && handleClick()}
+>
+
+
+
+

+
+
+ {#if hasWarnings}
+
+ ⚠️ Revisar
+
+ {/if}
+
+
+
+
+
+ {view.name || view.id}
+
+
+
+
+
+ {#if view.options.length > 0}
+ {#each view.options as group}
+ {@const currentOptionId = appState.getCurrentOption(view.id, group.id)}
+ {@const optionValue = currentOptionId ? appState.getOptionValue(currentOptionId) : null}
+ {@const requiresConsult = currentOptionId ? appState.requiresConsultation(view.id, group.id, currentOptionId) : { required: false }}
+
+
+
+ {group.name || group.id}
+
+
+
+ {optionValue?.name || currentOptionId || 'No seleccionado'}
+
+ {#if requiresConsult.required}
+ ⚠️
+ {/if}
+
+
+ {/each}
+ {:else}
+
+
Sin opciones específicas
+
+ {/if}
+
+
+
+ {#if total > 0}
+
+
+
+ Extras:
+
+ {formatearPrecio(total)}
+
+
+
+
+ {/if}
+
+
+
\ No newline at end of file
diff --git a/src/lib/data/DataConfig.ts b/src/lib/data/DataConfig.ts
index 8268253..5b0d1fc 100644
--- a/src/lib/data/DataConfig.ts
+++ b/src/lib/data/DataConfig.ts
@@ -9,7 +9,7 @@ export const dataConfig : DataConfig = {
// sources: directorios de los diferentes elementos: imágenes, textos, etc
sources: {
// logos: Directorio donde se ubican los logos del proyecto
- logos : '',
+ logos : './img/lg/',
// images
images : './img/',
// imgViewsHi: Directorio donde residen las imágenes de las vistas de
@@ -50,6 +50,12 @@ export const dataConfig : DataConfig = {
home : 'edificio_openbox.jpeg',
},
+ logos : {
+ company : 'logo_ebrosa_living.png',
+ project : 'logo_openbox.png',
+ },
+
+
gallery: [
{ img: '1.jpg', thumb:'1.jpg' },
{ img: '2.jpg', thumb:'2.jpg' },
@@ -200,7 +206,7 @@ export const dataConfig : DataConfig = {
name : 'Muebles altos negros y muebles bajos arena fina',
text : '',
image : 'muebles/mnaf.jpg',
- thumb : './img/mt/mnaf_thumb.png',
+ thumb : 'mnaf_thumb.png',
},
mvaf: {
value : 'mvaf',
diff --git a/src/lib/data/DataConfigTypes.ts b/src/lib/data/DataConfigTypes.ts
index 765703f..80be8df 100644
--- a/src/lib/data/DataConfigTypes.ts
+++ b/src/lib/data/DataConfigTypes.ts
@@ -87,6 +87,7 @@ export interface DataConfig {
texts: Record
;
images: Record;
+ logos : Record;
gallery: ImageGallery[];
options: {
diff --git a/src/lib/data/DownloadTypes.ts b/src/lib/data/DownloadTypes.ts
new file mode 100644
index 0000000..8447d15
--- /dev/null
+++ b/src/lib/data/DownloadTypes.ts
@@ -0,0 +1,3 @@
+// DownloadTypes.ts
+
+export type DownloadState = 'idle' | 'creating' | 'downloading' | 'success' | 'error'
\ No newline at end of file
diff --git a/src/lib/views/VwSelection.svelte b/src/lib/views/VwSelection.svelte
index bc16b1b..4a292ef 100644
--- a/src/lib/views/VwSelection.svelte
+++ b/src/lib/views/VwSelection.svelte
@@ -1,7 +1,270 @@
+
+
+
+
+
+
+
+
Resumen de Configuración
+
Revisa y modifica tu selección de acabados
+
+
+
+
+
+
+
+ {#each appState.getAllViews() as view}
+
+ {/each}
+
+
+ {#if hasIncidencias}
+
+
+
+
+ ⚠️
+ Opciones que requieren consulta
+
+
+ {#each Object.entries(incidencias) as [viewId, listaInc]}
+
handleViewClick(viewId)}
+ onkeydown={(e) => e.key === 'Enter' && handleViewClick(viewId)}
+ >
+
+ {listaInc[0].viewName}
+
+ {listaInc.length} {listaInc.length === 1 ? 'opción' : 'opciones'}
+
+
+
+
+ {#each listaInc as inc}
+
+
+ {inc.groupName}: {inc.optionName}
+
+
{inc.mensaje}
+
+ {/each}
+
+
+ {/each}
+
+
+
+ {/if}
+
+
+ {#if totalGeneral > 0}
+
+
+
+
+
+ Total Extras
+
+
+
+
+ {#each appState.getAllViews() as view}
+ {@const total = getTotalView(view.id)}
+ {#if total > 0}
+
+ {view.name || view.id}
+ {formatearPrecio(total)}
+
+ {/if}
+ {/each}
+
+
+
+
+ TOTAL
+ {formatearPrecio(totalGeneral)}
+
+
+
+
+ {/if}
+
+
+
+
+
+ {#if showGeneralOptions}
+
+
+
+ {dataConfig.texts.title_options_general || 'Opciones Generales'}
+
+
+
+ {#each Object.entries(dataConfig.options.general) as [key, group]}
+ {@const currentOptionId = appState.getCurrentOption('general', key)}
+ {@const optionValue = currentOptionId ? appState.getOptionValue(currentOptionId) : null}
+
+
+
+ {group.name || group.id}
+
+
+ {optionValue?.name || currentOptionId || 'No seleccionado'}
+
+
+ {#if optionValue?.thumb}
+

{
+ (e.target as HTMLImageElement).style.display = 'none'; }}
+ />
+ {/if}
+
+ {/each}
+
+
+
+ {/if}
+
+
+
+
+
+ ℹ️ Las imágenes son orientativas y pueden no corresponder exactamente con el resultado final.
+ Los acabados están sujetos a disponibilidad.
+
+
+
+
+
+
+
+
\ No newline at end of file