Spaces:
Running
Running
| // ================================ | |
| // INICIALIZACIÓN Y CARGA DE DATOS | |
| // ================================ | |
| $(document).ready(function () { | |
| // Cargar datos principales al inicializar | |
| cargarDatosIniciales(); | |
| // Configurar event handlers | |
| configurarEventHandlers(); | |
| // Configurar validación en tiempo real | |
| configurarValidacion(); | |
| }); | |
| // Cargar todos los datos iniciales desde archivos JSON | |
| function cargarDatosIniciales() { | |
| // Cargar tipos y categorías | |
| fetch('tipos_categoria_subcategoria.json') | |
| .then(response => response.json()) | |
| .then(data => { | |
| window.data = data; | |
| cargarTipos(); | |
| }) | |
| .catch(error => console.error('Error al cargar tipos y categorías:', error)); | |
| // Cargar usuarios | |
| fetch('usuarios.json') | |
| .then(response => response.json()) | |
| .then(usuariosData => { | |
| window.usuarios = usuariosData; | |
| cargarUsuarios(); | |
| }) | |
| .catch(error => console.error('Error al cargar usuarios:', error)); | |
| } | |
| // ================================ | |
| // EVENT HANDLERS | |
| // ================================ | |
| function configurarEventHandlers() { | |
| // Cambiar categorías al seleccionar tipo | |
| $('#tipo').change(function () { | |
| cargarCategorias(); | |
| }); | |
| // Manejar envío del formulario | |
| $('#transaccion-form').on('submit', function (e) { | |
| e.preventDefault(); | |
| procesarFormulario(this); | |
| }); | |
| } | |
| // ================================ | |
| // PROCESAMIENTO DEL FORMULARIO | |
| // ================================ | |
| function procesarFormulario(form) { | |
| // Validar formulario | |
| if (!form.checkValidity()) { | |
| mostrarMensaje('Por favor, completa todos los campos requeridos.', 'error'); | |
| return; | |
| } | |
| // Preparar datos | |
| const formDataArray = $(form).serializeArray(); | |
| const jsonData = prepararDatos(formDataArray); | |
| // Mostrar spinner | |
| mostrarSpinner(); | |
| // Enviar datos | |
| enviarTransaccion(jsonData); | |
| } | |
| function prepararDatos(formDataArray) { | |
| const jsonData = {}; | |
| // Agregar fecha actual formateada | |
| const datetime = new Date().toLocaleString('es-PE', { | |
| timeZone: 'America/Lima', | |
| hour12: false | |
| }); | |
| jsonData['fecha'] = formatearFecha(datetime); | |
| // Convertir datos del formulario a JSON | |
| formDataArray.forEach(item => { | |
| jsonData[item.name] = item.value; | |
| }); | |
| return jsonData; | |
| } | |
| function formatearFecha(datetime) { | |
| return datetime.replace(/(\d+)\/(\d+)\/(\d+), (\d+):(\d+):(\d+)/, '$3-$2-$1 $4:$5:$6'); | |
| } | |
| function enviarTransaccion(jsonData) { | |
| const url = 'https://script.google.com/macros/s/AKfycbyoS_q9j7Hixi1-dxVg6S7LKqb9o_Pma2I0mnBPmZ_vlKKSWyPY8lpw66woTMkyaD04/exec'; | |
| fetch(url, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify([jsonData]), | |
| mode: 'no-cors' | |
| }) | |
| .then(() => { | |
| mostrarMensaje('¡Transacción registrada exitosamente!', 'exito'); | |
| setTimeout(() => location.reload(), 4000); | |
| }) | |
| .catch(() => { | |
| mostrarMensaje('Hubo un problema con la solicitud.', 'error'); | |
| }) | |
| .finally(() => { | |
| ocultarSpinner(); | |
| }); | |
| } | |
| // ================================ | |
| // FUNCIONES DE CARGA DE DATOS | |
| // ================================ | |
| function cargarTipos() { | |
| const tipoSelect = document.getElementById('tipo'); | |
| tipoSelect.innerHTML = '<option value="">Selecciona un tipo</option>'; | |
| if (window.data?.tipo) { | |
| Object.keys(window.data.tipo).forEach(tipo => { | |
| const option = crearOption(tipo, tipo); | |
| tipoSelect.appendChild(option); | |
| }); | |
| } | |
| } | |
| function cargarCategorias() { | |
| const tipoSelect = document.getElementById('tipo'); | |
| const categoriaSelect = document.getElementById('categoria'); | |
| // Limpiar categorías | |
| categoriaSelect.innerHTML = '<option value="">Selecciona una categoría</option>'; | |
| if (window.data?.tipo && tipoSelect.value) { | |
| const categorias = Object.keys(window.data.tipo[tipoSelect.value]); | |
| categorias.forEach(categoria => { | |
| const option = crearOption(categoria, categoria); | |
| categoriaSelect.appendChild(option); | |
| }); | |
| } | |
| } | |
| function cargarUsuarios() { | |
| const usuarioSelect = document.getElementById('usuario'); | |
| usuarioSelect.innerHTML = '<option value="">Selecciona un usuario</option>'; | |
| if (window.usuarios?.nombre_usuarios) { | |
| window.usuarios.nombre_usuarios.forEach(usuario => { | |
| const option = crearOption(usuario, usuario); | |
| usuarioSelect.appendChild(option); | |
| }); | |
| } | |
| } | |
| // ================================ | |
| // UTILIDADES | |
| // ================================ | |
| function crearOption(value, text) { | |
| const option = document.createElement('option'); | |
| option.value = value; | |
| option.textContent = text; | |
| return option; | |
| } | |
| function mostrarSpinner() { | |
| $('#loading').show(); | |
| } | |
| function ocultarSpinner() { | |
| $('#loading').hide(); | |
| } | |
| function mostrarMensaje(texto, tipo = 'info') { | |
| const contenedor = document.getElementById('mensaje'); | |
| const iconos = { | |
| exito: `<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path> | |
| </svg>`, | |
| error: `<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> | |
| </svg>`, | |
| advertencia: `<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path> | |
| </svg>` | |
| }; | |
| contenedor.innerHTML = ` | |
| <div class="mensaje-${tipo} flex items-center"> | |
| ${iconos[tipo] || ''} | |
| <span>${texto}</span> | |
| </div> | |
| `; | |
| // Auto-ocultar después de 5 segundos | |
| setTimeout(() => { | |
| contenedor.innerHTML = ''; | |
| }, 5000); | |
| } | |
| // ================================ | |
| // VALIDACIÓN EN TIEMPO REAL | |
| // ================================ | |
| function configurarValidacion() { | |
| document.addEventListener('DOMContentLoaded', () => { | |
| const inputs = document.querySelectorAll('input, select, textarea'); | |
| inputs.forEach(input => { | |
| // Validar al perder foco | |
| input.addEventListener('blur', () => { | |
| validarCampo(input); | |
| }); | |
| // Limpiar validación al escribir | |
| input.addEventListener('input', () => { | |
| limpiarValidacion(input); | |
| }); | |
| }); | |
| }); | |
| } | |
| function validarCampo(input) { | |
| if (input.hasAttribute('required')) { | |
| if (input.value.trim() === '') { | |
| marcarComoInvalido(input); | |
| } else { | |
| marcarComoValido(input); | |
| } | |
| } | |
| } | |
| function marcarComoInvalido(input) { | |
| input.classList.add('field-invalid'); | |
| input.classList.remove('field-valid'); | |
| } | |
| function marcarComoValido(input) { | |
| input.classList.add('field-valid'); | |
| input.classList.remove('field-invalid'); | |
| } | |
| function limpiarValidacion(input) { | |
| input.classList.remove('field-invalid', 'field-valid'); | |
| } | |
| // ================================ | |
| // FUNCIONES GLOBALES (Para compatibilidad) | |
| // ================================ | |
| // Mantener estas funciones para compatibilidad con el HTML actual | |
| window.cargarCategorias = cargarCategorias; | |
| window.mostrarSpinner = mostrarSpinner; | |