Herramientas de usuario

Herramientas del sitio


codes:registroone

¡Esta es una revisión vieja del documento!


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
function doGet(e) {
  return HtmlService.createTemplateFromFile('index')
    .evaluate()
    .setTitle('Agrega aquí el titulo de tu app');
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

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
<!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="Ingrese la 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>

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
<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>

Este modulo o archivo hace el estilo de la web app

JS.html
<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>

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
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
}

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.

← Volver al Codes

codes/registroone.1771511212.txt.gz · Última modificación: por ggaita