logo

midulive


Transcribed podcasts: 605
Time transcribed: 13d 3h 7m 36s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

Venga, vamos por faena. ¿Qué es lo que queremos hacer hoy?
Hoy tenemos diferentes cositas.
Mira, vamos a poner aquí lo que vamos a tener hoy.
Mergear las PRs, ya lo hemos hecho.
Ver los últimos cambios, no lo hemos hecho, pero ya los comento rápidamente.
En el archivo hice la galería, que la dejamos el otro día a medias.
La galería, y fijaos con la galería lo que hice fue hacer un masonry, ¿vale?
Fijaos que aquí hice un masonry donde teníamos esto al pasar al siguiente.
Y ahora ya estaban bien todos los efectos con todas las resoluciones y todo, ¿vale?
Así que... Ah, y además hice esto de descubre las todas para que se cargasen el resto de imágenes.
¿Qué es lo que hemos conseguido con esto?
Pues obviamente lo que conseguimos es que quede más bonito, ¿no?
De que las imágenes verticales queden mejor integradas y además solo cargue un trozo de la galería en lugar de cargarlas todas, ¿no?
Y al darle a descubre las todas, pues se cargan todas ahí y ya está.
Le das aquí y fijaos que hace el efecto ese de hacer el zoom que queda bastante bonito.
Para hacer esto, para hacer ese efecto, lo que hicimos aquí, que está bastante interesante por si lo queréis saber,
en scripts tenemos diferentes scripts que lo que hacen es, por ejemplo, crear los zoomles de la galería.
Estamos utilizando BAN, que es una alternativa a Node, y lo que hacemos aquí es recuperar todas las imágenes de la galería.
Y lo que hacemos es quitarle mucha calidad y hacerlas más pequeñitas.
Bueno, no hacemos más pequeñitas, lo que hacemos es quitarle calidad.
Porque así, pues ocupan menos.
Así tenemos dos imágenes ahora.
La que tiene poca calidad, que sería esta, que es más pequeña, ¿vale?
Esta imagen que veis aquí tiene menos calidad.
Voy a ver si podemos ver aquí las imágenes.
Vale, veo que es bastante mejorable.
Sería mejorable esto porque no veo que...
Ah, pues veo que no se están cargando las pequeñas, ¿no?
Yo creo que no.
Ah, sí, sí, sí.
Sí, sí, sí, sí.
Sí, sí, sí.
Sí, porque fijaos.
Fijaos, la pequeña son 27K y la grande son 630.
Esta tiene como esta calidad y esta tiene...
Es clavada.
O sea, es muy parecida.
La verdad es que no sé hasta qué punto tiene sentido.
Sí que es verdad que se nota un poco en la frente, un poco los detalles,
pero podría pasar una por otra porque ya ves tú la diferencia.
No tiene mucho sentido, la verdad.
Bueno, las podemos optimizar todavía más y hacerlas más pequeñas y ya está.
Si lo hacemos con esto, aquí lo que podríamos hacer es,
guardando la relación de aspecto, hacerlas todavía más pequeñas
o bajarle incluso más la calidad, ¿sabes?
Podríamos bajarla a 20, que igual es un poco exagerado.
Pero ahora sí podríamos ejecutar este script, este script create meta
y así lo que haríamos es todas las...
Ah, no, porque es con van.
¿Y qué pasa con esto?
Undefine is not a constructor.
Ah, porque a lo mejor no tengo van actualizado a la última.
Es que, claro, como he estado trabajando en el portátil en lugar de trabajar aquí,
igual, ¿veis?
Ahora sí.
Ahora sí.
¿Vale?
Ahora debería haber bajado todavía más la calidad de esta imagen.
Ah, bueno, pero esto son...
Esto es en producción, ¿vale?
Vale, a ver aquí.
Bueno, la verdad es que se sigue viendo bastante bien las imágenes.
Se siguen viendo bastante bien.
¿Habrá bajado la calidad?
O sea, ¿habrá bajado la imagen 1, 27?
Pues no sé si es que a lo mejor esta calidad...
A ver, si le pongo 1, algo exagerado, algo exageradísimo.
A ver.
Ah, create meta.
Es que además me he equivocado.
No es create meta.
Es...
No es create meta.
Es create zooms.
Me he equivocado de script, ¿vale?
Es create zooms, ¿vale?
Ahí está.
Y...
Ah, vale.
Vale, vale, vale.
Ahora, ahora, ahora tiene sentido, amigos.
Ahora tiene sentido, ¿eh?
Es que ya decía yo que había convertido tan rápido las imágenes.
Claro, esto lo que hace es pillar una imagen y transformar el thumbnail a una calidad más pequeña.
Claro, ahora lo que veremos seguramente...
¿Ves?
Ahora sí que se nota que tiene peor calidad.
¿Vale?
A ver.
1, igual me he pasado, que lo he puesto a 1.
Igual lo podemos dejar a 25.
Y...
Y ahora, pues, ver cómo quedarían más o menos, ¿vale?
Y bueno, ahí se vería.
Y aquí se vería con la calidad buena.
O sea, aquí calidad mala y aquí calidad buena.
Eso sería un poco la idea.
Mejorarlo.
Y está chulo porque hace esa transición entre la de calidad mala a la buena.
Pero lo hace con una transición que casi no se nota, ¿sabes?
Está bastante chula.
Así que nada, podríamos ajustar ahí la calidad, pero lo importante es que ya sabéis cómo se hace.
Vamos a hacer la autentificación, ¿vale?
Venga, vamos a hacer el sistema de votos, que si no, no avanzamos.
Y entonces no se va a ver nada.
No se notó nada.
No se nota nada, pero ha bajado bastante, ¿eh?
Si os fijáis, fijaos que aquí sí que se nota que ha bajado bastante la calidad, ¿eh?
De hecho, esta imagen debo ocupar mucho menos que antes.
Ahora, ¿veis?
Ocupa 16K.
Y antes ocupaba 22.
Bueno, pues son 6K.
Pero a larga es tener dos imágenes.
Claro, es que la clave es tener dos imágenes.
Y esto es bastante interesante, tener dos imágenes.
Por cierto, aquí hay un error que habría que arreglar.
Ah, mira, el palmarés este nos ha roto la página.
Vamos a hacer lo de Twitch.
Vamos a hacer la autentificación con Twitch.
Para hacer la autentificación con Twitch, porque si vamos a los premios SESLAN,
vais a ver ahora que cuando vais a votar aquí, que está bastante chulo,
para empezar a votar hay que iniciar sesión, que tiene sentido, ¿vale?
Le dais aquí.
Hace una cosa rara porque como que primero va a un sitio y luego te envía a otro y ya está.
Y luego aquí tienes que votar, ¿vale?
Que la verdad es que los votos, pues está bastante chulo.
Me da un poco de rabia que si votas una quinta vez, entonces te lo resetea.
Pero bueno, el diseño está bastante bien.
Cosas que no me gustan, ¿vale?
Cosas que no me gustan mucho.
Lo primero, que cada vez que tú vas a votar, tienes que volver a iniciar sesión.
Es súper raro.
Es súper raro, ¿veis?
Hay que volver a iniciar sesión.
Y entonces te vuelve a enviar y hace esto.
Es como que no se acuerda.
O sea, si tú sales de aquí y vas a votar otra vez,
tienes que darle al botón para que realmente empieces a votar.
Es un poco raro, ¿vale?
Sí, puede ser que no guarde el token.
No lo sé, pero sí que es un poco extraña la funcionalidad.
Otra cosa que a mí personalmente creo que podría mejorarse es el hecho de mover el botón arriba.
Que eso es una cosa que ya veis que ya he hecho en esta.
En esta, que es la nuestra, como veis, lo que he hecho es poner el botón arriba.
¿Por qué he hecho esto?
No lo he hecho por nada, sino porque me parece raro que en ciertas resoluciones,
aquí por ejemplo al 100% en 1920x1080, es raro que el botón, que es el call to action más importante,
se tenga que hacer scroll.
No es grave, ¿vale?
No es grave, no es lo peor del mundo.
Pero yo creo que a lo mejor incluso se podría pensar en poner aquí, no sé.
Creo que es mejor ponerlo lo más arriba posible.
Yo por eso lo he movido aquí, ¿eh?
Es una forma de leerla normalmente de empezar.
Ya, pero encima teniendo en cuenta que cada vez que tú entras,
cada vez que tú entras, te vuelve a aparecer, pues tienes que hacer scroll.
Es un poco raro.
Y si es por el tema de las normas, entonces una cosa que yo hubiera hecho
es intentar hacer más cortas las normas.
Hubiera cambiado el diseño para intentar que el botón estuviese visible desde el principio, ¿sabes?
Para evitar, para evitar justamente tener que scrollear, ¿eh?
Pero bueno, es mi opinión, ¿eh?
Ahora, lo que queremos es que cuando le demos aquí a empezar las votaciones,
inicie sesión en Twitch para asegurarnos que el usuario, pues, puede votar y ya está.
¿Qué vamos a hacer?
Pues vamos a añadir la autentificación, ¿vale?
Para añadir la autentificación vamos a utilizar un paquete que se llama outjs.dep.
Lo malo de este paquete, ¿vale?
Es que tenemos una demo para Next.js, una demo para Svelte, una demo para Solid
y no hay demo para Astro.
Y es una pena, la verdad, porque ojalá en algún momento saquen una demo para Astro
que estuviese súper bien.
Lo más interesante es que tenemos un paquete que no me acuerdo si es Astro.out, no me acuerdo.
¿Cómo es?
Out Astro, ¿es este?
Sí, este es.
Es este, ¿vale?
Pues tenemos este paquete que justamente nos sirve para hacer la autentificación
sin tener que preocuparnos utilizando out.js.
Tenemos que seguir unos pasos, pero nos lo deja bastante más caíto.
Así que lo vamos a hacer.
Vamos a utilizar este npm run astro at as astro, ¿vale?
Joder, qué complicado.
¿Vale?
Le damos aquí.
Y esto, lo típico, lo que te hace es preguntarte, oye, ¿quieres utilizar este paquete?
Le decimos que sí.
Y ahora nos dice, vale, pues voy a tener que añadir estas dependencias.
Le decimos que sí.
Y ahora nos va a decir, pues voy a tocar esta configuración.
Y le diremos que sí también, ¿vale?
Así que nada, está instalando las dependencias.
Ah, ¿no me ha añadido la configuración?
O sí.
A ver si me ha añadido la configuración.
Astro.config.
Sí, sí que la he añadido, ¿no?
Porque la he puesto aquí.
Qué raro que no me ha preguntado, ¿no?
Es raro que no me haya preguntado.
No sé si es que la había puesto yo antes.
Puede ser que la haya puesto yo antes.
Pero bueno, lo importante es que necesitamos en la configuración de astro
importar out from out astro.
Y en las integraciones tendríamos telwin, priac y out, ¿vale?
Estas serían las tres.
Así que esto, súper importante para que no funcione,
al menos el principio de todo esto.
¿Dónde vamos a querer utilizar la autentificación?
En los botos.
Aquí, ¿vale?
Y lo vamos a hacer justamente en este botón.
Así que lo que vamos a hacer es configurar la autentificación con Twitch.
Aquí nos dice cómo lo tenemos que hacer con Geekha,
pero en Twitch es muy parecido.
Tenemos que crear un archivo de configuración en el root de nuestro proyecto.
que, ah, mira, que ya la había creado.
Y parece ser que ya la había, o sea, ya la había subido también.
Bueno, no pasa nada.
Que sería esta, que básicamente es copiándome.
Mira, lo voy a copiar para que lo tengamos así y ahora lo cambio.
Básicamente, tenemos que importar el provider,
que sería en este caso Twitch.
Nos aseguramos de cambiar esto también a Twitch.
Y aquí en providers ejecutamos Twitch y nos aseguramos de utilizar
las variables de entorno correctas, que ahora verás de dónde las sacamos.
Ponemos aquí Twitch y Twitch.
Y estas variables de entorno, vamos a ir al .env, .env,
y vamos a crear tanto el Twitch Client, ¿vale?
Como el Twitch Client Secret.
Vale, perfecto.
Para tenerlo en local, a ver, lo bueno es que este archivo .env,
ves que está como apagadillo.
Esto lo va a ignorar y no lo vamos a subir sin querer.
Pero lo que sí que puede ser interesante es ponerlo aquí en los ejemplos,
ves, en .env.example, por si alguien se baja al repositorio,
que sepa cuáles son las variables de entorno que tiene que utilizar.
Entonces, la pones aquí, le pones unos valores de mentira y ya está.
Y este archivo sí que lo podemos subir para que la gente entienda
que necesita estas variables de entorno.
Y aquí pondremos las reales.
¿De dónde sacamos esto?
Bueno, pues tenemos que ir a dev.twitch.tv, si no me acuerdo mal.
¿Vale? Hacemos un login en Twitch y aquí, pues nada,
autorizamos que pueda haber un montón de cosas.
Vale, parece que no ha hecho nada, pero ha cambiado esto de aquí.
Esto de aquí, ves que pone tu consola.
Bueno, pues le damos aquí, tu consola.
Y aquí tenemos que crear una nueva aplicación.
Aquí le damos a registra tu aplicación, le ponemos un nombre,
es land web y aquí tenemos que ponerle la URL de redireccionamiento del OAuth.
¿Vale? ¿Qué es esto?
Esto básicamente es que cuando iniciemos la sesión le vamos a decir a Twitch,
oye Twitch, quiero iniciar sesión con mi cuenta de Twitch.
Y Twitch lo que va a hacer es enviar la información de identificación de acceso
a nuestro servidor, a nuestra API.
Y en la API le tenemos que pasar con todo el token y todo esto
para que pueda validar y guardar en las cookies que se ha identificado correctamente.
¿Vale? Hace la validación y ya está.
Ahora, ¿qué necesitamos una vez que haga esta petición?
Necesitamos que sepa cuál es la URL, cuál es el endpoint donde le permitimos acceder.
Porque si no aquí, si no pusiéramos nada, nos podrían piratear rápidamente
y sería súper peligroso.
Entonces le tenemos que decir, oye, ¿cuáles son las URLs de redireccionamiento
que nosotros estamos controlando y que realmente sí que estamos soportando?
¿Vale? ¿Qué vamos a hacer?
Vamos a añadir la de localhost primero, ¿vale?
Podríamos poner http localhost 4 3 2 1 barra y aquí en api barra aus barra callback barra Twitch.
¿De dónde sale esto?
Pues esto sale de la documentación.
Porque si nos ponemos a mirar, ¿ves?
Aquí ya nos comenta.
Hay algunos OAuth providers que nos piden tener un callback URL
donde va a enviar el client toda la información de identificación, ¿no?
Y esto es algo que tenemos que tener nosotros.
Ahora bien, lo bueno es que nuestro paquete este ya hace toda esta magia por nosotros.
No vamos a tener que crear nosotros este endpoint,
sino que automáticamente lo va a crear gracias a lo que tenemos
en el archivo de configuración que hemos visto antes.
Se crea automáticamente.
Así que en provider utilizamos Twitch y ya está.
Ponemos el puerto correcto donde normalmente tenemos este proyecto.
El 4 3 2 1 barra api barra aus barra callback Twitch.
¿Vale?
Me voy a asegurar que lo he puesto bien, que nos liemos api, aus, callback y Twitch.
¿Vale?
Api, aus, callback, Twitch.
¿Vale?
Y ahora lo mismo tendríamos que hacer, pero con la web de producción.
Vamos a la web de producción, que sería esta de aquí.
La copiamos y tendríamos esta URL.
¿Vale?
Slang-web.versell.app api, aus, callback, Twitch.
Y ahí es donde vamos a tener los resultados de las autorizaciones de cliente de Twitch.
Ahora, la categoría, website integration y en tipo de cliente le vamos a poner confidencial.
Porque por suerte la integración que vamos a hacer va a ser a través del backend.
Va a ser a partir del backend, no en el frontend.
Si quisiéramos que fuese público, o sea, si queremos que sea algo de JavaScript en el frontal,
podríamos utilizar este.
¿Vale?
Pero fíjate, los clientes públicos no pueden mantener la confidencialidad de sus credenciales.
De hecho, una cosa interesante.
Hace poco han hackeado a Resend.
Mirad, os voy a explicar una historia que es bastante interesante de una cosa que pasó el otro día.
Y además, fue por culpa de los React Server Components.
Es buenísimo.
Es, utilizando los React Server Components, se le coló, justamente se le coló, el hecho de...
Mira, ves, aquí.
Un atacante utilizó una variable de entorno que se le coló hackeando.
O sea, hackeando.
Se le coló utilizando como un React Server Component y eso llegó al frontend y la lió parda.
La lió parda.
Así que nada, si le queréis ir a un vistazo, lo tenéis aquí, todo explicado.
Que es bastante interesante.
Pero es verdad que esto lo que quiere decir es que puede pasarle a cualquiera.
Así que los React Server Components, esta idea de quitar la frontera de servidor y frontal,
ya veis que no siempre es tan buena idea.
Venga, le vamos a dar a crear y esto lo que nos va a crear ahora va a ser justamente la integración con Twitch.
¿Vale?
Aquí la integración de los SESLAN.
¿Vale?
Vamos a darle a administrar.
Aquí tenemos ya el ID del cliente.
¿Ok?
El ID del cliente.
Así que nos vamos a la página web que la teníamos aquí.
¡Pum!
Y aquí la ID del cliente.
Pero nos falta el secret.
Y el secreto lo tendríamos aquí.
¿Ves que pone secreto del cliente?
Le tendríamos que dar aquí y nos aparecería el secreto.
Pero como sé que tenéis más peligro que una caja de bombas, ¿vale?
Pues le voy a dar al nuevo secreto.
Me lo va a generar.
No os voy a poner la pantalla para que no me la liéis parda.
Lo voy a guardar en la variable de entorno.
Lo voy a cerrar.
Y voy a cerrar también esto de aquí para que no haya ningún tipo de problema.
Y ya está.
Pero lo único que tenéis que saber es que he creado el secreto correctamente.
¿Vale?
Para que no me la liéis.
Ya tendríamos el client ID, el client secret.
Nos falta un detallito porque veis que pone aquí setup environment variables.
Hay dos variables más que necesitamos.
Que es auth secret, que tenemos que crear aquí un secret.
Hay que generarlo aquí.
¿Vale?
Que te da una ID.
Esto en realidad es básicamente...
Cada vez que entras te da uno totalmente diferente.
Creo que no añadiste la red de URL para producción.
Yo creo que sí.
Lo vamos a mirar.
Lo podemos mirar.
Así que...
Sí, mira.
Aquí está.
Aquí está.
Sí, sí.
Si le das añadir, lo que significa es raro para creer.
Pero lo que pasa es que añade otro más.
Es súper raro, tío.
La UI no está muy bien hecha.
No está muy bien hecha.
Bueno, aquí cada vez que entréis, veis que os genera un chunk totalmente diferente.
Vale.
Pues lo que vamos a hacer con esto es añadirlo primero en el example.
Aquí, para que la gente lo tenga.
Y aquí, pues nada.
Esto sería un 2, 3 también.
Y ahora lo que voy a hacer es añadir este auth secret, que se tiene que generar como este aquí.
Lo voy a hacer en la variable de entorno.
¿Vale?
En la de verdad.
Pero como no me fío de vuestras capacidades de hacker, pues lo vamos a hacer.
¿Te vieron la key?
No, porque voy a generar una nueva.
Entonces no pasa absolutamente nada.
Esa key básicamente se utiliza a la hora de generar...
Creo que, si no me equivoco, es...
No recuerdo bien si está hecha con OpenSSL, pero no sé si es como para generar el token.
¿Sabéis?
Como para generar su propio token interno.
Y con esto ya tendríamos toda la configuración.
Ya no hay que hacer nada más.
¿Vale?
De configuración ya lo tendríamos.
Ya está.
Punto.
Ya con esto lo tenemos listo.
Ahora aquí lo que nos dice es cómo podemos iniciar la sesión.
Así que vamos a darle cañita.
¿Vale?
A ver cómo podemos iniciar la sesión.
Voy a mirar una cosa.
Vale.
Sí, sé la extensión que me dices.
NERKER.
NERKER me dice que hay una extensión que oculta las variables de .env.
Pero no es así.
O sea, sí que es así.
Pero funciona mal.
Funciona mal.
Y muchas veces el...
E-CLOCK.
Lo he utilizado alguna vez.
Pero funciona mal.
Funciona con un poquito de retraso.
Y lo que ocurre es que, por desgracia,
si tú abres el archivo,
hay un milisegundo en el que se ve,
en el que se ven todas las variables
y la gente, claro, ¿qué pasa?
Que la gente, si tiene un vídeo,
lo puedes pausar y ya está.
Entonces es un poco rollo.
No sé si se podría mejorar esto,
pero ojalá.
Ojalá se pudiera.
Pero es muy interesante la extensión.
Es una pena que no funcione del todo bien.
Venga, vamos a conseguir ahora la autentificación.
Que esto está súper interesante.
Porque esto normalmente es una cosa que cuesta bastante.
Pero con esto, si lo hemos hecho todo bien,
que creo que sí,
ahora deberíamos ser capaces,
por un lado,
de detectar si el usuario tiene sesión.
Vamos a poder recuperar el getSession
de AuthServer,
que veo que no me lo está pillando.
Y me estoy imaginando que...
No, AuthServer no.
AuthAstro.
Es que no me lo está pillando.
No sé si es que no me lo ha instalado.
Si está aquí.
¿Por qué no me lo ha instalado?
O sea, parece que sí que lo ha instalado.
Porque está aquí el add.
Pero no me está pillando el...
¿Por qué no me está pillando esto?
Ahí sí que está la dependencia.
Server.
No se encuentra AuthAstro.
¿Es AuthAstro?
A ver.
AuthAstro barra server.
¿Ves?
Está aquí.
¿Por qué no me lo está pillando esto?
¿Por qué no me lo está pillando?
A ver, voy a quitar un momento esto.
Voy a quitar también el pnpmlog.
Y voy a hacer otra vez la instalación.
Reload.
Está mal escrito session.
Bueno, puede...
Sí, sí.
Esto puede estar mal escrito.
Pero es esto lo que me preocupa.
El AuthAstro este.
Que no me está encontrando el módulo.
Ese es el problema.
Ni sus declaraciones.
No me está encontrando.
Y esto es land web.
Y aquí está el server.
Pero no me lo está encontrando aquí.
No sé si es que estoy haciendo algo...
Me pasa cada rato.
Puede ser...
Voy a recargar y ya está.
A ver qué tal.
Vale.
Ahora sí que funciona.
Yo qué sé.
Cosas raras.
Lo interesante es que ahora ya con esto deberíamos ser capaces de recuperar la sesión si le pasamos el astro.request.
Le pasamos la request y esto lo que va a hacer es ver si tiene la cookie para saber si el usuario está registrado o no está registrado.
Pero ¿cómo tenemos que registrar al usuario?
Obviamente necesitamos que el usuario inicie sesión antes de liarla.
Así que vamos a hacer el sing-in con el botón.
Para hacer el sing-in con el botón, este botón de aquí, este con este botón, vamos a crear un script aquí abajo.
Esto lo voy a sacar de aquí.
Que me parece que queda un poquito mejor.
Hacemos el script aquí.
Y aquí podemos importar el sing-in de...
A ver si ahora tampoco funciona aquí.
Import.
Austro.
Vale, ahora sí que lo pillo.
Entonces, cuando document.querySelector, cuando pillemos el botón de...
Vale, perfecto.
Casi, casi.
Vamos a hacer esto.
Esto vamos a hacer el evento aquí con un prevent default.
Porque ese botón es un anchor que no es correcto.
Debería ser un botón, pero no me da tiempo ahora a arreglarlo.
¿Vale?
Vamos a poner aquí el button.
Lo vamos a guardar aquí.
Voy a poner un comentario porque luego en YouTube...
¿Por qué pongo un delante para que se vea que es un elemento del DOM?
Es una cosa que se hacía en el pasado con jQuery y es una manía que se me ha quedado porque me gusta.
¿Vale?
Porque esto me preguntan después 10.000 millones de veces.
10.000 millones de veces.
¿Pero por qué haces eso?
¿Por qué haces...?
No sé, porque se me quedó esto y la verdad es que me gusta poner el dólar delante porque visualmente entonces entiendo rápidamente que es un elemento del DOM.
Esa es la razón por la que lo hago.
Entonces, hacemos el button y si existe, escuchamos el click, hacemos asincronamente un sing-in de Twitch.
Aquí creo que hay un problema porque lo correcto lo arreglaremos.
Aquí deberíamos pasarle el callback URL para decirle dónde debería redireccionarlos.
Pero vais a ver que no funciona del todo bien.
Entonces, esto es una cosa que tendremos pendiente porque me parece que hay un bug.
He estado mirando aquí en la documentación y justo hay una ISU que está aquí creada.
¿Ves?
Setting up callback URL de hace tres semanas.
Y esto está mal.
O sea, no está funcionando.
Entonces, lo voy a tener que mirar y si hace falta haré un fork de la biblioteca para arreglarlo.
Porque esto no funciona como se supone que debería funcionar.
Pero con esto ya deberíamos ser capaces, si todo ha ido bien, de ir aquí, darle aquí y no funciona.
Ah, no, porque esto no es local.
Vale.
Bien, me gusta.
Esto sí que es local.
Venga.
Deberíamos ir aquí, darle aquí y...
¡Tatán!
Tenemos Twitch.
¿Vale?
Ya tenemos Twitch.
Le damos a autorizar para iniciar sesión.
¿Veis?
Aquí está el problema.
El problema es que aquí debería redireccionarme a votar y no lo hace.
Y es porque está ignorando esto.
Esto no está funcionando y debería funcionar.
Porque es para eso.
O sea, esto es para eso.
No sé por qué.
¿Ves?
Que pone aquí...
Especifica qué URL de usuario será redireccionado una vez que haga el sing-in.
Por defecto va la página que lo inició, pero no lo está haciendo.
Entonces, hay algún tipo de problema ahí porque esto debería funcionar y si no, lo arreglamos.
¿Vale?
La pantalla en blanco no es problema mío.
La pantalla en blanco justamente es de Twitch.
No se puede hacer nada.
Ahora, si vamos aquí a votar, ahora sí, al menos, vamos a hacer una cosa.
Vamos a hacer que todo esto solo se vea si el usuario no ha iniciado sesión.
¿Vale?
O sea, que vamos a poner que esta parte de aquí, esta parte de aquí, si no tenemos sesión,
entonces vamos a enseñar este div de aquí.
Todo este div.
¿Vale?
¡Pum!
Ahora nos aparece vacío.
Nos aparece vacío porque justamente sí que tenemos la sesión iniciada.
¿Vale?
Para notar más que tenemos la sesión iniciada o no iniciada, otra cosa que podemos hacer
es cambiarle el fondo.
Si os fijáis, ellos, que me parece súper bien, cambian el fondo cuando estás dentro
de los votos.
O sea, cuando le das aquí a votar y te das a empezar a votar, ¿veis que la página
en blanco también le sale a ellos?
Eso es de Twitch.
Es que ahí no podéis hacer nada.
Pero bueno, este fondo lo cambian y es cuando vas a empezar los votos, ¿no?
Vale, pues vamos a hacer lo mismo.
Vamos a cambiar el background.
Vamos a poner background.
Si tenemos sesión, porque si no tenemos sesión, es que el usuario no ha iniciado
sesión, será nul.
De hecho, si nos ponemos encima no debería decir, ¿ves?
¿Es sesión o nul?
Bien, entonces, si es nul, pues vamos a poner una cosa, una imagen y si no ponemos otra.
Creo que aquí en public, si no me equivoco, tenía ya la imagen en public.
Debería tener la imagen vota.
Vale, tendríamos por un lado vota webp y vote system webp.
Así que vamos a poder cambiar esto a aquí.
Cambiamos esto.
Esto habría que ponerlo así.
Y esto así.
Y ya está.
Ahora deberíamos tener las dos imágenes.
O sea, pues no.
A ver si la sesión, si tenemos sesión, a ver si tenemos sesión.
Porque igual no tenemos sesión y yo estoy aquí pensando felizmente que tenemos sesión.
¿Vale?
Porque este console.log no se ve.
Sí, sí que tenemos sesión.
Se ve aquí.
¿Vale?
Aquí se puede ver que tenemos la información.
Y esta es la imagen de Twitch del usuario.
¿Vale?
Si tenemos sesión, bkg.
Si tenemos sesión es vota.
Pero a ver si me he equivocado de la imagen.
Vota.
¿Vale?
Vota.
Y vote system es la otra que deberíamos...
Que es la azul.
O sea, que está bien.
Y esta imagen es la que debería aparecer aquí.
Y otra vez...
No sé por qué no lo está pillando, ¿no?
O sea, no me está haciendo el cambio de la imagen.
Me he equivocado.
¿No está al revés?
No.
Si tenemos sesión...
Ah, tienes razón.
Tienes razón.
Está al revés.
Joder.
Sí, sí, tienes razón.
Está al revés.
Está al revés.
Con lo pejiguero que soy.
Nada.
Me equivoqué.
Perdón.
Está al revés.
Vale.
Ahora sí.
Ha de tener toda la razón.
Vale.
Entonces, ya estamos enseñando la imagen.
¿Vale?
Bueno, vamos por...
Porque aquí hay faena, ¿eh?
Aquí hay faena ahora.
Lo que vamos a hacer es...
Claro, el tema de las votaciones tiene que ser bastante dinámico.
Porque fijaos que cambia esto, cambia lo otro.
Entonces, para simplificar e ir más por faena y que tengamos esto funcionando...
Esto está muy chulo porque vamos a ver...
Vamos a ver paginación, vamos a ver un montón de cosas.
Pero lo más importante es que necesitamos seguro que si tenemos sesión vamos a mostrar un vote system.
Vamos a cargarlo cuando el usuario...
Cuando se cargue la página.
Y este vote system vamos a hacer que sea un componente.
¿Vale?
Vote system.tsx.
Un componente de PRIAC.
Así que exportamos la función vote system.
Y aquí vamos a poner un div.
Vote system.
Por ahora lo dejamos así vacío.
Y esto lo vamos a importar aquí arriba.
Y esto es una cosa muy chula porque, como se puede ver, podéis mezclar tanto componentes,
de TypeScript, hay componentes de Astro, con componentes de PRIAC, de REAC, de Svelte, de lo que queráis.
Y esto es lo que hace realmente interesante Astro.
Y esto se queda aquí y esto va a ser solo interactivo cuando llegue al cliente y cuando lo cargue.
Pero podríamos poner que sea cuando es visible y todo esto.
O sea, podemos poner aquí.
Cuando sea visible.
Pero aquí queremos que se cargue luego cuanto antes.
Entonces no tiene mucho sentido que esperemos y que haga ninguna cosa.
Vamos a darle cañita al vote system que aquí hay un montón de cositas.
Lo primero, vamos a tener que crear una API, ¿vale?
Vamos a tener que crear una API porque fijaos que en cada paso que demos,
en cada paso que demos, se muestra diferente información de cada uno de los candidatos según la categoría.
Necesitamos la información de la categoría, el título.
Necesitamos también cada una de las imágenes y todo esto.
Si alguien se pregunta, oye, ¿y cómo sacas esta información?
Yo te lo explico.
Hay un tema que es bastante bestia.
Si ponen la ruta absoluta con el dominio, ¿tampoco funciona?
Yo creo que tampoco funciona.
Lo puedo probar.
Lo puedo probar.
Localhost 4, 3, 2, 1, barra, bota.
Lo voy a probar.
Igual es eso.
Pero estoy bastante seguro que no es eso.
Estoy bastante, bastante seguro porque yo esto lo he utilizado en otros sitios y debería funcionar.
Hostia, es con cookies.
¿Vale?
Cookies.
Tu, tu, tu, tu, tu.
Ay, cookie.
Cookie.
Cookie.
¿Vale?
Ahora me volverá a salir esto.
Empezar con las votaciones.
¿Vale?
Me hace la redirección.
¿Ves?
No hace la redirección correctamente.
Yo creo que es un error.
Es un error que tenemos en la biblioteca.
Hay un error ahí que no está funcionando bien.
Venga, vamos a ir estilando esto un poquito.
Aquí me voy a copiar una cosa porque en el no session, este dip me lo voy a copiar para que quede exactamente igual.
¿Vale?
Esto me lo voy a copiar aquí.
Vale, cositas, cositas.
Aquí vamos a poner el category title, que por ahora vamos a poner categoría y vamos a poner category title.
Esto lo arreglaremos después y lo haremos en condiciones para que quede bastante bonita.
¿Vale?
Vamos a poner un children y vamos a poner que el children es un string.
Y vamos a poner retur h1 children.
¿Vale?
Esto lo arreglaremos después, el category title.
Luego vamos a tener aquí lo que serían los nominados.
¿Vale?
En el ul tendríamos los nominados.
Y luego vamos a tener un footer, ¿vale?
Que va a ser la navegación.
Navegación.
Por ahora lo dejamos así porque lo más interesante que necesitamos ahora mismo y que además está muy chulo es porque vamos a tener que hacer un poquito de backend, ¿vale?
Vamos a tener que hacer una API para poder recuperar esta información.
Porque cuando entremos, mira, lo vamos a hacer aquí para que veamos lo que necesitamos.
Cuando hagamos un...
Cuando entremos al componente, queremos mostrar la información.
Y en lugar de recuperar toda la información de golpe, que a ver, no está mal, pero es, por ejemplo, lo que hacen aquí.
Aquí, si alguien se pregunta cómo hemos recuperado toda la información, que la tenemos aquí, vote system o vote info o info...
A ver, info.json...
Ah, no me acuerdo dónde está.
Pero tenemos toda la información aquí, ¿vale?
¿Veis? Aquí está toda la información de los votos.
Toda la información la tenéis aquí.
Imágenes, enlace, si la categoría...
Toda la información está aquí, ¿vale?
El nombre del candidato.
¿Y cómo se pilla esto?
Pues es que el tema es que si nos ponemos a mirar aquí el JavaScript...
Hostia, qué heladilla que esto no se guarda nunca el usuario, ¿eh?
Y le damos a JS.
Aquí en el index, que es un archivo ahí de JavaScript que tiene un montón de cosas,
si buscamos aquí, por ejemplo, AuronPlay, AuronPlay, fijaos, ¿qué tenemos por aquí?
Tenemos, bueno, tenemos ese, pero tenemos más.
Aquí lo tenemos.
Candidatos, AuronPlay, nombre.
O sea, tú te copias este objeto, este objeto te lo copias y ya lo tienes.
Ya tienes toda la información.
Básicamente, en lugar de tener un bug en una base de datos, lo tienen un JSON.
Que no está mal, o sea, está bien porque al final es muy poca la información que tiene y ya está.
Ahora, el problema que tiene en general la información, o sea, este JavaScript que ellos utilizan,
es que no es este el problema, es que lo tienen todo, todo, todo, incluso los assets.
Por eso hacen que sea tan, tan grande toda la información.
Si buscáis AuronPlay, vais a ver que sale unas cuantas veces justamente por esto,
porque todos los assets los tienen ahí en una lista.
Y claro, esto hace que sea bastante tocho, ¿eh?
Bastante, bastante tocho.
De hecho, son 187 minificado, que es bastante, ¿eh?
Bastante teniendo en cuenta que podría ser menos, medio mega.
Lo podéis hacer así, no hay ningún problema, pero ¿qué pasa?
Que, como ya os he dicho, yo os quiero enseñar cómo hacerlo un poquito mejor
para mejorar la experiencia del usuario o que sea un poquito más óptimo, ¿vale?
Entonces vamos a hacer una función que sea FetchCandidates, ¿vale?
Y donde aquí vamos a tener la respuesta después de hacer un fetch
y aquí vamos a crear nuestra API para recuperar los candidates.json, ¿vale?
Ahora os explicaré por qué el .json.
Le pasamos la categoría que queremos recuperar, que ahora mismo vamos a poner aquí
que es categoría, no sé, empezamos con el cero, ¿vale?
La primera categoría.
Y aquí ahora ya tendríamos la respuesta, pues tendríamos la data,
response.json y aquí sí que vamos a tener la información en un estado.
Vamos a poner pageInfo, setPageInfo, useState y podemos dejarlo vacío, ¿vale?
Por ahora lo dejamos vacío y aquí haremos setPageInfo de la data.
Y aquí nada más entrar en el useEffect, el efecto la primera vez que se ejecute,
pues llamamos a este método fetchCandidates.
Ahora, tenemos que crear esta API.
Aquí vienen las cosas interesantes.
Esto está muy chulo porque es una forma de crear endpoints en Astro,
que se puede sin ningún problema, igual que harías en NACs, en Next.js
o en cualquiera de estos.
Y lo único que tienes que hacer es, te vas a Pages, aquí, ves, aquí tenemos API
y yo ya creé uno para la galería.
Fíjate que yo creé ya un JSON para la galería.
Para en lugar de tener que cargar todo el JSON desde el principio de la galería,
lo que hago es, bueno, si le da el botón, me descargo los que necesitamos.
De hecho, lo podéis ver aquí.
Mira, si os vais a Archivo, veis la galería.
Hasta que no le das a este botón, no se empieza a descargar el resto de imágenes.
Y lo podéis ver aquí.
Si le damos a ese botón, vale, aquí, pam, pam, pam, le damos a este botón,
vais a ver que ahora van a aparecer aquí unas requests, ¿vale?
Bueno, no, porque lo he hecho mal, pero ahora sí.
Vale, veis, ha pillado el JSON, que son 26 milisegundos, que no lo va a notar de ninguna forma,
pero hemos evitado cargar toda esta información en nuestro JavaScript
porque no sabemos si el usuario lo va a necesitar.
Esto es súper importante para vuestra vida.
Es una cosa muy sencilla, pero es una cosa que muchas veces puede marcar la diferencia
de cómo tratáis el rendimiento y la experiencia del usuario, ¿vale?
Porque muchas veces lo que pasa es que intentamos cargar, queremos cargar todo de golpe,
en un JSON o nada más cargar la página, quiero cargar toda la galería y tal.
Pero si lo tenemos detrás de un botón, lo que tenemos que pensar muchas veces es
¿realmente tengo que cargar todas las imágenes si no las está viendo el usuario?
Si hay un botón que me está como separando esa información del usuario
hasta que no le dé al botón, lo que voy a hacer es no cargar esas imágenes
porque no necesitas eso.
Entonces lo que hacemos es, pum, cuando necesitamos realmente esas imágenes,
las cargamos cuando le da al usuario.
Esto lo podéis mirar con una modal, lo podéis hacer también cuando está haciendo scroll,
por ejemplo, podríamos hacer un infinite scroll.
En este caso no queremos hacer un infinite scroll, primero, porque no a todo el mundo
le interesan las imágenes y lo que quiere a lo mejor es ver los números
o lo que hay debajo o lo que sea, pero por ejemplo puede tener sentido
un infinite scroll según el caso.
Pero lo importante es, solo cuando lo necesita, se lo cargamos,
en lugar de estar metiéndole todo el JavaScript de primeras
que no sabemos si lo necesita.
Y por eso hicimos esto.
Pero si no lo has entendido, no te preocupes porque vamos a hacer lo mismo
un poco con los candidatos ahora y lo vas a entender.
Mira, para crear un endpoint que haga esto, que nos devuelva el JSON que necesitamos,
aquí en API vamos a crear uno que se llama candidates.json.ts.
¿Por qué el .json?
El .json básicamente es para indicarle a Astro cuál es el tipo de dato que tiene que devolver.
Hay diferentes formas que eso puedes indicar y lo tenéis por aquí explicado.
Son static file endpoints, porque al final lo que trata es como si fuese un archivo.
En realidad nosotros lo vamos a tratar como una API, pero lo vamos a poder cachear,
lo va a tratar como un archivo, como si fuese un archivo y ya está.
Y esto lo que nos hace es simplificar la creación del endpoint.
Total, como tenemos que devolver JSON y siempre vamos a devolver los mismos candidatos
que no es muy dinámico, ya nos va bien.
No van a cambiar los dinámicos mientras estamos trabajando.
¿Sabes? Siempre van a ser los mismos.
Así que vamos a importar la información que tenemos.
A ver dónde tenemos la información.
En data, ves que tenemos editions vote.
Pues esto lo importamos de data barra editions vote.json.
Y aquí lo que vamos a hacer es traernos editions vote.
O votes info, le voy a llamar, ¿vale?
Votes info.
Ahora que tenemos esto, esto ya nos lo ha tipado o no, ¿sí?
Sí, vale, ya lo teníamos tipado.
Tenemos que exportar una constante que es el método get.
Y esto va a ser una API root de astro.
Hacemos esto porque así tenemos los tipos y así ya va a detectar perfectamente
cuáles son los parámetros con los que tenemos que trabajar,
que es params y request.
Creo que params no lo necesitamos, o sea que lo vamos a quitar, ¿vale?
Y lo tenemos aquí.
Y aquí lo que tenemos que devolver seguro es una respuesta y podríamos hacer json stringify
directamente con el votes info.
Esto sería el endpoint mínimo, ¿vale?
Estamos importando el json y lo estamos exportando.
Alguien ahora se preguntará, bueno, ¿y por qué no devuelves directamente el archivo json y ya está?
Bueno, porque lo que vamos a hacer, esto obviamente ya os digo que es un archivo json pequeñito
y que podría tener sentido enviarlo directamente y ya está.
¿Pero qué vamos a hacer?
Para que veáis cómo funcionan los endpoints y cómo se puede hacer un pequeño filtro
que puede ser bastante útil para un archivo json que sea muy grande y que os interese,
pues decir, bueno, devuélveme solo una parte, ¿no?
Que esté filtrado por la categoría, por ejemplo.
Pues lo que podemos hacer es pasarle, como hemos hecho aquí, un query param
diciéndole devuélveme solo los candidatos de la categoría 0, de la 1, de la 2,
en lugar de recuperarlos todos.
Vamos a recuperar la URL de la request y de esta URL vamos a recuperar los search params.
Con new URL le pasamos la URL y tendríamos aquí los search params.
Los search params, si no saben lo que es, es básicamente esta parte que hay justo después del interrogante.
Y lo que nos permite ahora es que le decimos, de los search params, quiero que me recuperes el category.
Hacemos search, bueno, category no, search params, ahí está, search params.getcategory.
Y ya hemos recuperado con esto el valor que le estamos pasando justamente aquí.
Como lo que siempre se le pasa en una URL, porque es incapaz de detectar si es un número,
si es una cadena de texto, si es un boleano, siempre lo que le pasamos por query params,
siempre, por desgracia, se va a crear que es una cadena de texto.
Por lo tanto, lo que tenemos que hacer con esto es transformarlo a un número.
Y para evitar, por si lo que sea, no nos informan del número,
imagínate que nos pasan esto sin esto y no queremos que pete.
Por lo tanto, lo que vamos a hacer aquí es hacer un nullish collection operator,
o sea, que si esto es nulo, si no está informado, vamos a decir que el valor por defecto sea 1.
De hecho, lo podemos poner aquí, default category param, ¿vale?
Ponemos el 1 y ya está.
Y lo ponemos aquí y ahora ya no tenemos un magic string.
Lo ponemos así y ya está.
Entonces, ya sea que nos viene por la URL o el valor que tenemos por defecto,
lo transformamos en número y ya tenemos aquí la categoría.
Recuperamos la categoría info, nos vamos al votes info y vemos cómo tenemos que recuperar.
Si miramos el JSON, vemos que es un array y que cada objeto del array es una de las categorías, ¿vale?
Por lo tanto, es por posición.
La categoría 0 es el clip del año.
La categoría 1 es el enfado del año, ¿vale?
Pues entonces, lo que tenemos que hacer aquí es pasar al category y ya tendríamos el category info,
que es lo que vamos a querer devolver de esta API, de este endpoint.
Y con esto, ahora tendríamos que ver si esto funciona, así que vamos a poner aquí un console.logdata, ¿vale?
Para ver si esto realmente funciona.
Vamos a poner aquí rápidamente al menos, a ver, page info, candidates, vale.
Vamos a recuperar el candidates y el... y ya está, ¿no?
O sea, no hay...
Ah, y la categoría, claro, el nombre de la categoría.
Categoría, candidates y esto lo recuperamos del page info.
Y esto, ¿qué puede ser esto?
Vamos a hacer la propiedad de categoría, no existe...
No existe en el tipo, claro, page info, como podéis ver, se cree que va a ser vacío.
Entonces, a ver, podríamos crearle un momento la interfaz y ahora os leo en el chat a ver si tenéis alguna duda
y os lo comento, ¿eh?
La categoría, que es un string, y el candidates, que es un candidate, interface, candidate...
¿Vale? A ver si lo detecta.
No exactamente.
Es nombre, imagen y enlace.
Nombre, imagen y enlace.
Y esto es un string, pero puede ser vacío.
Esto lo quitamos así.
Y este page info es el que vamos a poner aquí para que sepa que puede ser un page info.
Y ahora no nos debería dar problemas esto.
Vale.
Y, claro, si ponemos esto, sí que se lo va a comer.
La categoría ya la ponemos aquí.
Y los candidates...
Ah, porque la categoría puede ser undefined.
¡Hala!
Ya está.
Y aquí en candidates vamos a poner candidates, mapeamos, cada candidato.
Y aquí es donde vamos a tener que trabajar básicamente en el diseño, ¿vale?
Pero por ahora lo pongo así un poco para que lo tengamos así de cualquier forma.
Vamos a volver aquí a nuestro bota.
¿Vale?
No aparece nada.
Ahora veremos qué problema tenemos.
Alguna cosa habrá pasado, pero no pasa nada.
Ahora lo miramos.
Bueno, sí que tenemos aquí, ¿veis?
Que tenemos categoría, candidatos.
O sea, tenemos la información, pero aquí no está mostrando la información.
No pasa nada.
Ahora lo miramos.
Todo es arreglable.
Es en español.
Ah, lo he puesto mal.
Es que he puesto candidates.
Y tenéis razón.
Es candid...
Claro, yo lo he tipado, pero es candidatos.
Hostia, es verdad.
Candidatos.
Que la madre que los parió.
Candidatos.
Candidatos y...
Bueno, esto lo voy a dejar así, ¿eh?
¿Vale?
Vale.
Ahora lo que está mal en la imagen, no pasa nada.
Esto, la imagen, tú, tú, tú.
La imagen, esto lo ponemos aquí.
Y la imagen, la imagen la sacamos de public, voting assets, voting assets, ¿vale?
Entonces, barra, voting assets, barra, y ya está.
Ahí lo tendríamos.
¿Vale?
Esto ya empieza a pintar un poquito mejor, ¿eh?
Esto ya empieza a tener un poquito de buena idea.
Voy a poner unos estilos así rápidos, que me imagino que nos funcionarán, para que se vean mejor.
Grid, calls, 5, un poquito de separación.
Y no sé si ponerle separación por aquí.
Vamos a ponerle separación, pero se la vamos a quitar después, ¿vale?
Para que tenga un poquito...
Y ya con esto, ya esto ya pinta un poquito mejor, ¿eh?
Ya pinta un poquito mejor.
En el category title...
Category title...
Es que, claro.
Tendría que poner el SVG.
Los SVGs y tal, para que quede más o menos.
A ver.
Voy a hacer algo más o menos.
Font, extra light...
¿No hay otro más light todavía que el extra light?
No.
Bueno, pues ponemos el extra light.
Vamos a mezclar...
Vamos a poner esto un poquito por aquí.
Que tenga un poquito de separación.
Vamos a hacer que sea un poquito...
Que tenga un poco de separación las letras.
Le ponemos la letra esta de Tomaso, que teníamos por aquí.
¿Vale?
La hacemos bastante más grande.
Le ponemos un máximo.
Flex, Justify, Center, Item, Center.
Y yo creo que ya está.
Con esto...
Porque blanco ya se ve, ¿no?
¿Vale?
No sé si ponerle un alto...
A lo mejor no tan bestia.
Pero más que nada, para que tengamos la separación que se supone que tiene más o menos algo así.
¿Vale?
Bueno, entonces, al menos ya teníamos esto.
Ahora ya podríamos empezar a navegar entre...
Para ir cargando las categorías conforme la vamos necesitando, ¿eh?
También lo que podríamos hacer es...
Bueno, podemos estilar...
Ahora vamos comentando, ¿eh?
Yo creo que deberíamos hacer la navegación para ir pasando entre páginas.
Y luego podríamos hacer la votación.
¿Vale?
Para tenerlo entre uno y otro.
Pero al menos ya tendríamos esto.
Claro, porque lo interesante es ahora ver la categoría, la navegación de siguiente y anterior.
Para ver cómo van cambiando.
Para asegurarnos que cambian.
Porque si no, la vamos a liar parda.
Y una vez que tengamos eso, entonces añadir la votación.
Fijaos que los SESLAN, la página de los SESLAN, que está bien, pero hasta que no lo votáis todo, hasta que no lo votáis todo, no podéis enviarlo a la base de datos.
Está bien porque eso te obliga a diferentes cosas, pero bueno, eso lo vamos a mantener.
¿Vale?
Vamos a hacer la navegación, que es un momento, me parece un quick win la navegación.
Y además, lo bueno de añadir la navegación es que al final así veremos cómo van cambiando las categorías.
¿Vale?
Así que vamos a quitar todo esto y vamos al vote system.
¿Vale?
Y aquí vamos a necesitar otro estado que sea category.
Category, set category.
Esto es un momento.
O sea, es que esto va a ser un momento.
Va a ser más complicado.
El hacer el frontend que no esto.
Ya verás.
Vale.
Entonces, esto está muy interesante.
Y si sabes React, no te costará.
Pero si no sabes React, te sorprenderá.
Bueno.
A ver.
Handle navigation.
Vamos a añadir handle navigation, donde vamos a poner aquí el new category, por ejemplo.
O el category index.
Category index.
Esto va a ser un número y tenemos que tener en cuenta aquí.
Vamos a poner, como han hecho aquí, hacia adelante y hacia atrás.
Pero, ¿qué pasa?
Ah, aquí lo ocultan.
Bueno.
A ver.
No es mala idea.
¿Qué opináis?
¿Lo ocultamos?
¿Preferís que lo ocultemos?
¿O preferís que si le das para atrás, vayas al primero?
Claro.
Yo la verdad es que aquí tengo el corazón un poco dividido.
Porque si lo ocultas, una cosa que es una ratada, es que imagínate que estás en el número 12.
Claro, estás en el número 12 y quieres volver al 1.
Tienes que dar toda la vuelta.
Y con todo esto, ¿sabes?
Con todo esto que encima tarda un montón.
Tengo el corazón dividido de si dar la vuelta, ¿sabes?
De que si del 1 vaya al 12.
Entonces, voy a hacer una cosa.
Voy a hacer primero eso.
Voy a hacer una lógica aquí, que básicamente, si el category index es menor, o sea, si voy a ir al menos 1, pues le doy la vuelta, que sería el 11.
Y luego ya veremos.
Espero que esto me va a ayudar a debuggar antes.
Y luego, si queréis, pues hago que esté disabled o lo que sea, ¿vale?
Que he leído ahí que queríais que fuese disabled.
Set category, category index, ¿vale?
Este handle navigation lo vamos a tener que utilizar aquí.
Tengo por aquí, tengo por acá, aquí.
Tengo un SVG.
Este es SVG.
Tengo un SVG, no es el más bonito del mundo, ¿vale?
Pero vamos a poner dos botones, uno aquí y otro aquí.
Esto habría que arreglarlo mejor, ¿vale?
De hecho, lo voy a poner aquí para que...
Function, arrow, arrow, rotated.
Es un SVG que básicamente es una flecha, ¿vale?
Entonces, mira, en lugar de hacer esto aquí dos veces, lo que vamos a hacer es poner esto, arrow.
Vale, no se puede asignar.
Vale, porque hemos puesto aquí rotated, rotated.
Esto vamos a decir que sea booleano.
Pero vamos a poner que si no está, pues nada.
Y vamos a ponerle aquí const class name.
Si está rotado, lo rotamos 180 y si no lo dejamos vacío.
Y utilizaríamos este class name.
Lo que estamos haciendo aquí es que...
Ahora os enseñaré el SVG, ¿eh?
Lo vais a ver ahora.
Pero básicamente es una flecha.
Y entonces, lo que vamos a hacer es reutilizar dos veces la misma flecha.
Solo que en una estará rotada, que será esta, rotated, para que se vea para la izquierda.
Y otra para que se vea para la derecha.
Y así esto...
Navegación.
No sé qué es lo que tenía la navegación en medio.
Me imagino que el número de categorías...
Ahora lo arreglaremos.
Pero por ahora, ¿vale?
Ya teníamos esto.
¿Ves?
Son dos flechas.
No tiene mucho misterio.
Ahora arreglamos.
A ver.
Podríamos poner class...
Y onclick.
Y cuando hagamos un click, hacemos el Handle Navigation.
Y esto va a ser category...
Category menos uno.
Y en el otro, pues sería category más uno.
Y ya está.
Y la lógica de dar la vuelta, en realidad, está dentro del Handle Navigation.
Y así no nos tenemos que preocupar.
Como veis, ahora parece que no hace nada.
Pero ahora veremos si hace nada o no.
Aquí en navegación, si miramos aquí...
Vale, pone categoría seis de doce.
Vale, pues ponemos categoría...
Vale, categoría más uno.
Tiene sentido.
Y vamos a ver...
Bueno, ha puesto doce.
Vamos a ver aquí...
MaxCategories.
Vamos a poner doce.
Aunque esto podría ser interesante que desde el principio lo pusiese la base de datos.
O sea, la API y todo esto.
Pero bueno, por ahora lo dejamos así.
Y al menos para tenerlo en un sitio...
Vamos a poner MaxCategory menos uno.
Menos uno.
Para que si lo cambiamos en un sitio, se cambien todos.
Y luego ya lo tengamos arreglado.
Y aquí lo mismo.
¿Vale?
Aquí sería MaxCategories.
La categoría...
Ponemos aquí el Span.
Pa, pa, pa, pa, pa.
Y hacemos que sea un poquito más grande.
TextXL.
Y esto en realidad también tendría que ser un Span.
Porque yo creo que también está un poquito más grande.
Igual esto es LG Font SemiVolt.
Algo así.
Y vamos a ver...
Vale, vale.
¿Veis?
Ahora funcionar.
Funciona esto.
Pero no va cambiando ninguna información de aquí.
¿No?
Y para adelante y para atrás...
Vale.
Por ahora funciona como queremos.
Lo que queremos aquí es que cada vez que cambia la categoría, queremos volver a ejecutar el UseEffect.
Entonces, lo que podemos hacer con este UseEffect es...
Oye, cada vez que cambie la categoría...
Me vuelves a recuperar los candidatos, me recuperas la información de la categoría y la mostramos.
Y ya está.
Entonces, ahora, si le doy a siguiente...
Ya tenemos aquí las 12 categorías.
En un plis.
Ya tenemos las 12 categorías.
¿Puede mostrar el UseEffect de vuelta?
Sí.
A ver, es que tiene mucha...
No sé si te refieres a por qué utilizo PRIAC para crear el componente, pero es porque, como puedes ver, sí que tiene bastante reactividad, tiene estados y te facilita mucho la vida.
Meterlo en HTML sería un poco más rollo.
Teníamos que estar parcheando el HTML.
Es más complicado de trabajarlo.
Este sería el UseEffect.
Lo que hemos hecho es el FetchCandidates.
Aquí haríamos el fetching de datos.
¿Y qué pasa?
Que tenemos un efecto con una dependencia.
Lo que le estamos diciendo es, cada vez que cambie la categoría, ejecuta el efecto este y me recuperan los nuevos candidatos.
Por eso, cada vez que yo cambio la categoría y cambio aquí la categoría, también vemos que cambia los candidatos que aparecen.
Y ya lo tendríamos ahí.
¿Vale?
Esa sería un poco la idea de la animación esa.
¿Por qué definir la función dentro del UseEffect?
Buena pregunta.
Lo hago dentro del UseEffect, primero porque tiene más sentido, porque solo la utilizo dentro del UseEffect.
Y lo segundo es porque si la pongo fuera, por ejemplo, aquí, ¿vale?
Y que se podría hacer sin ningún problema.
En realidad aquí estarías creando esta función cada vez que se renderiza el componente.
Tendrías que utilizar el UseCallback, de forma innecesaria, para volver a crearla.
La verdad es que tiene más sentido las funciones y variables, tiene más sentido ponerlas más cerca de donde las vas a utilizar.
No tiene más sentido que eso.
Siempre que podáis, ponéis la función y la variable lo más cerca de su uso.
Esto estaría volviendo a fechar las categorías del backend cada vez que cambia la categoría.
Efectivamente, cada vez que cambia la categoría.
Pero también es verdad que, al final, esto, tened en cuenta...
A ver, lo podemos mirar.
Si, por ejemplo, clip del año.
Vale, perfecto.
Clip del año.
Y aquí nos vamos al siguiente.
O sea, claro, esto está tan blanco que no se ve.
Vamos a darle aquí.
Categoría.
Vale.
Nickwork.
Y tal.
Si miramos aquí, quitamos esto.
Ponemos el Fetch URL.
¿Vale?
¿Vale?
Y volvemos.
Al final, esto, porque también además tengo la cachea.
Espérate.
Vale.
Ta-ta-ta.
JSON.
Ah, pues no.
Sí que lo...
Pero lo podríamos guardar, ¿eh?
O sea, veis que lo está fechando cada vez.
Aunque lo tenga cacheado.
Pero bueno, lo podríamos arreglar, ¿eh?
No habría ningún problema.
Que en un punto de quiebre se cambie de color negro.
Bueno, podríamos hacer primero...
A ver, aquí no hay problema porque se centraría aquí.
No habría ningún problema.
Y luego lo que podemos hacer es ponerle más un fondo o algo así, ¿eh?
Si se va la conexión, habría que cachearlo, ¿no?
Sí, o sea, lo podemos cachear de una, ¿eh?
No hace falta que esperemos.
Lo podemos cachear y ya está.
A ver, para arreglar un poco lo de la navegación y...
Vamos a hacer esto.
Lo vamos a poner en un deep.
Deep, deep, deep, deep, deep.
Class.
Ponemos flex.
Justify Center.
Item Center.
Gap X.
No sé si poner dos o algo así.
VG Black.
No sé, a 50.
Backdrop.
Blur.
LG.
¿Vale?
Esto también.
Flex.
Justify Center.
Item Center.
Le damos un poquito de separación.
¿Vale?
Y aquí también vamos a ponerle algo así.
Rounded.
P2.
Bueno, algo así.
Incluso le podemos separar más.
Y los botones para que se noten más.
Porque, por ejemplo, esto se podría notar bastante más.
Para que no de...
Ah, bueno, no da salto, ¿no?
Los números pensaba que iba a dar salto, pero no.
Lo que también se puede hacer es que los botones estos, pues ponerlos dentro de...
Rounded, Border, Border, White, Hover, Border, Transparent, Hover, VG White, y Text, Sky, 950.
Bueno, algo así.
¿Vale?
¿Cómo quedaría esto?
Bueno, vale.
Esto debería ser hacer Hover, Hover, y tendríamos que poner esto 6 y H6.
P4.
Aquí centrado, P2, más pequeño.
¿Vale?
Con la Transition, algo así, ¿vale?
Y esto nos lo copiamos en el botón.
¿Vale?
Ya mejoraremos más los estilos, ¿eh?
Es solo que quiero más o menos que sea visible en condiciones para que no tengamos ningún problema.
¿Vale?
Y ya tengamos aquí esto.
¿Vale?
Pues al menos vamos a meter esto.
Add Navigation.
¿Vale?
Y lo que nos quedaría son las votaciones.
Las votaciones, Votes, Set Votes, podría ser un estado que fuese un array de las máximas categorías y tengamos un array.
O sea, un array de arrays, donde la primera posición sea la categoría 1, la 2, y en cada array, en cada posición, guardaremos los votos del usuario.
¿Vale?
Entonces, ¿qué haremos aquí?
Claro, aquí hay que hacer diferentes cosas.
En el Handle Vote, aquí lo que tendríamos que hacer en el Handle Vote es mirar diferente información, porque, por ejemplo, el usuario no debería poder votar más de cuatro veces y este tipo de cosas.
Entonces, vamos a tener la categoría y el candidato.
No sé si llamarle candidate o candidato.
Ya vivo con miedo.
Pero en cada sitio, primero vamos a chequear, check if the user has already...
Si ya ha votado para esta categoría cuatro veces, para evitar que vote más veces.
¿Vale?
Entonces, estos votos de la categoría, si son mayor a cuatro, esto tiene sentido.
Mirad, de hecho, voy a hacer Votes Category.
Votes Category.
Lo vamos a recuperar aquí y así no estaremos todo el rato mirando esto.
Votes Category.
¿Vale?
Luego, teníamos que mirar si se ha votado ya el item.
¿Vale?
Y si ya ha votado, entonces, sí.
Votes Category incluye el candidato.
¿Vale?
Si en los votos de la categoría ya tenemos a este candidato, o sea, que ya lo ha votado.
¿Por qué dice que no se le puede asignar Votes Category?
Ah, porque en el estado, la madre grupo, Vario.
Vale, no pasa nada.
El tema es que en el estado, como estamos haciendo que esto sea un array vacío, no sabe que van a ser números.
¿Vale?
Entonces, tenemos que crear TypeScript.
Voto sea un array de array de number y ya está.
¿Vale?
Entonces, le decimos que esto es de tipo Votes.
Y ahora sí que debería...
¿Ves?
Ahora sí que funciona.
Sí, ahora sí que funciona.
Entonces, si a esta persona ya ha votado a este candidato, claro, si ya lo ha votado, lo tendríamos que quitar.
¿Vale?
Para quitarlo, lo que podemos hacer es crear nuevos votos con los Votes Categories, filtrando a todos aquellos que no sean el mismo candidato.
O sea, le quitamos el voto.
Es como cuando tú lo clicas una vez, lo votas.
Pero si lo clicas otra vez, lo desvotas.
Entonces, de los votos de las categorías, vamos a filtrar ese voto.
¿Vale?
Y entonces actualizamos los votos con los votos anteriores y ahora...
Buah, es que esto va a volar la cabeza.
A ver, podríamos hacer un Slice, podríamos hacer cosas muy chungas, ¿vale?
Pero es que esto sería muy bonito, hacer esto.
Quiero los votos anteriores, pero en la categoría quiero los nuevos votos.
¡Buah!
¡Dios, cómo mola!
Me gusta que ya no escribe este vivo, este vivo, este vivo.
Básicamente es...
¡Guau, guau, guau!
Esto está muy chulo, ¿eh?
Para eso está este método GIF, WID.
Es nuevo este método GIF, pero básicamente lo que nos va a hacer es devolvernos una copia del array.
Lo que va a pasar es, de los votos anteriores, quiero que en la posición donde tenemos esta categoría, me pongan los nuevos votos y me vas a devolver un nuevo array con todos esos votos.
Está muy chulo.
Esto si no, ¿con qué se podría hacer?
Se podría hacer con un punto MAP, pero sería mucho más complejo, o con un SLICE, que es normalmente como lo hacen con los estados de Redux y tal.
Pero es que esto es que es el caso perfecto.
¿Ves?
El punto WID, tú le pasas un índice y luego le pasas el valor de lo que quieres que haya en ese índice.
Y es que en este caso es exactamente lo que queremos.
Queremos que en el índice de esta categoría me guarden los nuevos votos y quiero que me devuelvas un nuevo array.
Porque es lo que necesitamos para los estados.
Siempre tiene que ser un nuevo array.
No puedes mutarlo.
O sea, es tremendo.
Es tremendo.
Si no lo entiendes, revisa el punto WID porque la verdad es que es el caso perfecto.
Si ya ha votado cuatro veces, si ha votado cuatro veces, si...
¿Qué nos falta?
Ah, nos falta, claro, el voto, ¿no?
Otherwise, add the vote.
Claro, si no, pues set votes.
Y mira, aquí otra vez lo podemos utilizar.
El prefVotes y prefVotes.
prefVotes, perdón, Votes.
Los votos anteriores con la categoría que va a tener todos los votos que tenemos aquí en Votes Category más el nuevo voto.
Y ya está, ¿vale?
Estos serían los nuevos votos.
Lo podríamos meter aquí, si no, en New Votes.
¿Vale?
Para que lo tengamos claro.
New Votes.
Y ya hemos hecho el sistema de votación.
Joder, pero si lo hemos hecho en un momento.
A ver, o sea, estoy bastante contento.
Pensaba que nos costaría...
A ver, que no está mal, ¿eh?
Pero pensaba que estaríamos un ratito para esto.
Igualmente, me faltaría...
Por un lado, tendríamos que ver los votos realizados, ¿no?
Entonces, podríamos poner Votes for Category.
¿Cómo le hemos llamado aquí?
Votes Category.
¿Vale?
Aquí deberíamos tener en el footer, igual que tenemos aquí esto de votos realizados aquí.
Esto también lo podemos tener nosotros, ahora que tenemos esta información.
Porque podemos hacer aquí un div y votos realizados serían los Votes Category.length y aquí Max Votes per Category.
¿Vale?
Esto lo vamos a poner una constante.
Lo ponemos aquí arriba.
Solo puede haber cuatro, ¿vale?
Y ya estaría.
O sea, ya tendríamos aquí Votes realizados, la longitud de los votos por la categoría.
Como es una red Arrays en Votos, accedemos a la categoría en la que estamos, recuperamos sus votos y ya lo tendríamos.
Y otra cosa que podemos hacer, muy interesante, es también podemos indicar ya cuáles son los...
¿Vale?
IsVote...
¿Podemos hacer esto para ver si está votado?
Podemos hacer esto, pero luego haríamos otra cosa, ¿eh?
Ya veréis.
Ya veréis por qué esto puede ser interesante de complicarlo un poquito más.
Y luego veréis por qué.
¿Vale?
Vamos a poner P1.
Vamos a poner que si está votado, vamos a poner esto, lo vamos a poner así.
Si está votado, lo voy a poner de color amarillo, ¿vale?
Solo para que lo veamos bien.
Y si no está votado, VG Blue 900, ¿vale?
Para que se vea que está así.
Y le vamos a poner el hover, que va a estar VG Sky 500, yo que sé.
Un poquito para que lo veamos.
Transition.
Y text center, para que se centre todo.
¿Vale?
Vale.
Vale.
No está haciendo...
Vale, no está haciendo porque no le he puesto el botón aquí, claro.
Si no le pongo el botón...
Si no pongo aquí el botón que hacemos el handle...
¿No?
Si no ponemos aquí onclick y aquí le ponemos el handle vote, donde le pasemos por un lado
la categoría, que es la misma categoría, y el candidato, que es el mismo candidato.
¿Vale?
Dice category, no se puede, y candidate, no se puede...
No se puede asignar el tipo number.
El tipo de categoría procede a la cantidad que es que se declara aquí el tipo...
A ver, ¿qué es lo que pasa aquí?
Si aquí pone candidate, que es tipo number...
¡Ah!
Porque no es...
Vale.
Porque esto sería el índice, ¿vale?
El candidate que se le pasa aquí es el índice.
Claro, no se le puede pasar a todo el objeto.
¿En este sentido?
Vale.
No se quita el voto.
Cosa que...
Mal.
Pero...
Ya estamos votando.
Y además, ¿ves?
Aquí tenemos lo de votos realizados.
Ahí tendríamos lo de votos realizados.
Voy a arreglar un momento eso para que se vea bien, ¿vale?
Para que veamos lo de votos realizados.
Vamos a poner todo esto también aquí.
Al menos para que lo veamos.
Luego ya lo arreglaremos.
Luego...
O sea, ya tenemos tiempo de mejorar cosas.
Pero ahora mismo...
Al menos...
Cuatro...
Tres.
Para que quede más o menos igual.
¿Vale?
Entonces, le damos...
Aquí ya están los votos.
Voto, voto, voto.
Le damos al siguiente.
Vamos al anterior.
Tengo los votos.
Se guardan los votos.
No hay ningún problema.
Ahora, el único problema es que cuando le doy no se cambian.
O sea, no está haciendo lo de si ya está votado.
Si ya está votado...
Porque esto no lo está haciendo.
¿Pusiste el return cuando ya tenía cuatro votos?
Ah, claro.
Esto debería ir después, ¿no?
Claro.
Claro.
Exacto.
Muy bien visto, ¿eh?
Bien visto.
Tendríamos que ponerlo aquí.
Tendríamos que ponerlo aquí.
Claro, tiene que ser justamente después, ¿no?
Porque si no, como ya lo hemos votado, justamente...
Claro, claro.
Bien visto.
Bien visto, ¿eh?
Bien visto.
Ay, que casi se me escapa.
Vale, vale.
¿Sabes de dónde explicará esa API backend?
Claro, en Vercel se va a desplegar sin ningún tipo de problema, ¿no?
Vale, vale.
Pues fijaos.
Ya lo tendríamos.
Lo bueno es que también lo que podríamos hacer es que cuando estén los cuatro,
que se pongan...
Que se quiten a lo mejor.
Claro, porque no puedes hacer más.
¿Qué pasa si por X razón la API cambia el orden de los clips?
Los votos ya no corresponden.
Sí, a ver.
Obviamente.
Lo ideal, obviamente.
Lo ideal sería tener la acidez.
En este caso no lo tenemos porque no tenemos las ideas y tal, ¿no?
O sea, podríamos generarle una idea a cada elemento y no depender de los índices.
Nosotros estamos dependiendo de los índices porque básicamente lo estamos haciendo así, sencillo y tal.
Lo ideal es que cada uno tuviese una idea, un identificador único.
De hecho, tampoco pasaría nada, ¿eh?
Podríamos hacerlo en un momento.
Podríamos generar y se lo podríamos decir a HGPT.
Le podríamos decir, oye, quiero que me generes para cada uno de los elementos una idea,
que es lo que tiene todo el sentido del mundo, ¿vale?
Que aquí posponga una idea única, que sea lo que sea.
Que sea lo que sea.
Pero que tenga una idea.
Si lo podemos hacer, simplemente lo he hecho con índice porque no me da la vida.
Pero porque estaríamos aquí todo el día y no tenemos todo el tiempo del mundo.
Y por eso hemos hecho, porque tampoco vamos a cambiar el orden y todo esto.
Pero con una idea es como habría que hacerlo, ¿eh?
Con una idea.
Vamos a poner esto, ¿vale?
Add Simple Votes System.
¿Vale?
Vamos a poner el sistema este de votos.
A ver, nos ha faltado alguna cosita, pero hay que tener en cuenta que esto ya está detrás.
Joder.
Ah, esto está chulo, ¿eh?
Esto está chulo.
Porque le das a votar y mira, te lleva directamente al voto, ¿eh?
Te lleva directamente al voto.
Esto está chulo o no está chulo.
Está chulo.
Está bien porque así no tienes que volver a ponerle, a darle, que no sé qué, no sé cuánto.
Al menos a mí me gusta más.
Entiendo que es el tema ese de que vuelvan a poner.
Si no está registrado no pasa nada.
Lo que podríamos hacer en algún sitio es cerrar la sesión.
Eso sí.
Podríamos hacerlo de cerrar la sesión.
Y faltaría que cuando terminemos todos, que lo guarde en la base de datos.
Pero ya estaría.
Y bueno, aquí lo tendríamos.
Podríamos ir actualizando todos.
¿Vale?
Pam, pam, pam, pam.
Vamos poniendo.
Y al final, cuando ya los tienes todos, al final debería aparecer una página como quieres enviar tú finalmente.
Que es como funcionan los Slam.
¿Vale?
Bueno, os pusheo esto, amigos.
Os lo dejo por ahí.
Slam web.
Hemos avanzado.
En la siguiente vamos a hacer básicamente...
A ver.
Es que ahí me ponéis tres.
Este es de hace tres minutos.
Podemos remover, dejar.
En caso de que FIM no encuentre la dirección correcta.
Añadir las props del componente.
A ver, si este está en verde.
Vale, pues vamos a mergear este.
Lo siento si alguien lo ha hecho antes.
Pero es que está en verde y ya me parece que está bien.
Y así podemos ver que esto funcione.
Y ya está.
Bueno, a ver.
Tarda menos de un minuto en desplegarse.
O sea, es bastante rapidito.
No tarda casi nada.
Ahora tarda cinco minutos.
Solo para callarme la boca.
Ya verás.
Tarda súper poco.
La verdad es que PNPM va muy rápido.
Muy rápido.
Mira, 30 segundos.
30 segundos.
Y ya está en la bill.
O sea, ya...
Entre que creo que han mejorado NextGS.
Ah, NextGS.
Astro.
NextGS.
Yo también.
Entre que creo que han mejorado Astro en la última versión.
Y tal.
Mira, ya ha terminado.
27 segundos.
O sea, es que me parece increíble.
27 segundos en desplegarse.
Vale.
Pues tendríamos el bota.
¡Ay!
Las variables de entorno.
Tengo que arreglar las variables de entorno.
¡Ay!
La madre me parió.
Las variables de entorno.
Digo, ¿y esa página en blanco?
Las variables de entorno.
Tengo que añadir las variables de entorno.
Bueno, no pasa nada.
Bueno, amigos.
Pues nada.
Lo dejamos aquí.
Ya tenemos el código.
Voy a añadir las variables de entorno.
Os quiero un montón.
Nos vemos la semana que viene.
Porque mañana no sé si podré hacer stream para terminar esto de aquí.
Pero nada.
Muchas gracias por acompañarme.
Os quiero un montón.
Sé que os gusta mucha polémica.
Pero no seáis polémicos, hombre.
No seáis polémicos.
Simplemente disfrutad de la vida.
Sed buenos.
Cuidado mucho.
Descansad.
Y un besito muy grande.
Cuídense, amigos.
Nos vemos pronto.
Hasta luego.