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

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
codes:registroone [2026/02/19 13:23] 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.1771507425.txt.gz · Última modificación: por ggaita