dev 8 months ago
parent cf92086628
commit 9907057c31

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 4.1 MiB

@ -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 @@
<!-- Iterar sobre todos los grupos de opciones -->
{#each appState.currentView.options as group (group.id) }
<DpOptionGroup group={group} />
<DpOptionGroup
group={group}
viewId={appState.selection.currentViewId}
/>
{/each}
</div>
@ -158,5 +162,7 @@
</div>
</div>
<PnDebug enabled={true} />
</div>

@ -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'

@ -1,18 +1,25 @@
<script lang="ts">
import type {OptionGroup} from "../data/DataConfigTypes";
import {appState} from "../data/AppState.svelte";
import BtOptionValue from "./BtOptionValue.svelte";
import BtOption from "./BtOption.svelte";
let {
group,
// Recibimos viewId opcional. Si no viene, usamos la vista actual seleccionada.
viewId = appState.selection.currentViewId
} = $props<{
group: OptionGroup;
viewId?: string;
}>();
// ❌ BORRA ESTO: Estaba forzando a mirar siempre la vista actual,
// ignorando si viewId era "general"
// const currentViewId = $derived(appState.selection.currentViewId);
// const viewState = $derived(appState.selection.views[currentViewId]);
// ✅ AGREGA ESTO: Obtenemos el valor seleccionado correctamente según el viewId
// Svelte rastreará automáticamente las dependencias dentro de getCurrentOption
const selectedValue = $derived(appState.getCurrentOption(viewId, group.id));
</script>
<div class="mb-6">
@ -20,9 +27,10 @@
<div class="grid grid-cols-2 gap-4">
{#each group.values as optionRef (optionRef.id) }
{@const isSelected = appState.getCurrentOption(viewId, group.id) === optionRef.id}
<BtOptionValue
{@const isSelected = selectedValue === optionRef.id}
<BtOption
{optionRef}
groupId={group.id}
{viewId}

@ -0,0 +1,103 @@
<script lang="ts">
import { appState } from "../data/AppState.svelte";
let {
enabled = false
} = $props<{
enabled?: boolean;
}>();
let expanded = $state(true);
</script>
{#if enabled}
<div class="fixed bottom-4 right-4 z-50 w-80 bg-gray-900 text-white rounded-lg shadow-2xl overflow-hidden">
<!-- Header -->
<div class="bg-gray-800 p-3 flex items-center justify-between border-b border-gray-700">
<div class="flex items-center gap-2">
<span class="text-lg">🔍</span>
<span class="font-bold text-sm">AppState Inspector</span>
</div>
<button
onclick={() => expanded = !expanded}
class="text-gray-400 hover:text-white transition-colors"
>
{expanded ? '−' : '+'}
</button>
</div>
{#if expanded}
<div class="p-4 max-h-96 overflow-y-auto text-xs font-mono space-y-3">
<!-- Current View -->
<div>
<div class="text-blue-400 font-bold mb-1">Current View:</div>
<div class="bg-gray-800 p-2 rounded">
<div><span class="text-gray-500">ID:</span> {appState.selection.currentViewId}</div>
<div><span class="text-gray-500">Name:</span> {appState.currentView.name}</div>
<div><span class="text-gray-500">Options:</span> {appState.currentView.options.length}</div>
</div>
</div>
<!-- General Options -->
<div>
<div class="text-green-400 font-bold mb-1">General Options:</div>
<div class="bg-gray-800 p-2 rounded space-y-1">
{#each Object.entries(appState.selection.general) as [key, value]}
<div>
<span class="text-gray-500">{key}:</span>
<span class="text-yellow-300">{value}</span>
</div>
{/each}
</div>
</div>
<!-- Current View Options -->
<div>
<div class="text-purple-400 font-bold mb-1">
View Options ({appState.selection.currentViewId}):
</div>
<div class="bg-gray-800 p-2 rounded space-y-1">
{#if appState.selection.views[appState.selection.currentViewId]}
{#each Object.entries(appState.selection.views[appState.selection.currentViewId]) as [key, value]}
<div>
<span class="text-gray-500">{key}:</span>
<span class="text-yellow-300">{value}</span>
</div>
{:else}
<div class="text-gray-500 italic">No options</div>
{/each}
{:else}
<div class="text-red-400">⚠️ View state not initialized!</div>
{/if}
</div>
</div>
<!-- All Views -->
<div>
<div class="text-orange-400 font-bold mb-1">All Views:</div>
<div class="bg-gray-800 p-2 rounded flex flex-wrap gap-1">
{#each appState.getAllViewIds() as viewId}
<span
class="px-2 py-0.5 rounded text-xs"
class:bg-blue-600={viewId === appState.selection.currentViewId}
class:bg-gray-700={viewId !== appState.selection.currentViewId}
>
{viewId}
</span>
{/each}
</div>
</div>
<!-- Actions -->
<div class="pt-2 border-t border-gray-700">
<button
onclick={() => appState.inspect()}
class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded text-xs font-bold transition-colors"
>
Log Full State to Console
</button>
</div>
</div>
{/if}
</div>
{/if}

@ -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 });
}
}
}

@ -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',
}
*/
],
},
],

Loading…
Cancel
Save

Powered by TurnKey Linux.