292 lines
8.6 KiB
JavaScript
292 lines
8.6 KiB
JavaScript
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 = `<input type="text" value="${columnaActual}" class="input-descripcion-gasto">`;
|
|
|
|
// Convertir monto a input
|
|
celdas[1].innerHTML = `<input type="number" value="${montoActual}" step="0.01" min="0" class="input-monto-gasto">`;
|
|
|
|
// 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');
|
|
}
|
|
}
|