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.