# Demo Overrides Pattern — qué overridea un demo y cómo

> Cuando el core preset declara `"demo": "demo-X"`, el sistema arranca a usar todas las piezas específicas de ese demo. Este doc explica las **7 piezas** que el demo controla + cómo se conectan con módulos.

---

## Las 7 piezas que un demo overridea

| # | Pieza | Archivo | Selección automática |
|---|-------|---------|----------------------|
| 1 | **Header** (navegación principal) | `resources/views/layout/front/headers/{demo}.blade.php` | `get_demo_layout_mapping()` en `app/helpers.php` |
| 2 | **Footer** (pie de página) | `resources/views/layout/front/footers/{demo}.blade.php` | idem |
| 3 | **Page-header** (banner de páginas internas) | `resources/views/layout/front/partials/page-header-{base}.blade.php` (sin prefijo "demo-") | `config/page-headers.php` + `@include` desde cada módulo |
| 4 | **Welcome** (home) | `resources/views/modules/cd-base/frontend/demos/{demo}/welcome.blade.php` | `DemoViewHelper::getDemoView('welcome')` |
| 5 | **About** (`/about`) | `.../demos/{demo}/about.blade.php` | `DemoViewHelper::getDemoView('about')` |
| 6 | **Contact** (`/contact`) | `.../demos/{demo}/contact.blade.php` | `DemoViewHelper::getDemoView('contact')` |
| 7 | **Demo CSS** (estilos visuales) | `public/template/css/demos/{demo}.css` | cargado en `_styles.blade.php` después del skin |

Más una **8ª pieza condicional** dentro de cada módulo:

8 | **Dynamic-header** del módulo | `resources/views/modules/{modulo}/frontend/partials/dynamic-header.blade.php` | `@elseif($activeDemo === 'demo-X')` cases

---

## Selector dinámico: cómo el sistema elige el archivo correcto

### Nivel 1 — `DemoViewHelper::getDemoView($viewName)`

```php
// app/Helpers/DemoViewHelper.php
public static function getDemoView(string $viewName, string $fallbackView = null): string
{
    $activeDemo = config('cd-system.theme.demo', 'demo-construction');
    $demoViewPath = "modules.cd-base.frontend.demos.{$activeDemo}.{$viewName}";

    if (view()->exists($demoViewPath)) {
        return $demoViewPath;
    }
    return "modules.cd-base.frontend.{$viewName}";  // fallback default
}
```

Usado por `HomepageController::index()`, `::about()`, `::contact()`, `::menu()`. Si el demo NO tiene la vista, cae al default genérico.

### Nivel 2 — Mapping de header/footer/page-header

```php
// app/helpers.php
function get_demo_layout_mapping(): array {
    return [
        'demo-law-firm-2' => [
            'header' => 'layout.front.headers.demo-law-firm-2',
            'footer' => 'layout.front.footers.demo-law-firm-2',
            'page_header' => 'page-header-law-firm-2',
        ],
        ...
    ];
}
```

`master.blade.php` (layout root) hace `@include(get_layout_partial('header'))` que resuelve via mapping.

### Nivel 3 — Skin CSS

```php
// app/helpers.php
function get_demo_skin_mapping(): array {
    return [
        'demo-law-firm-2' => 'skin-law-firm-2',
        ...
    ];
}
```

`_styles.blade.php` carga `<link id="skinCSS" href=".../skins/{skin}.css">` según mapping.

**Importante**: el skin estático SOLO carga la paleta inicial. En cada request, el `<style id="brandColors">` inline (generado por `SkinColorService`) sobreescribe con los colores del brand_kit del tenant. Por eso cualquier producto puede usar cualquier skin como base — los colores reales vienen de DB.

### Nivel 4 — Demo CSS

```php
// _styles.blade.php
@if($currentDemo)
    <link rel="stylesheet" href="{{ asset('template/css/demos/'.$currentDemo.'.css') }}">
@endif
```

El demo CSS carga **DESPUÉS** del skin → tiene prioridad de cascade. Por eso el demo puede customizar tipografía, márgenes, layouts específicos.

### Nivel 5 — Dynamic-header del módulo

```blade
{{-- modules/services/frontend/partials/dynamic-header.blade.php --}}
@php $currentDemo = get_theme_demo(); @endphp

@if($currentDemo === 'demo-law-firm-2')
    @include('layout.front.partials.page-header-law-firm-2', [...])
@elseif($currentDemo === 'demo-architecture-2')
    @include('layout.front.partials.page-header-architecture-2', [...])
@else
    {{-- fallback --}}
@endif
```

Cada módulo (services, blog, gallery, projects, products, team, references, menu, faqs, cd-base) tiene UN `dynamic-header.blade.php` con N cases — uno por demo activo. **10 archivos en total que tocar al sumar un demo nuevo**.

---

## Integración con módulos — cómo el demo consume data

### A) Bloque embebido en welcome/about del demo

El demo escribe SU propio markup en `demos/{demo}/welcome.blade.php` y lee data de las variables que el `ViewComposerServiceProvider` inyecta:

```blade
{{-- modules/cd-base/frontend/demos/demo-law-firm-2/welcome.blade.php --}}
@if(is_module_active('services'))
<div class="owl-carousel-wrapper law-firm-services-carousel">
    @forelse($services as $service)   {{-- $services del ViewComposer --}}
        <div class="card custom-card-style-1">
            <h2>{{ $service->title }}</h2>
            <p>{{ Str::limit(strip_tags($service->description), 120) }}</p>
        </div>
    @empty
        ...
    @endforelse
</div>
@endif
```

**Cada demo decide**:
- Cuántos items (`take(3)`, `take(6)`)
- Layout (cards, lista, grid, slider, masonry)
- Qué campos mostrar
- Animaciones
- Clases CSS específicas

Pero **NO** modifica el módulo en sí. Eso queda intocado.

### B) Vista standalone del módulo

Las páginas `/services`, `/team`, `/blog`, etc. son **vistas únicas universales** (`modules/{modulo}/frontend/{modulo}.blade.php`). NO se duplican por demo. La customización por demo se hace via:
- `dynamic-header` partial (con cases por demo)
- Clases CSS específicas en `demo-{name}.css` (`html.demo-X .services-list { ... }`)
- Helpers en runtime: `get_theme_demo()`, `get_active_demo()`

### C) Detail page del módulo

Idem standalone — vista única (`{modulo}-detail.blade.php` o `service-detail.blade.php`) con partials/CSS condicionales.

---

## Reglas de oro (extraídas de `estandar-demo.md`)

### ✅ El demo SÍ controla

- Layout visual de welcome / about / contact (markup HTML/blade)
- Header / footer / page-header completos
- CSS específico (`demos/{demo}.css`)
- Cómo embebe items de un módulo (cards, sliders, etc.)
- Tipografía base (font-size, font-weight; **NO** font-family — eso vive en `cd-system.theme.fonts`)
- Clases CSS de overrides (`html.demo-X .target { ... }`)

### ❌ El demo NO debe

- Tener lógica de negocio (queries, control de flujo de datos)
- Definir CSS variables del brand (`--primary`, `--secondary`) — eso es del skin/brandColors
- Hardcodear hex (`#1A325D`) — usar `var(--primary)`
- Hardcodear textos en inglés sin `__()` o config
- Hardcodear nombres "John Doe" / "Lorem ipsum" — usar nombres genéricos en español
- Apuntar a paths absolutos del template Porto sin fallback (`cd-project/img/demos/X/`) — siempre con fallback a `cd-project/img/defaults/`

### ✅ Módulo NO debe contener

- Lógica visual específica de un demo (`<div class="law-firm-card">`)
- Hex de colores
- Textos en demo-specific styles

---

## Patrón de fallback de imagen (canónico)

```blade
@php
    $imgSrc = !empty($item->image)
        ? (filter_var($item->image, FILTER_VALIDATE_URL) ? $item->image : asset($item->image))
        : asset('cd-project/img/defaults/{tipo}/{tipo}-' . (($loop->index % {N}) + 1) . '.{ext}');
@endphp
<img src="{{ $imgSrc }}" alt="{{ $item->title ?? '' }}" />
```

Donde `{tipo}` es `team`, `blog`, `gallery`, `projects`, etc., y N es la cantidad de archivos en el defaults pack.

NO hacer:
```blade
{{-- ❌ MAL: rompe si $item->image es URL Cloudinary --}}
<img src="{{ asset($item->image) }}" />

{{-- ❌ MAL: fallback al template específico, no genérico --}}
<img src="{{ asset('cd-project/img/demos/law-firm-2/team/team-1.jpg') }}" />
```

---

## Patrón de welcome — Tipo A vs Tipo B

`docs/bewpro2.0/arquitectura-vistas-base.md` lo documenta en detalle.

**Tipo A — config-heavy** (legacy):
- Welcome lee 30+ keys de `config('site.welcome.*')` para textos hardcoded
- Demos ejemplo: `demo-law-firm-2`, `demo-accounting-2`, `demo-insurance`
- Requiere admin con 30+ inputs (paridad admin↔front)

**Tipo B — data-driven** (target):
- Welcome usa solo 7 campos universales (site.name, site.tagline, etc.) + datos de módulos
- Demos ejemplo: `demo-digital-agency-2`, `demo-restaurant`
- Admin tiene 7 inputs canónicos universales

**Estado actual**: la mayoría de los 8 demos productivos son Tipo A. Migrar a Tipo B es prerequisito para el "template selector" (futuro feature donde el cliente cambie demo desde admin).

---

## Cuándo crear un demo nuevo

Cuando ningún demo existente sirve para el producto que querés vender:
1. Identificar template Porto fuente (https://www.okler.net/previews/porto/)
2. Seguir [`../product-readiness/guia-nuevo-demo.md`](../product-readiness/guia-nuevo-demo.md) — los 5 pasos canónicos
3. Crear los 7 archivos blade + CSS demo + skin CSS
4. Registrar en `helpers.php::get_demo_layout_mapping()` + `get_demo_skin_mapping()`
5. Registrar en `config/page-headers.php`
6. Agregar caso en los 10 `dynamic-header.blade.php` de los módulos
7. Documentar en `demo-{slug}.md`

---

## Referencias

- Estándar canónico: [`../product-readiness/estandar-demo.md`](../product-readiness/estandar-demo.md) (636 líneas, fuente de verdad técnica)
- Guía paso a paso: [`../product-readiness/guia-nuevo-demo.md`](../product-readiness/guia-nuevo-demo.md)
- Patrón welcome A/B: [`../arquitectura-vistas-base.md`](../arquitectura-vistas-base.md)
- Skin CSS: [`../branding/skin-css.md`](../branding/skin-css.md)
- Componentes blade: [`../product-readiness/blade-components.md`](../product-readiness/blade-components.md)
