the ugly organization - lifts front-end

desu

你好!

Os traigo mi último proyectito de front-end.

Vite + React + Shadcn + Tailwind

Getting started

He seguido esto:

https://ui.shadcn.com/docs/installation/vite

El código y el front-end

Lo he puesto en Github mismo:

https://github.com/vrnvu/lifts/

Esta desplegado ahora mismo por aqui, no me hagais ddos eh jeje
https://lifts-two.vercel.app/

Objetivo 1

  • Plan view
  • Usuario introduce sus datos
  • Web adapta el programa al usuario

Objetivo 2

  • Program view
  • Web muestra un programa de entrenamiento adaptado al usuario

Objetivos extras

  • Múltiples planes, para cada plan dos vistas: program + plan
    • Starting Strength, Starting Lifts, 5/3/1, GZCLP y similares
  • Permitir al usuario personalizar ejercicios del clúster de entrenamiento entre una lista de opciones
    • Opciones para STRENGTH, CARDIO, ENDURANCE
  • Refinamientos, permitir al usuario trabajar con un WRM, ondular progresiones, podría hacerlo.
  • Refinamientos en visualización de datos y UX

Estado actual

Tenéis imágenes en el repositorio de Github.

De momento he hecho la maqueta con un par de componentes y mi objetivo es el Lunes empezar a hacerlo funcional.

Objetivos del diario

Como sabéis yo no alineo divs, tan solo en la intimidad como Rajoy, así que mi primer objetivo es resolver el problema de la manera más horrible posible. Para algo funde la ugly organization. Seguidamente, le dedicaré un tiempo a mejorar el código React y aprender un poco de CSS con Tailwind. Tercero, quizás os lo despliego según me vea, he leído que hay gente a quien se le atraganta desplegar front-ends y protegerse de DDoS, así que lo mismo les echo un cable.

Tutoriales

  • Que es y como usar una librería de componentes? #2
7
desu

Dia 1

Bueno, abro el hilo y comento lo que hay hecho. Mi objetivo es tener un frontend para los excels típicos de entrenamiento, el usuario introduce un par de datos y todo se genera. Son programas simples, eficientes y los que mejor funcionan. Tengo un par de ideas que ya lo veréis. A ver como queda.

Día 1, pues todo maqueta, no funciona nada.

A mí me gusta montarlo primero y luego ir haciéndolo funcional, me gusta montarlo porque me da una visión de como el usuario va a interactuar con la web y pienso que es más importante tener una buena UX desde el principio.

El motivo por el que recomiendo montar siempre es:

  • Comparado a hace 15 años, hoy en día con las librerías de componentes que tenemos vas follado... Dedicar tiempo a hacerlo en Photoshop es perder el tiempo.
  • Con tailwind hasta hacerlo responsive para múltiples dispositivos es trivial.
  • UX que no UI. Visualizar los flujos de datos e interacciones desde el primer momento. Esto es lo más importante, a veces la gente piensa en hacer las cosas bonitas y se olvida que tiene que usarlo alguien.
  • Maquetear te ayuda a tomar decisiones de código, como de grandes deben ser los componentes, qué propiedades dinámicas requerirán, etc.
  • Maquetear te ayuda a hacer las cosas SIMPLES y DIRECTAS. En mi código ahora mismo tengo 5-6 tipos de Card que son exactamente lo mismo cambiando las props... pero yo prefiero tener 5-6 componentes que 1 genérico. Las abstracciones y generalizaciones prematuras son el diablo.

En este caso, las únicas decisiones de UX que he tomado son:

  • tener el plan aparte del programa, una vez lo metes, ¿para qué quieres visualizarlo?
  • poder ocultar las semanas que ya has hecho, tener el toggle me parece una forma muy simple de esto... si pusiese algo como un calendario, que parece lo más obvio, añadiría complejidad innecesaria.

Y tengo algunas ideas de refinamiento que justifican estas dos vistas y organización, que ya veréis cuando lo pruebe. Pero primero quiero hacer esta primera versión funcional y luego mejorar la UX.


Que es una libreria de componentes y como se usa?

Hace tiempo abrí este hilo preguntando.

La gracia de las librerías es que permite tener componentes típicos y habituales al alcance y son la base de todo proyecto. En empresas más grandes pues hay equipos tanto de front-end como de diseño que se encargan de prepararlas para que todos los productos tengan la misma "marca" e "imagen" cohesiva.

Si eres un novato y te intimida el front-end, lo primero que necesitas es buscar una librería. Yo he elegido la más recomendada por el foro. Si visitas la documentación te encontrarás todos los componentes disponibles, como usarlos y ejemplos.

Componentes:

Ejemplos y bloques re-utilizables:

Además hay temas, como digo, estas librerías permiten tener todo muy cohesivo facilmente:

Veamos un ejemplo de como usar un componente, para que el fpero de primero de DAW que me lea pueda aprender algo.

Tenemos siempre la preview y el code. Y la manera de agregar el componente.
Hoy en día, todos los componentes son ALTAMENTE modulares y sin dependencias externas o mínimas (css i.e). Esto permite que añadiendo el componente a nuestro código podamos acceder a él.

Según la docu tiramos un:

npx shadcn-ui@latest add card

Con esta libreria shadcn, nos lo mete en esta carpeta, y lo bueno es que podemos ver todo exactamente y modificarlo:

Hace muchos años, cuando el ricitos de Codely aún no había alineado su primer div, estas librerias eran mas difíciles de usar e instalar, y para modificar, muchas veces requerian tocar los node_modules. Esto como digo ya ha terminado, y un buen detector de buena libreria, es su modularidad.

Estos componentes son independientes de la librería o framework que uses. Se pueden usar con Astro, Next, React, Angular, Vite, Remix etc. Tendrán un paso de instalación para configurar el proyecto para esta librería/framework concreta, pero la experiencia de uso debe ser muy similar.

Con esto tienes el conocimiento suficiente para hacer una maquieta front-end. Fin del tutorial. El próxima día veremos el ogro, el estado.

desu

Hoy también he estado una hora, 60 minutos, re-haciendo código porque en lugar de tener un archivo tsx tenía un archivo ts y no tiraba el jsx.

React está muy mal por diseño, para tener una variable global necesitas mil historias con contextos y providers y sobre-ingeniería de hooks. Luego me pondré en contacto con los developers para que mejoren los errores de mensaje al menos del transpiler.

Termino el Domingo con el primer programa completamente terminado. Listo.

Ahora ya ir mejorando.

2
desu

El estado lleva volviendo locos a los aliena divs más de 30 años. Antes de que miudev cagase su primer pañal ya se estaba dando vueltas al ciclo server side render, componentes modulares y demás parafernalia para mover el estado al backend y antes de que le petaron su primer cliente por DDoS ya se habian sacado 1582 (podeis verificarlo en wikipedia) frameworks de javascript para poder cambiar una variable de true a false.

React viene de Flow de Hack de ReasonML, una serie de proyectos de Facebook que en 2010, que trataron de convertir todo el codigo de Facebook en programación funcional pura. Como os podéis imaginar el mal siempre gana, y seguimos escribiendo javascript de mierda, con 10 capas de sobre-enginieria, para poder cambiar una variable de True a False. Pero eh, antes eran componentes feos y ahora usamos "hooks", que funcionales somos. Dejando de lado la clase de historia y como el equipo de React dejo el proyecto por Reason y Elm a los 6 meses y que la gente a quien se le atribuye crear React son unos subnormales, y si sigo ban de conferencias de Facebook no puedo atender aún, hoy quería hablar del estado un poco en React. Al igual que ayer, un mini tutorial por si algún DAWero sigue el hilo, que le pueda servir de algo. Quizás otro día sigo con la clase de historia.

Estado:

Estado es tan facil como una celula de memoria, de tu RAM seguramente, que le quieres cambiar el valor, a veces esta vacio, a veces le pones un 0 y a veces le pones "hello world". No espera, que "hello world" no cabe en una celula fpero, ahi ya entran punteros y se nos complica, hay que meter otro framework encima. Fijaros en nuestro amigo Miudev poniendo una celula de memoria a 0 y flipando en el chat de Twitch.

En el frontend lo que hacemos es gestionar el estado del DOM y arbol html y esas cosas, y tambien tenemos un poco de memoria, digo un poco pero en realidad todos los programadores de frontend sabemos que la memoria del browser es infinita y nuestras wecs pueden pesar 10GiB.

Vamos a simplificar el arbol y pensar en que hay 2 tipos de nodos, los de logica y los de vista. Los de logica escriben a memoria, y los de vista SOLO leen. En morado Twitch de las gafas de Miu uno, y en el color rosa de sus granos otro. Para tener una guia de estilo clara.

Ahora, el objetivo, es que el estado NUNCA debe gestionarse en los nodos de color rosa grano, por que? Porque entonces estamos acoplando la gestion del estado. Y madre mia que dolores de cabeza durante 30 años para hacer esto. Existen librerias y frameworks para todos. En un primer paso, lo que se decidio hace 10 anos, yo no estaba muy de acuerdo, era que la gestion del estado SIEMPRE se debia subir al nodo padre mas cercano, y de esta manera teniamos sub-arboles independientes que gestionaban el estado. Spoiler: no termino bien. Spoiler 2: angular con el dual binding funciono muy bien, pero por desgracia, los fperos seguian sin entender que era eso del estado. Y pensad que en esa epoca no teniamos mil canales de Youtube explicandote como hacer un for en javascript... hacer programación era cosa de titanes!

Y que hacemos Desu? Pues el siguiente paso fue volver atrás en el tiempo, volvimos a la programación funcional y sacamos el estado en un global. De ahí vinieron por desgracia los Redux y las sobre-enginierias. Recordad que un fpero, siempre va a resolver un problema que requiere pensar poniendo más código! El fpero nunca usará el cerebro para pensar o Codely no podrian vender videos en su trabajo.

Fijaros en como los componentes de lógica leen y escriben, y como los de vista solo leen. Pues bien, la lógica es muy simple. En React y otros frameworks y librerías... No tanto. Por desgracia esto tan fácil hay que venderlo cada vez que toca como una revolución tecnológica o nadie usara nuestro framework de javascript de moda.

Final: la manera de hacer esto por lo que he visto hoy en 2024, porque hace 10 años en React era distinto y dentro de 10 será distinto... es con useContext y provider. ¡Para cada ESTADO, para cada ESTADO, una célula recordad!!! Necesitamos un context un provider.

https://react.dev/reference/react/useContext

Y para que sirven los useState? Y los props? Nada. Yo no lo recomiendo para el fpero medio, si haces esa pregunta es que no estás capacitado para usarlos. Cualquier que comprende los componentes de lógica, vista y la gestión del estado, sabe cuando puede usarlos sin problema.

3
desu

Os voy a explicar un detalle técnico de React. (MAL DISEÑO).

Los hooks de React son dinámicos, no pueden ser nunca estáticos. Si tu quieres definir un hook como una variable estática global te va a petar con el siguiente error:

Nosotros necesitamos tener contextos para guardar el estado, y también necesitamos poder modificar estas variables. Esto se puede hacer mediante useState o useReducer. Los useReducer se inventaron para desacoplar el estado del hook, de esta manera tener "useState" dinámicos. Os lo enseño:

En mi código, uso un custom hook para poder comprobar que se ha inicializado el contexto, esto lo hago dinámicamente porque estáticamente es imposible.

Este código que escribiríamos en otros frameworks y librerías de javascript, NO funciona en React.

En Rxjs son 2 líneas de código:

// RxJS v6+
import { BehaviorSubject } from 'rxjs';

const subject = new BehaviorSubject(123);

// two new subscribers will get initial value => output: 123, 123
subject.subscribe(console.log);
subject.subscribe(console.log);

// two subscribers will get new value => output: 456, 456
subject.next(456);

// new subscriber will get latest value (456) => output: 456
subject.subscribe(console.log);

// all three subscribers will get new value => output: 789, 789, 789
subject.next(789);

// output: 123, 123, 456, 456, 456, 789, 789, 789

https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject

Tan solo estamos almacenando en memoria y variable global, pero a React, se le atraganta, y para lograr esto necesitas 20 líneas de código...

O usar un reducer, aquí un ejemplo de nuestro crack @isjvidal
https://github.com/jvidalv/astrale/blob/master/src/contexts/global.js

Fijaros como usa un reducer para tener la función. Esta es la manera en que react, DE MUY MALA MANERA, MAL DISEÑO RECORDAD, ha parcheado este problema.

Obligándote, para cambiar una variable de valor, a escribir 5 líneas de código:

export const reducer = (state, action) => {
  switch (action.type) {
    case 'switchTheme':
      return {
        ...state,
        theme: action.theme,
      };
    case 'setLogOut':
      return {
        ...state,
        session: default_session,
      };
    case 'toggleLoader':
      return {
        ...state,
        showLoader: !state.showLoader,
      };
    case 'setSession':
      return {
        ...state,
        session: { ...state.session, ...action.fields },
      };
    case 'setDay':
      return {
        ...state,
        day: action.day,
      };
    default:
      return {
        ...state,
      };
  }
};

¡En lugar de tener el caso en una función, tienes que comprobar con un enum/string el nombre!

React = Patético

1 respuesta
desu

Me chivan por el pinganillo que React tiene Signals, https://www.skcript.com/blog/react-signals/

Así que probablemente mis dos antiguos posts están mal, y hay que oblidarse completamente de useState y useReducers y usar siempre signals.

desu

Voy a poner un ejemplo de refactor, el cual es un ejemplo claro por el que tengo el diario para enseñar.

Muchos me criticaron por empezar mi código de la manera más simple y guarra posible. Como comenté ayer, no tenía claro si quiero permitir al usuario añadir ejercicios, customizar ejercicios (cambiarles el nombre), o como exactamente se va a comportar esta parte del código. Así que opte por no tomar ninguna decisión.

Como veis en estos commits https://github.com/vrnvu/lifts/commit/737290199219abfd3e1adf6b111b5cfb8d7fcb8f https://github.com/vrnvu/lifts/commit/faf5e38c7821170a2ede08b84012bfc525985ffb he añadido una abstracción básica. El cambio ha sido directo, y sin problema. He decidido añadir un enum por tipo de ejercicio para poder combinarlos fácilmente en múltiples planes de entrenamiento y crear días de entreno donde los ejercicios sean parametrizables.

De aqui:

He pasado aquí con el enum:

Y me he añadido unos helpers para poder usar el código así:

Como podéis ver todo encaja a la perfección, código simple, directo, incluso ahora la "abstracción" o el "genérico" es mínimo, absoluto y parametrizable.

Cuando venga un Miudev de la vida y os diga, "que código mas feo jaja porque usas un for loop? mejor un map y un reduce!!", seguramente vais por el buen camino. Llegaréis más lejos, antes y sin cansaros.

Fijaros como sigo usando un array y accedo por indice con los [0] y [1] en mis helpers... que problema hay? Ninguno, es rapido, simple, eficiente, y facil de modificar.

Ademas, voy a terminar el proyecto sin escribir un solo test porque no me hacen falta. Si no escribes bugs, no necesitas tests. (Esto no es un consejo para el mundo profesional).


Por ultimo el realizar el codigo mas simple y directo me ha permitido POR MI MISMO, sin encesidad de tutoriales ni leer documentacion, comprender el useState/useReducer y comprender los limites de React.

  • Por mi mismo, he sido capaz de comprender, deducir y entender, porque React no permite usar useState en contextos dinamicos.

  • He podido entender por qué React creo el useReducer para permite "mockear" los useState en contextos dinámicos.

  • He llegado a la conclusión de como gestionar el tipado en typescript mediante una función que comprueve el check. Cosa que me han pasado por pinganillo que es un patrón de "buena practica" recomendado.

  • También he aprendido (ya lo sabía) que en lugar de tener las variables y las funciones, es buena práctica, y hay guías de estilo, que recomiendan devolver las tuplas [variable, useStateParaModificarVariable]. Pero yo esto ya lo sabía de hacer FP. Así que, si quieres aprender React, aprended Haskell y LISP HAHAHA.

Si en lugar de hacerlo yo mismo y pensar, hubiese seguido tutoriales, no habría aprendido en 2h todo esto sin duda. Habría tardado 12h de cursitos llenos de fallos que explican las cosas sin hacerte COMPRENDER el porqué.

Si que es cierto que se me ha pasado lo de los signals... hace 5 años React aún no los tenía así que no sabía que ya se podía usar algo parecido a rxjs. Pero de nuevo, nadie es perfecto, yo cometo errores también y no conozco todo, así qué gracias al usuario que me ha ayudado con esto.

desu

Relacionado con las componentes de logica y vista que comente en #4. Ahora mismo es muy simple porque solo tengo un estado, pero cuando tenga multiples programas esto crecerá linealmente. Y todos si resuelves el primero bien, funcionaran de la misma manera. Veamos una analisis rapido de la estructura:

Primero en alto nivel tenemos lo siguiente, para cada programa de entrenamiento:

He creado una vista calendar que voy a re-usar entre mis programas. Porque todos harán lo mismo, mostrar semanas de entreno, bloques de entrenamiento. También tengo lo que llamo vistas o view, una view es una "página" de toda la vida. Como sabemos tenemos dos views, plan y program.

Para cada calendario, le insertare semanas o bloques de entreno. Ahora decido como lo llamo. La idea es que un Calendario tiene bloques de entreno con que hacer, el usuario introduce en plan los datos para configurar esto.

El ejercicio que hay que hacer SIEMPRE es tener claro que compoente es logica y cual es vista, y si es de logica, el padre tambien es de logica! Y si el padre es de logica, podemos mover la logica del hijo al padre? Fijaros. Programa es todo vista. Por tanto yo puedo ir al padre, en este caso calendar o mi vista de programa, y ahi preparar TODAS mis componentes en el mismo lugar. Una componente de vista debe ser lo mas simple posible, SOLO MUESTRA INFORMACION.

En cambio, la vista de logica en CLUSTER, un cluster es un grupo de ejercicios y sus pesos configurados, vemos como tenemos un estado de logica y que por tanto debo pensar si puedo mover esta logica. En este caso, en lugar de ir hacia el padre, una logica debe ir siempre al hijo. La scope del "side-effect", del cambio de efectos, debe ser siempre MINIMA. Un componente debe tener acceso y modificar el MINIMO de logica posible. Aqui mucha gente hace el error de subir la logica al padre ? Esto esta mal. Hay que idintifcar que padres tienen logica pero no mover el codigo arriba.

Resumen:

  • Componentes de vista, la buena practica siempre es mover el codigo para preparar la vista lo mas arriba posible en el árbol. Esto hace que la cohesion y dependencias entre modulos y componentes sea ideal. El flujo de datos es UNIDIRECCIONAL. Va de parent => children. Y todos sabemos donde encontrar donde se genera unos datos que mostramos al usuario.
  • Componentes de logica, la buena practica es mover el codigo de logica al hijo, hoja mas abajo posible del nodo. Esto se hace de nuevo para que los side effects y la superficie de complejidad sea MINIMA. Siempre modificaremos en el componente hoja mínimo y modificaremos una variable global. En caso de React un context.

FAQ:

  • Pero desu ese ejemplo es muy simple jeje. El mundo real es mas complicado!

Exactamente, yo desarrollaba front ends que tenian input de usuarios, polling y push de backend con sockets y hasta SSE... todo a la vez jaja Si no tienes la base bien, no podrás resolver las inconsistencias de dominio.
Por ejemplo, que pasa si por websocket me llega valor A y por polling me llega valor B? Con que valor me quedo? Si lo haces como te digo, tendrás que tomar la decisión obviamente, pero lo que nunca te pasara es no saber que valor tiene prioridad ni de donde te vienen los datos.

  • Pero desu ese ejemplo es muy simple jeje. Si muevo todo a la vista lo más arriba posible no se hará un cacao?

Si, la recomendación es para cosas complejas donde haya dependencias / cohesión entre componentes. Por ejemplo, 5 componentes tienen que mostrar 5 datos muy relacionados, por ejemplo, la telemetría de una máquina. Estos datos hazlo en el componente padre.

desu

Ya tengo otro programa, 5/3/1 para beginners, bloque principal. Y al final, en lugar de añadir abstracciones, he deshecho la que iba a hacer. ¿Iba a hacer navegación, pero para que si tengo múltiples pestañas?

Llegados a este punto código muy fácil de mantener.

JuAn4k4

Por que no haces el tipo de ejercicio genérico ? Así puedes meter cualquier ejercicio del tipo que sea y son todos iguales, reps + peso. Y que el usuario meta ejercicios ?

1 respuesta
desu

#10 En que ejemplo dices? Estos programas te dicen exactamente lo que tienes que hacer, por ejemplo:

https://thefitness.wiki/routines/5-3-1-for-beginners/

Lo que el usuario puede cambiar a su gusto son los accesorios, pero yo no lo pongo nunca en los programas.

Las repes que he puesto y los ejercicios son los que son para estos dos planes y lo único que cambia el usuario son los pesos máximos, que con el tiempo el objetivo es progresar. Por ejemplo, mi inspiración fue esta web: https://boringbutbig.com

Si te refieres a que el usuario cree un programa custom, creando el ejercicio, seleccionar movimiento, reps y peso, podría hacerse. Aunque no veo la utilidad para nada. Sí que pensaba el opcional de añadir los accesorios por plan, pero no veo la UI/UX clara.

Si añadiese accesorios, en lugar de tener una vista plan, movería el plan en una sección para cada programa... al final es mas lógico. Quizas lo hago...

1 respuesta
JuAn4k4

#11 Ah vale ya entiendo, pensaba que era para que cada uno se hiciera sus planes.

También podrías hacerlo genérico y tener el plan como datos, aunque sean fijos, así el código no cambiaría.

1 respuesta
desu

#12 estuve mirando y si permito que todo se pueda customizar, es mejor tener la ventanita de plan dentro de cada programa especifico... porque ya no se compartiran las cosas...

lo mismo hago el re-factor y lo muevo y hago que se puedan agregar ejercicios accesorios...

pero bueno, el primero objetivo que era pasar un excel a frontend ya esta.

desu

Estoy seguro que en Tailwind hay alguna manera de hacer mis componentes responsive de manera global y no tener que ir una por una tocando el css no?

Bueno asi se queda de momento:


Tambien he preparado el codigo para ser mas generico y permitir ejercicios custom, mi cluster ahora recibe un array de ejercicios y se pinta:

No estoy contento con tailwindcss en este punto. No se si alguien me podria iluminar como soportar multiples resoluciones de manera que no tenga que poner sd, md and ld en todos lados............

no se puede crear clases? me gustaria separar el in-line css de tailwind en clases y eso se que de puede.

desu

Me han pedido el feature de el progreso de todos los ejercicios, lo tengo asi:


Como veis con un ENUM todo es parametrizable y fácil de customizar cuando lo haga.

Lo malo es que typescript no tiene type switch exhaustivo, en las funciones getWeight() getLastWeight() no tengo type safety... Y errores que en otros lenguajes este codigo detectaria en tiempo de compilacion cualquier error pues aqui fallara runtime...

Fpero tip: por que tengo un toName() para saber el nombre del enum? los enums NUNCA deben ser strings.

Ahora ya tengo el código bien preparado para mover la vista de plan a cada programa, algo que originalmente no quería hacer pero para permitir más flexibilidad en el programa con los ejercicios y segundo que estos ejercicios sean parametrizables de manera muy fácil y dinámicos. Clean code.

Asi la URL: https://lifts-two.vercel.app/

En desktop se vera bien, en mobile no porque aunque use tailwind la UI esta pensada para usar en el PC. Pero le estoy dando vueltas para tener un re-design.

JuAn4k4

Atomic Design, ir diseñando componentes que se reusen y sean responsive, así puedes reusar átomos, moléculas, etc.. de pequeño a grande.

Y con TW es más cómodo tener postcss y crear classnames que tengan las clases de tw en un .pcss

2 respuestas
desu

#16 Es que pensaba que SHADCN eran componentes responsive por defecto... y aunque se vea mal al menos pensaba que se veria algo pero nada.

Lo voy a arreglar, a ver como lo hago.

HeXaN

Muy chulo el proyectito @desu . Algo similar tenía yo pensado para tema dieta porque siempre me ha parecido que las aplicaciones actuales están completamente "bloated".

1 respuesta
desu

#18 Pues si, lo más difícil es una UI y UX fácil y simple.

Yo por ejemplo he descartado los calendarios, como es algo para ti con localstorage chutas, y cosas asi que he comentado.

Lo que estos días he pensado que realmente, si quiero ser mejor que un excel, necesito tener buena visualización, porque en excel hacerte gráficos del histórico de RMs o distribución de volumen según grupos musculares es super fácil... Y creo que estas dos cosas son lo mas importante. Volumen por grupo muscular semanal, y evolucion del volumen.

Otro tema de UX se me ha ocurrido con la GZCLP, seguramente la conoces, es una rutina MUY difícil de configurar y llevar al día... Para cada ejercicio tienes 2 tiers y 3 niveles. Aquí se me ha ocurrido hacer una app móvil estilo "tinder" + "journal". Cada día te muestra lo que te toca y tu le das swipe izqueirda o derecha según has cumplido o no... Esto con la dieta que comentas también lo veo. Un journal para introducir fácilmente tus datos día a día, y luego en otra app o funcionalidad COMPLETAMENTE aparte, una visualización del progreso y análisis.

El problema que yo veo, el "bloat" que dices, es querer hacer TODO y todo en la misma vista.

Ahora pongo un ejemplo de UI que estoy pensando:

Tier 1 - Bench press, en Stage 1
Tier 2 - Squat, en Stage 2

Si hago swipe left del squat lo muevo a Tier 3, si hago Ok sigo en Tier 2.

Al final en la GZCLP hay que penar que cada ejercicio + stage es un id único, un ejercicio ÚNICO, BP+Stage1 y BP+Stage2 y tienes 2 progresiones de 2 ejercicios distintos, aunque sean BP.

Y en otra vista distinta configurarias los RM, quizas verias lo que hay que hacer la proxima semana, y en otra verias tu progresion.

Lo que a nivel de UI, si lo haces asi, todo es muy minimalista y se ve muy vacio ajjaja por eso imagino que los que hacen estas apps de gym lo meten todo en el mismo sitio, para rellenar... jaja

Don_Correcto

#16 hay alguna libreria de componentes asi? o toca hacerlo a manubrio?

1 respuesta
JuAn4k4

#20 Alguna tienes pero pocas se preocupan del responsive, suelen dar muchos componentes pequeños (botones, tabs, etc), y ni aún así.

Pero es normal, el responsive cambia mucho dependiendo de lo que tengas de contenido, como mucho se preocupan en los menús y desplegables/tabs y ya.

7 días después
desu

Hello voy a hacer un update.

El problema que tengo es, que en excel, lo monto todo en 5 minutos.
Y para que el frontend sea "funcional" y mejor que excel, necesito dedicarle 2 semanas.

HAHAHA.

Quitando las ideas de rutinas que comente, he fracasado en diseñar una buena UI y fácil, otro plan era trabajar los mesociclos, mi objetivo era tener un planificador de ciclos, donde cada micro sea la rutina que tu quieras, y te vaya analizando el volumen semanal. Por ejemplo, en 3 meses cuanto cardio y que músculos he hecho y que rangos? Quiero planificar un bulk? Cuando empiezo si quiero cortar antes de X fecha? Tengo una marathon el día X/XX/XXXX cuando debo empezar a prepararme y modificar mi planning?

Así lo tengo en el Excel. Y no me da ninguna estadística, pero para yo tener una idea de mis próximos meses de entreno y saber qué he hecho, pues está bien... Como todo mi entrenamiento se basa en ciclos cortos y progresiones fijas, puedo programar muy fácil. Si mañana hago boxeo, tan solo tengo que meter la actividad, cambiar la rutina de fuerza por una de 2 días y ajustar el cardio a mantenimiento porque con boxeo ya cubriré mis necesidades.

Lo bueno del frontend vs el excel es que puedes meter varios entrenos al día... Am/Pm, que te calcule horas de descanso aproximadas e identifique errores de planning, es todo mucho más dinámico y tiene más potencial. También puedo tener bloques de entrenamiento / ciclos más pequeños, del estilo "abs/core" que sean 2 series de abs, y meterlo cuando quiera, la flexibilidad es mayor. Como veis en el excel, solo entiendo yo lo que tengo que hacer jaja.

  • Conclusión 1, el proyecto me interesa mucho, creo que esta parte de planificación de ciclos tiene potencial, incluso se puede llegar a comercializar, pero ahora mismo no tengo tiempo para pushear hasta el final.
  • Conclusión 2, la parte de rutinas y visualizar progreso lo despriorizo, cuando lo retome me centraré en la periodización de entrenamiento.
  • Conclusión 3, de hecho he trabajado en algunas vistas nuevas, y he probado a meter un calendario vs hacer unas cuadrículas como el excel yo a mano, y me gusta mas lo segundo. No lo pusheo pero learning final, a veces hay que probar cosas y tirarlo a la basura. Y a veces las cosas que haces nadie las va a ver.
2
Maaarc

Congrats por el farmeo, super interesante. Siempre haces proyectos web? Algun frameworl interesante puramente en phyton? Normalmente uso streamlit para fronts pero es muy cutre y 0 profesional.

ReloaD1010

#5 Un poco tarde y no me he leído todo el post, pero te recomiendo ojear algún tipo de state management (Redux toolkit por ejemplo).
Por eso es muy común ver por ahí React y Redux juntos, React no se dedica a una una buena gestión del DX del estado pero librerías como Redux si. Si la app crece y vas necesitando persistir el estado en más sitios lo agradecerás, aunque tendrás que dedicarle un poco para tenerlo funcionando y migrar los contextos que tenías.

Y por curiosidad, tienes experiencia en Java? Es que por el estilo del código me da la sensación :D
Por ejemplo, el uso del == cuando en general es una mala práctica, o como defines el mapa de ejercicios. Yo lo hubiera hecho algo así:

const [benchPress, setBenchPress] = useState(0);
const exercises: Record<ExerciseType, { value: number, setValue: (num: number) => void }> = {
  [ExerciseType.BENCH_PRESS]: { value: benchPress, setValue: setBenchPress }, 
}

Vas aprendiendo rápido. Si te quedas atascado o quieres que te tire algún palo o review avisa.

PD: el light theme en los IDEs atrae a los bugs

1 respuesta
desu
#24ReloaD1010:

React y Redux juntos

No me gusta Redux. Me parece una monada algebraica demasiado compleja en general. Prefiero tener state stores reactivas como se hacen con rxjs o frameworks reactivos de otros lenguajes, pero por como funcionan los hooks (#7) en buildtime no puedo hacerlo así. Igual que crearon los useReducers para las limitaciones de useContext imagino que crearon los signals para lo que quería hacer, pero no los he probado.

Cuando vuelva a darle al proyecto tengo pensado empezando con tratar de refactorizar a signals a ver que ofrece React.

Aunque tengo la sensación por como funciona el lifecycle y los estados de rendering internamente que no irá fino como debería.

1 respuesta
SupermaN_CK

#25 No necesitas Redux, tienes Zustand que es infinitamente más simple.

2 1 respuesta
desu

#26 thx me gusta a primera vista, https://docs.pmnd.rs/zustand/guides/flux-inspired-practice

los slices no me gustan, aunque entiendo el curry... es la mierda de react como en #7 o el tema de rxjs, menuda mierdota

pero vamos le echare un ojo a esto y los signals, si solo quiero stores globales... madre mia que dificil lo hace react ajaj

veo Valtio tambien, quizas es lo mas simple que busco, si es mutable es referencia dinamica?

https://valtio.pmnd.rs/docs/api/basic/proxy

1 mes después
desu

Hello, hoy tenia un rato y como voy a cambiar el programa he aprovechado y arreglado el hecho de que no se visualizase bien el mobile/tablet etc. Ahora se debería ver bien en todos los dispositivos XD

https://lifts-two.vercel.app

Nota: es un video donde cambio el margen

Tengo aun pendiente meter lo del lucalstorage, como me cambie el portátil me daba pereza hacerlo XD ahora lo hare que ya tengo el portátil nuevo.

He hecho el frontend porque para otros programas usaba el Garmin, porque para todos los ejercicios usaba el mismo % y sets/repes, pero para este planning que es como un 5/3/1 full body donde hay varios rangos por ejercicio voy a usar la web esta que me he montado para seguir mis entrenos.

1
desu

He añadido el 90% training max:

Entrenar con el 100% real de tu RM es sub-optimo e ineficiente.

El porcentaje podría ser variable, por ejemplo en 5/3/1 en etapas de volumen alto como leaders con 5s pro y similares se recomienda 80-85%.

De momento lo dejo en 90% que es un buen numero.

1
HeXaN

Te está quedando flama :thumbsup: