Descripcion del proyecto

El proyecto consiste en un bloc de tareas en el cual cada usuario se autentica utilizando un magic link y puede agregar, borrar y marcar como completadas sus tareas. Ademas de poder agruparlas en grupos de tareas y poder descargar un pdf con todas las tareas de ese grupo, tambien se puede agregar una imagen a cada tarea para poder indentificarla.

El proyecto utiliza las tecnologias: react, supabase, docker, nodejs y npm que son las que hemos enseñado a introducirlas en un proyecto

Desarrollo de supabase

A la hora de desarrollar con supabase tenemos que conocer como funciona su libreria (En este caso para javascript), en funcion de lenguaje de programacion estes utilizando tendras que usar la que corresponda

La librería de Supabase tiene que ser capaz de gestionar todo un backend con lo que conlleva (base de datos, autenticación del usuario, lógica, etc.). Para hacer todo esto, utiliza:

  • - PostgreSQL como base de datos relacional. PostgreSQL es una base de datos de código abierto y altamente potente y escalable.

  • - Realtime Postgres. Supabase utiliza la funcionalidad de notificaciones de PostgreSQL para proporcionar actualizaciones en tiempo real a través de WebSockets.

  • - PostgREST como capa de API REST. PostgREST es una herramienta que genera una API RESTful sobre una base de datos PostgreSQL, lo que permite interactuar con la base de datos utilizando peticiones HTTP.

  • - Auth. Supabase utiliza un sistema de autenticación basado en JWT (JSON Web Tokens) para autenticar usuarios y gestionar sesiones de usuario de forma segura.

  • - Storage. Supabase proporciona un servicio de almacenamiento de archivos, que utiliza almacenamiento en la nube (como AWS S3) para almacenar los archivos de los usuarios.

  • - GraphQL. Supabase ofrece soporte para GraphQL, lo que permite a los desarrolladores consultar y manipular los datos utilizando un lenguaje de consulta flexible y poderoso.

  • - WebSockets. Supabase utiliza WebSockets para proporcionar funcionalidades en tiempo real, como notificaciones y actualizaciones automáticas de datos.

Gracias a estas tecnologias supabase nos proporciana funciones de autenticación del usuario como puede ser supabase.auth.getUser() la cual nos da en JSON toda la informacion acerca del usuario que esta autenticado o supabase.auth.signOut() que nos permite deslogear al usuario en cualquier contexto

Tambien podemos utilizar supabase.from("tabla") que nos permite seleccionar cualquier tabla de la base de datos para poder hacer operaciones crud en ella

  • supabase.from("tabla").insert()
  • supabase.from("tabla").update()
  • supabase.from("tabla").delete()
  • supabase.from("tabla").select()

Por supuesto que podemos hacer comprobaciones a lo hora de hacer update, delete o select utilizando la funcion .eq()

Y el resultado de la operacion la podemos recoger añadiendo la funcion .select() al final de la sentencia. Por ejemplo para añadir una tarea en nuestro proyecto y recoger el resultado de la operacion haremos lo siguiente:

  • const user = supabase.auth.getUser();
  • const { error, data } = await supabase.from("tasks").insert({ name: taskName, userid: (await user).data.user.id, }).select()

Como podemos ver se recoje el usuario para hacer el insert de la tarea con su usuario insertado, y hacemos el insert dentro de la tabla "tasks", y para recoger el resultado y guardar el {data, error} de este utilizamos la sentencia .select() al final

Por ultimo, a la hora de realizar la subida y descarga de archivos para que se muestren y eliminarlos en el caso de que la tarea a la que estan asociados se borre.

Para ello utilizamos los buckets los cuales son almacenes de archivos con permisos propios los cuales nos ayudan a gestionar la subida de archivos. Estos se pueden crear y gestionar desde la interfaz web de supabase como hemos explicado en el setup del proyecto pero tambien podemos hacerlo desde react utilizando algo asi como un "CRUD" pero para buckets:

  • supabase.storage.createBucket()
  • supabase.storage.getBucket()
  • supabase.storage.updateBucket()
  • supabase.storage.deleteBucket()

Ovbiamente que tenemos mas opciones para trabajar con buckets pero no son tan importantes por lo que os dejo la referencia a la documentacion por si quereis mas informacion

Ahora para subir nuestra imagen en nuestro proyecto simplemente tendremos que hacer otro CRUD muy sencillo y parecido al que hemos hecho antes pero para poder subir, descargar y eliminar archivos

  • supabase.storage.from("bucket").upload()
  • supabase.storage.from("bucket").download()
  • supabase.storage.from("bucket").remove()

Recordemos que tenemos opciones para mover, copiar, listar todos los archivos de un bucket, etc... pero no son tan importantes y no son tan usadas igualmente puedes ver todas estas operaciones aqui

A la hora de guardar la tarear de la misma forma de la que lo hemos hecho antes, vamos a insertar la imagenes tanto la ruta en el campo de la base de datos como el archivo en el bucket, lo que nos quedaria asi:

  • const { data, error } = await supabase.storage
  • .from("tasks") .upload(`task_images/${image.name}`, image);
    taskData.image_url = data.path;

De esta forma ya sabemos como podemos hacer cualquier operacion realacionada con la base de datos, subida de archivos y con la autenticacion del ususario, si quieres saber mas informacion puedes encontrar cualquier cosa sobre supabase en su documentacion que esta muy bien explicada y te sera muy sencillo encontrarlo. Por ultimo, es interesante revisar la documentacion periodicamente ya que hacen bastantes cambios de una version a otra

Desarrollo de React

A la hora de desarrollar con React o con cualquier otro lenguale de programacion debemos tener en cuenta las caracteristicas y fundamentos bases del lenguaje y es lo que hemos utilizado para desarrollar nuestro proyecto, usar funcionalidades basicas e intentar abordarlas todas para que sirva de ejemplo para desarrollar cualquier otro proyecto.

Lo primero que tenemos que tener en cuenta es que React no es un lenguaje de programacion como tal si no que es un framework de javascript, por lo que los fundamentos/principios son los mismos que en javascript ovbiamente no va a ser exactemente iguales pero al final "el que sabe arreglar una moto sabe arreglar una bici"

Como funciona javascript?

Entonces, ¿qué es JavaScript? ¿Y cómo funciona? JavaScript es un lenguaje de programación interpretado que se utiliza principalmente para crear contenido dinámico en las páginas web. A diferencia de HTML y CSS, que se utilizan para la estructura y el diseño de una página, JavaScript permite que los desarrolladores implementen funcionalidades interactivas, como la manipulación del DOM, la validación de formularios, la creación de gráficos animados y la comunicación asíncrona con servidores a través de AJAX. JavaScript se ejecuta en el navegador del usuario, lo que significa que puede responder rápidamente a las acciones del usuario sin necesidad de recargar la página.

Los fundamentos de JavaScript incluyen variables, operadores, estructuras de control de flujo (como bucles y condicionales), funciones, y objetos. Una característica distintiva de JavaScript es su capacidad de trabajar de manera asíncrona, lo que permite que el código continúe ejecutándose mientras se esperan respuestas de operaciones como llamadas a servidores. Además, JavaScript soporta la orientación a objetos basada en prototipos, lo que facilita la reutilización de código y la creación de aplicaciones más complejas y mantenibles.

IMPORTANTE: a la hora de conocer javascript tenemos que tener muy en cuenta nodejs

Como funciona react y se utiliza en el proyecto?

Una vez ya sabiendo los fundamentos de JavaScript podemos empezar a utilizar react en nuestro proyecto. Pongamos un ejemplo

Una vez declarada nuestra conexion con supabase en react podemos exportar la conexion para poder utilizar las funciones en cualquier sitio de nuestro proyecto. Entonces simplemente usamos export const supabase = createClient(supabaseUrl, supabaseAnonKey) y ya tenemos la variable supabase para importarla desde cuaqluier otro sitio para usarla import { supabase } from "../supabase/client" esto es la funcion principal de react y se considera un "hook"

Tambien podemos utilizar estados de input y demas componentes para controlarlos muy parecido a como hariamos en kotlin por ejemplo con onChange={(e) => setEmail(e.target.value)} podremos recoger el email del usuario para autenticarlo

Otro apartado muy importante de react y que utilizamos en nuestro proyecto es la gestion de rutas y roles para esto utilizamos la dependencia react-router-dom que podemos agregar con npm install react-router-dom y podremos gestionar las rutas y roles de nuestra aplicacion, asi que en nuestra App.js que es como el main de nuestra aplicacion agregaremos las rutas y en ella indicaremos las paginas que tenemos declarada en nuestra carpeta/paquete para ser redireccionadas y la aplicacion sepa que pagina mostrar en funcion de la url. Tambien en la App.js con navigate (que es otra funcion de esta libreria) podremos navegar entre las rutas y asi en el caso de que el usuario no este autenticado hacer que vaya una ruta especifica de esta forma no podra salir de hay hasta que no se autentifique, de esta forma podemos hacer al gestion de roles de nuestra aplicacion.

A continuacion se ofrece el proyecto en github para poder acceder al codigo completo