You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
6.9 KiB

# Arquitectura Reactiva - Documentación
## 🏗️ Estructura Híbrida
La arquitectura separa **estado agnóstico del framework** de los **adapters específicos**:
```
src/
├── state/ # ← Estado puro (sin framework)
│ ├── SelectionState.ts
│ ├── ValidationState.ts
│ └── ConfigurationState.ts
│
└── adapters/ # ← Adapters por framework
└── svelte/
├── stores/ # Wrappers Svelte
└── components/ # Componentes UI
```
---
## 📦 Capa 1: Estado Agnóstico (`/state`)
### `SelectionState.ts`
Gestiona qué opciones están seleccionadas.
**Responsabilidades:**
- Almacenar selecciones: `Record<AttrID, OptionID>`
- Notificar cambios via listeners
- Historial de cambios (undo/redo)
- Persistencia (toJSON/fromJSON)
**API:**
```typescript
const selection = new SelectionState();
// Establecer valor
selection.set('at:suelo', 'op:parquet');
// Obtener valor
selection.get('at:suelo'); // → 'op:parquet'
// Limpiar
selection.clear('at:suelo');
// Suscribirse a cambios
const unsubscribe = selection.subscribe((event) => {
console.log(`${event.attrId} cambió a ${event.newValue}`);
});
// Deshacer
selection.undo();
```
---
### `ValidationState.ts`
Gestiona validaciones y violaciones usando el `RuleEngine`.
**Responsabilidades:**
- Validar selecciones contra reglas
- Detectar violaciones (errores/warnings)
- Verificar valores permitidos/prohibidos
- Determinar atributos requeridos
**API:**
```typescript
const validation = new ValidationState();
// Configurar reglas
validation.setRules(catalog.rules);
// Validar estado
const result = validation.validate(selectionState);
console.log(result.isValid); // → boolean
console.log(result.violations); // → Violation[]
// Helpers
validation.isValueAllowed('at:suelo', 'op:marmol', state);
validation.getAllowedValues('at:suelo', state);
validation.isRequired('at:material', state);
```
---
### `ConfigurationState.ts`
**Orquestador principal** que coordina todo.
**Responsabilidades:**
- Gestionar catálogo y objeto
- Coordinar SelectionState + ValidationState
- Navegación (sección/vista actual)
- Auto-validación en cambios
- Persistencia completa
**API:**
```typescript
const config = new ConfigurationState({
catalog: CATALOGO_VIVIENDAS,
objectId: 'ob:apartamento',
autoValidate: true
});
// Selección
config.selectOption('at:suelo', 'op:parquet');
config.getSelection('at:suelo');
// Navegación
config.setCurrentSection('sc:salon');
config.setCurrentView('vw:front');
// Validación
config.validate();
config.isValid();
config.getViolationsForAttribute('at:suelo');
// Helpers
config.getAllowedValues('at:suelo');
config.isRequired('at:material');
// Persistencia
const saved = config.toJSON();
config.fromJSON(saved);
// Utils
config.reset();
config.undo();
```
---
## 🔌 Capa 2: Adapters Svelte (`/adapters/svelte`)
### `stores/configuration.ts`
Wrapper que convierte `ConfigurationState` en Svelte store.
**Características:**
- ✅ Reactivo automático (subscribe)
- ✅ API idéntica a ConfigurationState
- ✅ Derived stores para valores específicos
- ✅ Type-safe
**Uso:**
```typescript
import { createConfigurationStore } from '@/adapters/svelte/stores';
const config = createConfigurationStore({
catalog: CATALOGO_VIVIENDAS,
objectId: 'ob:apartamento'
});
// En componentes Svelte
$: selection = $config.selection;
$: isValid = $config.isValid;
$: currentSection = $config.currentSection;
// Acciones
config.selectOption('at:suelo', 'op:parquet');
config.setCurrentSection('sc:salon');
```
**Derived stores:**
```typescript
const currentSection = deriveCurrentSection(config);
const validation = deriveValidation(config);
const isValid = deriveIsValid(config);
```
---
## 🎨 Capa 3: Componentes UI (`/adapters/svelte/components`)
### `Configurator.svelte`
Componente principal de ejemplo.
**Features:**
- ✅ Navegación de secciones
- ✅ Selector de vistas
- ✅ Panel de atributos
- ✅ Preview visual
- ✅ Validación en tiempo real
- ✅ Undo/Reset
**Uso:**
```svelte
<script>
import Configurator from '@/adapters/svelte/components/Configurator.svelte';
import { CATALOGO_VIVIENDAS } from './fixtures';
</script>
<Configurator
catalog={CATALOGO_VIVIENDAS}
objectId="ob:apartamento"
/>
```
---
## 🔄 Flujo de Datos
```
User Action (click)
↓
Component Handler
↓
Store Action (config.selectOption)
↓
ConfigurationState
↓
SelectionState.set()
↓
Notifica listeners
↓
ValidationState.validate() (si autoValidate)
↓
Notifica cambio
↓
Svelte Store actualiza
↓
UI re-renderiza (reactive $config)
```
---
## ✅ Ventajas de esta arquitectura
### 1. **Separación de concerns**
- Estado = Lógica de negocio (testeable sin UI)
- Adapter = Integración con framework
- Components = Solo presentación
### 2. **Framework agnostic**
El 90% del código está en `/state` y no depende de Svelte.
Añadir React es fácil:
```
/adapters/react/
└── hooks/
└── useConfiguration.ts ← Wrapper con useState/useEffect
```
### 3. **Testing simple**
```typescript
// Test estado SIN montar componentes
const config = new ConfigurationState({...});
config.selectOption('at:suelo', 'op:parquet');
expect(config.getSelection('at:suelo')).toBe('op:parquet');
```
### 4. **Type-safety completo**
Todo tipado con TypeScript. El editor te ayuda en cada paso.
### 5. **Reactivo por defecto**
Cambias el estado → UI se actualiza automáticamente.
---
## 📝 Ejemplo completo
```svelte
<script lang="ts">
import { createConfigurationStore } from '@/adapters/svelte/stores';
const config = createConfigurationStore({
catalog: MY_CATALOG,
objectId: 'ob:producto'
});
// Reactivo automático
$: selection = $config.selection;
$: isValid = $config.isValid;
$: violations = $config.validation?.violations || [];
</script>
<!-- UI reactiva -->
<div>
<h1>{$config.object.name.es}</h1>
<select on:change={(e) => config.selectOption('at:color', e.target.value)}>
<option value="">Seleccionar color</option>
<option value="op:rojo">Rojo</option>
<option value="op:azul">Azul</option>
</select>
{#if !isValid}
<div class="errors">
{#each violations as v}
<p>{v.rule.message.es}</p>
{/each}
</div>
{/if}
<button disabled={!isValid}>
Confirmar
</button>
</div>
```
---
## 🚀 Próximos pasos
1. ✅ Estado agnóstico implementado
2. ✅ Adapter Svelte implementado
3. ✅ Componente de ejemplo creado
4. ⏳ Implementar renderizado de imágenes
5. ⏳ Añadir precio dinámico
6. ⏳ Implementar más componentes (AttributePanel, ValidationPanel, etc.)
7. ⏳ Testing de stores
8. ⏳ Documentación de componentes
---
## 📚 Archivos clave
- `/state/ConfigurationState.ts` - Orquestador principal
- `/adapters/svelte/stores/configuration.ts` - Svelte store
- `/adapters/svelte/components/Configurator.svelte` - Componente ejemplo
- `/docs/ARCHITECTURE.md` - Este archivo

Powered by TurnKey Linux.