Introducción al Frontend en el proyecto

    A partir de hoy, vamos a estar integrando el backend que veníamos desarrollando a una interfaz de usuario hecha con html + css + javascript. Para ello, vamos a tener que crear una nueva carpeta que contenga el frontend. Si bien siempre que se entienda, cualquier separación es correcta, vamos a ofrecer 3 opciones para que tengan en cuenta:

    • Separar el backend y el frontend en carpetas distintas: Para esto, todo lo que veníamos haciendo lo vamos a colocar en la carpeta backend y todo lo que vayamos a hacer relacionado con el frontend lo vamos a poner en la carpeta frontend. Ambas carpetas se suben a un mismo repo
    • Separar el backend y el frontend en repositorios diferentes: Lo mismo que lo anterior, pero ambas carpetas se suben a repositorios distintos
    • Crear una carpeta public dentro del proyecto que ya tenemos, y dentro de ella poner todo lo relacionado con el frontend. Esta es la solución que vamos a usar para los ejemplos del blog

    En cualquier caso, la carpeta que se elija contendrá los archivos html, css y js que vamos a usar para hacer la interfaz de usuario.

    Configuración previa

    Antes de comenzar con la interfaz de usuario, vamos a tener que permitir cors en el backend. Para ello, vamos a tener que hacer uso de la libreria cors, que nos permite recibir solicitudes http de distintos dominios (como el de nuestro frontend)

    npm install cors
    

    Y luego en el archivo de nuestra API express:

    import express from 'express';
    import routes from './routes/index.js';
    import cors from 'cors'; // Importamos cors
    
    const app = express();
    
    // Middlewares
    app.use(express.json());  // Para poder leer el req.body
    app.use(cors());           // Para permitir cors
    
    // Rutas
    app.use(routes);
    
    const port = process.env.PORT || 3000;
    app.listen(port, () => {
      console.log(`Mi aplicacion esta funcionando en http://localhost:${port}`);
    })
    

    Creación de la carpeta frontend

    Vamos a crear la carpeta donde va a ir la interfaz de usuario, y dentro de ella, vamos a crear los archivos que vamos a usar para hacer la interfaz de usuario.

    |-generated
    |-lib
    |-prisma
    |-public
    |--css
    |---styles.css
    |--js
    |---api
    |----tareas.js    // Interacción con el backend para las tareas
    |--pages
    |---tareas
    |----index.html   // Listado de tareas
    |----create.html  // Formulario para crear tareas
    |--index.html     // Pag. principal de su aplicación
    |-routes
    |-.env
    |-.gitignore
    |-index.js
    |-package.json
    

    Archivo api.js

    Es el archivo que va a hacer la interacción con el backend. En principio, vamos a tener solo un archivo que va a hacer la interacción con el backend para las tareas, y vamos a llamarlo tareas.js

    Este archivo va a hacer uso de un comando de javascript llamado fetch, que nos va a permitir hacer solicitudes http a la API. Este comando toma 2 parametros, siendo el primero la URL de la API y el segundo (opcional) un objeto con la configuración de la llamada.

    // public/js/api/tareas.js
    const API_URL = 'http://localhost:8000/tareas'  // URL de la API
    
    export async function getTareas() {
      // Llamada a la API
      const response = await fetch(API_URL)
      const tareas = await response.json()
    
      return tareas // Devuelve las tareas
    }
    
    export async function createTarea(tarea) {
      // Llamada a la API
      const response = await fetch(API_URL, {
        method: 'POST', // Metodo HTTP
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(tarea) // Cuerpo de la llamada (los datos que enviaremos al backend)
      })
      const data = await response.json()
      
      return data;
    }
    

    Uso de las funciones en el HTML

    Para usarlo, vamos a tener que importarlo dentro de nuestro documento html pages/tareas/index.html haciendo uso de la etiqueta <script type="module">. De la siguiente forma

    Listado de tareas

    <!DOCTYPE html>
    <head>
      <title>LIstado de tareas</title>
    </head>
    <body>
      <h1>Listado de tareas</h1>
      <a href="./create.html">Crear nueva</a>
    </body>
    <script type="module">
      import { getTareas } from "../../api/tareas.js";  // Importamos la funcion getTareas
    
      document.addEventListener('DOMContentLoaded', async () => { // Cuando se cargue el DOM
        const tareas = await getTareas()  // Obtenemos las tareas
        console.log(tareas) // Imprimimos las tareas
      })
    </script>
    </html>
    

    Tengan en cuenta que el hecho de poder tener una variable con el listado de tareas es más que suficiente para ser capaces de acceder a las tareas y, más adelante, manipularlas en la interfaz. Mostrarlas en consola es solo una demo de las posibilidades que tenemos.

    Crear una nueva tarea:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
        <h1>Crear tarea</h1>
        <form id="crear-tarea-form">
          <label for="titulo">Titulo</label>
          <input type="text" id="titulo" name="titulo">
          
          <label for="descripcion">Descripcion</label>
          <input type="text" id="descripcion" name="descripcion">
          
          <label for="path">Path</label>
          <input type="text" id="path" name="path">
          
          <button type="submit">Crear</button>
        </form>
    </body>
    <script type="module">
      import { createTarea } from '../../api/tareas.js'
      
      const form = document.getElementById('crear-tarea-form')  // Obtenemos el formulario
    
      form.addEventListener('submit', async (e) => {  // Cuando se envie el formulario
        e.preventDefault()  // Evitamos que la página se recargue
    
        const formData = new FormData(form) // Obtenemos los datos del formulario
    
        const tarea = { // Creamos el objeto de la tarea
          titulo: formData.get('titulo'), 
          descripcion: formData.get('descripcion'), 
          path: formData.get('path')
        }
    
        await createTarea(tarea)  // Creamos la tarea en el backend
        console.log("Tarea creada con exito!")  // :D
      })
    </script>
    </html>