Categorías
Desarrollo web General Temporada 2

SleepTracker 0.1-a

Siguiendo con la idea de trabajar en mini-proyectos, hace unas semanas comencé a crear una aplicación web que fuera capaz de hacer un seguimiento de las horas de sueño.

Aquí la complejidad vendría de la mano de tener que desarrollar el stack completo:

Arquitectura

En la parte del servidor he creado un pequeño server con NodeJS y Express que monta una API sencilla sobre la que realizar las consultas.

Los datos están almacenados en una base de datos MongoDB que almacena todas las entradas, tanto las completadas como las que no.

Decidí que fuera la lógica del cliente la que decidiera qué valores mostrar.

La parte del front-end la estoy haciendo con una aplicación simple en React organizada por componentes con la lógica y las consultas extraídas de ella para manejarlas de forma más sencilla.

Diseño frontend

Ahora queda la parte más visual y la de tratamiento de datos.

Una vez comprobadas las conexiones y viendo que la aplicación web es capaz de obtener todos los datos del servidor he empezado a trabajar con ReCharts (https://recharts.org/en-US) para la presentación gráfica.

Lo cierto es que, por ahora, la forma de mostrar las gráficas está siendo bastante sencilla, pero me estoy empezando a encontrar problemas a la hora de personalizar bien los estilos.

Siguientes pasos

Voy a intentar perfilar un poco mejor la presentación gráfica, adecuando los estilos al diseño de la página y terminaré de añadir algunos de los componentes restantes.

Una vez que haya terminado la parte más visual, prepararé el diseño de la inserción de datos, que ha de dividirse en dos partes:

  • Nueva entrada: En el momento de ir a dormir, para marcar el inicio del tiempo.
  • Cierre de entrada: En el momento de despertarse, para marcar el fin del tiempo.

Esto se hará desde un acceso paralelo y mucho más simple para que se puede hacer de forma rápida desde el teléfono móvil.

Categorías
Desarrollo web

RecipeApp: Log 1

Esta es la última de las mini aplicaciones que quiero desarrollar en esta primera serie y, por tanto, es la que más complejidad quiero que añada.

Por eso, al hecho de implementar el front y el back como TypeScript, le quiero añadir la gestión de la API de recetas mediante GraphQL.

La API de recetas, además, deberá conectar con una base de datos MongoDB donde pretendo almacenar todas las recetas y sus ingredientes.

Mi intención es que el desarrollo de esta solución incluya la posibilidad de una mejora que permita integrarla en un sistema de gestión de recetas bastante más complejo, si llegase el caso.

Objetivos principales

Frontend

  1. Desarrollar un diseño responsive que permita su integración en dispositivos móviles.
  2. La aplicación va a estar gestionada desde una única página pero va a permitir el uso de rutas para acceder a las recetas.
  3. Todo el sistema estará desarrollado en TypeScript

Backend

  1. API conectada con base de datos MongoDB
  2. Gestión de la API mediante GraphQL estandarizando las queries y las mutations.
  3. El backend también estará escrito en TypeScript

Base de datos

Base de datos NoSQL con dos colecciones de documentos principales: recetas e ingredientes, relacionadas entre sí 1:n.

La gestión de los distintos elementos tipados la va a hacer la propia API, puesto que tendrá que añadir elementos de a los objetos definidos.

Así, mi idea es que los Intgredientes sean, en realidad, un objeto que incluya su ID, la cantidad y el peso.

Objetivos secundarios

La implementación del tipo Ingrediente puede abrirme a la posibilidad de introducir datos específicos de los ingredientes, esto es, información nutricional o el precio.

Aunque en la primera versión de esta aplicación no van a tener una utilidad real, quiero dejar preparada la estructura de datas para posibles futuras actualizaciones.

El problema que esto plantea es que su gestión genera alguna capa más de dificultad, tanto a nivel de la gestión de los datos, como de la interfaz de usuario a la hora de introducir nuevos ingredientes.

Categorías
Desarrollo web General

Trabajando en miniproyectos

Uno de los obstáculos con los que me estoy enfrentando a la hora de seguir mi aprendizaje en el mundo del desarrollo web es que los proyectos que inicio suelen eternizarse.

Esto, al final, tiene un efecto importante y es que afecta a la motivación y el interés por el proyecto y, por ende, en el aprendizaje, decae.

Excesiva complejidad = expansión en el tiempo

Cuando te lanzas a entender y comprender un nuevo lenguaje de programación y asimilas algunas de sus estructuras básicas y su potencia puedes tener la tentación de querer abarcar más de lo que eres capaz en realidad.

Como un Sísifo del código, te impones una roca demasiado grande y una montaña demasiado elevada.

A los numerosos parones a los que tienes que enfrentar tu motivación por tratarse de un constante proceso de aprendizaje, has de añadirle que el proyecto, por su propia complejidad, crece en el tiempo y se termina por eternizar.

Aquí es cuando el impulso inicial se diluye y, lo más normal, es el abandono prematuro del proyecto.

Agilidad, especificidad y retorno rápido

Con la idea de los mini proyectos, lo que busco es alcanzar los mismos objetivos de aprendizaje, pero segmentándolos en tareas cerradas más sencillas.

De esta forma, el proyecto tiene un principio y un final mucho más definido, se extiende mucho menos el tiempo y el retorno en forma de satisfacción al haber completado los objetivos es más inmediato.

Lista de mini proyectos

To Do App

Lista de tareas implementada con React & Typescript con un backend basado en SQLite.

Fue mi primer contacto con NES.css, un pequeño framework de CSS con un rollo pixelart muy divertido.

QuizApp

Sistema de preguntas y respuestas. Aquí también empleé React y TypeScript, aunque no desarrollé backend. En su lugar, gestioné las preguntas con un archivo JSON bastante sencillo.

La parte más interesante del proyecto fue su despliegue en Heroku y ver cómo respondía ante un acceso de un usuario externo.

Aplicación de recetas

En proceso.

Categorías
Desarrollo web

Client-side rendering vs Server-side rendering

En el momento en el que aterrizas en el mundo del desarrollo web, una tormenta de terminología te sacude dándote la bienvenida.

Uno de esos términos que aparentan ser complejos, pero que en realidad son una forma ‘cool’ de decir algo simple, es lo que se conoce como Client-side rendering (CSR) y Server-side rendering (SSR).

La comunicación web

Client-side rendering

El Client-side rendering (CSR) es el funcionamiento más común: nuestro navegador (cliente) realiza una petición de una serie de recursos y el servidor los devuelve. Entre ellos, los archivos Javascript (.js), que se ejecutan en el navegador del cliente, realizando así los procesos programados en el lado del cliente.

Server-side rendering

El Server-side rendering (SSR), en cambio, nos facilita una primera versión pre-renderizada del contenido de forma que mejoramos la velocidad de respuesta. El contenido servido se puede mostrar directamente en el navegador. No obstante, y esto es importante, la parte dinámica de nuestra aplicación no se procesa. Esto se hace con posterioridad, descargándose los archivos Javascript necesarios.

La diferencia es obvia, la primera versión estática pre-cargada en nuestro navegador se realiza de forma mucho más rápida y eficiente, mientras que la descarga de la parte más pesada y dinámica se realiza mientras el usuario ya tiene la posibilidad de ver contenido.

En una solución CSR, el usuario debe esperar hasta que se descarguen todos los recursos para poder interactuar con la página.

Categorías
DSM5Tool Temporada 1

Log 1.7: DSM5Tool – Versión 0.2.4

Seguimos con el proyecto después de unos días de relax.

Las mejoras propuestas para la versión 0.2.4 son:

  • Gestión de usuarios
  • Bloque #2 de trastornos completado
  • Página para trastornos: TrastornoPage.jsx
  • Paginación
  • Implementación de técnicas

Gestión de usuarios

🟩🟩🟩🟩🟩

Ya he desarrollado la parte del servicio de consulta

import axios from 'axios'
 const baseUrl = '/api/login'
 const login = async credentials => {
   const response = await axios.post(baseUrl, credentials)
   return response.data
 }
 export default { login }

Además, el frontend ya tiene definido la pantalla de login y ya simula el acceso de usuario

Ya he terminado el backend. Ahora ya no sólo se puede acceder a la parte de la API enfocada al Login, sino también he creado un endpoint para crear nuevos usuarios y la edición de los trastornos requiere ahora de autorización mediante token.

En el frontend todo está más o menos listo, a falta de la actualización de los trastornos puesto que tengo que incluir en la cabecera el token generado.

La base de datos ya dispone de un documento para usuarios al que he modificado ligeramente el esquema inicial: he considerado más útil emplear el correo electrónico como usuario en lugar de andar creando nombres de usuario porque añadía una capa de complejidad innecesaria y porque, en realidad, me interesará en el futuro disponer de una base de datos de usuarios a los que contactar mediante email.

interface usuario = { 
	nombre: String,
	email: String,
	password: String,
	tipo: String
}

Con esto zanjo la gestión de usuarios prevista para la versión 0.2.4.

Bloque #2 de trastornos

⬜⬜⬜⬜⬜

Página para trastornos

⬜⬜⬜⬜⬜

Paginación

🟩🟩🟩🟩🟩

A pesar de que existen soluciones como react-pagination, como, en realidad, la aplicación no requiere de un sistema de paginación complejo; he optado por utilizar hooks y desarrollar yo mi propio sistema.

Ahora mismo la aplicación ya pagina correctamente, en bloques de 8 trastornos (por tratarse de una Grid de 4 elementos) y lo hace independientemente del total de trastornos mostrados.

Cada vez que hay un cambio en el motor de búsqueda, como, por ejemplo, seleccionar una determinada categoría, el sistema reinicia la paginación y la adapta al nuevo número de páginas.

Tuve algunas dudas acerca de cuál debería ser la funcionalidad de los botones Sig y Prev, y al final me decanté porque salten un nuevo intervalo de páginas, en lugar de ir moviéndose de una en una.

Por ahora los botones de «…» son meramente decorativos y no añaden funcionalidad.

Implementación de técnicas

🟩⬜⬜⬜⬜

La lista de técnicas avaladas por la evidencia científica está casi completada. Una vez la termine me gustaría centrarme en la implementación de las técnicas en la base de datos y así dejarlo todo lo listo para la parte de integración en el sistema tanto en la parte del front como en la del back.

Categorías
DSM5Tool

Log 1.6: DSM5Tool – Versión 0.2.3

Voy a aprovechar que tengo el devlog para ir publicando los avances que haga respecto a las distintas versiones del DSM5Tool. De esta manera puedo usarlo como recordatorio de las tareas pendientes que tenía proyectadas:

Las mejoras propuestas para la versión 0.2.3 son:

  • Refactor de TrastornoEdit
  • Bloque #1 de trastornos completado
  • UX/UI del formulario
  • UX/UI de TrastornoDetail
  • Análisis de datos: Técnicas
  • Diseño de implementación de técnicas»

Refactor de TrastornoEdit

Completado

🟩🟩🟩🟩🟩

He editado bastantes de los hooks [https://dev.mdgmedia.es/2021/01/25/dsm5tool-usando-custom-hooks/] que tenía definidos para hacerlos más eficientes y reducir la cantidad de código dedicado a ello.

He extraído un par de funciones más, creando un archivo dedicado para ellas:

export const addSubCriterio = (
  target,
  i,
  j,
  trastornoCriterios,
  setTrastornoCriterios
) => {
    const newTrastornoCriterios = [...trastornoCriterios];

  if (newTrastornoCriterios[i].Subcriterios) {
    newTrastornoCriterios[i].Subcriterios[j] = target.value;
  } else {
    const newCriterio = {
      Descripcion: newTrastornoCriterios[i].Descripcion,
      Subcriterios: [target.value],
    };
    newTrastornoCriterios[i] = newCriterio;
  }
  setTrastornoCriterios(newTrastornoCriterios);
};


export const addTrastornoCriterio = (target, i, trastornoCriterios, setTrastornoCriterios) => {
    const newTrastornoCriterios = [...trastornoCriterios];
    const newCriterio = {...newTrastornoCriterios[i],
      Descripcion: target.value,
    };
    newTrastornoCriterios[i] = newCriterio;
    setTrastornoCriterios(newTrastornoCriterios);
  };


export default { addSubCriterio, addTrastornoCriterio };

La idea es tener localizadas todas las funciones dentro de la misma carpeta para, así, poder reutilizarlas de forma cómoda y rápida.

Bloque #1 de trastornos completado

Completado

🟩🟩🟩🟩🟩

Esta tarea es, probablemente, la más aburrida de esta versión, porque se trata de ir configurando manualmente los distintos trastornos. El objetivo de esta primera fase es completar 50 trastornos con su descripción y criterios diagnósticos. De esta forma, en diez fases alcanzaremos los 477 diagnósticos que actualmente tiene la aplicación almacenados.

UX/UI del formulario

En progreso

🟩🟩🟩🟩🟩

He encontrado algunos modelos que puede resultar interesante implementar. Una de las cosas que veo más posibles es la de tabular la información.

8cd0dd2ab88ecd6459d1ede16cde49e7

Me gustan este tipo de diseños sencillos y limpios.

También me resulta interesante trabajar con tonos de grises y colores pastel suaves, que facilitan mucho el trabajo de inserción de datos. Esto me ha llevado a plantearme también que en futuras versiones, tal vez la 0.2.6 o la 0.2.7, podamos plantear la posibilidad de introducir un modo oscuro.

Tras los cambios, el formulario de edición de trastornos ha quedado más sencillo y limpio:

UX/UI de TrastornoDetail

Completado

🟩🟩🟩🟩🟩

He modificado el diseño de TrastornoDetail para hacer más sencilla la forma en la que se muestran los criterios y los subcriterios:

  • Cada criterio ahora está precedido de una letra.
  • Cada subcriterio está integrado dentro del criterio de forma que quedan claramente diferenciados.
  • Visualmente es más vistoso, puesto que se añaden tonos azules que mantiene la tónica cromática de la aplicación.

Análisis de datos: Técnicas

Completado

🟩🟩🟩🟩🟩

He dado con una web bastante interesante que relaciona una gran cantidad de trastornos con terapias respaldadas por su eficacia contrastada científicamente. Además, he planteado una forma de mostrarlas de tal manera que sea sencillo identificarlas y me permita añadir información en futuras actualizaciones. Este es un pequeño prototipo que he hecho basándome en esa idea.

Diseño de implementación de técnicas y tratamientos

Completada fase 1

🟩🟩🟩🟩🟩

Ya tengo lista la definición básica del objeto ‘técnica’. La idea es crear un documento nuevo en MongoDB y enlazar esta información con el actual documento de trastornos.

Con esto doy por finalizada la versión 0.2.3, que ya está subida a GitLab y me pongo manos a la obra con la versión 0.2.4.

Categorías
DSM5Tool

DSM5tool: Usando custom hooks

La complejidad de algunas partes del código está aumentando excesivamente y eso me ha motivado a empezar, en paralelo con el progreso del proyecto, tareas de refactorización del código para intentar simplifcarlo.

Una de las primeras cosas que he conseguido hacer es reducir la cantidad de hooks que utilizaba a la hora de definir el objeto trastorno.

Inicialmente definía un estado para cada propiedad del objeto. En lugar de eso, ahora, tengo custom hook definido específicamente para ello, de forma que toda manipulación del objeto Trastorno se realiza directamente ahí:

import { useState } from "react";

const useTrastornos = (valor) => {
  const [trastornos, setTrastornos] = useState(valor);

  const changeTrastornos = (valor, parametro) => {
    const newTrastornos = trastornos
    newTrastornos[parametro] = valor
    setTrastornos(newTrastornos);
    
  }

  const updateTrastorno = (trastorno) => {
      setTrastornos(trastorno)
  }
return { trastornos, updateTrastorno, changeTrastornos };
};

export default useTrastornos;

Exporto simultáneamente el objeto Trastorno y las funciones que me sirven para actualizar el objeto al completo y una de sus propiedades en particular.

De esta forma, en el componente TrastornoEdit puedo acceder directamente a las funciones haciendo la llamada al hook correspondiente:

const trastornoHook = useTrastornos(trastornoProp);

const trastornoEdit = async (event) => {
    event.preventDefault();
    const nuevoTrastorno = {
      id: id,
      Trastorno: trastornoHook.trastornos.Trastorno,
      Codigo: trastornoHook.trastornos.Codigo,
      Indice: trastornoHook.trastornos.Indice,
      Categoria: trastornoHook.trastornos.Categoria,
      Tipo: trastornoHook.trastornos.Tipo,
      Descripcion: trastornoHook.trastornos.Descripcion,
      Criterios: trastornoCriterios,
    };
    setIsLoading(true);
    const updatedTrastorno = await trastornoServices.update(nuevoTrastorno);
    trastornoHook.updateTrastorno(updatedTrastorno);
    setTrast(updatedTrastorno);
    setIsLoading(false);
    setEdit(false);
  };

Esto formaría ya parte del progreso de la version 0.2.3, que por cierto, ya tiene nueva iteración, con la 0.2.4 y su gestión de usuarios.

Ya os contaré más de ello en la siguiente entrada.

Categorías
DSM5Tool

Log 1.4: Añadiendo trastornos, repensando criterios.

Para poder seguir avanzando con el desarrollo de DSM5Tool he terminado de listar todos los trastornos. El proceso fue algo lento, porque la fuente de información era una guía diagnóstica en PDF.

Primero listé todos los trastornos añadiéndoles propiedades como descripción, categoría, tipo o los códigos CIE-9 y CIE-10 en un documento Excel.

Ese documento lo exporté a CSV y, de ahí, lo convertí en CSV empleando https://csvjson.com/csv2json como herramienta.

Uno de los problemas principales a los que me tuve que enfrentar fue a la definición del objeto trastorno.

Este, dadas sus características, incluye criterios que, a su vez, pueden incluir subcriterios.

Gestionar matrices dentro de matrices ha sido un poco un quebradero de cabeza, pero finalmente completé la fase 0.2.1 y puedo editar cualquier tipo de trastorno.

interface Criterio { 
  descripcion: string;
  subcriterios?: string[];
}

Además, reconfiguré completamente el backend para trabajar con MongoDB de forma que los trastornos ya no están en un archivo. La gestión de los métodos GET y PUT está terminada: los formularios funcionan perfectamente gracias al uso de axios.

Con esto concluyo la versión 0.2.2 y me dispongo a enfrentarme con las tareas asociadas a la 0.2.3:

Ahora mismo me resulta clave ir incrementando la información almacenada en la base de datos, pero, al mismo tiempo, necesito refactorizar el código e implementar mejoras en la interfaz de usuario de algunas partes del proyecto.

¡Nos vemos en la 0.2.3!

Categorías
DSM5Tool Temporada 1

Log 1.3: DSM5Tool

Uno de los grandes problemas que he tenido que gestionar estas primeras semanas ha sido que, en determinado momento, al trabajar solo, me he sentido algo perdido.

Esa sensación suele traer consigo falta de motivación y, en muchas ocasiones, pérdida de interés por el proyecto. Por eso, para evitar que eso suceda, puede resultar interesante desarrollar cosas en paralelo que vayan a ser útiles en un futuro.

La idea de DSM5Tool es sencilla: un índice de los distintos trastornos que aparecen en el manual de diagnóstico de psicología DSM-5 (https://www.psychiatry.org/psychiatrists/practice/dsm).

El objetivo de esta miniapp es la de coger algo de soltura con ReactJS y con Chakra UI para ir avanzando de forma más sostenida.

Por ahora ya he completado la primera fase de la aplicación que incluye:

  • Estructura de datos básica
  • Buscador por trastornos
  • Buscador por categorías/subcategorías
  • Listado de criterios diagnósticos.

Todavía me falta definir completamente la estructura de los datos, puesto que el DSM-5 no sigue un esquema predeterminado y eso complica un poco la forma de parametrizar la información.

En la siguiente iteración del proyecto mis objetivos son:

  • Concluir la estructura de los datos
  • Buscador por criterios/etiquetas
  • Información completa por trastorno

Por ahora la definición de mi estructura de datos sigue el esquema:

export const dsm = [
  {
    categoria: "Trastornos del desarrollo neurológico",
    tipos: [
      {
        tipo: "Discpacidades intelectuales",
        trastornos: [
          {
            codigo: "F70",
            trastorno: "Discapacidad intelectual leve",
            indice: "317",
            descripcion: "La discapacidad intelectual (trastorno del desarrollo intelectual) es un trastorno que comienza durante el período de desarrollo y que incluye limitaciones del funcionamiento intelectual como también del comportamiento adaptativo en los dominios conceptual, social y práctico.",
            criterios: [
              "Deficiencias de las funciones intelectuales, como el razonamiento, la resolución de problemas, la planificación, el pensamiento abstracto, el juicio, el aprendizaje académico y el aprendizaje a partir de la experiencia, confirmados mediante la evaluación clínica y pruebas de inteligencia estandarizadas individualizadas.",
              "Deficiencias del comportamiento adaptativo que producen fracaso del cumplimiento de los estándares de desarrollo y socioculturales para la autonomía personal y la responsabilidad social. Sin apoyo continuo, las deficiencias adaptativas limitan el funcionamiento en una o más actividades de la vida cotidiana, como la comunicación, la participación social y la vida independiente en múltiples entornos, tales como el hogar, la escuela, el trabajo y la comunidad.",
              "Inicio de las deficiencias intelectuales y adaptativas durante el período de desarrollo."
            ]
          }
        ]
      }
    ]
   }
  ]

Pronto os mostraré partes del diseño gráfico y de cómo avanza la parte de la lógica tras la aplicación.