Calendario de Tareas con Tabla Interactiva en Vue.js y Element-UI

Este ejemplo técnico demuestra cómo desarrollar un calendario de tareas pendientes con Element-UI en Vue.js, incluyendo indiacdores visuales en el calendario y una vista de tabla expandible. El sistema muestra marcas verdes para tareas completadas y rojas para pendientes, con un panel lateral que lista las tareas en formato tabla.

Estructura de Componentes

La aplicación se compone de tres componentes esenciales:

  • comprobador-tareas.vue: Evalúa cada fecha para mostrar indicadores según el estado de las tareas.
  • lista-tareas.vue: Presanta un popover con la lista de tareas al interactuar con una fecha.
  • tabla-tareas.vue: Renderiza las tareas en una tabla con capacidad de plegado.

Datos de Prueba y Estado

Se simulan datos de tareas con campos para fecha, resumen, descripción y estado (0=completado, 1=pendiente).


const mockTareas = [
  {
    fechaRegistro: "2023-12-05",
    titulo: "Preparar presentación",
    contenido: "Crear diapositivas para reunión de seguimiento",
    completado: 1
  },
  {
    fechaRegistro: "2023-12-05",
    titulo: "Enviar reporte mensual",
    contenido: "Exportar datos y enviar por correo electrónico",
    completado: 0
  }
];

Gestión de Estado con Vuex

Se utiliza un módulo Vuex para manejar las tareas, cargando automáticamente todos los módulos en el directorio correspondiente.


// Configuración del módulo de tareas en el store
const actions = {
  fetchTareasPorRango(context, { inicio, fin }) {
    return new Promise((resolve, reject) => {
      // Lógica para obtener datos (simulada)
      setTimeout(() => {
        const resultados = mockTareas.filter(t => t.fechaRegistro >= inicio && t.fechaRegistro <= fin);
        resolve({ exito: true, datos: resultados });
      }, 300);
    });
  }
};

export default {
  namespaced: true,
  actions
};

Implementación del Calendario Principle

El componente principal integra el calendario de Element-UI, consulta tareas por mes y gestiona la vista de tabla lateral.


<template>
  <div class="contenedor-app">
    <div class="cabecera">
      <el-button>
        {{ textoBotonTabla }}
      </el-button>
    </div>
    <div class="area-principal">
      <div :style="{ width: anchoCalendario }" class="seccion-calendario">
        <el-calendar v-model="fechaActual">
          <template data="" date="">
            <comprobador-tareas :fecha-celda="data.day" :tareas-agrupadas="tareasAgrupadas"></comprobador-tareas>
            <div v-if="data.isSelected">
              <lista-tareas :fecha-celda="data.day" :tareas-agrupadas="tareasAgrupadas"></lista-tareas>
            </div>
            <span :class="{ 'dia-seleccionado': data.isSelected }">
              {{ formatearFechaMostrar(data.day) }}
            </span>
          </template>
        </el-calendar>
      </div>
      <div :style="{ width: anchoTabla }" class="seccion-tabla" v-if="tablaVisible">
        <tabla-tareas :registros="tareasTotales"></tabla-tareas>
      </div>
    </div>
  </div>
</template>

<script>
import ComprobadorTareas from './subcomponentes/ComprobadorTareas.vue';
import ListaTareas from './subcomponentes/ListaTareas.vue';
import TablaTareas from './subcomponentes/TablaTareas.vue';
import { agruparArregloPorClave } from '@/herramientas/procesamiento.js';
import { obtenerPrimerDiaMesAnterior, obtenerUltimoDiaMesSiguiente } from '@/herramientas/fechas.js';

export default {
  components: { ComprobadorTareas, ListaTareas, TablaTareas },
  data() {
    return {
      fechaActual: new Date(),
      tareasTotales: [],
      tareasAgrupadas: {},
      tablaVisible: true,
      textoBotonTabla: 'Replegar Tabla',
      anchoCalendario: '50%',
      anchoTabla: '50%'
    };
  },
  created() {
    this.cargarDatosTareas();
  },
  watch: {
    fechaActual: 'cargarDatosTareas'
  },
  methods: {
    async cargarDatosTareas() {
      const fechaInicio = obtenerPrimerDiaMesAnterior(this.fechaActual);
      const fechaFin = obtenerUltimoDiaMesSiguiente(this.fechaActual);
      const respuesta = await this.$store.dispatch('tareas/fetchTareasPorRango', { inicio: fechaInicio, fin: fechaFin });
      if (respuesta.exito) {
        this.tareasTotales = respuesta.datos;
        this.tareasAgrupadas = agruparArregloPorClave(this.tareasTotales, 'fechaRegistro');
      }
    },
    toggleTabla() {
      this.tablaVisible = !this.tablaVisible;
      this.textoBotonTabla = this.tablaVisible ? 'Replegar Tabla' : 'Expandir Tabla';
      this.anchoCalendario = this.tablaVisible ? '50%' : '100%';
      this.anchoTabla = this.tablaVisible ? '50%' : '0%';
    },
    formatearFechaMostrar(fechaCompleta) {
      return fechaCompleta.split('-').slice(1).join('-');
    }
  }
};
</script>

Los componentes secundarios manejan la lógica de visualización de indicadores y listas, utilizando propiedades computadas para determinar el estado de las tareas y aplicar estilos condicionales.

Etiquetas: vue.js element-ui vuex Calendar Table

Publicado el 7-16 22:56