let gastosActuales = {}; let columnasGastos = []; // Columnas dinámicas de gastos document.addEventListener('DOMContentLoaded', () => { cargarEstructuraGastos(); setupFormListeners(); }); function setupFormListeners() { // Formulario para agregar nuevo tipo de gasto const formAgregarTipo = document.getElementById('form-agregar-tipo-gasto'); if (formAgregarTipo) { formAgregarTipo.addEventListener('submit', handleAgregarTipoGasto); } } // ========== CARGAR ESTRUCTURA DINÁMICA ========== async function cargarEstructuraGastos() { try { const response = await fetch('../php/Obtener_Gastos.php'); const data = await response.json(); if (data.success) { columnasGastos = data.columnas || []; gastosActuales = data.gasto || {}; construirFormularioDinamico(); } else { console.log('No hay gastos registrados:', data.message); columnasGastos = []; construirFormularioDinamico(); } } catch (error) { console.error('Error al cargar gastos:', error); } } // ========== CONSTRUIR FORMULARIO DINÁMICO ========== function construirFormularioDinamico() { // Solo mostrar tabla de gastos mostrarTablaGastos(); } // ========== AGREGAR NUEVO TIPO DE GASTO ========== async function handleAgregarTipoGasto(e) { e.preventDefault(); const nombre = document.getElementById('nombre-nuevo-gasto').value.trim(); const monto = parseFloat(document.getElementById('monto-nuevo-gasto').value); if (!nombre || monto < 0) { alert('Por favor completa los datos correctamente'); return; } // Validar nombre (solo letras y espacios) if (!/^[a-zA-Z\s]+$/.test(nombre)) { alert('El nombre del gasto solo puede contener letras y espacios'); return; } try { const response = await fetch('../php/Registrar_Gastos.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nuevo_gasto: nombre, monto: monto }) }); const data = await response.json(); if (data.success) { alert('Nuevo tipo de gasto agregado correctamente'); document.getElementById('form-agregar-tipo-gasto').reset(); cargarEstructuraGastos(); } else { alert('Error al agregar gasto: ' + data.message); } } catch (error) { console.error('Error:', error); alert('Error de conexión'); } } // ========== MOSTRAR TABLA DE GASTOS ========== function mostrarTablaGastos() { const tabla = document.getElementById('tabla-gastos'); if (!tabla) return; const tbody = tabla.querySelector('tbody'); tbody.innerHTML = ''; if (columnasGastos.length === 0) { const tr = document.createElement('tr'); const td = document.createElement('td'); td.colSpan = 3; td.textContent = 'No hay gastos configurados'; td.style.textAlign = 'center'; td.style.color = '#999'; tr.appendChild(td); tbody.appendChild(tr); return; } columnasGastos.forEach(columna => { const tr = document.createElement('tr'); const monto = gastosActuales[columna] || 0; const descripcionFormato = columna.charAt(0).toUpperCase() + columna.slice(1); // Descripción const tdDesc = document.createElement('td'); tdDesc.textContent = descripcionFormato; tr.appendChild(tdDesc); // Monto const tdMonto = document.createElement('td'); tdMonto.textContent = `$${parseFloat(monto).toFixed(2)}`; tr.appendChild(tdMonto); // Acciones const tdAcciones = document.createElement('td'); tdAcciones.style.display = 'flex'; tdAcciones.style.gap = '10px'; // Botón Editar const btnEditar = document.createElement('button'); btnEditar.type = 'button'; btnEditar.className = 'btn-editar-gasto'; btnEditar.textContent = 'Editar'; btnEditar.addEventListener('click', () => activarEdicionGasto(btnEditar, columna)); tdAcciones.appendChild(btnEditar); // Botón Eliminar const btnEliminar = document.createElement('button'); btnEliminar.type = 'button'; btnEliminar.className = 'btn-eliminar-gasto'; btnEliminar.textContent = 'Eliminar'; btnEliminar.addEventListener('click', () => abrirModalEliminar(columna)); tdAcciones.appendChild(btnEliminar); tr.appendChild(tdAcciones); tbody.appendChild(tr); }); } // ========== EDITAR GASTO ========== function activarEdicionGasto(btnEditar, columnaActual) { const fila = btnEditar.closest('tr'); const celdas = fila.querySelectorAll('td'); const descripcionActual = celdas[0].textContent; const montoActual = parseFloat(celdas[1].textContent.replace('$', '')); // Convertir descripción a input celdas[0].innerHTML = ``; // Convertir monto a input celdas[1].innerHTML = ``; // Crear botones Guardar y Cancelar const btnGuardar = document.createElement('button'); btnGuardar.type = 'button'; btnGuardar.textContent = 'Guardar'; btnGuardar.className = 'btn-guardar'; btnGuardar.addEventListener('click', () => guardarEdicionGasto(fila, columnaActual, montoActual, descripcionActual)); const btnCancelar = document.createElement('button'); btnCancelar.type = 'button'; btnCancelar.textContent = 'Cancelar'; btnCancelar.className = 'btn-cancelar'; btnCancelar.addEventListener('click', () => cancelarEdicionGasto(fila, columnaActual, montoActual, descripcionActual)); // Reemplazar botones en la celda de acciones celdas[2].innerHTML = ''; celdas[2].appendChild(btnGuardar); celdas[2].appendChild(btnCancelar); } function cancelarEdicionGasto(fila, columnaActual, montoActual, descripcionActual) { const celdas = fila.querySelectorAll('td'); // Restaurar descripción celdas[0].textContent = descripcionActual; // Restaurar monto celdas[1].textContent = `$${parseFloat(montoActual).toFixed(2)}`; // Restaurar botones Editar y Eliminar const btnEditar = document.createElement('button'); btnEditar.type = 'button'; btnEditar.className = 'btn-editar-gasto'; btnEditar.textContent = 'Editar'; btnEditar.addEventListener('click', () => activarEdicionGasto(btnEditar, columnaActual)); const btnEliminar = document.createElement('button'); btnEliminar.type = 'button'; btnEliminar.className = 'btn-eliminar-gasto'; btnEliminar.textContent = 'Eliminar'; btnEliminar.addEventListener('click', () => abrirModalEliminar(columnaActual)); celdas[2].innerHTML = ''; celdas[2].appendChild(btnEditar); celdas[2].appendChild(btnEliminar); } async function guardarEdicionGasto(fila, columnaActual, montoActual, descripcionActual) { const nuevoNombre = fila.querySelector('.input-descripcion-gasto').value.trim(); const nuevoMonto = parseFloat(fila.querySelector('.input-monto-gasto').value); if (!nuevoNombre) { alert('El nombre no puede estar vacío'); return; } if (isNaN(nuevoMonto) || nuevoMonto < 0) { alert('El monto debe ser un número válido y mayor o igual a 0'); return; } try { const response = await fetch('../php/Editar_Gasto.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ columna_actual: columnaActual, columna_nueva: nuevoNombre, monto: nuevoMonto }) }); const data = await response.json(); if (data.success) { alert('Gasto editado correctamente'); cargarEstructuraGastos(); } else { alert('Error al editar gasto: ' + data.message); cancelarEdicionGasto(fila, columnaActual, montoActual, descripcionActual); } } catch (error) { console.error('Error:', error); alert('Error de conexión'); cancelarEdicionGasto(fila, columnaActual, montoActual, descripcionActual); } } // ========== ELIMINAR GASTO ========== function abrirModalEliminar(columna) { const confirmar = confirm(`¿Deseas eliminar el gasto "${columna}"? Esta acción no se puede deshacer.`); if (confirmar) { eliminarGasto(columna); } } async function eliminarGasto(columna) { try { const response = await fetch('../php/Eliminar_Gasto.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ columna: columna }) }); const data = await response.json(); if (data.success) { alert('Gasto eliminado correctamente'); cargarEstructuraGastos(); } else { alert('Error al eliminar gasto: ' + data.message); } } catch (error) { console.error('Error:', error); alert('Error de conexión'); } }