---
title: "Cuaderno Técnico: Plugin «Agenda Indaga» (v1.3.0), parte 3"
description: "Entrega 3: Los Shortcodes de Frontend (Formulario y Calendario Interactivo) Valencia, 25/10/2026, G.B. En las entregas anteriores vimos cómo levantar los cimientos del plugin en la base de datos y cóm..."
url: https://indaga.net/cuaderno-tecnico-plugin-agenda-indaga-v1-3-0-parte-3/
date: 2026-10-25
modified: 2026-10-25
author: "Directorio Indaga"
image: https://indaga.net/wp-content/uploads/2026/10/agenda.jpg
categories: ["Recursos y Utilidades", "WordPress"]
tags: ["agenda indaga", "blog", "cuadernos técnicos", "plugins indaga", "wordpress"]
type: post
lang: es
---

# Cuaderno Técnico: Plugin «Agenda Indaga» (v1.3.0), parte 3

### Entrega 3: Los Shortcodes de Frontend (Formulario y Calendario Interactivo)

Valencia, 25/10/2026, G.B.

En las entregas anteriores vimos cómo levantar los cimientos del plugin en la base de datos y cómo estructurar el panel de administración en el backend. En este tercer bloque me centro en la parte visible para el usuario: los shortcodes que dan vida a la agenda en el frontend de la web.

Para conseguirlo, divido la funcionalidad en dos shortcodes independientes pero complementarios: `indaga_agenda` (entre corchetes) para gestionar el alta, edición y listado de citas, y `calendario_agenda` (entre corchetes) para renderizar el calendario mensual interactivo.

### 1. El Shortcode de Gestión y Formulario (`indaga_agenda`) (entre corchetes)

Este shortcode permite desplegar un formulario de alta y edición de eventos, acompañado de una tabla con los registros actuales de la instancia. Todo ello protegido mediante comprobaciones de sesión de usuario, validación de nonces y funciones de saneamiento de datos.

```
public function renderizar_shortcode_agenda( $atts ) {
    global $wpdb;
    $tabla = $wpdb->prefix . 'indaga_agenda';
    $atts = shortcode_atts( array( 'id' => 'default' ), $atts, 'indaga_agenda' );
    $grupo_id = sanitize_text_field( $atts['id'] );
    $user_id = get_current_user_id();
    $mensaje = '';

    // Procesamiento del formulario de guardado / edición
    if ( isset( $_POST['indaga_agenda_frontend_nonce'] ) && wp_verify_nonce( $_POST['indaga_agenda_frontend_nonce'], 'guardar_evento_frontend' ) ) {
        if ( !is_user_logged_in() ) {
            return '<p style="color:red;">Debes iniciar sesión para gestionar la agenda.</p>';
        }

        $evento_id = isset( $_POST['evento_id'] ) ? absint( $_POST['evento_id'] ) : 0;
        $titulo = sanitize_text_field( $_POST['titulo'] );
        $descripcion = sanitize_textarea_field( $_POST['descripcion'] );
        $fecha_inicio = sanitize_text_field( $_POST['fecha_inicio'] );
        $fecha_fin = sanitize_text_field( $_POST['fecha_fin'] );
        $categoria = sanitize_text_field( $_POST['categoria'] );

        if ( !empty( $titulo ) && !empty( $fecha_inicio ) ) {
            $datos = array(
                'user_id' => $user_id,
                'grupo_id' => $grupo_id,
                'titulo' => $titulo,
                'descripcion' => $descripcion,
                'fecha_inicio' => $fecha_inicio,
                'fecha_fin' => !empty( $fecha_fin ) ? $fecha_fin : $fecha_inicio,
                'categoria' => $categoria
            );

            if ( $evento_id > 0 ) {
                $wpdb->update( $tabla, $datos, array( 'id' => $evento_id ), array( '%d', '%s', '%s', '%s', '%s', '%s', '%s' ), array( '%d' ) );
                $mensaje = '<div style="background:#d4edda; color:#155724; padding:10px; margin-bottom:15px; border-radius:4px;">¡Evento actualizado con éxito!</div>';
            } else {
                $wpdb->insert( $tabla, $datos, array( '%d', '%s', '%s', '%s', '%s', '%s', '%s' ) );
                $mensaje = '<div style="background:#d4edda; color:#155724; padding:10px; margin-bottom:15px; border-radius:4px;">¡Evento creado con éxito!</div>';
            }
        }
    }
    // ... (código de renderizado de la vista y formulario)
}
```

#### Puntos clave del formulario:

- **Soporte multinstancia por atributo**: A través del parámetro `id="nombre_instancia"` (por defecto `default`), delimito los registros que pertenecen a esa agenda concreta.
- **Doble funcionalidad (Alta / Edición)**: Si el sistema detecta un parámetro `editar_id` en la URL, carga automáticamente los datos del evento en los inputs para modificarlos sin duplicar registros.

### 2. El calendario interactivo (`calendario_agenda`) (entre corchetes)

Para mostrar los eventos en una vista de calendario mensual limpia y visual, transformo los registros de la base de datos a un array de JavaScript y construyo una cuadrícula dinámica.

```
public function renderizar_shortcode_calendario( $atts ) {
    global $wpdb;
    $tabla = $wpdb->prefix . 'indaga_agenda';
    $atts = shortcode_atts( array( 'id' => 'default' ), $atts, 'calendario_agenda' );
    $grupo_id = sanitize_text_field( $atts['id'] );

    $eventos = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $tabla WHERE grupo_id = %s ORDER BY fecha_inicio ASC", $grupo_id ) );
    
    $eventos_js = array();
    foreach ( $eventos as $ev ) {
        $eventos_js[] = array(
            'id' => $ev->id,
            'titulo' => $ev->titulo,
            'descripcion' => $ev->descripcion,
            'categoria' => $ev->categoria,
            'fecha_inicio' => $ev->fecha_inicio,
            'fecha_fin' => $ev->fecha_fin
        );
    }
    // ... (retorno del HTML y script de renderizado)
}
```

#### Características del motor visual en JavaScript:

- **Navegación fluida por meses**: Botones de avance y retroceso (`cambiarMes()`) que recalculan los días de la semana y sitúan correctamente el primer día del mes.
- **Fichas modales emergentes**: Al hacer clic sobre cualquier evento listado dentro de una casilla del calendario, se despliega una ventana flotante con los detalles completos (horarios, categoría y descripción).
- **Conexión directa con el alta**: El botón superior *«+ Añadir Evento»* o hacer clic directamente sobre cualquier día del calendario desplaza la vista automáticamente hacia el formulario y precarga la fecha seleccionada.

Con esta tercera entrega queda completamente documentada la arquitectura del plugin **Agenda Indaga (v1.3.0)**: desde los cimientos en la base de datos, pasando por el panel de administración multinstancia, hasta la interacción visual en el frontend.
