Herramientas de usuario

Herramientas del sitio


codes:registroone

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Próxima revisión
Revisión previa
codes:registroone [2026/02/19 13:22] – creado ggaitacodes:registroone [2026/02/19 14:28] (actual) ggaita
Línea 1: Línea 1:
-======Formulario Google App Script - Monocurso======+======Formulario Google Apps Script - Monocurso====== 
 + 
 +------ 
 + 
 +====Inicios==== 
 + 
 +Mediante este formulario, buscamos una adaptacion al googleForm pero más personal... 
 +Se debe crear un nuevo "sheet", y desde allí acceder a la pestaña extensiones y seleccionar Apps Script. 
 + 
 + 
 +====Modulos==== 
 + 
 +La app se resuelve en 5 modulos o archivos, cada uno con la extensión .gs o .html, propias de apps script.  
 + 
 +==server.gs== 
 + 
 +<code> 
 + 
 +function doGet(e) { 
 +  return HtmlService.createTemplateFromFile('index'
 +    .evaluate() 
 +    .setTitle('Agrega aquí el titulo de tu app'); 
 +
 + 
 +function include(filename) { 
 +  return HtmlService.createHtmlOutputFromFile(filename).getContent(); 
 +
 + 
 +</code> 
 +Este módulo: 
 + 
 +  * Recibe una petición web. 
 +  * Carga index.html. 
 +  * Procesa el template. 
 +  * Define el título. 
 +  * Permite incluir archivos HTML adicionales. 
 + 
 +==index.html== 
 + 
 +<code> 
 +<!DOCTYPE html> 
 +<html lang="en"> 
 +<head> 
 +    <meta charset="UTF-8"> 
 +    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
 +    <title>EJEMPLO DE TITULO</title> 
 +    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css"> 
 +    <?!= include('CSS'); ?> 
 +</head> 
 +<body> 
 +    <main> 
 +        <!--<div class="form-container"> 
 +        <h3>Gracias por Comunicarse</h3> 
 +          <p>Se ha superado el número de inscriptos en relación a las vacantes.</p> 
 +          <p>Le invitamos a inscribirse para el <strong>Segundo Sementre 2025.</strong></p> --> 
 +          <form id="registroForm"> 
 +                <div class="form-group"> 
 +                    <h2>Curso para Docentes: </h2> 
 +                    <h2>PRE-INSCRIPCIÓN AL CURSO</h2> 
 +                    <h2>h2</h2> 
 +                    <h3>h3</h3> 
 +                    <img src="imagen que quieras" alt="Logo"> 
 +                    <p><strong>Importante:</strong> "Texto que quieras".</p> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="nombre">Nombres</label> 
 +                    <input type="text" id="nombre" name="nombre" placeholder="Ingrese su nombre" required> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="apellido">Apellidos</label> 
 +                    <input type="text" id="apellido" name="apellido" placeholder="Ingrese su apellido" required> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="dni">Documento</label> 
 +                    <input type="text" id="dni" name="dni" placeholder="Ingrese su DNI" maxlength="8" required> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="telefono">Teléfono</label> 
 +                    <input type="text" id="telefono" name="telefono" placeholder="Ingrese su teléfono" required> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="email">Email</label> 
 +                    <input type="email" id="email" name="email" placeholder="Ingrese su email" required> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="localidad">Localidad</label> 
 +                    <input type="text" id="localidad" name="localidad" placeholder="Ingrese su localidad" required> 
 +                </div> 
 +                <div class="form-group"> 
 +                    <label for="condicion">Condición</label>           //Un Select 
 +                    <select id="condicion" name="condicion" required> 
 +                        <option value="">Seleccione...</option> 
 +                        <option value="Estudiante">Estudiante</option> 
 +                        <option value="Docente">Docente</option> 
 +                    </select> 
 +                </div> 
 +                 
 +                <div id="docenteExtras" style="display: none;"> 
 +                    <div class="form-group"> 
 +                        <label for="institucion">Institución</label> 
 +                        <input type="text" id="institucion" name="institucion" placeholder="institución"> 
 +                    </div> 
 +                    <div class="form-group"> 
 +                        <label for="nivelEducativo">Nivel Educativo</label> 
 +                        <select id="nivelEducativo" name="nivelEducativo"> 
 +                            <option value="">Seleccione...</option> 
 +                            <option value="Inicial">Inicial</option> 
 +                            <option value="Primario">Primario</option> 
 +                            <option value="Secundario">Secundario</option> 
 +                            <option value="Superior">Superior</option> 
 +                            <option value="Otro">Otro</option> 
 +                        </select> 
 +                    </div> 
 +                </div> 
 +                <div class="form-group"> 
 +                <button type="submit">Enviar</button> 
 +                </div> 
 +            </form> 
 +        </div> 
 +    </main> 
 +    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.js"></script> 
 +    <?!= include('JS'); ?> 
 +    <script> 
 +        document.getElementById('condicion').addEventListener('change', function() { 
 +            var extras = document.getElementById('docenteExtras'); 
 +            extras.style.display = this.value === 'Docente' ? 'block' : 'none'; 
 +        }); 
 +    </script> 
 +</body> 
 +</html> 
 +</code> 
 + 
 +Este archivo es la interfaz de usuario de tu Web App, que muestra un formulario dinámico con validación básica y campos condicionales, usando modularización de HTML, CSS y JS dentro de Apps Script. 
 + 
 +==CSS.html== 
 + 
 +<code> 
 +<style> 
 + 
 +body { 
 +    font-family: Arial, sans-serif; 
 +    margin: 0; 
 +    padding: 0; 
 +    display: flex; 
 +    justify-content: center; 
 +    align-items: center; 
 +    align-items: center; 
 +    min-height: 100vh; 
 +    background-color: #2a395e; 
 +    color: #b6bed4; 
 +
 + 
 +.form-container { 
 +    width: 90%; 
 +    max-width: 600px; 
 +    background: #FEFADC; 
 +    padding: 20px; 
 +    border-radius: 8px; 
 +    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); 
 +    align-items: center; 
 +    box-shadow: -3px 3px 2px rgba(71, 69, 69, 0.269); 
 +    display: flex; 
 +    flex-direction: column; 
 +    justify-content: center; 
 +    align-content: center; 
 +    margin: 15px 0; 
 +
 + 
 +img { 
 +    width: 250px; 
 +
 + 
 +h2, 
 +h3, 
 +p { 
 +    text-align: center; 
 +
 + 
 +h2 { 
 +    font-size: 22px; 
 +
 + 
 +h3 { 
 +    font-size: 20px; 
 +
 + 
 +.form-group { 
 +    margin-bottom: 15px; 
 +    align-items: center; 
 +    display: flex; 
 +    flex-direction: column; 
 +
 + 
 +label { 
 +    display: block; 
 +    margin-bottom: 5px; 
 +    font-weight: bold; 
 +    font-size: 18px; 
 +
 + 
 +input { 
 +    width: 90%; 
 +    padding: 10px; 
 +    border: 1px solid #a9a4a4; 
 +    border-radius: 4px; 
 +    font-size: 16px; 
 +
 + 
 +select { 
 +    width: 93%; 
 +    padding: 10px; 
 +    border: 1px solid #a9a4a4; 
 +    border-radius: 4px; 
 +    font-size: 16px; 
 +
 + 
 +button { 
 +    margin-top: 25px; 
 +    width: 90%; 
 +    height: 60px; 
 +    align-items: center; 
 +    padding: 10px; 
 +    background-color: #59bd68; 
 +    color: rgb(255, 255, 255); 
 +    border: none; 
 +    border-radius: 4px; 
 +    font-size: 30px; 
 +    cursor: pointer; 
 +    box-shadow: -3px 3px 2px rgba(71, 69, 69, 0.269); 
 +
 + 
 +button:hover { 
 +    background-color: #06d425; 
 +    color: black; 
 +
 + 
 +@media (max-width: 1024px) { 
 + 
 +    .form-container { 
 +        padding: 15px; 
 +    } 
 + 
 +    input, select { 
 +        font-size: 28px; 
 +    } 
 + 
 +    button { 
 +        font-size: 30px; 
 +    } 
 +    h2 { 
 +        font-size: 50px; 
 +    } 
 + 
 +    h3 { 
 +        font-size: 32px; 
 +    } 
 + 
 +    p { 
 +        font-size: 28px; 
 +    } 
 + 
 +    label { 
 +    margin-bottom: 10px; 
 +    font-size: 32px; 
 +    } 
 +
 + 
 +</style> 
 +</code> 
 + 
 +Este modulo o archivo hace el estilo de la web app 
 + 
 +==JS.html== 
 + 
 +<code> 
 +<script> 
 +document.getElementById("registroForm").addEventListener("submit", function(event) { 
 +  event.preventDefault(); 
 + 
 +  // Mostrar loading 
 +  const swalLoading = Swal.fire({ 
 +    title: 'Enviando datos...', 
 +    text: 'Estamos procesando su solicitud. Por favor espere.', 
 +    icon: 'info', 
 +    showConfirmButton: false, 
 +    allowOutsideClick: false, 
 +    willOpen: () => { 
 +      Swal.showLoading(); 
 +    } 
 +  }); 
 + 
 +  // Obtener valores 
 +  const nombre = document.getElementById("nombre").value.trim(); 
 +  const apellido = document.getElementById("apellido").value.trim(); 
 +  const telefono = document.getElementById("telefono").value.trim(); 
 +  const dni = document.getElementById("dni").value.trim(); 
 +  const email = document.getElementById("email").value.trim(); 
 +  const localidad = document.getElementById("localidad").value.trim(); 
 +  const condicion = document.getElementById("condicion").value; 
 +  const institucion = document.getElementById("institucion").value.trim(); 
 +  const nivelEducativo = document.getElementById("nivelEducativo").value; 
 + 
 +  // Validación básica 
 +  if (!nombre || !apellido || !telefono || !dni || !localidad || !condicion || !email) { 
 +    swalLoading.close(); 
 +    Swal.fire({ 
 +      icon: 'error', 
 +      title: 'Error', 
 +      text: 'Por favor complete todos los campos.', 
 +      confirmButtonText: 'Aceptar' 
 +    }); 
 +    return; 
 +  } 
 + 
 +  // Validar DNI (8 números) 
 +  if (!/^\d{8}$/.test(dni)) { 
 +    swalLoading.close(); 
 +    Swal.fire({ 
 +      icon: 'error', 
 +      title: 'Error', 
 +      text: 'El DNI debe tener 8 dígitos.', 
 +      confirmButtonText: 'Aceptar' 
 +    }); 
 +    return; 
 +  } 
 + 
 +  // Validar Teléfono (7 a 15 números) 
 +  if (!/^\d{7,15}$/.test(telefono)) { 
 +    swalLoading.close(); 
 +    Swal.fire({ 
 +      icon: 'error', 
 +      title: 'Error', 
 +      text: 'El teléfono debe tener entre 7 y 15 dígitos.', 
 +      confirmButtonText: 'Aceptar' 
 +    }); 
 +    return; 
 +  } 
 + 
 +  // Validar Email 
 +  const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; 
 +  if (!emailPattern.test(email)) { 
 +    swalLoading.close(); 
 +    Swal.fire({ 
 +      icon: 'error', 
 +      title: 'Error', 
 +      text: 'El formato del correo electrónico es inválido.', 
 +      confirmButtonText: 'Aceptar' 
 +    }); 
 +    return; 
 +  } 
 + 
 +  // Enviar a Apps Script 
 +  google.script.run 
 +    .withSuccessHandler(function(response) { 
 +      swalLoading.close(); 
 + 
 +      // 🚫 Cupos completos 
 +      if (response === "cuposCompletos") { 
 +        Swal.fire({ 
 +          icon: 'warning', 
 +          title: 'Cupos Completos', 
 +          text: 'Se alcanzaron las 400 plazas disponibles. Espere al próximo Semestre.', 
 +          confirmButtonText: 'Aceptar', 
 +          confirmButtonColor: '#d33' 
 +        }); 
 + 
 +        // Desactivar botón 
 +        document.getElementById("registroForm").reset(); 
 +        document.querySelector("button[type='submit']").disabled = true; 
 +        return; 
 +      } 
 + 
 +      // ✅ Registro exitoso 
 +      if (response === "registrado") { 
 +        Swal.fire({ 
 +          icon: 'success', 
 +          title: 'Registro Exitoso', 
 +          text: 'Usted ha sido registrado correctamente.', 
 +          confirmButtonText: 'Aceptar' 
 +        }); 
 + 
 +        document.getElementById("registroForm").reset(); 
 +        document.getElementById("docenteExtras").style.display = "none"; 
 +        return; 
 +      } 
 + 
 +      // ⚠ DNI existente 
 +      if (response === "existente") { 
 +        Swal.fire({ 
 +          icon: 'warning', 
 +          title: 'DNI ya registrado', 
 +          text: 'Este DNI ya se encuentra inscripto.', 
 +          confirmButtonText: 'Aceptar' 
 +        }); 
 +        return; 
 +      } 
 + 
 +      // ⚠ Email existente 
 +      if (response === "emailExistente") { 
 +        Swal.fire({ 
 +          icon: 'warning', 
 +          title: 'Email ya registrado', 
 +          text: 'Este correo electrónico ya se encuentra inscripto.', 
 +          confirmButtonText: 'Aceptar' 
 +        }); 
 +        return; 
 +      } 
 + 
 +      // ❓ Respuesta inesperada 
 +      Swal.fire({ 
 +        icon: 'error', 
 +        title: 'Error', 
 +        text: 'Respuesta inesperada del servidor.', 
 +        confirmButtonText: 'Aceptar' 
 +      }); 
 + 
 +    }) 
 +    .withFailureHandler(function(error) { 
 +      swalLoading.close(); 
 +      Swal.fire({ 
 +        icon: 'error', 
 +        title: 'Error', 
 +        text: 'Hubo un error al procesar su solicitud.', 
 +        confirmButtonText: 'Aceptar' 
 +      }); 
 +    }) 
 +    .registrarConductor( 
 +      nombre, 
 +      apellido, 
 +      telefono, 
 +      dni, 
 +      email, 
 +      localidad, 
 +      condicion, 
 +      institucion, 
 +      nivelEducativo 
 +    ); 
 + 
 +}); 
 +</script> 
 +</code> 
 + 
 +Este modulo:  
 + 
 +  * Intercepta el envío del formulario. 
 +  * Valida los datos en el navegador. 
 +  * Muestra un loading profesional. 
 +  * Envía los datos al servidor (Apps Script). 
 +  * Maneja todas las posibles respuestas del backend. 
 +  * Muestra mensajes según el resultado. 
 + 
 +Es el controlador frontend que valida datos, se comunica con Apps Script y maneja la lógica de inscripción según la respuesta del servidor. 
 + 
 +==validator.gs== 
 + 
 +<code> 
 +function registrarConductor(nombre, apellido, telefono, dni, email, localidad, condicion, institucion, nivelEducativo) { 
 +  var ss = SpreadsheetApp.openById('Acá pones el ID de tu Sheet'); // ID de la hoja 
 +  var sheet = ss.getSheetByName('registro'); //Acá el nombre de tu hoja, o tabla 
 +   
 +  var registros = sheet.getDataRange().getValues(); 
 + 
 +  var MAX_CUPOS = 400;  // Puse un cupo, para tener un freno. 
 + 
 +  if ((registros.length - 1) >= MAX_CUPOS) { 
 +    return "cuposCompletos"; 
 +  } 
 + 
 +  // Verificar si el DNI ya existe (columna D - índice 3) 
 +  for (var i = 1; i < registros.length; i++) { // Empezamos en la fila 1 para omitir encabezados 
 +    if (registros[i][3] == dni) { // Columna D (DNI) 
 +      return "existente"; // DNI ya registrado 
 +    } 
 +  } 
 + 
 +  // Verificar si el Email ya existe (columna F - índice 5) 
 +  for (var i = 1; i < registros.length; i++) { // Empezamos en la fila 1 para omitir encabezados 
 +    if (registros[i][5] == email) { // Columna F (Email) 
 +      return "emailExistente"; // Email ya registrado 
 +    } 
 +  } 
 + 
 +  // Calcular el siguiente ID (columna A) 
 +  var id = registros.length; 
 + 
 +  // Agregar un nuevo registro (orden correcto según las columnas) 
 +  sheet.appendRow([ 
 +    id,              // A: ID 
 +    nombre,          // B: NOMBRES 
 +    apellido,        // C: APELLIDOS 
 +    dni,             // D: DNI 
 +    telefono,        // E: TELÉFONO 
 +    email,           // F: EMAIL 
 +    localidad,       // G: LOCALIDAD 
 +    condicion,       // H: CONDICIÓN 
 +    institucion,     // I: INSTITUCIÓN 
 +    nivelEducativo   // J: NIVEL EDUCATIVO 
 +  ]); 
 + 
 +  return "registrado"; // Confirmación de registro exitoso 
 +
 +</code> 
 + 
 +Esta función es el controlador de negocio que valida cupos, previene duplicados y guarda la inscripción en Google Sheets, devolviendo estados específicos al frontend. 
 + 
 + 
 + 
 + 
 +[[CoDES:CoDES|← Volver al Codes]]
codes/registroone.1771507377.txt.gz · Última modificación: por ggaita