diff --git a/public/img/hi/bano1_alpino_ducha_onyks_sensow..jpg b/public/img/hi/bano1_alpino_ducha_onyks_sensow.jpg similarity index 100% rename from public/img/hi/bano1_alpino_ducha_onyks_sensow..jpg rename to public/img/hi/bano1_alpino_ducha_onyks_sensow.jpg diff --git a/src/lib/ views/ViewConfig.svelte b/src/lib/ views/ViewConfig.svelte index d7085ef..bdc893c 100644 --- a/src/lib/ views/ViewConfig.svelte +++ b/src/lib/ views/ViewConfig.svelte @@ -4,6 +4,7 @@ import { fade } from 'svelte/transition'; import BtViewSelector from "../cmps/BtViewSelector.svelte"; import DpOptionGroup from "../cmps/DpOptionGroup.svelte"; + import PnDebug from "../cmps/PnDebug.svelte"; let isLoading = $state(true); let imageUrl = $state(''); @@ -150,7 +151,10 @@ {#each appState.currentView.options as group (group.id) } - + {/each} @@ -158,5 +162,7 @@ + + \ No newline at end of file diff --git a/src/lib/cmps/BtOption.svelte b/src/lib/cmps/BtOption.svelte index bf260ac..7cbb524 100644 --- a/src/lib/cmps/BtOption.svelte +++ b/src/lib/cmps/BtOption.svelte @@ -15,7 +15,7 @@ isSelected?: boolean; }>(); - let isValid = () => true; + const isValid = $derived(appState.isValid(optionRef.rules)); const optionValue = $derived(appState.getOptionValue(optionRef.id)); const consultation = $derived(appState.requiresConsultation(viewId, groupId, optionRef.id)); @@ -27,7 +27,7 @@ class="group relative p-0 rounded-lg border transition-all duration-200 cursor-pointer flex flex-col h-full text-center {isSelected - ? isValid() + ? isValid ? 'border-blue-200 bg-blue-50 ring-1 ring-blue-200' : 'border-red-200 bg-red-50 ring-1 ring-red-200' : 'border-gray-200 hover:border-gray-400' diff --git a/src/lib/cmps/DpOptionGroup.svelte b/src/lib/cmps/DpOptionGroup.svelte index 3c5e9de..e98e716 100644 --- a/src/lib/cmps/DpOptionGroup.svelte +++ b/src/lib/cmps/DpOptionGroup.svelte @@ -1,18 +1,25 @@ - -
@@ -20,9 +27,10 @@
{#each group.values as optionRef (optionRef.id) } - {@const isSelected = appState.getCurrentOption(viewId, group.id) === optionRef.id} - + import { appState } from "../data/AppState.svelte"; + + let { + enabled = false + } = $props<{ + enabled?: boolean; + }>(); + + let expanded = $state(true); + + +{#if enabled} +
+ +
+
+ 🔍 + AppState Inspector +
+ +
+ + {#if expanded} +
+ +
+
Current View:
+
+
ID: {appState.selection.currentViewId}
+
Name: {appState.currentView.name}
+
Options: {appState.currentView.options.length}
+
+
+ + +
+
General Options:
+
+ {#each Object.entries(appState.selection.general) as [key, value]} +
+ {key}: + {value} +
+ {/each} +
+
+ + +
+
+ View Options ({appState.selection.currentViewId}): +
+
+ {#if appState.selection.views[appState.selection.currentViewId]} + {#each Object.entries(appState.selection.views[appState.selection.currentViewId]) as [key, value]} +
+ {key}: + {value} +
+ {:else} +
No options
+ {/each} + {:else} +
⚠️ View state not initialized!
+ {/if} +
+
+ + +
+
All Views:
+
+ {#each appState.getAllViewIds() as viewId} + + {viewId} + + {/each} +
+
+ + +
+ +
+
+ {/if} +
+{/if} \ No newline at end of file diff --git a/src/lib/data/AppState.svelte.ts b/src/lib/data/AppState.svelte.ts index 4513660..55afa3f 100644 --- a/src/lib/data/AppState.svelte.ts +++ b/src/lib/data/AppState.svelte.ts @@ -2,9 +2,6 @@ import { dataConfig } from './DataConfig'; import type {DataConfig, Rules, OptionGroup, View} from './DataConfigTypes'; import type { AppState } from './AppStateTypes'; - - - class DataConfigStore { imgSrc : string = dataConfig.sources.imgViewsHi @@ -18,24 +15,50 @@ class DataConfigStore { views: {} }); + // ============================================ + // DEBUGGING + // ============================================ + private debugLog(method: string, data: any) { + console.log(`[AppState.${method}]`, { + timestamp: new Date().toISOString(), + currentViewId: this.selection.currentViewId, + ...data + }); + } + + // Método público para inspeccionar el estado completo + inspect() { + console.group('🔍 AppState Inspector'); + console.log('Current View ID:', this.selection.currentViewId); + console.log('Current View:', this.currentView); + console.log('General Options:', this.selection.general); + console.log('All Views State:', this.selection.views); + console.log('Available Views:', Object.keys(dataConfig.options.views)); + console.groupEnd(); + return this.selection; + } + // ============================================ // CONSTRUCTOR E INICIALIZACIÓN // ============================================ constructor() { this.init(); + + // Exponer en window para debug desde consola + if (typeof window !== 'undefined') { + (window as any).appState = this; + console.log('✅ appState disponible en window.appState'); + console.log('📝 Usa: window.appState.inspect() para ver el estado'); + } } private init() { - // Obtener todas las vistas disponibles const viewIds = Object.keys(dataConfig.options.views); - // Validar que existe al menos una vista if (viewIds.length === 0) { throw new Error('Configuración inválida: debe existir al menos una vista'); } - - const state: AppState = { currentViewId: viewIds[0], general: {}, @@ -58,6 +81,12 @@ class DataConfigStore { }) this.selection = state; + + this.debugLog('init', { + initialViewId: state.currentViewId, + viewsCount: viewIds.length, + availableViews: viewIds + }); } // ============================================ @@ -66,11 +95,21 @@ class DataConfigStore { /** Cambiar de habitación/estancia */ setView(viewId: string) { + const previousViewId = this.selection.currentViewId; + if (!dataConfig.options.views[viewId]) { - console.warn(`Vista ${viewId} no existe`); + console.error(`❌ Vista ${viewId} no existe`); + this.debugLog('setView', { error: 'View not found', viewId }); return; } + this.selection.currentViewId = viewId; + + this.debugLog('setView', { + from: previousViewId, + to: viewId, + success: true + }); } /** Cambiar una opción (General o de Vista) */ @@ -80,7 +119,17 @@ class DataConfigStore { console.warn(`Grupo ${groupId} no existe en general`); return; } + + const previousValue = this.selection.general[groupId]; this.selection.general[groupId] = valueId; + + this.debugLog('setOption', { + type: 'general', + groupId, + from: previousValue, + to: valueId + }); + this.revalidateAll(); } else { if (!(viewId in this.selection.views)) { @@ -91,7 +140,18 @@ class DataConfigStore { console.warn(`Grupo ${groupId} no existe en vista ${viewId}`); return; } + + const previousValue = this.selection.views[viewId][groupId]; this.selection.views[viewId][groupId] = valueId; + + this.debugLog('setOption', { + type: 'view', + viewId, + groupId, + from: previousValue, + to: valueId + }); + this.revalidateView(viewId); } } @@ -107,8 +167,11 @@ class DataConfigStore { view.options.forEach((group: OptionGroup) => { this.selection.views[viewId][group.id] = group.default; }); + + this.debugLog('reset', { viewId, type: 'single' }); } else { this.init(); + this.debugLog('reset', { type: 'all' }); } } @@ -119,12 +182,12 @@ class DataConfigStore { get currentView(): View { const view = dataConfig.options.views[this.selection.currentViewId]; if (!view) { + console.error(`❌ Vista ${this.selection.currentViewId} no existe en la configuración`); throw new Error(`Vista ${this.selection.currentViewId} no existe en la configuración`); } return view; } - /** Nombre de la imagen de la vista ACTUAL */ get currentFileName() { const viewId = this.selection.currentViewId; @@ -201,6 +264,16 @@ class DataConfigStore { return this.selection.views[viewId]?.[groupId]; } + /** Obtener todas las vistas disponibles */ + getAllViews(): View[] { + return Object.values(dataConfig.options.views); + } + + /** Obtener los IDs de todas las vistas */ + getAllViewIds(): string[] { + return Object.keys(dataConfig.options.views); + } + // ============================================ // VALIDACIÓN // ============================================ @@ -239,6 +312,8 @@ class DataConfigStore { /** Revalidar todas las vistas */ private revalidateAll() { + this.debugLog('revalidateAll', { trigger: 'general option changed' }); + Object.keys(dataConfig.options.views).forEach(vId => { this.revalidateView(vId); }); @@ -249,13 +324,25 @@ class DataConfigStore { const view = dataConfig.options.views[viewId]; if (!view) return; + const changes: any[] = []; + view.options.forEach((group: OptionGroup) => { const currentId = this.selection.views[viewId][group.id]; const opt = group.values.find(v => v.id === currentId); if (opt?.rules && !this.isValid(opt.rules)) { + changes.push({ + group: group.id, + from: currentId, + to: group.default, + reason: 'rule validation failed' + }); this.selection.views[viewId][group.id] = group.default; } }); + + if (changes.length > 0) { + this.debugLog('revalidateView', { viewId, changes }); + } } } diff --git a/src/lib/data/DataConfig.ts b/src/lib/data/DataConfig.ts index 3f88bf2..1d184ce 100644 --- a/src/lib/data/DataConfig.ts +++ b/src/lib/data/DataConfig.ts @@ -453,10 +453,12 @@ export const dataConfig : DataConfig = { { id: 'mnaf' }, { id: 'mvaf'}, { id: 'mbmb'}, + /* Descartada { id: 'mbpe', amount: 'consultar', } + */ ], }, { @@ -468,10 +470,12 @@ export const dataConfig : DataConfig = { values : [ { id: 'keyla' }, { id: 'kairos'}, + /* Descartada { id: 'enpe', amount: 'consultar', } + */ ], }, ],