This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Muy buenas tardes, ¿qué tal? Bienvenido, bienvenida
Espero que estés súper bien
Y hoy, para mover las manitas, si veis que tengo la voz un poco pillada, es que estoy un poco malito
Estoy un poco malito, espero que con vuestro apoyo y vuestra comprensión y ternura
Seguro que sale súper bien
Pero vais a ver que tengo la voz un poco regulinches
De hecho, me voy a acercar el agua porque estoy un poco resfriado
Estoy un poquito resfriado, me duele un poco la garganta
Pero no pasa nada porque yo soy autónomo
Y autónomo freelance
Y los autónomos no se ponen malos
Entonces mis anticuerpos de autónomo
Ahora pues me empiezan a hacer que me recupere y a seguir trabajando
Eso, ahora podré hablar más como Batman
No, pero en serio, tengo la garganta un poco pillada
Me duele un poquito al tragar y tal
Yo estoy igual, malo de la garganta
Bueno, y este fin de semana tengo que ir a Madrid
Voy a estar en Madrid por dos motivos
Por dos motivos
Uno, voy a estar en el Conec de Keep Coding
Que no sé si os habéis apuntado, creo que ya es demasiado tarde para apuntaros
Pero os lo recuerdo igualmente por si estáis por ahí
El 27 de abril voy a estar con Douglas Crockford
El creador de Jason
Voy a estar y con un montón, un plantel de gente muy muy top
Voy a estar dando una charla
Esto es el sábado
Que todavía, ah mira, todavía podéis conseguir vuestra entrada
Si no me equivoco, aunque pone aquí 500 euros
Si utilizáis el cupón KC-Midudev
Os lo dejan por 50
59, 30, casi, casi
Bueno, por si por lo que sea
Por lo que sea os podéis pasar y os interesa
Pues además estaré haciendo un regalo
Voy a estar regalando hasta fin de existencias
Voy a estar dando un regalo a toda la gente
Que se me acerque por ahí al mediodía
¿Vale?
Y si queréis os lo llevaréis firmaos
El regalo y todo, ¿vale?
Así que solo os digo eso
Si os pasáis y sois de Madrid
Es presencial
Pues os daré un regalito
Un detalle
Un detalle para la gente que está por ahí
Y también voy a hacer la media maratón
La media maratón es el domingo
Y si no estoy muy malo
Pues espero hacerlo
El libro de Git no, ojalá
De hecho, si queréis os explico una cosa
Que me ha pasado con el libro de Git
Porque es un fail en todas reglas
Pero bueno, no pasa nada
Estamos en confianza
Amigos, el tema es que
La idea era sacar el libro de Git
Y lo tengo aquí
Lo tengo aquí en Amazon
Pero no sé qué pasó
Hace un par de semanas
Que Amazon
Pues no revisaba mi libro
¿Sabes?
Lo dejó en revisión
Durante un montón de tiempo
Por cierto, qué rico está
Esta nocilla que he puesto
En la cesta
Está buenísima
Bueno, pues me lo dejó
En revisión un montón de tiempo
Y no ha habido forma
No ha habido forma
De que me lo publiquen antes
Y ahora por fin
Parece que se va a desbloquear
Pero todavía va a tardar
Entonces no me va a dar tiempo
A llevármelo a Madrid
Pero ya os anunciaré
Cuando lo tengáis disponible
En físico
Así que muy pronto
Lo vais a poder comprar
Ya os avisaré
No os preocupéis
Pero no sé
Amazon me troleó muy fuerte
Y no me dio tiempo
A sacarlo antes
¿Entrenaste hoy enfermo?
No, hoy no he entrenado
Hoy he descansado
Hoy he descansado
Buenas, Midu
Por fin llego a estar
En un live tuyo
Gracias
¿Cuánto te paga nocilla?
Nada
Porque ni siquiera es nocilla
Ojalá
Ojalá fuese nocilla
Y en formato Mobi
O EPUB
Eso ya lo tenéis
Desde hace tiempo
Si buscáis
Aprendiendo Git
En Limpap
Mira
Aprendiendo Git
Aquí lo tenéis
Que además lo tenéis
A un precio majísimo
Porque podéis pagar
10 dólares
Si queréis
Aquí lo tenéis
En ebook
PDF
Y Mobi
O sea que aquí
Lo podéis conseguir
Totalmente
Y pues nada
Lo compráis y ya está
Pues venga
Vamos por faena
Porque hay mucha tela
Que cortar
Hoy
Amigos y amigas
Ya sabéis que
En Discord
Tenemos un montón de cosas
Tenemos un canal
Que se llama pruebas técnicas
Y aquí la gente comparte
Pruebas técnicas
Obviamente no
Y hay un montón
De pruebas técnicas
Muy interesantes
De hecho ya os contaré
Que tengo una idea
De una cosa que quiero hacer
Pronto
A ver si tengo tiempo
Pero igualmente
Igualmente
Lo importante es
Esta prueba técnica
Que Leandro nos ha dejado
Hola gente
Necesito con urgencia
Ayuda para pasar
Un challenge test
Para entrar a una compañía
El 19 de abril
El challenge es este
A ver
Una cosa os digo
Con todo mi cariño
Es complicado
Es complicado
Aunque es verdad
Que Leandro
Ya había hecho bastante
Dice
Me queda hacer el deploy
Y los test
Nunca hice dos test
En líneas generales
Es una app
Con TypeScript
Note y React
En donde propósito
No sé qué
Eso lo vamos a mirar
Tengo hasta mañana
A las 4 y media
Hora Argentina
A ver
Es complicado
Es complicado
En real time
Poder ayudar y tal
Pero
No sé si Leandro
Habrá pasado o no
Espero Leandro
De todo corazón
Que te haya ido muy bien
La prueba
Pero está en la prueba
¿Qué vamos a hacer?
Vamos a hacer esta prueba
Así que
Vamos a echarle un vistazo
A la prueba
Leandro
Ya nos contarás
A ver cómo te ha ido
Esta es la prueba
Este es el challenge
Tenéis un notion
Además se ve por aquí
La empresa
Que hostia claro
Digo yo
Si la empresa ahora ve
Que Leandro
Le ha pasado
Bueno tampoco es cosa mía
O sea
¿Qué le vamos a hacer?
¿Qué le vamos a hacer?
Yo creo que sí que es
Nivel junior
Pero puede ser
Yo creo que es una prueba
Que puede ser cualquier nivel
Porque dependerá
De tu nivel
Que la puedes llevar
A un extremo u otro
Ahora lo veréis
Prueba para casa
De desarrollo full stack
O sea es una prueba
De estas
De llevarte a tu casita
Tranquilamente
El propósito de esta prueba
Es evaluar tus habilidades
En desarrollo backend
Y frontend
Ya os digo
Que es una prueba completa
Es una prueba
Que hay que trabajar
Debes construir
Una aplicación web
Que permita a los usuarios
Cargar un archivo CSV
Con datos preformateados
Y mostrar esos datos
Como tarjetas en el sitio web
Pudiendo filtrar los datos
Esto parece fácil
Pero vais a ver ahora
Que poco a poco
Se va complicando
Primero que tienes
48 horas
Para completar la prueba
Hostia
Una cuenta atrás
Yo voy a intentar
Hoy hacer en dos horas
Lo que pueda
Y la continuaremos
La semana que viene
El miércoles
Si veo que os gusta
El contenido
Y sois un montón
Pues la semana que viene
Continuamos
Y con mejores prácticas
Test
Y todo esto
No suban ningún código
Después de entregarlo
En este sistema
Joder
La verdad es que
No sé
Si me he equivocado
Alguna cosa
A mi estas cosas
De tienes 48 horas
Y no puedes agregar
Código después
A mi esto
No me gusta
Pero bueno
No pasa nada
Con todo mi cariño
Es que tampoco creo
Que haya que ser tan estricto
Tampoco hay que ser tan estricto
Si se ha equivocado
En alguna cosa
Si quiere mejorar alguna cosa
Que más da
Tu solución
Debe incluir
Pruebas automatizadas
Tanto para el frontend
Como para el backend
Tener una buena cobertura
Y probar todas las funciones
Es parte de la prueba
Todas las funciones
No una parte y tal
Esto ya os digo yo
Que las pruebas automatizadas
Seguramente
La tendremos que hacer
El segundo día
Debes enviar tu solución
Como un repositorio privado
En github
E invitar a
Projects
Shawan Partners
Como colaborador
De hecho estoy pensando
A ver si buscamos
Si por ejemplo
Buscamos esto
Acá escuchándote
Modo podcast
Festejando los 20 Kbits
Muchas gracias
Saludos
Muchas gracias
A ver
A ver si alguien
Se ha dejado
¿Cómo podríamos buscar?
Podemos buscar el
A ver
Shawanda Partners
Podríamos buscar
Shawanda Partners
A ver si alguien
Se ha quedado por ahí
En el código
A ver
Remote Jobs
Challenge
Shawanda
Shawanda Partners
Uy
Uy
Casi
Casi
Mira
React
Test
Shawanda
Mira
Aquí tenemos a alguien
Que se dejó el código
Aquí tenemos a alguien
Que se dejó el código
Mira
Mira
Mira
Aquí se lo ha dejado
May
Que te han dicho
Que tenía que ser privado
Y lo has dejado
Público
Tío
No sé si es exactamente
El mismo
Me da la sensación
Que sí
Que te dijeron
Que lo tenías que hacer
Privado
Robert
Robert
Hay gente que se la ha colado
Bueno no pasa nada
Estas cosas pasan
Pero si os dicen que sea privado
¿Vale?
Es importante
Porque también este tipo de detalles
Lo tienen bastante en cuenta
Porque fíjate que te lo ponen
En mayúsculas
Por algo
Invitar a Projects
Como colaborador
También puedes intentarlo
Con el nombre de usuario
SP
Test
¿Vale?
No crees dos repositorios
Tema interesante
Porque al no tener que crear
Dos repositorios
Significa que vamos a tener que crear
Un monorepositorio
Multipaquete
Luego vas a ver
Exactamente
Que es esto
Y como lo podemos conseguir
Con PNPM
Que está bastante bien
Espero que lo haya hecho público
Una vez
Que no lo hayan acertado
Puede ser
Puede ser
Pero aún así
Yo no lo haría público
En ningún momento
Asegurate de incluir todo el código
En el mismo repositorio
Crea una carpeta
Frontend y backend
Dentro de tu repositorio
Y codifica directamente
Dentro de ellas
¿Vale?
El frontend y el backend
Deben funcionar
Simplemente ejecutando
NPM install
Seguido de
NPM run dev
Para ejecutar la aplicación
O NPM run test
Para ejecutar todas las pruebas
No agregues
Las instrucciones adicionales
O comandos de Docker
En el Ritmi
Si algo más
Necesitas ser ejecutado
Antes de iniciar la aplicación
Asegúrate de incluirlo
En tu script de desarrollo
O sea que tienes que hacer
PNPM run dev
O NPM run dev
Y que ya te funcione todo
Los archivos JavaScript
Solo están permitidos
En archivos de configuración
De lib
O sea de librería
Todo tu código
Debe estar en TypeScript
Y completamente tipado
Bueno vamos a hacer lo que podamos
A ver que tal
Yo publico todas las pruebas técnicas
Dice Cristian
Es mi código
No hay contratos
Ni NDAs que le impidan
Eso es verdad
O sea es verdad
Pero yo creo que al principio
Al menos
Dejadlo privado
Para no enfadar
Y ya cuando
Si no os contratan
Entonces ya haced lo que penséis
¿Vale?
Pero no lo hagáis
Bueno
Características del frontend
Parte del frontend
Debe ejecutarse en el puerto 4000
Y todo debe estar en la ruta
Slash
Como una aplicación
De una sola página
SPA
Usando React
Un botón para seleccionar
Un archivo CSV
Desde la máquina local
Y otro botón
Para cargar el archivo seleccionado
Una barra de búsqueda
Que permita a los usuarios
Buscar datos
Dentro de este archivo cargado
La barra de búsqueda
Debe actualizar
Las tarjetas mostradas
Para mostrar solo
Los resultados coincidentes
Los datos cargados
Debe mostrar como tarjetas
En la web
Con cada tarjeta
Mostrando todos los datos
De una sola fila
Del archivo CSV
Un diseño responsive
Que funcione bien
Tanto en dispositivos
De escritorio
Como móviles
Manejo de errores
Claro y amigable
Para el usuario
Esa es la parte
Del frontend
Vamos con la parte
Del backend
Porque ya os he dicho
Que es una prueba
Full stack
Debe ejecutarse
En el puerto 3000
El backend
Debe implementarse
Como una API
Resful
Utilizando
Node
Node
Dice
Node
Node
No usen
Ningún framework
Con opiniones
Como
Adonis
O nest
Nest
JS
O sea que no utilicéis
Nest
JS
Ya me imagino
Que hay gente
Que lo hará igualmente
Que lo hará igualmente
Junior trailer
Es esto
A ver
Yo creo que sí
Que lo puede hacer un junior
Es verdad que 48 horas
Me parece un poco exagerado
No sé cuál es el salario
No pone el salario
De la oferta
La verdad
Pero sí que me parece
Una prueba bastante larga
Eso sí que os digo
El backend debe incluir
Los siguientes endpoints
Uno
Un post
Un endpoint que acepta
La carga de un archivo CSV
Desde el frontend
Y almacena los datos
Una base de datos
O una estructura de datos
Debe usar la clave file
En la solicitud del cuerpo
La ruta debe devolver
Estado 200
Y el objeto con la clave message
Con el valor
El archivo se cargó correctamente
O la ruta
Si hay un error
Debe devolver
Estado 500
Y un objeto con la clave message
Con un mensaje de error
En el valor
Y el otro endpoint
Que será un get
Con api barra users
Debe incluir un endpoint
Que permita al frontend
Buscar a través de los datos
O sea que le pasamos
Un parámetro de consulta
Con Q
Para que busque
En cada columna del CSV
En los valores
El filtro debe buscar
Coincidencias parciales
Y también debe ser
Insensible
A mayúsculas
Y minúsculas
Importante estos detallitos
Que luego habrá que tener en cuenta
Esta ruta
Debe devolver
Estado 200
Y un objeto
Con la clave data
Con un array de objetos
Dentro de él
O esta ruta
Debe devolver
El estado 500
Y un objeto
Con la clave message
Con un mensaje de error
En el valor
¿Qué van a evaluar?
Evaluarán tu solución
En función
De los siguientes criterios
Completitud
Completitud
Hostia
Completitud
Suena muy
Completitud
Me gusta
De todas las características
Y funcionalidades
Requeridas
Calidad
Y organización
Del código
Calidad
Y cobertura
De las pruebas automatizadas
Amigabilidad
Y capacidad
De respuesta
Del frontend
Rendimiento
Y eficiencia
Del backend
Y también
Entender los requisitos
También es parte
De la prueba
Por eso os digo
Que si os dicen
Que pongáis el repositorio
En privado
Y lo sacáis públicos
Pues que sepáis
Que igual lo tienen en cuenta
Para cualquier otro problema
Comunícate con
HR
Shawarma
Shawarma.com
Para obtener ayuda
Shawarma
Me imagino
Que debe ser esto
¿No?
O sea
Es la compañía
Que desarrolla
Los shawarmas
A domicilio
Me encanta
Me encanta
Bueno pues
Esta es la prueba
¿Qué queréis que hagamos antes?
Frontend o backend
Frontend o backend
Backend o frontend
Pero entonces es rest
No restful
Es rest
No restful
A ver
Rest y restful
No debería
O sea
¿Cuál es la diferencia
Más o menos?
Restful
Sería
La cualidad
De un programa
Hecho
Con arquitectura rest
¿No?
O sea
Restful
Sería como el adjetivo
Y rest
Sería el sustantivo
Entiendo que esa es la diferencia
Creo yo
Eso
Eso sería la diferencia
A ver
¿Qué me vota la gente?
Hostia
Un montón de gente
Quiere que haga el back
Primero
¿Qué os pasa?
Pero si somos una comunidad
De frontend
¿No?
Cabrones
¿Qué os pasa?
Bueno
¿Queréis que hagamos primero el backend?
Bueno
Me parece
Me parece bien
Si queréis hacemos el backend
A ver
Estoy pensando
¿Cómo haríamos esto?
Me sorprende
Un montón de peña
El backend
Bueno bueno
Me parece bien
Me parece bien
Me parece bien
A ver
Lo vamos a hacer todo
O sea
Que no os preocupéis
Si hacemos una cosa
Luego haremos la otra
Creo que tiene sentido
Empezar por el backend
La verdad es que tendría sentido
No es lo mismo rest
Que restful
Bueno pero es la diferencia
Ya te lo he dicho
A ver
¿Cuál es la diferencia?
¿Qué es api restful?
Api restful es una interfaz
Que dos sistemas de computadora
Utilizan para...
A ver
¿Qué es una api restful?
Un api rest
O api restful
O sea ya empieza
Empieza más la casa
¿Qué es un api rest?
Api restful
O api web restful
O sea es que veo
Que mucha gente
Lo utiliza como sinónimo
También conocidos como
Api de restful
Rest y restful
O sea yo creo que rest
Sería la arquitectura
¿No?
O sea rest es la arquitectura
Y restful sería como
Cuando está aplicada
La arquitectura
Rest sería un conjunto
De principios de arquitectura
Y a ver
Restful
Los servicios cuentan
¿Ves?
Es que lo están utilizando
Lo están utilizando
Como indistintamente
O sea restful sería
Que estás utilizándola
¿No?
Una cosa sería
El sustantivo
Mira cuál es la diferencia
Rest es una arquitectura
Y restful por otro lado
Son programas
Basados en rest
Pues ya está
Muchas veces se usan
En ambos términos
Como sinónimos
Bueno la fuente es Platzi
Pero creo que tiene sentido
¿No?
O sea al final
Ahí lo
Yo creo que muchas veces
Lo entiendo así
Pero bueno
Si me decís que hay otra
Diferencia diferente ahí
Pues me lo comentáis
Vale decís que empecemos
Con el backend
¿Vale?
Con el backend
Pues vamos a empezar
Con el backend
Vamos a intentar
Yo creo que lo mejor
Que podemos hacer
Para no liarla
Es
Vamos a enfocarnos primero
A intentar hacer
Lo que nos piden
Luego ya lo haremos mejor
E iremos
Increchendo
¿Ok?
Entonces
Primero vamos a hacer aquí
La prueba técnica
Shawarma
Vale es que no me acuerdo
Como era la
La empresa
Shawarma
Escrito mal
Prueba técnica
Shawarma
Prueba
Técnica
Shawarma
Vale
Perfecto
Venga
Abrimos aquí
Visual Studio Code
Vamos a cerrar este
Abrimos este
Y aquí en la
Shawarma
Vamos a hacer
Nos dicen
Que tendríamos que tener
Una carpeta
Frontend
Y tendríamos que tener
Una carpeta
Backend
¿Vale?
Así que eso
Vamos a empezar así
Que eso lo hemos entendido
Bastante claro
Voy a crear también aquí
Un challenge
Challenge.md
Y me voy a copiar
Todo esto
Que es el challenge
Para que lo tengamos
Por aquí
Challenge
Para tenerlo bastante
A la vista
Por si lo necesitamos
¿Vale?
Luego
Necesitamos un CSV
Le he pedido a ShawGPT
Que nos cree un CSV
Así que voy a poner aquí
Un demo.csv
Y aquí tendríamos esto
Voy a poner esto así
ID
Minúscula
Por si luego lo utilizamos
Por alguna cosa
Nombre, edad, departamento
Email
¿Vale?
Aquí ya tenemos un CSV
Son inventados todos los datos
O sea, no busquéis
No busquéis cositas
Pero mira
Vamos a cambiar a Ricardo
Y le vamos a poner
Pablo
Pablo Hernández
Que es Feralp
Y vamos a ponerle Feralp
¿Eh?
Un guiño
Un guiño
Un guiño a Feralp
Un guiño a Feralp
Ahí lo tenemos
¿Vale?
Ya tenemos la demo
Ya tenemos las carpetas
Las carpetas por ahora
Las voy a dejar así
Y luego ya veremos
Cómo las podríamos hacer
Lo importante es que
Empecemos en el backend
Y inicializamos con un pnpm init
Esto nos crea un package JSON
Y aquí ya vamos a crear nuestro server
.ts
Importante detalle
Importante detalle
Vamos a tener que crear .ts
Porque decía la prueba
Que todo tenía que estar hecho
Con TypeScript
¿Vale?
O sea
Claro
No lo podemos hacer con JavaScript
Y esto nos va a obligar
A buscar
Un paquetito
Tsnode
Si no me equivoco
Nos va a permitir
Ejecutar
Porque creo que
No sé si dice que el backend
Tiene que ser con Node
No dice nada
Sí, utilizando Node
Vale, pues nada
Porque digo
Igual podríamos utilizar
Van
O podríamos utilizar
Alguna cosa así
Pero ya veo que no
Pues vamos a utilizar este paquete
Que se llama
Tsnode
Que lo que nos permite
Es ejecutar
Node.js
Con TypeScript
Directamente
O sea
Sin tener que preocuparnos
Absolutamente
De nada
De si se puede utilizar o no
Así que
Tsnode
Ok
Y ya vamos
A nuestro
Package.json
Y vamos a poner aquí
Un dev
Que podremos poner aquí
Pues utilizando
Tsnode
Server.ts
A ver
Que ahora mismo
No tengo nada de server
Pero vamos a asegurarnos
Que al menos esto
Funciona
A ver si hacemos dev
Vale
No pasa nada
Como me esperaba
Pero ya
Al menos tenemos ahí
Alguna cosita
Vale
Entonces
Aquí tendríamos que hacer
Las dos primeras rutas
¿No?
La ruta esta del post
Y la del get
Podríamos empezar con la del get
Que es la más sencilla
Y ya está
Pero vamos a empezar
Por lo más difícil
Y luego iremos por lo más fácil
Vamos a utilizar express
Si os parece
Que yo creo que
Que es más conocido
Está bien testeado
Es el
El más típico
Y como tampoco
Parece que
No sé
Por como es el challenge
A mi me suena
A cosas muy establecidas
No me hagas inventos
Entonces
Pues bueno
Prefiero
Que vayamos sobre seguro
Vale
Tenemos aquí express
Vamos a importar course
También
Esto básicamente
Para crear la típica API
Desde el principio
¿No?
Express
Y luego
Luego arreglamos el tema
Del linter
¿Vale?
Y el puerto
El puerto lo vamos a pasar
Por variable de entorno
Pero si no tenemos
Le vamos a poner el 3000
El 3000
Era el que nos ha dicho
Que tiene que estar la API
En el challenge
Nos decía
¿Ves?
Debe ejecutarse en el puerto 3000
El backend
Para asegurarnos
Yo voy a poner aquí
Puerto 3000
¿Vale?
Y también vamos a tener aquí
Un start
¿Vale?
Port 3000
Tsnode
Server.ts
Que no va a haber
Ninguna diferencia
Entre el dev
Y este
Aquí podríamos utilizar
Node.mon
Para que se recargue
Automáticamente
Porque creo que
Tsnode
No tiene un watch
Para vigilar los cambios
Ojo
Watching
Tsnode
Si quieres
Restart
Del Tsnode
Puedes utilizar
Node.mon
OnChange
También hay un Tsnode
Dev
Modificada versión
De
Es incompatible
Con nuestro
Native
SM Loader
¿Y eso qué quiere decir?
Native
Tsm Loader
¿Qué quiere decir ese
Loader?
Debe ser para el tema
Del testing
El tema del testing
Ahí sí que con esto
Nos lo va a complicar un poco
Pero bueno
No pasa nada
Luego ya nos preocuparemos
De eso
Eso para
Cosas del futuro
Cosas del futuro
Pero entiendo que pueden ir
Por ahí los tiros
Los problemas
Del loader
No sé si este
Tsnode
¿Sabes?
Para utilizarlo
No sé si utilizarlo
Uff
Esto está actualizado
De hace años
De hace años
Tío
Esto de hace años
Mejora la
Bueno
Por si no
Utilizaremos
No.mon
Que está mejor preparado
Y ya está
Vale
Por ahora lo dejamos así
Tampoco no pasa nada
Por estar ejecutando
Unas cuantas veces
Cerrar
Y hacer esto
Utilizamos
App.usecores
¿Vale?
Para activar
Cores
Y que no dé problemas
Porque como vamos a tener
El frontend en un puerto
Y el backend en otro puerto
Nos iba a dar problemas
Seguro con esto
Luego ya lo configuraremos
Para que esté mejor
Aquí le podemos pasar
Una función
Para que no
No ponga el asterisco
Y nos lo solucione
Y ya está
Pero por ahora yo creo que
Que con esto ya no
Nos sirve
¿Vale?
Tenemos el puerto
Y aquí
Le decimos
Que el servidor
De la API
Está ejecutándose
En el localhost
Puerto
No sé qué
Todavía no tenemos
Ningún tipo de
Ay
Aquí
Todavía no hemos hecho
Ningún
Ningún endpoint
Ahora lo haremos
Pero primero vamos a asegurarnos
Que esto funciona
¿Vale?
¿Ves?
No funciona
No funciona
Y aquí es donde está
La magia ya de TypeScript
No funciona porque
No nos compila
¿Por qué?
Porque no puede encontrar
Las declaraciones
Del archivo de Cores
O sea que tenemos que
Empezar a instalar aquí
Por ejemplo
El types
Barra
Cores
Como dependencia de desarrollo
Por eso le ponemos
El menos D
Vamos a ver otra vez
¿Ves?
Como hay que ir
Poco a poco
¿Por qué?
Vale
Y ya tenemos aquí
Bueno
Esto ahora no hace nada
¿Vale?
No hace nada
Ya tenemos la API levantada
Pero no tenemos ningún endpoint todavía
Pero al menos ya
Sí que sabemos
Que está utilizando
TypeScript
Que se está ejecutando bien
Y que no hay ningún tipo
De problema
De que nos faltan en cositas
Tenemos que hacer
Dos endpoints
Voy a ponerlos aquí
Uno
El app post
Barra
API
Barra
Login
No
Files
Y esto
Tendría
Recres
Esto por aquí
Y vamos a ver
Lo que
Voy a pensar un poco
Lo que habría que hacer
Un poquito aquí
Este endpoint
Es el de API files
Y es un endpoint
Que acepta la carga
De un archivo CSV
Desde el frontend
Y almacena los datos
Una base de datos
Una estructura de datos
A ver
Lo de la base de datos
Igual lo hacemos
Pero yo por ahora
Pasaría
Porque como dice
Una estructura de datos
Esto de una base de datos
Me parece un poco exagerado
Pero bueno
Lo primero que tendríamos que hacer
Es
Extract file
From request
¿Vale?
Tendríamos la request
Ahí tendríamos el archivo
Luego tendríamos que hacer
Validate
That we have file
O sea que tenemos el archivo
Y que validate
De mimetip
El mimetip
Es el tipo de archivo
Que es
Que solo puede ser
CSV
Luego que tendríamos que hacer
Transformar
El file
O el buffer
¿Vale?
El buffer de datos
Es los bytes
Porque al final
Como vamos a tener
Esto es un churro
De memoria
Que no es una cadena de texto
Y la tenemos que transformar
A un string
¿Vale?
Y este string
Transformar
El string
A CSV
Tu CSV
Y finalmente
Save the JSON
To database
Or memory
¿Vale?
Que es lo que vamos a hacer
Y ya está
Return 200
With the message
And the JSON
Lo importante es que al final
Tenemos que hacer
Devolver
Con un 200
Y decir
Este mensaje
Que ha ido bien
Lo dice por aquí
Dice
Debe devolver
El archivo se cargó correctamente
Esto es lo que tenemos que hacer al final
Y yo creo
Que nos iría bien también
Devolver los datos
¿No?
El data
Con lo que sea
Que no sé que será
Pero algo así
Devolveremos los datos también
Estos serían los pasos
Que tendríamos que hacer
Para una cosa
Y para el otro
Vamos a ver el otro
Tenemos el otro endpoint
El API users
Barra API
Barra users
Async
A ver
Le pongo async
Porque no sé lo que vamos a hacer dentro
Igual después no necesitamos
¿Qué tenemos que hacer?
Debe incluir un endpoint
Que permita al frontend
Buscar a través de los datos
Esta ruta debe aceptar
Un parámetro de consulta
Q
¿Vale?
Pues entonces vamos a tener que
Eh...
No
Extract
The query param
Q
Q
From the request
¿Vale?
Otra vez
Validate
That we have the query param
Luego filter
The data
From
Bueno
With the query param
Y luego finalmente
Return
With the filter data
Y esto debería devolver
Aquí
200
JSON
Con el data
Y el message
Aquí
Ah no
Aquí no hace falta un message
¿No?
Aquí no hace falta un message
Aquí dice
Esta ruta devolver
El 2
Y un objeto
Con la clave data
Con un array
O sea aquí
Que no se necesita un message
O sea que
Aquí esto lo podemos
Dejar
Así
Y ya está
Bueno
Pues ahora vamos a por esto
¿Vale?
¿Están ready?
¿Están ready?
¿Cómo se la rifa el copilot?
El copilot se lo inventa
No entiendo el async
A ver
Pues el async
Ya te puedes imaginar
Que va a hacer el método
Asíncrono
Para poder utilizar dentro de la wait
Pero bueno
Ya veremos si lo necesitamos o no
Luego lo veremos
Try catch
Y metes el 500
Bueno
Vamos a intentar tener
Más que nada
Vamos a tener un control
Má granular del 500
¿Vale?
Para evitar esto
Midu
También vi lo de tu decisión
De no hacer más cursos acá
Y plantearte lo del bootcamp
Que no he dicho Felipe
Yo no he dicho
Lo de que no voy a hacer cursos acá
Digo
Que me los voy a replantear
Y los voy a hacer
Seguramente de otra forma
Y voy a ser más selectivo
Lo que dije
Creo que lo del bootcamp
Deberías ejecutarlo
Es un contenido demasiado valioso
Para subir la escala de conocimiento
Desde mi humilde aporte
Este proyecto
Sea espectacular
Muchas gracias
¿El anuncio decía
Sin frameworks?
Bueno
Decía
A ver
Si que decía sin frameworks
Porque fijaos que dice por aquí
Que express no deja de ser un framework también
Pero habla de
Framework con opinión
Mira, ¿ves?
El backend de implementarse
Como una API RESTful
Utilizando Node
No uses ningún framework
Con opiniones
Como Adonis o Nest
O sea
Entiendo que sí que acepta Express
Que es un framework
Pero que no tiene
No tiene tantas opiniones
¿Sabes?
Así que
Me parece que van por ahí
Un poco los tiros
Vamos por partes
¿Qué podemos hacer aquí?
Aquí
Vamos a utilizar
Para el tema del archivo
Para simplificarlo bastante
Vamos a utilizar
Multer
Que seguro que lo habéis
Utilizado alguna vez
Yo he utilizado unas cuantas veces
Multer
Es un middleware
Que te permite
Muy fácilmente
Pues
¿Ves?
Puedes
Tener un input type file
Que esto es lo que vamos a necesitar nosotros
Y subirlo
Tan fácilmente
Como que le metes aquí
Upload.single
¿Vale?
Y ya lo puedes recuperar
En request.file
Y ya vas a tener aquí
El archivo
Avatar
Sin ningún tipo de problema
Entonces
Vamos a instalar
Multer
Porque es el que vamos a utilizar
Vamos a instalar
Multer
Multer
Y también
Hay un
Convert.csv
To json
NPM
Y vamos a instalar también
Esta dependencia
Para convertir
El csv
A un json
¿Vale?
Este proyecto
No depende de otros paquetes
O librerías
¿Vale?
Genial
Pues este también
Lo vamos a instalar
Que este lo he utilizado alguna vez
Creo que lo utilizamos
Para el COVID vacuna
Es un proyecto que hicimos aquí
En directo hace mucho tiempo
Que básicamente
Tú le pasas un csv
Como este
Y te lo transforma
A una cosita así
Pues este
Es el otro que vamos a necesitar
Vamos a instalar estos dos
Como el csv
Vamos a instalar estas dos dependencias
Espero que no nos den muchos problemas
De tipos y de historias
Vamos a importarlas aquí
Multer
From
Multer
Y vamos a instalar también
El csv
To json
Que no sé si esto tiene un import dinámico
Por aquí
A ver
Import
No
Tiene aquí un require
Esto será
csv to json
From csv
Converse csv to json
¿Vale?
Por ahora veo que no se queja
De temas de TypeScript
Vale
Para configurar Multer
Vais a ver
Multer es como un middleware
Que lo que te permite es
Manejar muy fácilmente
La subida de archivos
Y para que funcione
Tenemos que utilizar ese middleware
Y ahora te explicaré un poco
Como pasa
Pero ves aquí que pone
App.post
Barra profile
Y ves este
Este upload.single
Que hay aquí
Esto es porque solo
Estamos subiendo un archivo
Podéis hacer subir más de un archivo
Y cositas así
Nosotros como solo vamos a querer subir un archivo
Vamos a utilizar el single
Pero podéis utilizar un punto array
Y ahí pasarle tanto a los archivos
Para subir como queráis
Entonces
Veis aquí que crea el upload
Lo que necesitamos con esto
Esto sería en el caso que queráis guardar el archivo
Pero nosotros no queremos guardar el archivo
Nosotros vamos a utilizar
El memory storage
Vamos a guardarlo en memoria
¿Vale?
Esto
Vamos a crear el storage
Multer.memory storage
Y luego vamos a crear como un upload
Que este va a ser el middleware
Que vamos a tener que utilizar
Así que esto
Vamos a ponerlo por aquí
Y entonces lo guardaremos en memoria
Temporalmente
Y este upload
Será el middleware
Que utilizaremos
Ya te explico como funciona esto exactamente
¿Vale?
Vamos punto single
File
Le voy a llamar file
Porque en el challenge
Fijaos
Que en algún sitio
¿Ves?
Debes usar la clave file
En la solicitud del cuerpo
Bueno pues
Vamos a utilizar
La clave file
Porque es justamente la que nos dice
¿Vale?
No es una cosa de la API
Es porque nos lo están diciendo
Entonces nosotros cuando lo subamos
Se lo enviaremos en el campo file
Para que lo tenga exactamente igual
¿Vale?
Y con esto ya tendríamos el tema de multer
¿Cómo funcionará esto?
Entrará la petición aquí
Pasará por acá
Porque esto es un middleware
Un middleware básicamente
Es un punto
En mitad de la petición
Que va a tratar esos datos
Y luego va a hacer que continúe
Hacia la siguiente
Entonces pasarán por aquí
La request
La petición pasará por aquí
Y lo que sea
Modificará información
Y hará que llegue a esta función
Y entonces ya habrá tratado
La subida del archivo
Y ya podremos extraer el archivo
De la request
Que de hecho
Ya como dice aquí
Ya he visto aquí
La documentación
Que tenía el rig.file
Este
Rig.file
Es de avatar file
¿Veis?
Pues nada
Ya entonces
Como teníamos aquí
El primer punto
Pues podemos extraer el file
De la request
La primera no existe
En el tipo request
Vale
Empezamos bien
Empezamos bien
No sé por qué
A ver
Request
No sé por qué
No me dice que el file
La primera no existe
En el tipo
Puede ser que no
Claro
Esto
Lo miraremos después
Pero yo me imagino
Que claro
Como esto lo modifica
No va a encontrar
A ver una cosa
Porque claro
Veo que este upload
Me está poniendo aquí
Enis
Eni
Eni
Puede ser que me falle esto
Un momento
Vamos a ver
Si me dice que instale
Los tipos
Vamos a ver
Empeer
Enrandep
Efectivamente
¿Ves?
Tip
Vale
Ese es el problema
Este
Este tema
Menos mal que están
Todos los tipos instalados
O sea
Ya creados
Pero esto es un poco rollo
Cuando la dependencia
Que utilizas
No tiene los tipos instalados
Que TypeScript
Se vuelve tonto
Y entonces empieza a darte
Ahí unos cuantos problemillas
Vale
Y ahora que se
Se queja porque
No
Overload
Vale
Pues igualmente
Porque me dice
En Overload
Dice
Upload.single
Pero esto está bien
¿No?
Upload.single
A ver
Me he equivocado en algo
A ver
Esto no hace falta
Multer
Memory Storage
A ver
Vamos a sacar de aquí
Ah bueno
No haría falta
Esto está bien
¿No?
Pero me dice
No sé que coincide
Con esta llamada
Empezamos bien
Empezamos bien
A ver
No bueno
Debe ser
Const file
No pero eso
Eso no
No es por eso
Tenía razón
DHH con TypeScript
Puede ser
A ver
No lo podemos saltar por ahora
Pero es raro
Porque esto sí que
No coincide con esta llamada
No se puede asignar un argumento
Al parámetro tipo
Tipo request
Me ha instalado los tipos
Sí que me los ha instalado
Los tipos de express
O sea
Eso sí que lo tengo
Son los tipos de multer
Ya ya
Pero
A ver
Bueno no
O sea
Esto no puede ser
No están instalados los tipos de multer
Si los acabo de instalar
Si los acabo de instalar
No tiene nada que ver
Si los acabo de instalar
¿Ves?
Porque está como en
Y se activa
Eso de la eni
Cha GPT
El patrón de Madrigo es la bomba
Me recuerda a monadas de programación
Los types de node
Es verdad
Los types de node
No los tenemos instalados
Pero no creo que sea ese problema
Y los de express
Yo creo que
Sí que los he instalado
Puede ser
Vamos a ver
Vale
Vamos a ver ahora
La verdad es que eso es un poco rollo
Pues mira
Eran los de express
Eran los de express
Oye
Qué raro
Porque como sí que me salían
Pero eran los de express
Que me faltaban
Bueno
Arreglado
Arreglado
Ya está
No pasa nada
No pasa nada
Pero es verdad que
Tengo que decir algo
Esto de typescript
Está súper genial
Cuando todo lo tienes tipado
Y todo funciona bien
Pero cuando estás empezando
Y te empiezan a dar estos problemitas
Que te
Pero bueno
Ya está
Al menos ya lo tenemos
Entonces
Esto normalmente veréis que
Esto sí que es verdad
Que es raro
Que no
Los tipos de express
No los tienen instalados
Si se me está quejando
Pero no me estaba diciendo
Esto es porque no los tenías instalados
Sino que me está dando un error
Un poco chungo
Pero muchas veces es por esto
Porque te faltan los tipos
Y por eso se vuelve un poco tonto
Ahora espero que sí que
Vale
Ahora sí que se come esto con patatas
Vale
Pues nada
Ahora ya
Validamos
Si no tenemos el file
Vamos a devolver
Status 500
Lo correcto aquí
Serían 400
Pero
Pero fijaos
Que en el challenge
Dice
Esta ruta debe devolver
El estado 500
Y un objeto
Con la clave message
Con un mensaje de error
En el valor
Le vamos a hacer caso
Vale
Pero bueno
File
File is required
Vale
Esto si no tenemos archivo
Luego podríamos decirle
Si el
MyMetip
Es diferente
Text csv
Entonces le decimos
Return res status 500
Y le decimos que el archivo
Tiene que ser csv
Vale
Esto no lo tiene que cerrar aquí
Luego
Este file
Ah mira
Dice
File expressmulte.file
Bueno
Yo entiendo que este file
Debe ser del tipo buffer
Lo que podemos hacer aquí
Try
Catch
Error
Vale
Vamos a intentar
El file
To string
No
Vale
Pues como se transformaba esto
Buffer
From
Buffer
From
To string
Creo que es así
Node.js
Si estoy buscando en google
Convert Node.js
Buffer
To string
A ver
Como conviertes
Buffer
Buffer
Buffer
Text encoding
Text encoding
Vale
Buffer from
Y luego
To string
Vale
Pues fácil
Esto sería
Buffer
From
Y le pasamos el file
Creo que con el file
No sobrecarga
Ninguno
Ah ya por dios
No sobrecarga
Punto
Ah mira
Stream
También podríamos hacerlo con stream
Vale pero veo que está aquí el buffer
O sea que no es del tipo buffer directamente
Porque fijaos
Claro tengo el mime tipe
Que lo he utilizado antes
El file name
Y tenemos diferentes cosas
Pero tenemos en el buffer
Que el buffer básicamente
Es lo que contiene todo el archivo
Lo que pasa es que está
En código binario
Y nosotros lo que queremos es crear
La cadena de texto
Queremos el contenido del archivo
Entonces
Vamos a hacer esto
Y lo convertimos a un to string
Con un to f8
Esto a lo mejor
Te asustas
Y dices
¿Pero qué es esto?
Es que esto es muy típico en Node.js
Porque al final los datos
Para que sea mucho más óptimo
Y eficiente
No viajan como cadenas de texto
Sino que viajan en formato binario
Y para poder transformarlo
Tenemos que hacer justamente esto
O podríamos crear un
Un rate stream
Para ir leyendo los datos
Y transformándolo
Pero esto sería como
Una de las formas más sencillas
Entonces tendríamos aquí el resultado
Y voy a hacer un console log de esto ya
Con el result
Esto debería tener una cadena de texto
Un string
Que sería el contenido
De nuestro fichero
Y ya tendríamos simplemente
Que transformar
Esto lo voy a poner aquí dentro
Vamos a poner esto aquí
Y esto aquí
Para tener bien los pasos
Tendríamos que transformar
Esa cadena de texto
A un CSV
Vamos a ir aquí
Vale
Convert
CSS
NPM
Convertir el CSV a JSON
Y vamos a ver un poco la API
Generar archivo JSON
CSV
Get json
From csv
Get json
Pero esto es pasando
Un archivo
Get json
A ver
String
Ajá
No se puede con un string
Parsec
Custom
UTF
Xencoding
JSON file
Ah mira
CSV string to json
Esto es lo que queremos
Esto es lo que queremos
Entonces
Con este resultado
El CSV
Esto sería el CSV
Vale
Tendríamos el resultado
Y esto
Lo tenemos que importar
Ah no
No se puede importar
Me parece
No
O sea
Hay que utilizarlo así
CSV to json
Y a ver si esta API
Hay que hacerlo así
CSV to json
CSV to json
Generate
Vale
Lo hacemos así
Y aquí ya deberíamos tener el CSV
Con esto ya tendríamos
Por ahora vamos a guardarlo
En memoria
Los datos del usuario
Vale
Lo voy a dejar por aquí
Vamos a hacer que sea
Un array vacío
Por ahora
O sea
Tenemos que guardar esto
En algún sitio
Para que al final
Luego podamos utilizarlo
En la otra API
Se supone que es una base de datos
Lo vamos a dejar ahí
Luego ya
Ya nos preocuparemos
Y una vez que tengamos esto
Lo ponemos aquí
Vale
No se puede asignar
El tipo any
No se puede asignar al never
Esto es porque
Le hemos dicho
Claro
No le hemos puesto aquí un tipo
Vamos a decir que esto es un array
De record
Con string
String
Luego ya nos preocuparemos
No podemos saber
El tipo de datos
Porque al final
Nos han dicho que es un CSV
Pero no nos han dicho los campos
Pueden ser cualquier campo
Así que vamos a hacer
Que sea un array
De objetos
Que tienen
Una key
Y un value
Que siempre son strings
Pero claro
Como nos puede pasar cualquier cosa
Nos vamos a tener que conformar con esto
No sabemos
Que es lo que puede pasar por ahí
Y una vez que ya tenemos esto
Aquí tendríamos el error
Lo que podemos hacer con el error
¿Vale?
Es ya devolver
El status 500
Y le decimos que tenemos aquí un error
Message
Error
Parsing
The file
¿Vale?
Vale
Si hemos llegado hasta aquí
Esto
Aquí podríamos devolver también
Ya el contenido
O lo podemos hacer
Como lo hemos hecho aquí
Lo que pasa es que aquí
Habíamos devuelto un array vacío
Pues aquí
Vamos a devolver el user data
Que es lo que tendríamos ahí
Y ya está
O incluso podríamos hacer aquí
Eh...
Eh...
Eh...
Eh...
Eh...
Eh...
CSV
Podríamos hacer aquí
Claro, esto no es un CSV
Esto sería el JSON ya
Esto no sería el CSV
El CSV sería esto
Vale, es que estoy pensando, eh
Este sería el CSV
Entonces
Esto sería el CSV
Esto sería el CSV
Podemos llamarle
Row
CSV
Porque está sin formatear nada
Aquí tendríamos el JSON
Lo guardamos
Y este JSON
Que lo voy a crear
Voy a llamarle aquí
Vale
Este JSON
Lo creamos aquí
Y así lo podemos devolver
Aquí
JSON
Y ya está
Save to JSON
Ah, bueno, claro
Esto
Esto se supone
Que será esto
Y ya está
Al menos tendríamos ya
Una de las dos APIs
La tendríamos hecha
¿Vale?
Falta la conversión a CSV
Como último
A CSV como último
Pero lo hemos transformado
A JSON, ¿no?
O sea
Falta la conversión a CSV
Como último
Pero aquí
Lo hemos transformado
A JSON
Y ya
Con el JSON
Ya tenemos suficiente
O sea
Lo que queremos es el JSON
En CSV
En realidad
Ya lo tenemos aquí
Aquí nos estaría trayendo
El tema
Es que tu .5 dice eso
Pero puede estar mal
Transform string to CSV
Claro
Es que está aquí
Transform string to CSV
Sería esto
To CSV
Claro
En realidad
To JSON
¿Vale?
Sería tu JSON
Transform string
CSV
To JSON
Tenías razón
Antes no lo he hecho bien
Pensad que
Es un poquito
Sobre la marcha
Que he estado haciendo
Los puntos
Para que tengamos esta guía
Bueno
Ya tenemos el endpoint
Yo creo que era el más difícil
Luego veremos si funciona
Pero yo creo que este
Era el más difícil
¿Vale?
Y luego
El user data
Por ahora lo vamos a utilizar aquí
¿Vale?
Que ahora parece que no estamos utilizando
Pero lo vamos a utilizar aquí
Porque va a ser utilizado
Como si fuese nuestra base de datos
En memoria
Luego ya arreglaremos
Pero no era que el front
Tendría que recibir un CSV
O nada que ver
Bueno
Es que el CSV
Es el que le vamos a pasar
A este endpoint
¿Vale?
Los mensajes van en castellano
Bueno
Bueno
Este lo he puesto aquí
Porque es justamente
El que ponía el challenge
No sé
Tampoco me parece tan importante
¿No?
Tampoco me parece tan importante
Bueno
Vamos con el otro
Que el otro
Yo creo que este es mucho
Mucho
Mucho
Mucho más fácil
Este es al final
De extraer
La información
Filtrar
Es este
Debe incluir un endpoint
Que permita al frontend
Buscar a través de los datos
Debe aceptar un parámetro
De consulta
Q
O sea que primero
Vamos a sacar el Q
Y lo sacamos de
Rec.query
¿Vale?
Tendríamos el Q
Podríamos mirar
Oye
Si no tenemos Q
Pues nada
Res status 500
Así nos aseguramos
Que seguro
Nos pasan
La query param
Por si alguien intenta
No filtrar
O por lo que sea
Vale
Y aquí va a estar
Lo más divertido
Vamos a sacar
El search
Fijaos una cosa aquí
Que nos dice
Debe buscar
En cada columna
Del CSV
El filtro
Debe buscar
Coincidencias parciales
Y también debe ser
Insensible
Mayúsculas
Y minúsculas
Bueno no se si lo veis
Pero lo pone ahí
¿Vale?
Minúsculas
Y minúsculas
Por lo tanto
Lo que sea que nos pasan
Como parámetro
Para la búsqueda
Lo que vamos a hacer aquí
Es decir
Vale
Primero
Vamos a poner
To lowercase
Vale
Dice
La propiedad
To lowercase
No existe en el tipo
String
Pars
QS
Array de string
Ay
Vale
Es que
Claro
Como aquí
Nos pueden estar pasando
Diferentes tipos
Ay
TypeScript
TypeScript
A ver
¿Qué nos podíamos
¿Qué podríamos hacer?
Una de dos
Podríamos hacer
Un montón de validaciones
¿No?
Para validar
En el caso
Que no se esté
Intentando pasar
Por ejemplo
Aquí pone
Que nos pueden pasar
Una cadena de texto
De strings
¿Ves?
Y de
Query strings
Parseados
¿Es verdad
Que lo podrían hacer?
Sería muy raro
Sería muy raro
De hecho
Podríamos hacer
Esto
¿No?
Podríamos decirle
Que esto
O sea
If
K.length
Es mayor
Claro
Es que claro
Si es un string
Podría ser un length
Claro
Array
Punto
Isarray
Vale
Si es un array
Le vamos a dar
También un error
500
Le vamos a decir
Que se vaya a su casa
Le vamos a decir
Tiene que ser un string
¿Vale?
Para que no nos pase más de uno
Y pues tampoco
¿Eh?
Porque dice que
Q
Es posiblemente
Undefined
No se puede invocar
Objeto
Posiblemente
No esté definido
Pero
Si ahora debería estar definido
Ah es que todavía
Es string
O query string
Pars
QS
Es que no sé
Que es esto
No sé que es este
A ver
Si que lo sé
Pero quiero decir
Que no sé
Que nos puede dar
A ver
Pues le decimos
Que nos lo transforme
A string
Y ya está
Pero que será
Este
Query string
Pars
QS
¿Sabes?
O sea
Claro
Como es parseado
¿Qué puede pasar?
Puede ser
Que el parseado
Pueda ser un número
Pueda ser un boleano
Entiendo que van por ahí
Los tiros
Entonces nada
Lo transformaremos
A un to string
Y luego le hacemos
El to lowercase
Y así nos aseguraremos
Al hacer to lowercase
Nos aseguraremos
Que independientemente
Que sea mayúsculas
O minúsculas
Pues lo podamos filtrar
Indistintamente
¿Vale?
Y con esto
Pues al menos
Ya lo tendríamos
¿Vale?
Pues ahora vamos a filtrar
Vamos a crear
El filter data
Aquí utilizamos
El user data
Que hemos utilizado antes
Y vamos a filtrar
¿Vale?
Filtramos aquí
Vamos a poner
Cada row
Espérate
Que esto me ha hecho
Algo raro
Row
Y aquí vamos a filtrar
Las cositas
¿Vale?
A ver
Voy a leeros
A ver cómo estáis
Junior con esteroides
A ver
Tampoco nos pasemos
Amigos
O sea
Un junior
Tiene que saber programar
Tío
O sea
A ver
Vamos a hablar claro
Esto
Un junior
Con tiempo
Lo puede hacer
Con tiempo
Que no lo va a hacer
Solo
No lo va a hacer
Ray
No lo va a hacer
Así y tal
Le va a costar
Y va a tener que estudiar
Y va a tener que dedicarle tiempo
Pero hombre
Yo creo que
Hasta ahora
Más o menos
Una persona
En 48 horas
No
Hombre
No sé
Te puede costar
El tema de
Multer
Que todavía no hemos probado
Que todavía no hemos probado
Que tenemos que ver
A ver si
Si funciona
Pero
Tampoco
Por ahora
Tampoco hemos puesto
Hemos hecho tanta cosa
Tan complicada
Como para decir
Que esto un junior
No lo puede hacer
A ver
Amigos
Un junior
Un junior
Con 10 años de experiencia
Yo no sé
No sé
Amigos
Si es verdad
A mí me parece la prueba
Que es bastante larga
Son muchas cosas
Y sí me parece larga
Pero
A ver
Yo no sé
Qué esperáis
Entonces
De qué queréis trabajar
¿Vale?
O sea
No sé
De qué queréis trabajar
Un junior
No puede ser
No tengo ni puñetera idea
De hacer absolutamente nada
De tiempo
Sí que coincido
Que puede ser
Que le tengas que dedicar
Bastante tiempo
Y me parece muy larga
Pero de dificultad
No sé
O sea
Hay que darle
Hay que darle cañita
O sea
Yo qué sé
Ahora mismo
Esto es
Un poquito más o menos
¿No?
Justifique su salario
Un junior
Viene siendo
Un
¿Cómo?
Un junior viene siendo
Un gran
Recién graduado de ingeniería
Eso sería un trainee
Un junior
Es una persona que tiene
De 0 a 5 años
De
De
De 0 a 3 años
O así
Más o menos
¿Cuánto tiempo de vida
Le das a Typesky?
¿Cuándo dejará de estar de moda?
Amigos
Typesky no va a estar
Dejar
No se va a dejar
De estar de moda
En mucho tiempo
Según tu mido
Es una prueba
Medio de dificultad
Yo creo que es
Una persona
Que realmente haya estado
Estudiando programación
Un año
Esto lo puede hacer
Yo creo
O sea
Un año
Un año
Y a partir de ahí
Cuanta más experiencia tengas
Creo que se puede hacer
Cada vez mejor
Yo creo que
Por ahí lo veo
Ahora
Que después lo hagas
Con las mejores prácticas
Eso sí que ya me parece
Un poco de mid
Y ya para hacer arquitecturas
Y patrones de diseño
Sí que me parecería
Un poco más de senior
Porque eso es un poco
Lo que dice por aquí
Pero más o menos
Como lo estamos haciendo
Por ahora
Yo creo que más o menos
Sí que lo podríais hacer
Porque todavía hemos hecho
Mucha cosa
Vale
Filter data
Vamos a filtrar
Los datos
Del usuario
Hay que filtrar
Cada una de las filas
Entonces
Vamos a recuperar
Los valores
De cada fila
¿Vale?
Los valores de cada fila
En cada fila
Vamos a tener
Por ejemplo
Si tenemos aquí
Este demo
Voy a hacer demo
Y voy a poner
Demo.json
Y vamos a pasar esto
A
A ver si soy capaz
A ver si me lo hace
GijacoPilot
Muy bien
GijacoPilot
Muy bien
Good boy
Good boy
Muy bien
No como al Gonzi
Que le insultas
Muy bien
Trabaja
Trabaja para mí
Muy bien
Ahí está
Me da rabia
Porque es un poco
Es un poco rata
Que dice
Pero no quiero seguir escribiendo
Estoy cansado jefe
¿Sabes?
Es como que dice
No, no
Sigue tú
Sigue tú
Porque hay un momento
Que no me lo sigue generando
Me dice
No, no, no
Sigue tú
Sigue tú
¿Veis?
Que tengo que
Como que escribir
Me lo pone
Pero cuando llega el email
No lo escribe
No sé si es
Fijaos que yo creo
Que esto del email
Es porque está
Está aquí
Limitado
Para no crear emails
Puede ser
Para evitar crear un email falso
Y que te diga
Ah, pues ahora voy a enviar emails aquí
Pues puede ser
Es raro que sea justo en el email
Y que luego no me diga nada
Fíjate que no me genera ningún email
No me dice nada
Raro, ¿eh?
Bueno
El tema es
El tema es
Que esto sería una fila
Esto sería una fila
Tenemos un array
Y por cada fila
Lo podemos llamar fila
Tenemos toda esta información
Vamos a recuperar los valores
Que sea la parte de la derecha
El 1
El Juan Pérez
El 34
Ventas
Pérez
Todo esto
Y con esa información
Claro, ahora estoy viendo que estos son números también
Bueno, no pasa nada
Con esta información en la que vamos a filtrar
¿Vale?
Entonces, para los valores
Lo que vamos a hacer es
Ver si hay alguno de estos valores
Que incluya
El valor
Lo pasamos al lowercase
¿Vale?
Y que incluya
La búsqueda que nos ha pasado el usuario
Y aquí tendríamos
Los datos filtrados
Vamos a hacer que esto
Que esté un poquito más bonito
¿Vale?
Tendríamos esto
Los datos filtrados
¿Vale?
Y con esto ya tendríamos
Creo que el backend
Con esto ya tendríamos el backend
Ahora faltaría
Que hagamos el frontend
Para probar que todo esto funciona
Y ahora lo probamos
En lugar de estar probándolo
Pues vamos avanzando
Con el frontend
Así lo conectamos con el frontend
Y nos aseguramos que funcione la cosa
¿Vale?
¿Hay alguna pregunta?
Antes que
Falta algún return
Igual me he liado
¿Dónde falta el return?
No
Está aquí el filter data
Y aquí tengo el return
¿Vale?
Pruébalo con postman
Da igual
Es que no
Es que vamos a estar perdiendo
Un poco de tiempo
¿No deberías tipear
Todas las variables?
¿Por qué?
No hace falta tipearlo
Todo en TypeScript
De hecho es hasta mala idea
Lo que hay que hacer
Cuando es necesario
¿Vale?
Cuando sea necesario
Ah, me falta este return
Tenéis razón
Menos mal
Muy bien
Muy bien visto
Tenéis toda la razón
Me faltaba este return
Tenéis razón
Gracias, gracias
Lo habéis visto ahí bien
Bien, bien
Gracias, gracias
Pensaba que decías este return
Y entonces no lo estaba
No lo está entendiendo
Gracias
Pues eso
En TypeScript
Lo mejor que podéis hacer
Es intentar utilizar la inferencia
El máximo tiempo posible
Por ejemplo
Si filter data
Ya te lo saca
No intentes tiparlo
Porque es que tipar
Todo el código constantemente
Es un poco rollo
Es un poco rollo
Muy bien
¿Ese correo de Feralp
Es correcto?
Sí
Podéis escribirle ahí directamente
Bueno
Ya tenemos el backend
Ahora lo probamos directamente
Con el frontend
Porque si no
Nos va a dar la vida
Vamos con el frontend
Y así iremos conectando
Bueno, voy a ver
Voy a levantar esto
A ver si se queja de alguna cosa
¿Ok?
Vale
Al menos me lo levanta
Que es importante
Que se levante
Npm create
Vamos con el frontend
¿Vale?
Vamos con el frontend
Sí, lo he guardado
Sí, que he guardado los cambios
Vale
Vamos con el frontend
Y así lo conectamos
Y lo probamos ahí directamente
Y le damos cañita
Vamos a ir a prueba técnica
Y aquí habíamos creado
La carpeta frontend
Aquí lo que vamos a hacer
Es npm
Pnpm
Create
Bit
Latest
¿Vale?
Vamos a crear un proyecto con Bit
Nos han dicho que podemos utilizar React
Y que además
Tiene que ser una SPA
Así que vamos a utilizar
En la carpeta frontend
React
Vamos a utilizar
TypeScript
Más
SWC
SWC
Es el compilador
Que está hecho con RAST
¿Vale?
Frontend
Pnpm install
Para instalar las dependencias
Y ahora hacemos un pnpm run dev
Y vamos a ver
Que nos levanta esto
Pnpm run dev
¿Vale?
Esto nos lo está poniendo
En el 5173
5173
¿Vale?
Eso lo vamos a cambiar
Y aquí en el package.json
Vamos a poner
Que esto nos lo ponga
En el puerto 4000
Porque recordad
Que eso es una cosa
Que nos habían pedido
En el challenge
¿Vale?
4000
Perfecto
Y ya tenemos aquí
Ahora nos ponemos aquí
A manejar cositas
Vámonos para acá
Ah y esto es el backend
Aquí
Source
App.tsx
Vamos a quitar aquí cosas
Vale
Hay un tema
El linter
Vale
El linter ya está configurado
Esto está muy chulo de bit
Que te lo tiene ya configurado
Vamos a hacer una cosa
Vamos a hacer una cosa
Es verdad que no te obliga
Pero te quita estos
Sí
Vamos a hacer una cosa
Porque
En el backend
No le hemos puesto linter
O sea
Que se supone
Que yo aquí hago esto
¿Veis?
Y esto se lo come
Vamos a aprovechar
Que el frontend
Nos ha configurado
El linter
Para hacer una cosita
Interesante
Y ya empezar a aprovechar
Tener la misma configuración
En el mismo sitio
La configuración del linter
La vamos a pasar
A la raíz
¿Vale?
Pum
La movemos a la raíz
Y en el frontend
Esto del package.json
Esto por ahora
Lo voy a quitar
Porque no vamos a utilizar
El comando
Luego veremos
Como lo utilizamos
Bueno lo podríamos utilizar
Pero en la raíz también
O sea
Esto lo podemos mover
En la raíz
Y así ya haremos
Un 2x1
Y desde la raíz
Ah mira
Voy a crear un package.json
Importante
Vamos a la raíz
Un momento
Npm init
Para que cree también
El package.json
De la raíz
Y aquí aprovechamos
Le ponemos esto
Y vamos a mover
Del package.json
Del frontend
Las dependencias
Que tengan que ver
Con el linter
Que son estas
Ah mira
Y esta
El parser este también
Todo esto
No sé si los tipos
Nada
Esos tipos no los necesitamos
Vale
Lo vamos a poner por aquí
Vamos a poner esto
En dev dependencies
Vale
Vamos a utilizar esto
Y el
TypeScript
Yo creo que
TypeScript
A ver
Lo podemos tener
Dos veces
No pasa nada
Pero
Vale
Vamos a hacer
Pnpm install
Y la idea
Si todo ha ido bien
La idea básicamente
Es que ahora
Como hemos movido
La configuración
A raíz
Vamos a ponerle
Que también queremos
Mirar
Note
Que tendríamos que poner
Algunas cositas más
Pero bueno
Al menos a ver
Si nos sirve
Y si vamos a
Note
Ya tenemos el linter
Visto
Ya tenemos el linter
Perfecto
Así que
Ahora ya
Tendríamos aquí
El linter
Lo tenemos también
Para el backend
Con la misma configuración
Que para el frontend
Y lo hemos puesto
En la raíz
Para reutilizarlo
En los dos sitios
Entonces así
Lo instalamos para todo proyecto
Y tal
Habría que configurar
Alguna cosita más
Para ver si es necesario
Configurar mejor
Para React
Y para Note
Y tal
Pero bueno
Al menos que nos funcione
Más o menos
Vemos a ver si esto
Sigue funcionando aquí
Correctamente
Vale
Sigue funcionando correctamente
Pues perfecto
Bueno
Ya tenemos el linter
Arreglado
Muy bien
Vamos con más cositas
¿Por qué no usas
Pnpm
¿Por qué usas
Pnpm y no ban?
Pues Garana
Por lo mismo
Por lo que no utilizo
Npm
Pero utilizo
Pnpm
O por qué no utilizo tal
Y tal
O sea
Es que
Porque sí
¿Vale?
Es que al final
Si no podríamos estar
Siempre infinito
¿Por qué utilizas?
¿Por qué utilizas?
¿Por qué utilizas?
Cuando al final son alternativas
Y ya están
No pasa absolutamente nada
Seguramente lo decoricé
Lo haremos docker
Al final
Así que no os preocupéis
Vale
Vamos a quitar esto
Que son los logos
Estos logos
No los vamos a necesitar
Vamos a quitar esto también
Vamos a poner aquí
Que esto es el challenge
Challenge
Search
No
Upload
CSV
And search
¿Vale?
Vamos a quitar todo esto
Tampoco lo necesitamos
Vamos a poner aquí
Un dip
¿Vale?
Y vamos a ponerle
¿Con qué deberíamos empezar?
Con el input
¿No?
Vamos a ponerle aquí el input
A ver
Es que podríamos poner el input
Type file
Bla, bla, bla
¿Vale?
Voy a quitar este estado
Por ahora
Voy a quitar este estado
Vamos a ver como esto
Vale
Que esto lo he cerrado
Nos vamos al frontend
PNPM run dep
¿Vale?
Puerto 4000
¿Vale?
Seleccionar archivo
Aquí ya teníamos el tema
De seleccionar archivos
Lo podemos dejar así
De hecho creo que lo voy a dejar así
Pero podríamos
O sea
Lo podríamos manejar
Con un label
Para que quede mucho mejor
El problema es que ahora
Si le damos a seleccionar archivo
A ver
Voy a ver que no aparezca nada extraño
Que tiene un poquito de peligro
Vale
El problema es que si lo dejamos así
Fijaos que podemos meter cualquier archivo
¿Vale?
Bueno
Lo primero que tendríamos que asegurarnos
Es que
Los únicos archivos
Que tienen que aceptar
Son los .csv
Y ahora veréis la diferencia
Que cuando le das
Te aparecen desactivados
Súper importante esto
Para mejorar la experiencia de usuario
¿Vale?
Si no lo ponéis
Fijaos que le das
Y puedes subir cualquier archivo
Y la validación ya
La harías demasiado tarde
En el backend
Entonces
Haced esto
Y ya evitáis un poco de trabajo
Que igual en el backend
Tenéis que hacer la validación
Pero hombre
Ya hacéis esto
Y os podéis evitar
Unos cuantos problemitas
¿Vale?
Y que la gente utilice esto
Sin ningún tipo de sentido
Le vamos a poner el name
El name como file
Porque cuando subamos
Tiene que ser con esta aquí
Porque es la misma que hemos puesto
En el backend
Y ya
¿Qué más?
Ah, bueno
Y vamos a poner
Que no change
Vamos a poner
Handle input change
Y ponemos aquí una función
Handle input change
Vamos a ver aquí
Esto va a tener un evento
Event
HTML
Hostia
React
Punto
Esto
No sé
No sé si
Fiarme tanto
De G-HackoPilot
React punto
Change event
Vale
Hasta ahí sí
Vale
Vale
No tiene mala pinta
Pero me parece que está haciendo
Como demasiadas cosas
Que no tienen mucho sentido
Yo creo que hasta aquí sí
Hasta aquí sí
Console.log.file
Vale
Y esto
En lugar de hacerlo así
Es que no me gusta mucho
No me gusta mucho
Utilizar esto
Cuando
Creo que se puede entender mejor
Cuando lo utilizas así
Esto es mi opinión
Aquí cada uno
Y en lugar de hacer esto
Vamos a poner una arribación
Y así ahora miraremos
Oye
Vamos a ver si tenemos un console.log
Aquí haremos
Si tenemos un archivo
Hacemos una cosa
O la otra
Vale
Yo creo que con esto
Más o menos
Bien
Ahora necesitamos poner un botón también
Que sea
Subir archivo
Porque tenemos que subir el archivo
Vale
Esto
Vamos a ponerle aquí
El div este
O
Ah mira
Mejor
Vamos a poner aquí
Dentro de un formulario
Formulario
Y esto
Vamos a ponerlo
Con un label
Label
Y este label
Vamos a poner unos estilos
No vamos a hacer muchos estilos
Ya os digo
Vale
Lo digo porque
Si alguien se espera muchos estilos
Lo siento
Pero no
Vamos a hacer los mínimos
Para que más o menos quede bien
Vale
Vamos a poner aquí
Label
Display
Block
Simplemente para que pegue el salto
Margin
Bottom
16px
Vale
Y ya tengamos esto
Vale
Y el subir archivo
Muy bien
Vamos con más cositas
Tenemos que subir el archivo
Cuando
Hagamos un submit
De esto
Así que vamos a poner aquí
Un handle
Submit
Por ahora
No me voy a preocupar
Tanto de la componentización
Y todo esto
Luego ya nos preocuparemos
Tenemos que hacer un
Prevent default
Para asegurarnos
Que cuando hacemos el submit
No nos recargue la página
Y aquí
Vamos a poner un to do
Vale
Y luego
Cuando ya tengamos todo esto
A ver
Vamos a mover esto
Así
Para que se lea un poquito mejor
Ok
Tenemos lo de subir archivo
Ya tenemos el tema
De los estilos
Vamos a tener diferentes estados
¿Vale?
Cuando tengamos aquí
Aquí ahora
Podríamos elegir el CSV
Vamos a mover
Este archivo CSV
Que tenía por aquí
Este CSV
Voy a moverlo
Al escritorio
Creo que era el escritorio
Eso
Puede ser
Sí
Vale
Lo muevo al escritorio
Y ahora ya
Deberíamos ser capaces
De darle aquí
Y nos sale aquí
¿Vale?
Entonces ya tenemos
Demo CSV
Y tal
Vale
Vamos a hacer que nuestra
Que nuestra UI
Digamos
Tenga diferentes pasos
Esto es una cosa
Que a mí personalmente
Me ayuda mucho
El hecho de ir
Paso a paso
De decir
Mi aplicación
Tiene diferentes estados
En los que se encuentre
Que visualmente va a cambiar
Entonces yo lo que suelo hacer
Es decir
Venga
¿Cuál es el estatus
De mi aplicación?
Vale
Pues tendríamos
El estado inicial
O yo le llamo idle
Que es como
Cuando acabas de entrar
Luego tendríamos
El típico error
Que no sé si lo utilizaremos
Pero bueno
Para que sepamos
Luego cuando esté
Subiendo el archivo
Luego cuando
El archivo
Ya se haya subido
¿Vale?
Y luego cuando ya
Podamos hacer
Las búsquedas
Ready usage
¿Vale?
¿Vale?
Ready upload
Esto para que esté
Cuando preparado
Para poder subir el archivo
No sé si ready upload
Tiene sentido
Porque sería lo mismo
Que el idle
¿No?
Ready
Ah no
No es lo mismo
Porque esto es
Al entrar
Cuando hay un error
Claro
Esto sería así
Perdón
Esto sería así
Esto sería
Al elegir
El archivo
Y antes
De darle al botón
Y antes
De subirlo
¿Vale?
O sea
Ya hemos elegido el archivo
Esto sería
Mientras se sube
Mientras se sube
Y esto es
Después de subir
De subir
¿Vale?
Esta sería un poco la idea
Vamos a poner como constante
Y una vez que tenemos esto
Esto ya nos va a permitir
Tener aquí un estado
AppStatus
Set
AppStatus
UseState
Y vamos a empezar
Con el idle
Una cosa que no me gusta
Mucho de
De esto
Es que
Vamos a tener que
Bueno
Ahora no lo voy a hacer
Pero vais a ver
Que TypeScript
Me va a dar problemas
Con esto que vamos a hacer
Vale
El submit
Solo lo podremos hacer
Cuando hay una cosa
En concreto
O sea
No lo podemos hacer siempre
¿Vale?
Espérate
Voy a añadir también
Un file
Setfile
UseState
File
Para guardar aquí el file
Vamos a decir
Que si tenemos file
Guardamos
El file
Y además
Le cambiamos el estado
Claro
Fijaos aquí el problema
El problema es que
Cuando hago el setstatus
Cuando ya tengo el archivo
Que lo quiero subir
Que lo quiero guardar al estado
Y digo
Vale
Pues voy a cambiar el estado
De mi aplicación
Fijaos
Que me dice
No se puede asignar
Un argumento del tipo
Porque
El parámetro
¿Por qué?
Porque entiende
Que en realidad
El estado
Siempre va a ser
Idel
Se cree que siempre va a ser
Idel
Que me da mucha rabia esto
Entonces tenemos que crear
Un tipo
En concreto
AppStatus
Type
Que sea esto
¿Vale?
Que sea justamente esto
¿Por qué esto no le gusta?
¿Por qué esto no le gusta?
Keyof
Pero esto está bien
Como constante
Ay
Porque he puesto
He puesto const
Y esto es type
Perdón
Ahí está
Entonces le tengo que decir
Que el estado
Va a ser
Una de las posibles
Uno de los posibles valores
Y es esto
Que me da mucho
Mucho
Mucho
Mucho
Coraje
La verdad
Escribirlo
Pero es lo que hay
Que lo que estamos haciendo aquí
En lugar de
Hacer aquí otra vez
Repetir
Que esto es lo que hace mucha gente
Que hace esto
Y lo repite
Que también podríamos utilizar
Un enum y tal
Pero bueno
Da igual
Es que me gustan más los objetos
Como constantes
Podríamos hacer esto también
Pero claro
Esto el día de mañana
Si yo añado uno más
Pues es repetirlo
¿No?
Pues para hacerlo automáticamente
Y hacerlo más dinámico
Se puede hacer
De esta forma
Y ahora
El appStatus
Directamente fíjate
Que toma los valores
Del objeto
Y ahora sí
Le podemos decir
Que este estado
En realidad
Puede ser uno de esos valores
Y ahora
No se me quejará con esto
Ahora esto es cuando
Cambiamos el archivo
¿Y por qué hago esto?
Esto lo hago porque
El botón de subir archivo
En lugar de aparecer siempre
Que aparece aquí
Vamos a hacer que solo aparezca
En el caso
De que el
AppStatus
Sea igual a
AppStatus
Punto
ReadyUpload
O sea
Cuando estamos preparados
Para subir el archivo
Y así
¿Ves?
Ahora no me sale el archivo
El botón
Le damos aquí
Y ahora sí que me sale el botón
Esa sería un poco la idea
De decir
Bueno pues al menos
Que el botón aparezca
Y así visualmente
Te vas a dar más cuenta
De que tienes ahí ese botón
Podríamos mejorar
Esto del
Seleccionar archivo
Y tal
Haciendo otras cosas
O sea ya os digo
Se podría estilar este label
Si tenemos tiempo
Luego lo hago
Porque tenemos que perder
Ahí un poquito de tiempo
Pero por ahora
Mira
Voy a poner aquí
El disable
Vamos a desactivar esto
En el caso
De que el AppStatus
Sea
Uploading
¿Vale?
Mientras estamos subiendo
Vamos a decir que
Que se
Desactive
Y aquí también
Podríamos tener
Un
Small
Subiendo
Ah bueno
Tampoco hace falta
Claro
Podremos
Podemos cambiar aquí
El texto del botón
También
Y también ponerle
Si es igual
A ready upload
Claro
Si es ready upload
Vamos a poner
Show button
¿Cuándo es
Tiene que mostrar el botón?
Cuando es ready upload
O
Ready usage
No
Cuando se está
Subiendo
Y vamos a tener
Un método
Que sea
Get button text
Que
Más o menos
Podríamos hacer esto
No soy muy fan
Pero esta sería un poco la idea
Podemos tener
Otro diccionario
Button text
Donde
En cada una
De los estados
¿Vale?
Podríamos decirle
Cuando el AppStatus
Es idles
O ready upload
Es subir archivo
Cuando es uploading
Es subiendo
Y
Realmente
Con estos dos
Yo creo que ya tendríamos
Entonces ya no necesitaríamos esto
Este show button
Sería el que utilizamos aquí
Y aquí ya tendríamos
El button
Text
O sea
El button text
Este que tenemos por acá
Que dependiendo
Del valor
Que le pasemos
Aquí
AppStatus
No
AppStatus
Así
Ya nos debería mostrar
Uno u otro
¿Vale?
O sea que vamos aquí
Le damos aquí
Subir archivo
Y se supone que cuando le demos
Y empieza a subir
Debería cambiar
A eso lo vamos a hacer ahora
Para llamar a nuestra API
Que para algo la hemos hecho
En verdad
En vez de ocultarlo
No sería disablearlo
Para que el usuario ya sepa
Que hay un paso posterior
Que hay un paso posterior
Al elegir
El del paso posterior
Lo vamos a hacer
O sea
No lo vamos a ocultar
Lo vamos a disablear
Que es justamente
Lo que estamos haciendo
O sea que
No hay ningún problema
Eh
Ta ta ta
Button text
Vale
Venga
Vamos a empezar a utilizar
Y este file
Este file
Este file
Para que queremos este file guardado
Para enviarlo
A la API
Que es lo que vamos a hacer ahora
¿Vale?
Para enviarlo a la API
Para enviarlo a la API
Tenemos aquí el handle submit
Hacemos el prevent default
Vamos a hacer una cosa
No se puede hacer un submit
Si el status
Es diferente
Al ready upload
Si el app status
Es diferente
A que nuestra aplicación
Este lista
Pues no hacemos nada
O si no tenemos archivo
Si no tenemos archivo
Pues que vamos a subir
Así que le decimos
Return
Nos vamos de aquí
¿Vale?
Si sí
Si sí que puede subir algo
Antes de hacer la petición
Vamos a hacer
Set app status
Le vamos a decir
Que pasa a uploading
Entonces
Ya con esto
Deberíamos ser capaces
De ver esto
¿Vale?
¿Ves?
Subiendo
Y el subiendo
También vamos a hacer
Que este botón
Vamos a hacer
Que esté disabled
En el caso
De que el app status
Sea igual
App status
Punto upload
Y fíjate
Ya la tendríamos así
Es raro
Porque este disable
No está del todo
No está del todo fino
¿Vale?
Vamos a poner
Bueno, no está fino
Porque hay que disable
Vamos a poner aquí
Pointer events
None
Para que no nos intenten
Hacer ahí
¿Vale?
Ahora sí
¿Vale?
Perfecto
Bien, bien, bien
Vale
Entonces seguimos con
Handle Summit
Aquí vamos a llamar
A un upload file
Que vamos a crear ahora
Pasándole el file
Esto va a poner una wait
Vamos a hacer una cosa interesante
Que me parece
Me parece bien
Vamos a hacer
Un estilo
De programación
Que no me acuerdo
Como se llama
Pero sí que sé
Que es de Golang
En el que
Las cosas asíncronas
Te devuelven
Una tupla
Donde primero tienes el error
Y luego tienes los datos
¿Vale?
Pues vamos a hacer esto
Que está bastante chulo
Y aquí vamos a poner
Un console log
Del error
Y el data
Lo pongo como un comentario
Porque todavía no hemos creado
Este archivo
Pero es lo que vamos a crear ahora
¿Vale?
Vamos a crear
Los servicios
Services
Y creamos aquí
Upload.ts
Vamos a crear aquí
Un método
Bueno una función
Totalmente separada
Para llamar a nuestra API
Así que
Export const
Upload file
Que le vamos a pasar
El file
El tipo file
Aquí es donde lo transformaremos
Con un form data
Y todo esto
Y lo que tiene que devolver
Hemos dicho
Joder
Que bien
Vale
A ver
Dice
Promise
Tiene que devolver error
Null
Y any
A ver
Y si volvemos aquí
Bueno esto no es exactamente
Correcto
O sea esto debería ser
Un error
Que puede ser opcional
Y este any
Vamos a crear los tipos
Un momento
Types.ts
Export
Type
Data
Rec
Array
Record
String
String
Que es que esto es lo que hemos creado antes
Vamos a utilizar este siempre
Para que no me la
No me mezcle
Porque si no
Me los va a estar
Mezclando
Y va a ser un poco rollo
Importamos este tipo
Data
Vale
Y así le diremos
Que la promesa
Nos tiene que devolver
O sea que aquí
Nos tiene que devolver
El data este
Vale
Ahora es normal
Que se queje
Pero ahora
Lo arreglaremos
Esto es asíncrono
Joder
Pues si me había hecho
Ahí todo lo que tenemos que hacer
Form data
New form data
Esto está bien
Vale
Form data
Vamos a hacer
Un append
De el file
Que es el que
Tenemos por aquí
Esto va a ser para
Hacer el fetching de datos
Con nuestra API
Que hemos creado antes
Así que hacemos aquí
La respuesta
De fetch
Vale
Espérate porque aquí
No podemos llamar a localhost
Vale
O sea
Si que podemos llamar a localhost
Pero no es la forma correcta
Voy a usarlo ahora
Pero esta no es la forma correcta
Y ahora lo arreglamos
Vale
Creo que era
Barra files
Vamos a backend
Api
Barra files
Vale
Api
Barra files
Y aquí lo que tenemos que decirles
Es que esto
El method
Es post
Y el body
Es el form data
Y ya está
Automáticamente esto
Lo va a enviar
Con el tipo
Correcto
O sea
No tenemos que enviarlo
Como un json
Ni nada
Lo tenemos que enviar
Como
Como se llama este
Url
Form
Code
Encode
No sé que
Es que no me acuerdo como se llama
Como es el
El
Default
Del
Default
Form data
Post
A ver
MDD
Como es el
Igual me lo decís
No es 4000
Es verdad es 3000
Multipart form data
Eso
Joder
No me salía el multipart
Multipart form data
Que es el
El por defecto
Tienes razón
Esto es 3000
Gracias
Gracias
Estáis super atentos
Muy bien
Estáis a tope
Muy bien
Muy bien
Exacto
Puerto 3000
Gracias
Gracias
Vale
Pues ahora que
Tenemos el form data
Y tal
Aquí tendríamos la respuesta
Con la respuesta
Primero deberíamos ver
Si la respuesta
No es ok
Entonces devolvemos
Un error
Y le decimos
Error
Uploading file
Y
Con el status text
Vale
Vale
¿Por qué se me queja aquí?
Porque res
Ah
Porque esto es una wait
Digo vale
Vale
Aquí tenemos la respuesta
Si la respuesta
Si la respuesta no está bien
Devolvemos
Fijaos
Una tupla
Donde en el primer resultado
Devolvemos el error
Esto es como funciona en Golang
Y muchas veces
Es un poco
No sé cómo decirlo
Pero la verdad es que me gusta
Me gustaría que estuviese de forma más nativa
En Javascript
Porque te ayuda a evitar mucho el try catch
Y es una forma de tratar como los errores
Mucho más fácil
Y que te obliga además a hacerlo
Pero bueno
Que si no
Pues lo podéis hacer otra forma
Y ya está
A mí me parece un detalle ahí interesante
Vamos a apiar el json
Red json
Y aquí vamos a tener el string
Vamos a poner en types
Export
Type
Aquí en el type
Que podríamos
Api
Response
Api
Upload
Response
Que aquí tendríamos el message
Y el data
Que es data
Y esto
Sería la respuesta
Vamos a importarlo
Vale
Y aquí devolveríamos
El json data
Null no se puede asignar
Undefined
Vale pues devolverlo así
Vale pues tampoco se puede
Tiene que ser undefined
Hostia pues entonces sí que prefiero que sea así
Porque prefiero que sea null
O sea prefiero hacerlo así
Me gusta más el null que el undefined
En este caso
En este caso
Aunque hay lenguaje de programación
Que dicen que el null era un error
Pero bueno
A ver
Bueno voy a dejar undefined
Y ya está
Para vivir más tranquilo
Es que me parece un poco
Undefined como que parece
Un valor mucho más forzado todavía
Que el null
Pero bueno
Y aquí en el catch
Pues nada lo mismo
En el catch
Devolveríamos el error
Que claro
Aquí el error
Ves que pone tipo unknown
No sé qué no sé cuánto
Claro nos tenemos que asegurar que viene
Si el error es del tipo error
O sea una instancia de error
Entonces devolvemos el error
El error
Y si no
Ah
Y si no
Ya llegamos aquí
Y creamos nuestro propio error
Unknown error
A ver
Toda esta gestión de errores
La estoy haciendo porque lo dice el challenge
Y como el challenge dice
Errores
Dice por ahí
Manejo de errores claro
Y amigable para el usuario
Que es lo que voy a hacer
Ahora veréis lo que voy a hacer
Lo que voy a hacer con todo esto
Con todo este manejo de errores
Es que
A ver
Yo podría haber hecho el fetch
Y ya está
Pero dice
Maneja los errores
Y hazlo amigable para el usuario
Ahora es donde viene la magia
Ahora es donde viene el momento
Para que ha servido todo esto
Bueno
Pues todo esto
Yo si fuese junior
Seguramente no hubiera hecho
Tanto manejo de errores
También os digo ¿no?
O sea
Yo hubiera hecho aquí
Pues que muchas veces
Pues no hubiera manejado tantos errores
O lo hubiera hecho mucho más general
Entonces aquí sí que entiendo
Que un junior hubiera dicho
Voy a ser menos granular
Y voy a manejar menos los errores
Bueno
Lo puedo entender
Pero lo bueno de esto
Es que
Cuando ya vengamos aquí
Y tengamos los errores
Lo genial
Voy a poner aquí
Vamos a importar aquí esto
Agregar importación desde services
Vamos a poner aquí
Que esto sea async
Lo que está genial
Es que vamos a tener el error
Y el error
Vamos a instalar
Soner
Para enseñarle al usuario
Los errores de forma amigable
¿Vale?
Con estos toast
Que aparecen aquí
Estos toast de aquí
Le vamos a enseñar errores
Y todo esto
Entonces vamos a instalar
Soner
Y así le podremos ir informando
Al usuario
Y aquí porque se me queja
Bueno no sé por qué no se me queja
Pero lo importante
Es que tenemos que instalar
Esta dependencia
Install
Soner
En el frontend
¿Vale?
Instalamos soner
Mira ya me he quitado las dependencias
Por ahí
¿Vale?
Vamos a importar
Import
Toast
Hostia no me acuerdo
Como se llama
Toast o toaster
¿Vale?
Definido
Pero nunca utilizado
Utilizamos el componente este
Aquí
Esto luego ya lo
Componentizaremos más
Ahora
Es para que tengamos algo ahí
Y aquí
Lo que podríamos hacer es
Vale
Pues si tengo un error
¿Sabes?
O sea
Si tengo un error
Voy a hacer una cosa
Si tengo un error
Si tengo error
Cambiamos
Por un lado
El estado de nuestra aplicación
Le ponemos que tenemos un error
Le decimos que
Enseñamos el error
Con el mensaje de error
Porque lo tenemos
También
Y lo devolvemos
Y si no tenemos un error
Pues nada
Le decimos que
AppStatus
Ya está listo para utilizarle
Le decimos que
Todo se ha subido correctamente
Y ya está
Pero
Ah
Y esto
Si tenemos datos
SetData
¿No tenía aquí los datos guardados?
Ah no
Pues mira
Creamos aquí
SetData
UseState
Con data
Que va a ser un array vacío al principio
UseState
Data
Con el array vacío al principio
Ha importado data
Type data
Vale
Y aquí vamos a poder guardar los datos
Porque los tendremos que
Hmm
Vale aquí
New data
Vamos a llamarle new data
Para que no se llame exactamente igual
Que el nombre del estado
Hemos hecho muchas cosas ahí
Y todavía no estamos viendo si funciona
Vale
Está asignado pero no utilizado
Bueno por ahora
Lo voy a dejar así
Vamos a probar ya todo esto
Que ya tengo ganas
A ver
Vamos a ver
Vamos a ver
Por donde puede fallar esto
Voy a abrir las herramientas de desarrollo
Y vale
Subimos el archivo
Archivo subido correctamente
Vale
Obviamente esto habría que quitarlo también
Eso lo hacemos ahora
Vamos a ver aquí
Vale
Fijaos que aquí
Si que
Ha funcionado en el backend
En el console.log
Me faltaría tener un console.log
Del data
¿No?
Para ver si realmente
El data que me ha devuelto
Console.log
New data
Y entonces con esto
Estaríamos verificando
Que nuestro backend funciona
Vale
Le tomamos aquí
Subir archivo
Mira
New data
Y aquí tenemos el JSON
Hostia pero el JSON está mal
¿Qué es esto?
¿Qué es esto?
Esto está mal
O sea
El CSV
No nos lo está formateando
Bueno
Funciona
A medias
Funciona a medias
Vale
Pero no os preocupéis
Lo arreglamos ahora
¿Por qué?
Esto tiene que ser el delimitador
Entonces
Vamos al backend
Un momento
Porque
Este
El row CSV
Funciona bien
Porque fijaos que aquí
Me lo está parseando bien
Lo que al transformarlo
En JSON
Este CSV
String to JSON
A ver
Tenemos por aquí
CSV
String to JSON
Delimiter
Define
Field
Delimiter
Pero es que por defecto
Ah
¿Eh?
¿Cómo?
Esto no había visto en mi vida
Dice que
El delimitador
Que es el necesario
Para separar los CSV
Dice que por defecto
Utiliza el semicolon
¿Qué sentido?
Es la primera vez
Que veo esto
Eh
No
Es la coma
O sea
Eh
Si es la coma
Entonces tal
Bueno
No sé
Yo siempre he visto la coma
Bueno
No sé
Igual me lo estoy imaginando
Anda
Ostras
Primera vez
No tenía ni idea
Son los dos
Ostia
Dice que en países
Como Estados Unidos
Y Reino Unido
Y Australia
El separador por defecto
Es la coma
Pero que en los países europeos
Es el punto y coma
O sea
Y yo que soy de España
Siempre he pensado
Que era la coma
A ver
Es que yo
Yo juraría
Que CSV
Justamente
No
CSV
Código de seguro
De verificación
No
Creo que significaba
Coma
Coma
Separate value
Entonces
Si lo dice el nombre
Si lo dice el nombre
Ostia
Es la primera vez
Me acaba de volar la cabeza
No tenía ni idea
No tenía ni idea
¿Por qué puede ser esto?
Puede ser
Porque
Claro
Como la coma
Está reservada
Para el símbolo
Nosotros en España
Por ejemplo
Los precios
Ponemos
49,90
O sea
44,99
Y utilizamos la coma
Como en Estados Unidos
Estos sitios utilizan el punto
Entiendo que pueden ir por ahí
Los tiros
Bueno
De hecho
No es que pongan por ahí los tiros
Es que lo dice aquí
¿Vale?
Dice
Está reservada para el decimal
Pero es verdad
Que no había caído
¿Sabes?
O sea
Yo daba por hecho
Que era la coma
Nunca había pensado en esto
Porque justamente
Como es CSV
Ya lo dice en el nombre
Entonces
Vale
Nunca te acostarás
Sin saber una cosa más
Feel.de
Luego me dice la gente
Esto
Lo tienes todo preparado
Ahí en un
Y así
La madre que te parió
Vale
Pues ya lo tenemos por aquí
CSV
A ver ahora
Ah, espérate
Que tenemos que reiniciar esto
Vale
CSV
Vale
Ahora sí
¿Vale?
Ahora sí que lo tenemos bien
O sea que
El backend está funcionando correctamente
Aquí
Esto debería desaparecer
Porque ya no es necesario
Lo que podemos hacer
Es que
Esta parte del formulario
Esta parte del formulario
En realidad este formulario
Podríamos ir
Igual que hemos hecho el show button
Podríamos hacer el show input
Y esto es
Si el app status es igual a
Idel
O readyupload
No
Si es diferente
A app status
Punto
Readyusage
Entonces enseñamos el input
O sea
Todo esto en realidad
Solo lo tenemos que enseñar
En el caso
De que todavía no estemos listos
Para el siguiente paso
Vale
Espérate que aquí
Hay alguna cosa
Formulario
El formulario lo metió donde no era
Esto por aquí
También podría haber instalado
Prettier
También os digo
Pero bueno ya
No hay marcha atrás
Vale
Esto
Que estoy asegurándome
Que no
No la estoy liando
Con ninguna cosa
Vale
Esto el label
Esto el formulario
Esto por aquí
Y esto por acá
Entonces
Ahora desaparecerá todo
Tiene sentido
Ponemos csv
Subir archivo
Bueno
Que se sube muy rápido
Por eso no vemos el subiendo
Ya aparece así
Y aquí lo que deberíamos hacer
Es
El segundo paso
Así que
Vamos a tener aquí
Steps
Vamos a llamarle steps
Que esto sea
¿Cómo le podemos llamar?
Filter
O search
Search
Search
Punto tsx
Export const
Search
Return
Vale
Por ahora vamos a hacer solo esto
Y esto
Lo vamos a mostrar
Cuando
Cuando al ipstatus
Sea ready usage
¿Vale?
Mira ahí pone con
Todo eso
Pero esto en realidad
Vamos a pasarle
El initial data
Le pasamos los datos
Que hemos recuperado
¿Vale?
Esto lo importamos
Que es el componente
Que hemos creado
Este initial data
Lo tenemos por aquí
Y este initial data
Initial data
Va a ser los datos
No se encuentra data
Pues lo importamos
Y aquí vamos a tener
Data
Set data
Use state
Initial data
Esto va a ser data
¿Por qué vamos a hacer esto?
Porque aquí
Vamos a poner
Un input
Un input
Type
Search
Para buscar
Handle search
Muy bien
Cuántas cositas
Cuántas cositas
Aquí vamos a poner
Set search
¿Vale?
Handle search
Event
Change event
Set search
Target value
Vale
Y esto cada vez que cambie
Playholder
Buscar
Información
En
La
Buscar información
Va a ser así
Vamos a poner dentro
De un formulario
Todo esto
Y luego el handle search
Vamos a poner
Un change
Handle search
Luego buscaremos
Para hacer un
Un throttle
¿Vale?
O sea un defer
Para que no busque todo el rato
Vale
Y cada vez que cambiemos
El search
¿Ves?
Esto está mal
Esto está mal
Cada vez que cambie el search
Vamos a
Update
Vamos a cambiar
Vamos a actualizar la url
Eso es lo que vamos a hacer
Vamos a actualizar la url
Porque
Luego lo haremos mejor
Pero primero
Necesitamos cambiar la url
Porque así la url
Será como la fuente
De la verdad
Que utilizaremos
A la hora de buscar
¿Vale?
Buscaremos a través de la url
Y si alguien entra en la url
Directamente
Verá ya
Con los archivos
O sea ya verá
Los resultados directamente
Y hombre yo creo que esto
Pues es buena idea
Entonces
Si el search
Es vacío
Si el search
Es vacío
O sea no
Tiene una cadena de texto vacía
Vamos a ponerlo así
Que es más específico
Lo que vamos a hacer es
Window.pushState
Y vamos a actualizar
La url
Joder
Esto hay que dejarlo vacío
Y esto
Con el
Window.location.pathname
Sin nada
Sin nada más
Window.pushState
Ay coño
Perdón
Vale
Si es vacío
Hacemos esto
Y hacemos un return
Y si no es vacío
Lo que hacemos es
Window.story.pushState
PushState
No sé si esto se puede hacer
Bueno
Vamos a verlo ahora
Vamos a ver
Vale
¿Veis?
Ahora ya voy escribiendo
Y conforme voy escribiendo
Se va cambiando la url
Cuando voy escribiendo
Y voy cambiando la url
Cuando lo quito todo
Se quita también el query param
Vale
Pues con esto
Ya lo tendría
Search
Vale
Viendo un poco el código este
Primero lo escribo
Y luego lo pienso
No sé si aquí
Si hago entonces esto
Si hago entonces esto
¿Sabes?
Si hago esto entonces
No
¿Sabes?
Ahí sí que necesito
Window.pathname
Vale
Pues vamos a poner
New.pathname
Vamos a poner
Si el search
Es igual a esto
Es
Window.location.pathname
Y si no
Hacemos esto
Y así
Nos quitamos el
Elif
Un poquito mejor
¿Vale?
Utilizamos una ternaria
Una ternaria
Y lo mismo
Vamos a hacer
Con la llamada
A la API
Aquí vamos a
Llamar a la API
Para filtrar
Los resultados
¿Ok?
Para filtrar los resultados
Habíamos creado el servicio
Bueno
Espérate
Voy a leeros
¿Cómo estáis?
¿Estáis bien?
Ahora faltan debons
Sí, lo vamos a hacer
Pero se crea un history nuevo
Para cada cambio
A ver
Podríamos hacer un push state
O hacer un replace state
Lo que queráis
La verdad
No pasa nada
Si hacéis un push state
Lo que estaremos haciendo
Es que vamos a tener
La navegación aquí
Y si hacemos un
Un replace state
Es que no tendremos la navegación
Cualquiera de las dos
Está bien
Cualquiera de las dos
Estaría bien
Vamos bien
Muy bien
Aslan
Te quiero Midu
Yo también te quiero a ti
Aventurer
¿Subirás esto a YouTube?
Me imagino
Me imagino
No sé si esperaremos
A tenerlo todo
Pero
Eventualmente
Lo subiremos
Vale
Pues vamos a hacer
El de la llamada
Ya está
Vamos a hacer
El de la llamada
En servicios
Vamos a poner aquí
Search.ts
Me voy a basar
En el upload
Porque es muy parecido
Y vamos a hacer
Search data
Donde aquí teníamos
El search
Esto sería
Un string
Esto no lo necesitamos
No haríamos aquí
En todo caso
Hostia
Hay que arreglar eso
Hay que arreglarlo
El localhost
Este
Hay que arreglarlo
El localhost
O sea que
Esto hay que arreglarlo
Hay que arreglar esto
A ver
Vamos al backend
En el backend
Era
API barra users
Claro
Aquí da por supuesto
Que son users
Es un poco
De aquella forma
Vale
Tenemos aquí el resultado
Error
Searching
Data
Appit
Upload response
Vale
La respuesta
En este caso
Export
Type
API
Search
Search response
Esto es data
Data
En este caso
Creo que no había
Un message
Si no me equivoco
Ah no me acuerdo
Si había un message
O no
Yo creo que no
Bueno
Si lo hay
Luego lo arreglamos
Searching data
API
Search response
Quitamos este
Me da rabia
Que no me lo importe
Como un tipo
Directamente
Vale
JSON data
Si no
Un error
Res status text
Vale
Search text
Esto sea el search data
Pues vamos a llamar aquí
Search data
Search data
Vale
Aquí tendríamos
No sé si hacer
Vale
Vamos a hacerlo aquí
Response
Nueva data
Si tenemos un error
Pues nada
Otra vez también
El toast este
Toast
Ah porque no
No me aparece
Bueno
Importamos
Básicamente para tener
Una forma amigable
De enseñarle al usuario
Los errores
Search data
Toast
Punto
Error
Error message
Y si ha ido bien
Pues set data
New data
No se puede asignar
Tipo data
Ah vale
Porque esto es solo en el caso
De que
If new data
De que realmente
Tengamos nuevos datos
Y ya nos faltaría aquí
Pues mostrarlos
A ver
New data
Punto map
Row index
Y aquí pues
Vamos a hacer
Que esto sea en un
UL
UL
Y aquí
Un
Lee
Dentro un article
Y
Ver index
Object rows
Tu tu tu
Vale
Este index como tal
No es necesario
Vamos a pensar
Que aquí
Todos los rows
Tienen una idea
Vale
Esto
Esto tampoco
Me parece que
Tenga mucho sentido aquí
O sea
Si que está haciendo aquí
Una iteración
De todas las keys
Pero bueno
En lugar de hacer
De todas las keys
Y hacer esto
Yo creo que tendría más sentido
Hacer
Object entries
Para tener
Por un lado
La key
Y el valor
Y directamente
Aquí pues renderizar
Rollo
P
Tenemos
Strong
Que sea la key
Le ponemos
Dos puntos
Y aquí
Value
Vale
Espérate
Que la he liado aquí
A ver
Vale
Y aquí
No
¿Qué me pasa aquí?
Ahora
El elemento
Enlace
A ver
¿Qué dice?
Tiene un tipo
Any implícito
Ay
Espérate
Que aquí la estoy liando
Object entries
Punto map
Madre mía
Data
Es que me estaba inventando
Hay cosas
Y ahora sí
¿Por qué dice esto?
No se puede asignar un argumento
Tipo any
Al parámetro
Vale
Porque el data
Me dice que es del tipo any
Data
No se encuentra el tipo any
Al parámetro
No se encuentra el nombre
Key
Object entries
Data
Punto map
A ver
Es que eso me está
Faltan paréntesis
¿Puede ser?
Estos
Tienes
Toda razón
Vale
Pero todavía
Este value
Ahora dice
El tipo record
No se puede asignar
El tipo
React Native
O sea
El key
Dice que es un string
Y el value
Me dice que es un record
String de string
No
Porque
Ah
Porque esto no es data
Esto es row
Ya está
Ah
Ya está
Ya está
Uh
El data
Ya he usado antes
Sí
Tenéis toda la razón
Tenéis toda la razón
Ahora ya
Ahora sí que está
Ahora sí
Ahora sí
Ahora sí
Vale
Vamos a poner esto un poquito más bonito
Para que
No nos asuste tanto
Vale
Vamos a dejarlo así
¿Vale?
En row
Yo te dije arriba
Perdón
Perdón
Sí
Es que claro
Pensad que estoy ahí
Pensando mucho
Y me gustaría leer todo el chat
Pero ostras
Pero no se supone que
Al query param
Va cuando haces la llamada a la API
¿Por qué lo estás colocando en la URL del frontend?
Porque
Mira
Qué buena pregunta
Gem
Vas a alucinar
¿Por qué?
A ver
Porque
Mira
Si yo voy aquí
Y me pongo a hacer esto
¿Vale?
Y yo subo el archivo
Ojo
Que ya
Está haciendo cosas
Es verdad que no doy todo bien
Pero está haciendo cosas
Están pasando cosas
Están pasando cosas
Vale
Aquí hay un error 500
Lo cual está bien
Esto significa que nuestra API está funcionando
Porque tenía que dar un error 500
Y por lo tanto
Este search data
Que habíamos hecho aquí
Tenemos que
Que si esto
No tiene search
Entonces lo que vamos a hacer es un return
Y vamos a setear
La data inicial
¿Vale?
Vale
Tenemos que ponerlo en la lista de dependencias
Que ya veo que aquí no la habíamos puesto
Initial data
Vale
Vale
Entonces
Voy a hacerlo otra vez
Demo
Subir archivo
Vale
Dice
Cada
Cada chico
Tiene que tener
Una key única
No sé por qué
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
O sea
Se supone que debe tener
Una
Una única
¿No?
O sea
El punto ID este
Del row
Si entiendo que este es el ID
No sé por qué me dice
Que debe tener una única
Porque si estoy recuperando el row
Y cada row
Debería tener el ID único
Se me ha copado
Los P
A ver
Espérate
Voy a poner esto
Los P
Ah
Claro, claro
Tienes razón
Es aquí
Es aquí
Gracias, gracias
Que me ha dicho los P
Es que no estaba cayendo
Vale
Entonces
El tema es que alguien dice
Pero
Si por qué pongo esto
Ojo
Que ya filtra
Que ya filtra
Ya filtra
Están pasando cosas
Vale
Fijaos que ya filtra
Ya filtra
Si ponemos aquí
Ventas
¿Veis?
Solo filtra ventas
Si ponemos aquí
Juan
Pues solo aparece Juan
O sea
Ya está funcionando correctamente
¿Por qué lo pongo en la URL?
La pregunta del millón
¿Por qué lo pongo en la URL?
¿No?
¿Por qué?
Ahora arreglamos esto
Que está haciendo demasiadas búsquedas
¿Pero por qué pongo esto en la URL?
Porque
Lo que estaría muy genial
Es que
Que bueno
Me faltaría cosas
¿Vale?
Teníamos que arreglar unas cuantas cosas
Pero lo que sería genial
Es que si alguien entrase directamente
Aquí
Que pudiese acceder
A esa información
Y buscarlo directamente
¿Te imaginas?
Pues eso es lo que podríamos hacer
Y para hacer eso
Lo único que tendríamos que cambiar
Es que
Aquí que tenemos como un string vacío
Podríamos tener
El estado inicial
Leer la URL
Y ya tener ahí
La búsqueda
Tendríamos ahí la búsqueda
Por ejemplo
¿Qué tendríamos que hacer aquí?
Este useState
Que habíamos hecho aquí
Le vamos a pasar
Un método
Y le vamos a decir
Vamos a recuperar
Los searchparams
De url searchparams
Punto
WindowLocationSearch
Recuperamos
Recuperamos
De searchparams
El queryparamq
Y si no le ponemos
La cadena de texto vacía
Por defecto
Y ya solo con esto
Lo que vamos a tener
Es que tú imagínate
Que ya
Tenemos aquí la url
Juan
¿Vale?
Pues fíjate
Que yo subo aquí el archivo
Demo.csv
Le doy a subir
Y ya me los ha filtrado por Juan
Ya me los ha filtrado por Juan
Porque en la url
Ya estaba el filtro
¿Sabes?
Y entonces eso es lo que hace
Que la url
Tenga sentido
Porque la url
Es la fuente de la verdad
En la que el usuario
Cuando entra ahí
Ve los resultados que espera
Que todavía podríamos arreglar
Algunas cosas y tal
Pero lo bueno de esto
Es que ahora
Podríamos tener la url
Con los filtros aplicados
Y le podríamos decir
A un cliente
Oye
Entra esta url
Con estos filtros ya aplicados
Sube tu csv
Que no te preocupes
Que ya
Te los va a filtrar
Y ahí es donde está la clave
Entonces
Todavía nos quedan cositas
No os preocupéis
Tengo dudas
¿Cuándo recomiendas bit?
Cuando solo necesitas una spa
Falta el valor en input
Y queda excelente
El valor en input
Claro
También tendríamos que ponerlo
Ahí en buscar información
Tienes toda la razón
Porque aquí este value
Claro
Lo malo de este value
No sé si tendríamos que poner
El default value
Y aquí
Podríamos ponerle
El search
¿Search?
Sería search
Vale
Faltan dos cosas
¿Ves?
Juan
Y esto ya lo podríamos cambiar
Y ponerle
Paco
Y ya
Teníamos ahí filtrado
Y fíjate
Que entramos aquí
Hostia
No sé por si había quedado así
Ponemos aquí
Le damos a subir
Y como aquí ponía Paco
Pues aquí pone Paco
Pero no hay ningún Paco
Pues no aparece nada
Pero si ponemos Juan
Pues ahí aparece Juan
Cosas
Cosas
Una cosa que vamos a arreglar ahora
Fácilmente
Rápidamente
Es el tema del devounce
Porque si nos ponemos aquí
A buscar mucho
O sea
Si nos ponemos
Si nos volvemos locos
Vamos a buscar aquí
Voy a cerrarlo todo
¿Vale?
En el service
Service
No
En el search
Este
Claro
El problema es que ahora
Fíjate que no es muy
No es muy eficiente
Si yo busco Juan
Se me pone a buscar aquí
Como si no era mañana
Cada vez que escribo
Pues se pone a buscar
Para hacer esto
Vamos a utilizar un
Use the bounce hook
El primero que encontremos
Este
Este es de Fiar
Este está bien
Que es una colección de hooks
Bastante chula
Vamos a instalar esta dependencia
Ay que rabia esto
Lo malo utilizar PNPM
Que
Que todo lo que te copias
Siempre es de en pie
Vale
Y esto para utilizarlo
Vamos a intentar utilizarlo
Sin mirar
A ver si me acuerdo
Básicamente
Importaríamos el use
The bounce
The bounce
Yo también me lo estoy inventando
De esta dependencia
El use the bounce
Nos va a servir
Para decirle
Quiero que el valor este
De search
Me lo guardes
Durante
Un tiempo
The bounce time
Vamos a ponerle 500
¿Vale?
Y este tiempo
Lo solo ponemos aquí
Ahora
The bounce search
Esto
Sin array
Lo que vamos a hacer con esto
Es que
Aunque nosotros
Cambiemos el estado
Este
The bounce search
Solo va a cambiar
Cada 500 milisegundos
O sea que va a esperar
A que el usuario termine
Y cuando termine
Entonces
Se pondrá a buscar
Este es el que vamos a utilizar
Aquí
Aquí
Aquí
Aquí
Aquí
Y aquí
Y solo con estos cambios
Si no hemos hecho nada mal
Si ahora
Ponemos esto
Vale
Ahí se ve
¿Vale?
Fíjate que yo
Voy
Voy escribiendo
Y hasta que no pasa
El medio
Segundo
Entonces
No lo hace
Lo cual
Mejora bastante
Estaba ahí
Momento tensión
Pero está
Está mucho mejor
Porque ahora sí
Si vamos escribiendo
Fíjate
No se está haciendo
Ninguna llamada
Pero cuando termino
Y pasa medio segundo
Entonces lo hace
Pero menos inmediato
Hombre
A ver
Lo puedes ajustar
Un poco más
No hace falta
Que sean 500 milisegundos
Creo
Si no me equivoco
Que
Una pulsación
De un usuario
Normal
Estándar
Suelen ser 250 milisegundos
Y cosas así
Yo suelo utilizar 300
Y ya queda bastante bien
Entonces
Creo que queda
Bastante inmediato
Y tal
O sea que tampoco
Se nota tanto
Vale
Esto por un lado
Hay otra cosa
Hay dos cosas
Que vamos a arreglar
Una
Fijaos que aquí
En los servicios
Hemos utilizado
El localhost
Aquí a pelo
Esto está mal
¿Vale?
Está mal
Porque lo que estamos
Haciendo con esto
Al final
Es ponerlo aquí a mano
Y cuando lo tengamos
Desplegado
Queremos que esto
Funcione correctamente
Vamos a crear aquí
Un archivo
Que sea
Config.ts
Y vamos a
Exportar
La constante
Bit
API
Host
Ahora te explico
Porque Bit
¿Vale?
Porque si no
Y la renombramos
A API
Host
Y hacemos
Import.meta.env
¿Qué le pasa a esto?
¿La propiedad
Env no existe
En el tipo
Import.meta?
¿Cómo?
Import.meta.env
Y dice
¿La propiedad
Env no existe?
¿Cómo que no existe?
Punto
Punto.meta.
Punto
Aquí me está dejando
Todo loco
A ver
Esto no puede ser
Import.meta.env
Porque no está
El puto
A ver
A ver
Entiendo que este
No exista
No existe
En el punto
O sea
Entiendo que ese
No exista
Pero el punto
Env
Si que debería existir
Si esto es
Como funciona
Bit
Amigo
Puede ser
Por el cambio
Que he hecho
No
No es por el cambio
No es por el cambio
Esto debería existir
¿Ves?
Import.meta.env
Te está saliendo
De la ropa
Autocontrol
Porfa
¿Te está saliendo
De la ropa?
De la ropa
No hombre
No sé si te refieres
A que me estoy
Cambiando
Estoy cambiando
De tal
Pero esto es
Súper importante
Porque a ver
No en el back
Ah que me he cambiado
De
No estoy en el front
O sea está bien
Estoy en el sitio
Correcto
En config
Esto es súper importante
Amigos
Porque si no
El API host este
Necesitamos indicárselo
Esto debería ir
No sé por qué
No lo está pillando
Pero
Saliendo de la ropa
Perdiendo la cabeza
Está bien
No debe ir jarcodeado
Claro
Es que esto no puede ir jarcodeado
Porque cuando hagamos
Después
El despliegue
Si no nos fallaría
Entonces
No sé por qué
Esto me falla
Lo que podría hacer
Es declarar
O sea
Declare
Global
Interface
Import
Meta
Enf
O sea esto debería funcionar así
Pero fijaos
Que me falla aquí
Y no sé por qué pasa
Porque eso no debería fallar
No sé si es
Un error
Que se le ha ido a la olla
¿Ves?
Ahora sí que funciona
Es el editor
Macho
Es el editor
Porque esto
Funciona
O sea
Sí que funciona
No sé
No sé por qué
A veces se le va
Yo creo que a lo mejor
Es por los cambios
Que hemos hecho
De dependencias y tal
Pero ahora
Ahora sí que funciona
O sea si hago
Import.meta.enf
¿Ves?
Me deberían aparecer estos
Desde el principio
Esto es otra cosa
De TypeScript
Que también a veces
Me pone de los nervios
Que ya no sabes
Si es error tuyo
Es el editor
Es tu mamá
O es lo que es
Bueno
Vale
Te explico
Hay que utilizar
Bit
Porque si no utilizas
Bit
No lo vas a poder utilizar
En tu código público
Y por lo tanto
No es público
Y si no es público
No lo puedes utilizar
Porque esto
Es JavaScript
Que carga el cliente
Así que si quieres utilizarlo
De forma que lo puedas leer
Desde cualquier archivo
JavaScript
Que vaya a descargar
El usuario
Tienes que ponerle
Prefijo de bit
Esto lo hacen
Para evitar
Que llegue a JavaScript
Que es para el cliente
Keys de base de datos
Api keys que no deberías
Y cosas así
Lo que vamos a hacer aquí
Es cambiarle el nombre
A api host
Y en el package.json
Vale
En el package.json
Aquí en el package.json
Del frontend
Aquí
Aquí
Vamos a ponerle
Bit
Api host
Local host
4000
Lo bueno es que esto
Lo vamos a poder utilizar
Después cuando tengamos el deploy
Para cambiar a la URL
Correcta en producción
Pero en desarrollo
Vamos a tenerlo aquí
En local host
3000
Perdón
3000
Importante
Vale
Ahora que ya tenemos esto
Y tenemos esta configuración
Podemos ir a todos nuestros archivos
Importamos el api host
Y al menos esta parte
Ya la podemos cambiar
A api host
Vale
Esto mismo lo podemos hacer
En el upload
Y queda mucho mejor
Porque esto nos permite
No tener que saber
Si están en 3000
Y no sé qué
Y en producción ya
No funcionará
Otra cosa que nos pedían
En el challenge
Y esto está
Esto está muy chulo
Porque vamos a hacer un
Monorepositorio multipaquete
En un momento
Vale
El tema es que dice
Que hay que hacer
Un npm run dev
Dice
El front y el backend
Deben funcionar
Simplemente ejecutando
Npm install
Seguido
De npm run dev
Entonces
Dice
Para ejecutar la aplicación
¿Qué vamos a hacer con esto?
Necesitamos
Que
Desde la raíz
Podamos
Levantar
Todo nuestro proyecto
O sea
Ahora lo que hemos hecho
Es ir a un sitio
Ir a otro
Y tal
Pues no
Lo que necesitamos es
Ir a la raíz
Y poder hacer
Pnpm run dev
Y que todo funcione
Por arte de magia
Entonces
¿Qué podemos hacer?
Vamos a crear
Un workspace
Un entorno
O
Si
Un entorno de trabajo
Se podría decir
¿No?
Los workspaces
Funcionan diferente
Dependiendo
Si utilizas en npm
En pnpm
En yarn
Cada uno tiene
Una forma diferente
Nosotros estamos utilizando
Pnpm
Es muy parecido
A como funciona
En npm
Pero hay algunas
Diferencias
Es
Yo la verdad
Lo odio bastante
Porque me gustaría mucho
Que estuviese todo
No sé
Estandarizado
Pero en el caso de pnpm
Hay que utilizar
Un archivo que se llama
Pnpm
Guión
Workspace
Yamel
Este es el archivo
Que tenemos que crear
Y lo que le vamos a decir
Aquí en la raíz
Aquí
Es decirle
Vale
Los paquetes
Que tenemos que utilizar
Son
Backend
Y frontend
Estos son nuestros
Multipaquetes
Dentro del mismo repositorio
Esto para que va a servir
Va a servir para dos cosas
Uno
Ahora
Desde aquí
Podríamos hacer un
Pnpm install
Y nos va a instalar
Fíjate que ha detectado
Tres workspaces
Ves que pone
Scope
Tres workspaces
Esto significa
Fíjate la diferencia
Así lo quito
Y hago un pnpm install
Ah bueno
Pues me ha detectado
Exactamente igual
Me ha detectado
El scope
No me digas
Que esto lo hace automático
A ver
Hostia
Pues esto antes
No lo hace automático
A ver
Igual lo hace automático
Ah no
No no no no
No
Es que había cacheado
El archivo
Es que había cacheado
El archivo
La madre que lo parió
No no
Es necesario
Es necesario
Ya decía yo
Estaba flipando
Bueno
Esta es la diferencia
¿Vale?
¿Veis?
La diferencia entre
No tener el archivo
Y tener el archivo
Que detecta aquí
Que hay tres workspaces
¿Por qué hay tres?
Porque le hemos dicho
Los paquetes que estamos utilizando
Dentro de este repositorio
Están en la carpeta backend
Y en la carpeta frontend
Entonces tendríamos
Un workspace
Que sería
El de la raíz
En este package.json
Otro dentro del backend
Con este package.json
Y otro dentro del frontend
Con este package.json
Y lo bueno de esto
Es que cuando tú haces
Desde la raíz
Un pnpm install
Va a instalar
Todas las dependencias
Del proyecto
Y de todos los paquetes
Que tengas dentro
Y los va a reutilizar
Que eso es lo más interesante
Todavía
Pero todavía hay más
Porque tenemos que levantar
El proyecto de una
¿Vale?
Tenemos que levantar
El proyecto de una
Así que vamos a levantar
También el proyecto de una
Una cosa que puedes hacer
Una vez que tienes ya
Los workspaces
Los tienes aquí configurados
Es que puedes ejecutar
Scripts
De un paquete en concreto
O sea
Podríamos hacer
Pnpm dev
Y decirle
Que solo ejecute
El del backend
No sé
No me acuerdo
Si era así
No
No era así
Pnpm
Filter
Backend
Dev
Ahora sí
Fijaos
Desde la raíz
He podido hacer
Vale
Quiero que
Me filtres
El del backend
Y me ejecutes
El comando
Dev
Del backend
Y veis que me ha levantado
El backend
Desde la raíz
Pues esto mismo
Lo puedo hacer
Del frontend
¿Vale?
Puedo hacer frontend
Y fíjate
Que me levanta entonces
El frontend
Desde la raíz
O sea
Es capaz de detectar
Como dentro
Los workspaces
Que tenemos
Y utilizando el filter
Podemos decir que lo filtre
Y además
Hay otra cosa
Que podemos hacer
No sé si el filter
Se puede utilizar
Más de uno
Que sería la clave
Voy a verlo
Que yo creo que sí
Que se puede
Filter
Filter
Filter
Package
Name
Filter
Package
Name
Coma
Es que no sé si se
Ah
Ago
Filter
Claro
Es que me pone aquí
Claro
Puedo hacer asterisco
Y ya está
O sea
Se supone que si hago asterisco
Asterisco
Asterisco
Vale
Perfecto
Eso es lo que queremos
Fíjate
Le estoy diciendo
Que me filtre todos
Pero como solo tengo dos
¿Qué más da?
Pues aquí me ha detectado ya
El backend
Y me ha detectado el frontend
Me ha detectado los dos
Que necesitamos
Pues este es el comando
Que vamos a querer utilizar
Desde la raíz
Para levantar nuestros proyectos
¿Os acordáis que decía
Con un solo comando?
Pues fijaos que maravilla
Que maravilla
Que esto lo podéis hacer
En un montón de proyectos vuestros
Que hagas así
Y que ya tengas funcionando
Tanto el backend
Como el frontend
Con un solo comando
Que es justamente
Lo que nos pedían
¿Veis?
Aquí tenemos ya
Funcionando el frontend
Subiendo el archivo
Vale
Ha fallado algo
No sé por qué
Me ha fallado la API
Pero bueno
Está bien
Que al menos
Hemos visto que funcionaba
New data
Me lo ha dado vacío
Espérate
Si es que no me ha levantado
Localhost 3000
Esto sí que me lo ha levantado bien
Ah
Vale
Está mal el bit
API host
El bit API host
Pero bueno
Está chulo
Está chulo
Porque fijaos
Que he podido ver
Que funciona correctamente
El fail to fetch este
O sea que
Funciona bien
El tema de
Molaría que
Todavía te mostrase más
Podríamos cambiar
Donde muestra esto
Pero bueno
Que al menos aparece el error
Vale
El problema
Está en el bit API host
Que aquí
Tendríamos que poner
HTTP
Bla bla bla
Ahora sí
Pero mira que maravilla
Porque además
Puede cerrar
Los dos servidores
A la vez
Los puede levantar
Otra vez
A la vez
Esto está muy chulo
Y ya está funcionando
Otra vez
Perfectamente
¿Ves?
Ahora sí que está funcionando
Ponemos Juan
Se filtra
Vale
Vale
Pues con esto
Ya hemos hecho
Bastante de la prueba
Porque tendríamos
Como toda la parte
Digamos
De implementación
Creo que no se nos ha quedado
Nada de implementación
¿Qué nos faltaría?
Nos faltaría
Testing
Nos faltaría un poco visual
Porque dice
Actualizar las tarjetas mostradas
Visualmente tendríamos
Que arreglar alguna cosa
Lo haremos
Entonces
¿Queréis que hagamos
Una segunda parte
Donde hagamos
El testing
Donde hagamos
Refactor
Porque habría que
Refactorizar alguna cosa
Donde hagamos el despliegue
También
¿Vale?
Y yo creo que
Eso sería como 48 horas
Hacerlo en dos días
En dos horas
Hemos hecho toda la parte
De la implementación
Y en otro
Pues podemos hacer
Todo el tema del testing
Podemos hacer
El despliegue a producción
Podemos hacer refactor
Para ver
Mejores prácticas
De cómo manejar mejor esto
Componetización
Algún patrón de diseño
Para la parte de la API
Y cosas así
¿No?
En dos horas
No terminaste
Mal ahí
Joder
Pero si son 48
Y he hecho dos
Mientras lo explicaba
Y tal
He hecho lo que he podido
He hecho lo que he podido
Si nadie
Si nadie en la empresa
Te sigue
Se rayarán pensando
En por qué de repente
Les empieza a llegar
Un montón de soluciones iguales
Bueno
Puede ser
Puede ser
Os voy a contar
Una anécdota
Muy interesante
De que una vez
Esto es muy fuerte
Una vez hice una prueba técnica
También como estas que hago
Como explicando
Cómo solucionarla y tal
Y era de una empresa
Una empresa X
Y me escribió
Me escribió
Uno de la empresa
Super picado
Y me dijo
Como
Pues que sepas
Vi que hiciste esta prueba
Y que sepas
Que con esa solución
No te hubiera contratado
Sabes
Ahí yo
Bueno vale
Pues tampoco te cabréis
No sé
A ver
Obviamente
Hay muchas cosas mejorables
También son dos horas
Donde estoy explicando
Un montón de cosas
Pero yo creo que sería
Un punto de partida
Para continuar
Con todo mi cariño
De que
No sé
Creo que lo hemos intentado
Hacer lo mejor posible
Creo que está muy bien
El tema del monorepo
Multipaquetes
Es una cosa que no se ve mucho
Y que es una cosa
Que se usa mucho
En empresas de producción
Por ejemplo
La de Vintage
Usamos un montón
Y fijaos que la experiencia
De desarrollo
Mejora mucho
Y es justo lo que nos pedían
En la prueba