# Sistema de PopUps

Sistema para mostrar mensajes al usuario después del login. Cada popup es un componente Vue desarrollado en código, y desde `/taxes_admin/notificaciones` (tab **PopUps**) se decide a qué usuarios o tipos de usuario se le muestra cada uno.

## Ubicación de los archivos

- **Popups concretos**: `resources/views/taxes_admin/notificaciones/popups/PopupXxx.vue`
- **Coordinador**: `resources/views/taxes_admin/notificaciones/popups/PopupQueue.vue` (registry + cola)
- **Admin UI**: `resources/views/taxes_admin/notificaciones/popups.vue` (lista y configura popups)
- **Backend service**: `app/Services/PopupService.php`
- **Controller público**: `app/Http/Controllers/PopupsController.php`
- **Controller admin**: `app/Http/Controllers/TaxesAdmin/TaxesAdminNotificacionesController.php` (métodos `popups_*`)
- **Rutas**:
  - Público: `routes/webs/popups.php` → `/popups/al-login`, `/popups/{id}/visto`
  - Admin: `routes/webs/taxes_admin.php` (bloque `/taxes_admin/notificaciones/popups/*`)

## Tablas (en `dbtaxes`)

- **`popups_definiciones`**: catálogo de popups que existen en el código. Cada fila vincula un slug con su componente Vue.
  - `slug`, `nombre`, `descripcion`, `componente_vue`, `version`
- **`popups_configuracion`**: a quién y cuándo se le muestra cada popup.
  - `popup_id`, `scope_tipo` (`user_type` o `user_id`), `scope_id`, `habilitado`, `mostrar_cada_vez`, `valido_desde`, `valido_hasta`, `mensaje_personalizado`
- **`popups_visualizaciones`**: log de cada vez que un user vio un popup.
  - `popup_id`, `config_id` (nullable), `user_id`, `accion` (`cerrado` / `click_cta` / `no_mostrar_mas`), `vista_at`
  - `config_id` permite medir estadísticas por configuración. Los registros previos a esta columna quedan en `NULL` y solo cuentan a nivel popup.

## Flujo en runtime

1. El usuario hace login y entra al dashboard → `dashboard.blade.php` renderiza `<popup-queue/>`.
2. `PopupQueue.vue` en `mounted()` consulta `GET /popups/al-login`.
3. El backend (`PopupService::getPopupsParaUser`) devuelve la lista filtrada por:
   - configuración habilitada
   - dentro de vigencia (`valido_desde` / `valido_hasta`)
   - scope coincide con `user_id` o `user_type_id`
   - si `mostrar_cada_vez=0`, excluye los que ya están en `popups_visualizaciones`
4. `PopupQueue.vue` renderiza el primero con `<component :is="popupActual.componente_vue">`.
5. El popup emite `@cerrar` con la acción.
6. `PopupQueue.vue` hace `POST /popups/{id}/visto` con la acción y avanza al siguiente popup de la cola.

## Cómo agregar un popup nuevo

### 1) Crear el componente Vue

`resources/views/taxes_admin/notificaciones/popups/PopupNuevoMensaje.vue`

```vue
<template>
  <b-modal v-model="visible" size="lg" centered hide-footer hide-header>
    <div class="popup-hero">
      <h2>Título del popup</h2>
      <p>{{ msg || 'Texto base si no hay mensaje personalizado' }}</p>
    </div>
    <div class="popup-actions">
      <button class="btn btn-primary" @click="onCta">Acción principal</button>
      <button class="btn btn-link" @click="onCerrar">Ahora no</button>
    </div>
    <b-form-checkbox v-model="noMostrarMas">No mostrarme esto nunca más</b-form-checkbox>
  </b-modal>
</template>

<script>
export default {
  name: 'PopupNuevoMensaje',
  props: {
    mensajePersonalizado: { type: String, default: '' },
  },
  data() {
    return { visible: true, noMostrarMas: false };
  },
  computed: {
    msg() { return this.mensajePersonalizado; },
  },
  methods: {
    onCta() {
      this.$emit('cerrar', 'click_cta');
      this.visible = false;
    },
    onCerrar() {
      this.$emit('cerrar', this.noMostrarMas ? 'no_mostrar_mas' : 'cerrado');
      this.visible = false;
    },
  },
  watch: {
    visible(v) {
      if (!v) this.$emit('cerrar', this.noMostrarMas ? 'no_mostrar_mas' : 'cerrado');
    },
  },
};
</script>
```

Reglas del componente:

- **Props**: aceptar `mensajePersonalizado` (string opcional). Si viene, prevalece sobre el texto hardcodeado.
- **Eventos**: emitir `cerrar` con uno de estos valores:
  - `cerrado` → cierre normal
  - `click_cta` → el user clickeó el botón principal
  - `no_mostrar_mas` → marcó el checkbox de no mostrar más
- **Auto-cierre**: setear `visible=false` después de emitir para que el modal desaparezca.

### 2) Registrar el componente en `PopupQueue.vue`

```js
import PopupNuevoMensaje from './PopupNuevoMensaje';

export default {
  components: {
    PopupQuieroSerPartner,
    PopupNuevoMensaje,   // <-- agregar aquí
  },
  // ...
}
```

### 3) Insertar la definición en `popups_definiciones`

```sql
INSERT INTO popups_definiciones (slug, nombre, descripcion, componente_vue, version, created_at, updated_at)
VALUES ('nuevo_mensaje', 'Mi popup nuevo', 'Descripción corta',
        'PopupNuevoMensaje', '1.0', NOW(), NOW());
```

El `componente_vue` **debe coincidir exactamente** con la `name:` del componente Vue.

### 4) Configurar el destino desde la UI

Ir a `/taxes_admin/notificaciones` → tab **PopUps** → "Nueva configuración":

- Elegir el popup recién creado
- Elegir scope: tipo de usuario (`user_type`) o usuario puntual (`user_id`)
- Definir vigencia (opcional)
- Habilitarlo

Listo. La próxima vez que ese user haga login, va a ver el popup.

## Decisiones de diseño claves

- **Una sola vez por user** salvo que se active `mostrar_cada_vez`. Se trackea con `popups_visualizaciones`.
- **Si un user matchea por `user_id` Y por `user_type`** del mismo popup, se le muestra una sola vez (dedupe en `PopupService::getPopupsParaUser`).
- **Tope por login**: se muestra como máximo **1 popup por login** (constante `PopupService::MAX_POR_LOGIN`). Los demás pendientes se van mostrando en los próximos logins, de a uno. Evita encadenar muchos popups seguidos si hay varias configuraciones que aplican al mismo user.
- **Prioridad de la cola**: primero los popups que el user **nunca vio** (entre esos, la config más nueva por `created_at` desc); después los recurrentes (`mostrar_cada_vez=1`) que ya vio. Así un recurrente ya visto no bloquea a uno nuevo cuando el tope por login es 1.
- **Mensaje personalizable por configuración**: el admin puede sobreescribir el texto base por configuración via `mensaje_personalizado`. Útil para A/B testing manual o targeting por segmento.
- **Vigencia**: `valido_desde` / `valido_hasta` permiten agendar popups con principio y fin.

## Acciones registradas

Cada vez que un user cierra un popup queda log en `popups_visualizaciones`:

- `cerrado` → cierre normal (X, ESC, botón "Ahora no")
- `click_cta` → clickeó el botón principal (conversión)
- `no_mostrar_mas` → marcó el checkbox

Tasa de cierre vs CTA = conversión del popup.

## Estadísticas (dos niveles)

- **Por popup (definición)**: suma todas las visualizaciones del popup sin importar la config.
  - Endpoint: `GET /taxes_admin/notificaciones/popups/stats/{popupId}` (`popups_stats`).
  - UI: botón "Ver stats" en el sub-tab **Disponibles**.
- **Por configuración**: solo las visualizaciones originadas por esa config (campaña/segmento). Sirve para comparar configs del mismo popup (distinto scope o `mensaje_personalizado`).
  - Endpoint: `GET /taxes_admin/notificaciones/popups/stats_config/{configId}` (`popups_stats_config`).
  - UI: botón de gráfico en cada fila del sub-tab **Configuraciones**.
- Ambos niveles comparten el mismo armado (`popups_stats_payload($column, $value)` en el controller) filtrando por `popup_id` o `config_id`.

## Cosas que NO hace (todavía)

- No hay triggers fuera del login (ej. mostrar al entrar a una sección específica). Si se necesita, el patrón sería montar `<popup-queue trigger="ruta_x"/>` con prop y filtrar en backend.
- No hay versionado activo: si se hace `version='2.0'` se considera otro popup desde el código pero la tabla no lo distingue.
