logo

midulive


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

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

Acaba de salir la quinta versión de Strapi, la nueva generación, dicen, de CMS.
Strapi es el CMS, yo creo que de los más conocidos que existen a día de hoy,
porque es de código abierto, porque se utiliza en un montón de sitios
y porque te permite hacer cosas maravillosas con muy poco.
Es como un WordPress, pero hipervitaminado, porque es que puedes crear tu propio WordPress.
Puedes crear tu propia colección de tipos, puedes crear restaurantes, puedes crear posts,
puedes crear videojuegos, puedes crear lo que quieras.
Nosotros, de hecho, vamos a intentar crear la tienda online de GitHub.
Vamos a crear la tienda donde vamos a tener categorías y vamos a tener productos
y vamos a tener también la posibilidad para que veáis, también se pueden tener tipos singulares.
Además de colecciones de productos, de categorías y todo esto,
también podéis utilizarlo para crear un blog o para crear páginas estáticas.
Y entonces lo que podéis hacer, imaginad que tenéis un cliente,
y esto está muy bien para temas freelance, por eso se utiliza un montón.
En el mundo freelance, porque los clientes te vienen y te dicen,
ah, es que tengo una página y me gustaría cambiarle el contenido.
Y puedes utilizar mil millones de historias.
Pero una de ellas, para que el cliente no te tenga que poner a tocar código fuente,
porque se le van a poner la vista así, pues podéis utilizar, por ejemplo, Strapi.
Y con Strapi podéis decir, vale, pues la página home te lo voy a crear
y tiene estos campos que puedes modificar.
Todo esto lo vamos a ver hoy, o sea, que no te preocupes.
Lo vamos a ver cómo lo podéis hacer.
Oye, de hecho, ¿por qué salgo aquí? Vale, me voy a mover, me voy a mover por acá,
me voy a mover por aquí y ya está.
Pues eso, todo eso lo vamos a ver hoy.
Cómo te genera la API, cómo podéis utilizarlo en un proyecto de Next.js,
eso lo vamos a ver paso a paso.
Cómo podéis filtrar datos, cómo podéis paginar, cómo podéis ordenar datos,
cómo podéis mejorar el rendimiento teniendo en cuenta que solo recuperáis
los campos que necesitáis.
Pues eso lo vamos a ver hoy.
Y también vais a ver cómo podéis generar una API, no solo de REST, sino también GraphQL.
Y es tan fácil que explota, es que explota.
O sea, es increíble, es increíble.
Pero antes, antes de empezar con Strapi, que es tremendo, que me gusta un montón.
Strapi, Strapi es la bomba.
Pero antes de darle cañita a Strapi, voy a recordar dos cosas.
Primero, os anuncio la fecha de la hackathon, la fecha de la hackathon.
Vamos a hacer una hackathon especial este mes con la gente de Claudinari.
Y vais a tener dos semanas para dar rienda suelta a vuestra imaginación
con unas reglas específicas que os diré la semana que viene.
El 8 de octubre, 8 de octubre, iniciamos la hackathon de Claudinari.
O sea, que el martes que viene, iniciamos la hackathon de Claudinari,
donde yo haré un pequeño desarrollo de ejemplo.
Y os explicaré cuáles son las reglas que tenéis que cumplir para participar.
Totalmente de código abierto.
Tenéis que utilizar servicios de Claudinari,
pero también hay que hacer unas cosas en concreto que os contaré.
¿Vale?
La semana que viene, el 8 de octubre, empieza la hackathon.
Y el 22 de octubre, termina la hackathon.
Y tenéis que entregar como máximo fecha límite 22 de octubre.
Y ojo, porque no os puedo contar los premios,
pero los premios, los premios, son espectaculares.
Son increíbles.
Son al nivel de los de Bersel,
pero es que además, no solo los ganadores van a tener premio,
sino que vamos a crear una camiseta exclusiva, única, para el evento,
donde el top, al menos 10, luego ya veremos,
pero el top 10, veremos si podemos conseguir más.
Pero vamos a hacer que los primeros, los que vamos a filtrar,
tengan esa camiseta exclusiva de la hackathon,
que estamos diseñando desde cero para todos ustedes.
Así que no solo vamos a tener premios,
premios monetarios, premios de créditos de Claudinari,
un montón de premios.
Vamos a tener premios, premios, premios.
Pero también vais a tener una camiseta exclusiva.
Empieza el 8.
Llegará hasta mi país tercermundista.
Oye, siempre que estamos haciendo premios y tal,
lo estamos llevando a todos los sitios.
Ya sea, hombre, tercermundista no sabría decir,
pero da igual dónde vivas, que estamos intentando hacerlo llegar.
Si es imposible porque resulta que vives en una isla remota,
pues, hombre, alguna cosa haremos para intentar que te llegue de alguna forma el premio.
¿Vale? O sea, que no te preocupes.
Ahí lo tenéis.
8 de octubre empezamos la hackathon la semana que viene
y termina el 22 de octubre.
El martes que viene estén atentos porque os contaré,
haremos un pequeño desarrollo que os servirá de base, si queréis.
Y luego también, pues, os contaré cuáles son las reglas que tenéis que cumplir.
Porque no es cualquier cosa.
No es cualquier cosa.
Y lo hacemos con la gente de Cloudinary.
Así que nada, muchas ganas, unas ganas tremendas,
unas ganas impresionantes de empezar 8 de octubre.
Ahí lo tenéis, ¿vale?
Muy bien.
Todavía tengo mis cosas de Cloudinary que regaló en la anterior hackathon.
Qué bueno, Hugo.
Es que la verdad, ¿puedo crear el evento de Discord?
Créalo, Ferad, lo puedes crear.
¿Midu has usado AppRite?
No lo he usado, pero tengo ganas de hacer algún día un curso desde cero
porque está bastante bien.
Acaba de salir la versión 5 de Strapi.
¿Strapi qué es?
Es un Headless CMS, CMS Content Management System.
¿Y qué significa Headless?
Headless significa que no te obliga a tener un frontend en concreto,
sino que tú este CMS te va a generar una API
y la vas a poder utilizar con un Next.js, lo puedes utilizar con un Astro,
con Naxx, con Ria, con Solid, con lo que te dé la gana, ¿vale?
O sea, es impresionante porque es...
O sea, lo puedes utilizar allá donde quieras.
Buenos días, señor Miduichat.
Gracias por este tutorial de QM.
Gracias a ti, Yare.
Pues entonces, cositas interesantes que tiene,
pues que es totalmente gratuito,
aunque luego veremos que si lo queréis desplegar, tenéis opciones.
Por ejemplo, lo podéis desplegar en un servidor tuyo, ¿vale?
Y es totalmente gratis.
Ahora, si quieres que Strapi utilice su cloud,
vas a tener que pagar como mínimo 29 dólares por proyecto,
que ya os digo yo que muchas veces para quitaros dobles de cabeza
lo vais a tener perfecto.
Ahora, tendréis otras alternativas como, por ejemplo, Render,
que si no me equivoco, si utilizáis la base de datos Skullite,
puede ser, puede ser que os pueda salir gratuito, puede ser.
Pero no lo tengo claro porque como tiene persistencia,
no sé si os costaría un poquito.
Pero también lo podríais desplegar con Render.
Hay un montón de opciones.
Con Fly.io también tenéis la opción.
Hay diferentes sitios en una VPS también.
O sea, tenéis un montón de posibilidades de dónde lo podéis hacer, ¿vale?
Y en cada uno de ellos, pues os saldrá un poquito diferente.
Pero bueno, ahí tendréis.
A ver si hoy nos da tiempo.
Y si no, no os preocupéis que lo veremos más adelante seguramente.
Entonces, ¿hoy qué vamos a hacer?
Mi idea es empezar una tienda online, ¿vale?
Obviamente no me da la vida de hacer la tienda online en menos de dos horas.
Que a mí me hace mucha gracia porque luego la gente...
Hombre, pero es que una tienda online...
A ver, que los directos son de menos de dos horas.
Que no me da la vida.
No me da la vida.
A ver qué haces tú trabajando dos horas, ¿eh?
Rata, rata.
Luego tú trabajas dos horas y le cambias el color de fondo al botón.
Y eso no lo pones en los comentarios de YouTube.
Que te veo.
A ver que te vea tu trabajo.
Me voy a meter en tu gira.
Te voy a controlar.
En fin.
Pues a ver.
Vamos a poner las bases.
Si veo que os gusta mucho, me gustaría continuar el desarrollo para llegar a poner integración de pagos con Stripe.
¿Vale?
Stripe.
No confundir con Stripe.
Es que se parece mucho.
Stripe es una infraestructura para pagos online.
Y podríamos añadirlo para que veáis cómo se podría hacer una tienda online con Stripe desde cero.
Que es lo que vamos a hacer.
Y luego integrarle Stripe para el tema de los pagos.
Que es verdad que Stripe no está disponible en algunos países de Latinoamérica.
Pero aún así se utiliza un montón.
¿Vale?
O sea que ahí lo tenéis.
Bueno.
Vamos a hacer la Github Shop desde cero con Stripe.
Os decía que acaba de salir la versión 5.
¿Y qué trae la versión 5 de Stripe?
¿Y qué tiene de interesante?
Bueno.
Pues la versión 5.
Acaba de salir una nueva Major.
Acaba.
O sea.
Está calentita.
Está calentísima.
Está calentísima.
¿Qué ha salido?
Bueno.
Tenemos cambios muy interesantes.
Lo primero.
Tenemos una nueva forma de ver el contenido que está en borrador.
Porque antes era un poco lioso el contenido en borrador.
El contenido publicado.
Os lo voy a enseñar ahora cuando lo añadamos.
Vais a ver cómo se diferencia mucho más fácilmente lo que es un contenido en borrador y publicado.
Y se puede ver fácilmente.
Luego Content History.
Esto lo que nos permite es tener un historial de todo el contenido de nuestro CMS.
O sea.
Si modificas algo.
Pues tendrías un historial de desde hace dos meses.
Que es lo que habías cambiado en ese momento.
Lo que has modificado.
Puedes volver atrás.
Es tremendo.
O sea.
Está muy bien.
Otra cosa que tenemos también.
Bueno.
TypeScript en esta nueva versión.
Pues lo están utilizando en todos los sitios.
Y significa que tenéis mejores tipos.
Menos errores.
Y todo esto.
Y además.
Y este es el notición.
Tenemos el empaquetador de Bit.
Que se está utilizando con Strapi 5.
Han pasado de Webpack a Bit.
Y esto se nota mucho.
Porque uno de los problemas históricos que tenía Strapi.
Es que no voy a decir que iba lento.
Pero que era bastante mejorable la velocidad que tenía.
Y conforme iba creciendo.
La verdad es que las builds tardaban bastante.
Bueno.
La nueva versión va volada.
Volada.
Gracias a que han pasado.
Han migrado a Bit.
Han mejorado la creación de plugins.
Hay algún breaking change.
Como este.
Bastante interesante.
Que han simplificado la respuesta de la API.
Esto lo vamos a ver.
Porque antes tenías que tener en el campo attributes.
Y tenías que acceder a attributes.
Bueno.
Pues ahora han puesto data.
Y una vez que han puesto data.
Ya tienes ahí todos los campos de tu CMS.
El contenido que tú hayas creado.
Lo tienes ahí directamente.
Antes era un poquito más complicado.
Ojo.
Porque esto es un breaking change importante.
Pero por suerte yo creo que era algo necesario.
Y que está bastante bien.
Bueno.
Pues ahí lo tenemos.
Vale.
Maravilloso.
Todas las mejoras.
Vamos a ello.
Vamos a ponernos para aquí.
Vamos a copiarnos esto.
Vale.
Y nos vamos a ir aquí.
Yo ya tengo aquí una carpeta que se llama curso Strapi.
Y como podéis ver.
Tengo una carpeta llamada web.
Donde ya he iniciado un proyecto de Next.js.
Porque a ver.
No va a ser un curso de Next.js.
Desde cero.
Va a ser un curso más de Strapi.
Pero lo vamos a integrar con un proyecto de Next.js.
Entonces.
Con Next.js.
Que sepáis.
Si vamos a nuestro proyecto de Next.js.
Que yo ya tengo unos estilos.
Unas páginas creadas.
Pero ahora mismo está vacío totalmente.
¿Vale?
O sea.
Ahora vais a ver.
¿Ves?
Title.
Description.
Show.
Categories.
Esto parece que está vacío.
Esto no funciona.
¿Esto qué es?
No os preocupéis.
Que a partir de aquí.
Vamos a ir.
Pues poco a poco construyendo.
Y vamos a ver ya.
Como podríamos utilizar el CMS.
Para que este title.
En lugar.
De tener que entrar en el código.
Y cambiar esta información.
Lo que vamos a hacer es utilizar el CMS.
Así que.
Vamos a tener aquí.
Igual que tenemos.
Una carpeta.
Mira.
Voy a dejar este.
Mira.
Voy a dejar esto.
Aquí abierto.
Con la web.
Y aquí.
Si eso.
Mira.
Lo dejamos justamente aquí.
Voy a volver para 3.
Y aquí.
¿Veis que tengo la web?
Pues aquí es donde vamos a ejecutar.
Este comando de Strapi.
¿Vale?
Para inicializar nuestro proyecto.
npx create strappy.
Arroba latest.
Aquí le podéis poner el nombre.
Pero se lo puedes quitar.
Solo con esto.
Ya te lo preguntará todo.
Y yo os voy a comentar.
Las cositas.
Que van a estar.
Comentando aquí.
¿Vale?
Dice.
Vale.
Proceder.
Sí.
Procedemos.
Esto instala todas las dependencias.
Para poder crear el proyecto de Strapi 5.
Importante.
Que ahora se hace con Strapi 5.
Hostia.
¿Qué ha pasado aquí?
Que dice.
Supporting engine.
Create strappy.
Ah.
Importante.
Importante.
Mira.
¿Ves?
Importante.
Aviso importante.
Tenéis que utilizar la versión 20 de Node.
No.
Menos mal.
Que me ha avisado con todo esto.
Me ha avisado con todo esto.
Y para estas cosas sirven.
El tema es.
Que me dice.
Este engine no se soporta.
Y es que es verdad.
Que aunque sea la última versión.
Tened en cuenta que la versión 22.
Todavía no está soportada.
La versión 22 de Node.
Y es.
Hay que tener en cuenta.
Que aunque es la última.
Aunque podéis ver.
Que es la última que han lanzado.
La realidad.
Es que no es la LTS.
La LTS.
Digamos que es la long term support.
La que se soporta durante más tiempo.
Y actualmente.
Es la 20.
Por lo tanto.
La 22.
Aunque.
Digamos que es la última.
No es la estable.
¿Vale?
Así que tened en cuenta eso.
Utilizad la versión 20.
¿Vale?
Y ahora sí.
Vamos a utilizarlo.
Y ahora no nos debería dar ningún problema.
Así que tened en cuenta esto.
Utilizad siempre que podáis la versión LTS.
Long term support.
Que es la versión estable.
Ya nos pregunta.
¿Cuál es el nombre de nuestro proyecto?
Le vamos a poner backend.
Le podéis poner backend.
Le podéis poner CMS.
Lo que queráis.
Pero lo cierto.
Es que no va a ser la web.
Va a ser toda la parte.
Que va a tener.
Yo creo que backend tiene sentido.
Porque aunque es verdad.
Que vamos a tener una parte visual.
Nos va a generar una API.
Es donde vamos a poder subir las imágenes.
Y todo esto.
¿Vale?
Entonces.
Voy a llamarle backend.
Porque nos creará la carpeta backend.
Y creo que tiene más sentido.
¿Vale?
Primera pregunta.
Ya.
Esto es súper importante.
Como veis.
Aquí nos dice.
Oye.
No hemos encontrado tus credenciales.
Para autentificación de Strapi.
Puedes crear una cuenta gratis.
En Strapi Cloud.
Y beneficiarte.
De hacer despliegues de tu proyecto.
Exclusivo.
Acceso exclusivo.
A un montón de sitios.
Y tal.
Y dice aquí.
Empieza un free trial.
De 14 días.
De dos semanas.
Esto es opcional.
¿Vale?
Cuidado.
Esto es opcional.
¿Veis?
Aquí le podéis dar.
A Skip.
Y os recomiendo.
Que le deis a Skip.
¿Por qué?
Porque para trabajar en local.
Esto no lo necesitáis.
No tiene sentido que iniciéis vuestros 14 días.
Hasta que no lo necesitéis.
Si el día de mañana.
Queréis desplegarlo.
¿Vale?
Pues hacéis lo de login.
Sing up.
Y ahí sí que.
Utilizáis los 14 días de trial.
Pero no los queméis así.
Si vais a empezar ahora.
A trabajar en local.
Porque no tendría ningún tipo de sentido.
Vais a perder la oportunidad.
Yo os diría.
Aquí le dais Skip.
Y ya está.
De hecho.
Esto es totalmente opcional.
No estáis obligados a hacer login.
Ni nada.
Strapi sigue siendo free.
Lo que pasa es que aquí te ofrece la posibilidad de utilizar Strapi Cloud para el despliegue.
Todo lo demás es totalmente gratis.
No hay ningún problema.
Pero si vais a trabajar en local.
No lo utilicéis.
Y el día de mañana cuando veníteis.
Entonces hacéis el login.
Y ahí os gastáis los 14 días.
¿Vale?
Skip.
Ahora.
¿Qué base de datos queréis utilizar por defecto?
Hay diferentes bases de datos que podéis utilizar en Strapi.
MySQL, PostgreSQL y SQLite.
Si no me equivoco son estos tres.
Creo que son estos tres que podéis hacer.
No me acuerdo si María debe.
Creo que no.
¿Se puede desplegar sin pagar ese servicio de despliegue?
Totalmente.
Lo podéis desplegar donde queráis.
En un VPS.
En un servidor propio.
En un montón de sitios.
Ahora.
¿Dónde no lo podéis desplegar?
En Vercel no se puede desplegar.
Mira.
SQLite, PostgreSQL y MySQL.
María no es compatible.
¿Vale?
No es compatible.
En este caso, en local, yo recomiendo SQLite.
Y de hecho, si vuestra aplicación es lo suficientemente pequeña, yo incluso recomendaría SQLite.
Siempre.
Porque es verdad que no, para escalabilidad no es lo mejor del mundo.
Pero si va a ser una aplicación que al final vas a tener 100, 500, 1000 usuarios, va sobrado.
Y te va a simplificar mucho la vida, el pricing y tal.
¿Por qué?
Porque el problema es que cuando lo desplegues, si necesitas un MySQL o un PostgreSQL, vas a necesitar ya pagar bastante más dinero.
Así que puedes empezar con SQLite y el día de mañana migrar a estas opciones en el caso de que te sea necesario.
Pero no empieces la casa por el tejado, que luego te vienen las facturas y dices, es que es muy caro, no sé qué.
Yo te recomiendo SQLite para empezar y sobre todo para toquetearlo.
MongoDB tampoco es compatible.
¿Vale?
¿Quieres empezar con una estructura de ejemplo?
Le voy a dar que sí, pero yo os recomiendo que si tenéis clara la idea, le digáis que no.
¿Vale?
Pero yo le voy a dar que sí para que así no lo veamos vacío.
Así que le digo que sí.
Vamos a empezar también con TypeScript.
Vamos a instalar las dependencias con NPM.
Aunque luego creo que lo vamos a instalar con PNPM, para que vaya un poco más rápido.
Inicializamos el repositorio de Git.
Y ya lo tenemos.
Ya está aquí creando la aplicación.
Está haciendo el NPM install.
Esto puede tardar un ratito.
Porque la verdad es que Strapi, quieras o no, tiene muchísimas, muchísimas dependencias.
Así que es totalmente normal.
SQL Server tampoco es compatible.
A ver, si digo que los que son compatibles es SQLite, PostgreSQL y MySQL, cualquiera que no sea uno de esos tres, no es compatible.
Es así de sencillo.
Entonces, por más que os guste o disguste, no va a ser compatible en ningún otro.
¿Vale?
Esto es lo que hay.
Voy a poner esto en modo oscuro, por cierto, que así se ve un poquito mejor.
Aquí lo tenéis.
SQLite, PostgreSQL y MySQL.
Esas son las tres.
Las podéis utilizar tanto en local como cuando desplegáis.
Y tenéis la posibilidad de poner toda la información de la conexión.
Por lo que sea.
Ya están instalando.
Perfecto.
Mientras esto instala, voy a ir cerrando.
Esto lo vamos a dejar.
Esto también.
De nuevo, recuerdo que lo del pricing es solo el Strapi Cloud, por si lo queréis desplegar.
No es necesario pagar y lo podéis desplegar en cualquier VPS que queráis, donde os dé la gana.
Vale.
Venga.
Ya está ahí.
De hecho, si vamos a nuestro Visual Studio Code, aquí tenemos la carpeta backend y aquí
veréis que ya nos ha creado un montón de archivos.
Tenemos aquí la configuración, tenemos aquí toda la data, tenemos la base de datos, tenemos
cosas públicas por aquí, que son los archivos públicos, los scripts.
Esto es por si queréis ejecutarlo para que os inicie ese template con todos los datos
como de prueba al principio.
Es opcional.
Yo os recomiendo que no lo hagáis, pero nosotros lo hacemos para que empecemos no desde cero.
¿Vale?
Aquí tenemos un montón de source.
Tened en cuenta que todos estos archivos que estáis viendo, que nos han creado, no
es necesario que los toquéis ni que los modifiquéis ni nada.
Porque a veces sí que podéis extender alguna funcionalidad, pero todo lo que veis aquí,
si os fijáis en config, son configuraciones que sí que podéis cambiar, por ejemplo, para
conexiones de base de datos y todo esto, pero que en realidad no hay nada de código que
en principio deberíais tocar, a no ser que queráis extender algún tipo de funcionalidad,
crear un plugin, un middleware o cositas así.
¿Vale?
O sea, que tened en cuenta que todo esto que veis aquí, como veis, es archivo vacío.
O sea, no son configuraciones, son más cosas de extensión, no tenéis, y nosotros de hecho
hoy no creo que toquemos ningún archivo del backend.
¿Por qué?
Porque ya nos viene preparado para que, mira, ya nos lo ha instalado y ya nos va a decir
por aquí que podemos, por ejemplo, inicializar Strapi en Watch Mode para que los cambios
que hagamos en el proyecto, pues, se vean reflejados y se reinicia.
De hecho, vamos a utilizar este en PN Run Develop, pero también podríais utilizar
en PN Run Start para que sea como modo producción, tendrías el de Deploy, que esto lo que haría
es intentar desplegarlo si estuvieseis en Strapi Cloud y todo esto.
Nosotros vamos a estar desarrollando, así que vamos a hacer en PN Run Develop,
Developer no, Develop, ¿vale?
Ah, a ver.
Ah, es que tengo que entrar en backend, tengo que entrar en backend, ahora sí, ¿vale?
Es que estaba fuera de la carpeta.
Vale, pues ahora esto está, vais a ver la diferencia.
Si has utilizado Strapi antes, te vas a dar cuenta que tarda bastante menos.
Uno de los problemas que tenía Strapi antiguamente es que esto te podía tardar
ya perfectamente 15 segundos y aquí ya veis que ha tardado 3,7 segundos,
o sea, va bastante, bastante más rápido.
Lo primero que vais a ver es que os va a pedir cómo tenéis que crear, pues, claro,
vuestro primer, vuestra información, ¿no?
Pues Miguel Ángel, Durán, vamos a poner aquí el email, vamos a poner miduga, arroba, gmail.com
y vamos a decirle aquí que nos sugiera una contraseña.
Tened en cuenta que esta contraseña como tal, ahora mismo, ahora mismo, no es importante
porque esto va a ser que va a estar ejecutándose en local.
Ahora bien, si por lo que sea la base de datos en local la queréis reutilizar cuando lo despleguéis,
tened en cuenta que estos passwords, todas las variables de entorno y todo esto,
que no se vean porque la podéis liar parda.
Pero si lo vais a utilizar en local, esta base de datos va a estar en local
y no vais a tener ningún problema.
Pero primero necesitáis una forma de autentificaros en el Content Management System
donde vais a administrar los contenidos de vuestra página web.
¿Vale? Así que aquí tendríamos ya todo esto.
¿Veis? Aquí tenemos la contraseña, que ahora mismo no pasa nada,
no estamos en base de datos, ¿vale?
Le decimos let's start, ¿vale? Perfecto.
Y ya hemos entrado en nuestro Content Management System.
Si has utilizado WordPress algún día, pues esto empezará a sonarte un poco.
Aquí, ¿qué tenemos? Bueno, una bienvenida y empezamos con los pasos.
Lo más importante de Strapi, y esto es para que te quede clarísimo,
Strapi es un Content Management System.
¿Esto qué es? Es un administrador de contenidos.
¿Qué contenido? El que te dé la gana, el que quieras.
Puede ser para una web de un restaurante, para una web de noticias de videojuegos,
puede ser un Twitter, puede ser lo que tú quieras.
De hecho, nosotros vamos a hacer una tienda, puede ser para un sitio de gatos,
para rescatar gatos. Podríais hacerlo, de perritos, lo que vosotros queráis.
Porque, como podéis ver, el primer paso es que hay que construir la estructura del contenido.
Entonces ya podemos ir al Content Type Builder y aquí nos dice,
oye, tendrías que crear tu primera colección.
Y dices, vale, pues quiero crear mi primera colección.
Ese es el primer paso.
Que tendríamos que decir, oye, ¿cuál es el tipo de colección que yo voy a tener?
Como veis aquí a la izquierda, ya hay algunos tipos,
pero esto es porque yo le he puesto que me ponga algunos tipos de ejemplo.
Nosotros no lo vamos a utilizar, pero ya me va bien para que veáis que se pueden crear un montón,
porque si no va a estar muy vacío, vais a decir, ostras, qué rollo, ¿no?
Pero quería que vieses que se puedan utilizar un montón.
Aquí ya nos está diciendo, oye, crea tu primer tipo de colección, ¿vale?
Entonces iríamos y tal. Puede ser lo que queramos.
Yo me lo voy a saltar y así os voy explicando.
Hay dos tipos, dos tipos de contenido.
Los que serían colecciones y los que serían single types.
Single type, como dice el nombre, solo puede haber uno.
Por lo tanto puede ser una página en concreto, la página home, por ejemplo.
Y de hecho vamos a empezar por ahí porque es interesante que tengamos ya nuestra página home, ¿no?
Que tenga datos.
Así que fijaos aquí que single types teníamos con la página about, la página global.
Y en about tiene un título, tiene bloques y cada uno de los bloques tenemos media, code, rich content, slider.
Y esto es una de las cosas más increíbles.
Es que tenéis un montón de tipos de datos que podéis utilizar.
Ahora lo veremos.
Pero que se pueden repetir, que se pueden agrupar, que se pueden relacionar.
Aquí, por ejemplo, en global, ¿qué tenéis?
Pues tendríais el nombre del sitio, el favicon, el site description, default SEO.
Y aquí la pregunta del millón que mucha gente se hace.
Bueno, pero ¿por qué haría esto aquí y no lo voy a hacer en el código?
De nuevo, piensa.
Si tú tienes un cliente, no le vas a pedir que modifique el código.
Le vas a decir, oye, vete a tu Strapi, inicia sesión y cambia los valores aquí.
¿Y qué es lo que haría el cliente?
Pues se iría aquí a Content Manager y en Content Manager tú le dices, oye, mira, en global tú puedes cambiar el nombre del sitio web, puedes cambiar aquí el favicon, la descripción del sitio, puedes cambiar el Open Graph Image.
Todo lo puedes cambiar aquí.
Y le das a Save y ya se cambia.
Y no tiene por qué tocar nada el código.
Y lo mejor de todo es que esto lo que hace es generar una API.
¿Que no te lo crees?
Vamos a verlo.
Mira, imagínate, en Content Type Builder os he dicho que teníamos por aquí esto.
¿Ves?
Tengo un title, tengo un description.
Pero este title y description podría ir a mano.
Yo podría ir a mano a la página.
Que sería un poco, a ver, ¿dónde he dejado el Visual Studio Code?
Aquí, vale.
Podría ir a mano a la página y donde hemos puesto el title, que si no me equivoco es el index.
No, el index este no, page.tsx, aquí.
¿Vale?
Tengo el componente giro.
Ahí está el componente giro.
Y yo aquí podría cambiar el title a mano.
Este title podría poner increíble tienda.
¿Vale?
Guardo los cambios.
Y aquí deberíamos ver increíble tienda.
Si todo ha ido bien.
Increíble tienda.
Vale, perfecto.
Pero claro, esto tendríamos que modificar el código.
O podríamos ir a un archivo más, un JSON y tal, pero tenemos que modificarlo.
Hacer un despliegue y todo esto.
Vamos a querer cambiar esta información sin necesidad de tocar el código.
Así que para eso, aquí, vamos a crear un nuevo tipo de contenido.
Y tiene que ser un single type.
Porque es una página en concreto.
En este caso vamos a llamarle que sería la home.
Fíjate que ya cuando has puesto el display name, ya me ha puesto la ID de la API.
Y también nos crea el plural.
Que en este caso no tiene mucho sentido porque home solo tenemos una.
Si vamos a Advanced Settings, aquí podéis ver que tenemos cosas interesantes.
Uno, Draft and Publish y Internacionalización.
Lo vamos a activar porque también te voy a enseñar cómo puedes hacer internacionalización muy rápidamente.
No me va a dar tiempo a hacer toda la página internacional, pero sí para que lo veas cómo se haría para que lo puedas hacer tú rápidamente.
Vale, pues le damos a continuar y con esto ahora nos dice, hey, necesito que me digas qué campos son los que tienen este tipo singular.
Le podemos decir, bueno, pues claro, la home que necesita un title, ¿vale?
Va a ser un short text, un texto corto, que por ejemplo son títulos básicos, nombres, enlaces.
En Advanced Settings podemos ponerle un valor por defecto, que no va a ser interesante, incluso un patrón de regex para asegurarnos que se valida correctamente, que el texto que pongamos pase este patrón es opcional.
Le decimos que es un campo requerido, que tiene que tener un, le podemos decir, contenido mínimo, bueno, pues como mínimo tiene que ser de cinco letras.
Si no, no funciona.
Si es un campo privado, en este caso no, porque queremos que se muestre la API y también si queremos que se pueda localizar este campo, ¿vale?
Entonces le vamos a decir que sí, que lo que queremos traducirlo, así que le vamos a dar a Finish y ya está.
Lo mismo ahora, tenemos el title, pero tendríamos que poner otro, ¿no?
Hemos visto que también teníamos una descripción justamente abajo.
Señor Midu, yo sé que acabas de decir que piense y que puede usarse para lo que uno quiera, pero igual pregunto,
he estado pensando en pasar un LMS que tengo en WordPress a Strapi, ¿es una buena idea?
Quiero desarrollar de cero el plugin.
Sí, a ver, es buena idea. Un LMS. ¿Qué es un LMS? ¿Qué es un LMS? Un sistema de gestión de aprendizaje. LMS, hostia.
Ah, Learning, claro, tiene sentido. Un Moodle, vale. Sí, tiene sentido. A ver, lo que pasa es que yo, si ya tuviese un WordPress preparado,
la verdad es que hacer una migración, buf, si estás empezando, pues sí, pero hacer toda la migración a mí me pondría, no sé, los pelos como escarpias, la verdad.
Pero sí, buena idea. Me parece que Strapi puede funcionar muy bien para hacer un estilo Moodle.
Vale, aquí tenemos texto, boleanos, texto enriquecido, JSON, números, emails, fechas, password, imágenes, archivos, vídeos, audios, listas de valores, relaciones,
identificadores únicos, texto enriquecido pero estilo Markdown, que yo siempre voy a recomendar el de bloques, luego veremos por qué.
Incluso puedes agrupar campos, puedes crear componentes que ya tenga los campos agrupados.
Por ejemplo, podrías crear un componente que siempre tenga, por ejemplo, un avatar. Un avatar puede tener el texto que sea el nombre del avatar, la imagen, porque es el avatar,
y eso, envolverlo en un componente, y aquí podrías decir, vale, quiero un componente que aquí justamente pueda elegir avatar, ¿vale?
En este caso, pues no lo vamos a hacer porque no lo necesitamos, pero, y también la zona dinámica que lo que te permite es que puedas añadir componentes conforme se edita el contenido,
que también es bastante poderoso. En este caso, con el title, que es un texto, y el texto enriquecido, que vamos a poner que es un bloque,
vamos a poner aquí que es description, le decimos que es requerido, que se tiene que localizar, ¿vale?
Y ya tendríamos aquí los dos campos que realmente teníamos aquí, y necesitamos un tercero, que es esta imagen de aquí.
Esta imagen de aquí, vamos a añadirla, le vamos a decir que es una imagen, y aquí le vamos a poner cover, ¿vale?
Le decimos que solo se puede subir un archivo, fijaos que puede subir más de uno o solo uno.
En Advanced Settings le decimos que solo queremos que se puedan subir imágenes, que sea requerido,
y que en este caso no le vamos a activar la localización, porque no tiene mucho sentido en este caso que se active la localización, ¿vale?
Así que title, description y cover.
Importantísimo, que esto me ha pasado así, así de veces.
Que no se os olvide que una vez que tenéis todo esto, no se guarda.
Tenéis que darle al botón Save.
A mí, sinceramente, no me gusta mucho el cómo está la UI para el Save, que está arriba a la derecha, ahí un botoncito pequeño.
Pero si no le dais, no se guarda y perdéis los cambios.
Entonces, acordaos de darle a Save.
Entonces, se va a reiniciar el servidor y ahora sí vamos a tener nuestro primer single type, que va a ser la página de la home.
Ahora que tenemos este tipo de contenido, tenemos que añadir el contenido.
Y para eso vamos al Content Manager.
En uno, el Content Type Builder sería para construir tipos de contenido.
Y en el Content Manager sería para administrar el contenido.
Aquí, vamos a ver que tenemos en Single Types, ahora tenemos la home.
Y vamos a poner aquí, pues yo qué sé, vamos a poner el Midu Shop.
¿Vale?
Como nos vamos a basar un poco a esto, vamos a poner aquí esta descripción.
Vamos a poner esta descripción aquí.
Y para que se vea favorito, vamos a poner Midu Gato.
Vamos a poner, para que no me denuncien por marca registrada, la Midu Shop.
¿Vale?
El Midu Gato lo voy a poner en negrita y la Midu Shop lo voy a poner en negrita.
Y vamos a poner esto que esté en cursiva.
¿Vale?
Al menos para que se note un poco que hemos tocado con texto enriquecido o algo.
¿Vale?
Y aquí podemos darle a Publish o a Save.
Podemos darle a Publish.
¿Vale?
Ah, y espérate.
Claro, me falta la cover.
Importante.
Sí.
Pero veis que ya tiene una validación porque esto era requerido y me dice, este valor
es requerido.
Por eso no me dejaba publicar.
Vale.
Pues vamos a guardar esta imagen mismo.
A ver si me la...
Ajá.
A ver si podemos robar esta imagen.
Robar no.
Tomar prestada.
Robar no se dice.
Está feo.
Vale.
A ver.
Mira.
Aquí veo que está la imagen.
Hostia, una forma rara, la verdad.
Esta imagen está un poco polémica ahí en medio.
Venga.
Guardar imagen.
Vale.
Y aquí vamos a...
Vamos a...
¿Ves?
Ya tengo algunos archivos.
Estos archivos no son míos.
Es porque yo al principio le he dicho que me ponga algunos archivos de
ejemplo.
Vale.
Vamos a poner esto por aquí.
Ya tenemos esta imagen.
La subimos.
Ya está seleccionada.
Le damos a finish.
Ahí se queda.
La publicamos.
Y ya estaría.
Fijaos en una cosa.
Aquí tengo ahora dos pestañas.
Esto es nuevo.
Tendríamos lo que sea publicado, que es lo que vería el usuario, y tendríamos la
parte de draft.
De esta forma lo publicado, ¿veis?
No se puede modificar.
Y el draft sí que lo podéis modificar.
Y hasta que no le dais a publicar, pues no se va a publicar.
No va a estar publicado.
Pero podéis guardar el draft para que, si queréis seguir en otro momento, pues el
draft, el borrador, se queda aquí.
Pero publicado hasta que no le deis a publicar, no aparece.
¿Vale?
O sea, es súper importante que tengáis esto clarísimo.
Porque si no, ¿qué es lo que pasa?
Que la gente dice, ostras, ¿por qué no se ven mis cambios?
¿Ve?
Ahora sí que se ven los cambios aquí.
New.
Laptop.
Sticker.
Vale.
Vamos a poner aquí el publish y tal.
Luego, también otra cosa.
¿Veis que aquí pone English?
Y le doy aquí y solo me parece en inglés.
Luego en las settings, lo veremos, podemos añadir tantos idiomas como queramos y podríamos
cambiar de activar la versión en inglés o en español y poner de cada uno su contenido.
Pero por ahora vamos a tener este para poder cambiar esto para que no quede así y empieza
a tomar un poco de forma.
¿Cómo tenemos que acceder a nuestra API con este contenido que tenemos nosotros?
Para poder acceder a la API, tendríamos que ir a la misma ruta barra API barra el nombre
del contenido, que en este caso sería home.
Pero vamos a encontrar un problema.
¿Vale?
¡Pum!
Forbidden error.
Y esto es porque Strapi, por defecto, es seguro.
Y entonces no te va a dejar utilizarlo si no le das permisos.
Puedes hacer un montón de formas los permisos.
¿Vale?
Vamos a hacer esto un poco más pequeño.
Pi, pi, pi, pi.
Nos vamos a settings.
A ver un poquito de magia.
Y aquí tendríamos overview, que aquí tenemos la información de cuál es la última
versión que tendríamos de Strapi, en qué plan estamos, si podemos customizar.
Esto lo podemos personalizar para que el iconito de aquí arriba a la izquierda se pueda ver
diferente y lo personalizamos para cada cliente y de forma que el cliente no tenga acceso
a estos settings para que no lo pueda cambiar él.
En API tokens, aquí podríamos cambiar el token.
Aquí esto es lo que vamos a modificar ahora, en un ratito.
Por ejemplo, tendríamos releases, que esto sí que está en la parte de pago.
O sea, esto no lo podéis hacer de forma gratuita.
Internacionalización.
Esto, por ejemplo, podemos añadir local.
Podemos decir, oye, quiero Spanish.
¿Vale?
Y vamos a decir que se muestre como español.
Y si este es el que es por defecto, no.
Le vamos a poner que sea false.
Lo guardamos.
Y ahora ya podríamos hacer el contenido, tanto en inglés como en español.
Bueno, en Media Library, aquí vamos a ver las preferencias para las imágenes que subimos.
Por ejemplo, si te hace autoorientación, si te va a optimizar las imágenes para que ocupen menos,
para que te genere diferentes formatos de la imagen.
De hecho, las imágenes que hemos subido ya, si vamos por aquí, bueno, claro, aquí vais a ver las que ya estaban anteriormente.
Pero vais a ver que ya tenemos algunas imágenes que se van subiendo de forma física a vuestro ordenador.
Digamos, o sea, no es que desaparecen.
De hecho, podéis resetear el servidor y vais a ver que las imágenes se mantienen ahí.
O sea, que van a persistir.
No van a desaparecer en ningún sitio.
¿Vale?
Luego tenemos el sistema de plugins instalados, que ahora mismo solo está Strapi Cloud.
Y el de roles y permisos.
Luego veremos otra cosa.
Tendríamos transfer tokens.
Esto es un poquito más avanzado.
Webhooks.
Esto es para notificar cambios.
Por ejemplo, que cuando hagáis un cambio en el contenido, podéis informar a un servicio externo.
Imaginad que queréis que cada vez que publique un contenido en este CMS, se haga un nuevo despliegue.
Por ejemplo, o que llegue un mensaje a Slack.
Pues esto lo harías con los webhooks.
Está bastante interesante.
Tendríamos los roles.
Podéis tener tantos roles como queráis.
Por ejemplo, podéis tener un superadministrador, que va a ser lo más típico, para que pueda cambiarlo todo.
Y uno que sea más a nivel de usuario para añadir el contenido, pero no pueda modificar los tipos de contenido.
¿Vale?
Así que solo vería menos iconitos y solo podría ir al del Content Manager.
Esto es una cosa que se hace mucho en WordPress, pero que aquí tiene especial sentido.
Los usuarios que tenemos.
Este soy yo.
¿Vale?
Tendríamos la configuración de email, porque también puede enviar emails para generar cuando creáis usuarios, para cuando hacéis una compra, se pueden hacer muy bien de cosas.
Y tenemos finalmente los permisos.
¿Vale?
Roles, autentificado, público.
Y aquí cada rol puede tener diferentes permisos.
Si, por ejemplo, puede leer, modificar y borrar cada uno de los tipos que hemos hecho.
También tenéis todo el tema de providers para iniciar sesión, porque también os lo da.
Y no solo podéis iniciar sesión con el email, como hemos visto, sino que podéis iniciar sesión casi que con un montón de servicios.
Con GitHub, con Google, con Instagram, con Microsoft, con LinkedIn, Twitch, Twitter y todo esto.
¿Vale?
Así que esto serían todas las cosas, pero queremos, podríamos cambiar el tema de los roles de permisos y hacer que la gente pública pueda acceder y pueda tirar de la API.
Por ejemplo, veis que aquí tenemos, por ejemplo, todo el contenido.
Y aquí tenemos Home.
¿Ves?
Aquí tendríamos, define todas las acciones que se pueden permitir con Home.
Y ahora mismo tenemos Delete, Find y Update.
Y están desactivadas.
Yo podría activar esto, guardarlo.
Y si no lo he hecho mal, deberíamos ser capaces ahora en el 1, 3, 7, API Home.
¿Ves?
Ahora tendría aquí la información de la Home.
Fijaos que esto antes no se podía acceder.
Pero lo ideal normalmente es que lo evitemos.
¿Vale?
Que le pongamos a 403.
Y lo que vamos a querer crear es tener un token de la API que vamos a tener que informar para que se utilice y así evitar que cualquier persona pueda tirar de la API y ver nuestros datos.
Esto depende un poco de cada caso de uso.
Pero yo os recomiendo que siempre que podáis tengáis un token y ahí digáis lo que puede y lo que no puede hacer.
Por ejemplo, aquí podemos poner Client.
Vamos a poner aquí ReadToken to allow web to render pages.
Por ejemplo, ¿vale?
La duración del token se la vamos a poner por siempre.
El tipo del token.
Aquí ya te dice si es personalizado para que vayamos uno a uno.
Acceso con total para que pueda borrar, eliminar.
Que este es un token que utilizaríamos obviamente en un backend si queremos borrar o modificar contenido.
O solo lectura, que es el que nos va a interesar a nosotros porque queremos que la web pueda leer todos los datos que tenemos.
Por ejemplo, en la Home, ¿ves?
Nos ha activado el Find.
Y en otros, pues veremos que nos habrá activado.
Podemos activar tanto que haga un Find de uno, o sea, un Find One o un Find All.
Para que los pueda encontrar todos o solo pueda encontrar uno.
Es bastante granular el tema de los permisos.
Pero ahora con este token vamos a guardar aquí.
Y aquí tenemos este token.
Este token, de nuevo, este token ahora mismo está en local.
O sea, ahora da igual que se vea porque nadie me va a poder hackear porque no tiene mucha historia.
Este token lo estoy yo teniendo en mi máquina local.
No es que todo el mundo lo puede ver y ya está.
Así que, eso sí, en el caso de que vayáis a desplegar los tokens, sí, por favor, guardadlos bien.
Vamos otra vez aquí en nuestro proyecto.
Y en la web voy a buscar, mira, aquí tengo en local.
Vamos a poner el Strapi.
Strapi token.
Token, ¿vale?
Lo ponemos por aquí.
Ahora veremos cómo lo tenemos que informar.
Y como Strapi host, que esto será lo que tenemos que cambiar cuando despleguemos.
Vamos a poner por ahora local 1, 2, 1, 3, 3, 7.
Una cosa que yo os recomiendo para probar rápidamente, para que no os volváis muy locos y tal, es que os creéis, especialmente cuando se trabaja en un Strapi, que tengáis aquí un archipo, por ejemplo, api.rest, utilizando la extensión de, ¿cómo se llama la extensión?
REST, REST, API REST, REST Client.
Esta extensión es una de las más antiguas y una de mis favoritas.
5 millones de descargas la avalan.
¿Qué es lo que hace?
Pues que tú puedes documentar aquí, puedes decir, vale, pues voy a hacer un GET de HTTP localhost 1, 2, 3, 7, barra API, barra home, ¿vale?
Y cuando hacen la request, pues aquí tendría la respuesta.
¿Ves?
Nos dan 403 porque no tenemos, no tenemos autorización.
Entonces le vamos a poner la cabecera de authorization, bidder y utilizamos aquí el token este que tenemos aquí, ¿vale?
Vamos a ver para ver si funciona correctamente, ¿vale?
Hacemos en request y ahora sí nos muestra la información.
Bueno, esto está bien para que lo documentéis, para que podáis hacer pruebas rápidamente y así ahora cuando tengamos que crear lo que es el código, pues ya lo tengáis bastante claro.
Así que ahora que ya tenemos acceso a esta API en nuestra página de Next.js, fijaos que tengo aquí el giro y ahora mismo tengo a mano el title, la descripción y la imagen.
Pues esto, en lugar de hacerlo aquí a mano, lo que vamos a hacer es crear unas utilidades para tirar de nuestra API de Strapi.
Vamos aquí en lib, yo ya tengo los archivos pero están vacíos para recuperar categorías, la información de la home, los productos y tengo aquí uno de Strapi que está totalmente vacío.
Lo que voy a hacer aquí, como para empezar con algo, me voy a crear una utilidad para preguntar siempre a la API de Strapi.
En lugar de estar repitiendo todo el rato el fetch con el token y todo esto, lo que voy a hacer aquí es recuperar el Strapi host y el Strapi, no sé si le llamo token o apiki, ¿cómo le llamo?
Token, vale. El token lo recuperamos del process.env y aquí vamos a exportar una función que le vamos a llamar query donde le pasamos la URL a la que queremos consultar.
Así que ahora ya podríamos tener el return fetch, ¿vale? Con el Strapi host que sería esta parte de aquí, Strapi host.
Aquí tendríamos que poner barra API barra la URL que le vamos a pasar y aquí entonces ya deberíamos pasar home, toda la información que queramos recuperar, ¿vale?
De los headers hemos visto que tenemos que pasar la autorización, authorization, utilizando Beader y pasarle el Strapi token, ¿vale?
Esto bien, cerramos y esto nos devuelve una promesa, así que devolvemos y la transformamos en un JSON.
Lo bueno de este método es que así nos vamos a tener que repetir esto constantemente, ¿vale?
Ahora, esta query vamos a ir a otra... Yo lo he dividido en archivos para que se vea más claro, pero lo podéis hacer todo en el mismo archivo, ¿vale?
Tengo aquí un método getHomeInfo, así que aquí vamos a importar la query, ¿vale?
Este es Strapi, export async function getHomeInfo y vamos a llamar a la query y le vamos a preguntar por la home, ¿vale?
Esta query es lo que hemos creado nosotros aquí, podríamos haber llamado de cualquier forma, pero le he llamado query porque creo que quedaba un poquito más corto, ¿vale?
Y aquí, pues le preguntamos a la query, podríamos esperar esto... Lo podéis hacer de dos formas, utilizando async o sin async, ¿vale?
Lo voy a hacer directamente con promesas y si veo que os da mucha rabia, entonces lo cambiamos.
Vamos a hacer un console.log.res y aquí devolvemos directamente la respuesta. Ahora lo mejoramos.
Pero con esto recuperaríamos la información de la home. Es exactamente lo mismo que hacemos aquí, ¿vale?
Solo que lo hemos dividido el código por una parte, la query, para no tener que repetir todo el rato la fetch.
Y aquí, lo único que le pasamos es esta parte de home, ¿vale? Y lo tenemos aquí, queryHome.
Y este home es el que llega aquí en esta parte de la URL.
Ahora, este método, getHomeInfo, nos vamos al giro y aquí vamos a poder preguntarle, getHomeInfo, const, homeInfo, ¿vale?
Await. Vale. A ver si me... ¿Por qué no me...? A ver. Que le pasa algo al... Ahora. Ahí está. Vale.
Cosas importantes. Lo que estáis viendo aquí es un React Server Component.
¿Qué quiere decir esto? Que este componente giro, si vamos a la página, fijaos que tenemos en la página home, en la página principal, tenemos el componente giro y el componente categories.
En Next.js, la última versión, todos los componentes son componentes de servidor o React Server Components por defecto, a no ser que tú pongas arriba Use Client.
Que eso lo tienes que hacer en el caso de que tengas un botón, que tengas algo que necesite la interacción del usuario, por ejemplo.
Entonces, por defecto, todos los componentes de React son componentes de servidor. Y lo bueno que tiene es que puedes hacer peticiones dentro del componente asíncronas como esta.
Por eso el componente es asíncrono y por eso podemos hacer esto de aquí. Y aquí ya tendríamos la información de la home.
Bueno, eso sí, vamos a ver que nos vamos a encontrar con unos cuantos problemas. Así que vamos a ver qué nos devuelve la consola.
¿Vale? Fijaos que en la consola ya tenemos aquí la data, tenemos el title, tenemos el description, pero el description es un poco raro porque es un objeto.
Esto lo vamos a ver ahora. Y también, si te fijas, no me está devolviendo la imagen.
La madre que la parió. Pero aquí no se ve la imagen por ningún sitio. Ahora vamos por partes. Vamos primero con el problema de la descripción.
Y vamos a ver. Este get home info podemos ver aquí que nos devuelve un objeto data y dentro tiene los campos que queremos.
Así que nos vamos a ir aquí al get home info. ¡Buah! Me encanta console ninja. ¡Qué pasada de extensiones console ninja!
Fijaos que aquí detecta automáticamente que el console log, lo que está devolviendo, y lo puedes ver aquí directamente a la consola.
Esto, si no te ahorra mil millones de horas, ya me dirás tú. Bueno, vamos a devolver directamente la data, que es lo que nos interesa.
¿Vale? Y ahora aquí ya deberíamos tener acceso tanto al title, la description y la imagen.
Y esto, que es lo que habíamos puesto a mano, ya lo podemos quitar. ¿Vale? Muy bien. Guardamos los cambios, nos vamos aquí y nos peta.
Porque nos dice que los objetos no son válidos en React. Y es porque, como hemos visto, la descripción me está devolviendo un objeto.
Es un poco raro esto. Así que por ahora voy a quitar la description, voy a ponerla aquí a mano, voy a poner description, description, y ahora te explico por qué pasa esto.
Entonces, vale, ya tengo aquí el title de MiduShop. Y lo bueno es que este title, conforme yo lo cambie en mi CMS, cuando el usuario diga, ostras, voy a ir al Content Manager, me voy a la Home y digo de MiduShop.
Best MiduShop in town. ¿Vale? Guardamos, publicamos. Puede ser que tarde unos segunditos, pero refrescamos. Vamos a ver si... Pues ya está.
Ya lo tenemos. Tardado unos segunditos, pero ahí tendríamos. Sin necesidad de desplegar o tocar código, ya estamos cambiando el título.
El título bien, pero ¿qué pasa con la descripción? El problema de la descripción es que si miramos los tipos del contenido, la descripción tiene esto, ¿no?
Que es un contenido enriquecido. Y lo que hace es que nos devuelve un objeto un poco raro. Que es difícil de que se pueda renderizar. ¿Vale?
Hacemos un console.log del description. ¿Ves? Y aquí tenemos. Tipo párrafo, children, texto, italic, true, no sé qué. O sea, nos da un JSON súper, súper complicado.
Por suerte, obviamente, la gente de Strapi tiene una forma de renderizar esto. ¿Vale?
Que es una dependencia que es esta de aquí, que se llama Strapi Blocks React Renderer.
Y esta dependencia te facilita un montón la vida. Es un componente de React que lo tienes que instalar, obviamente.
Así que vamos a instalarlo por aquí. Vamos a hacer en PM install.
Nos vamos a la misma carpeta que tenemos el proyecto web. ¿Vale? El proyecto web. Aquí.
Instalamos este componente en un momentito. Y esto nos va a permitir renderizar texto enriquecido de forma automática.
Tiene alguna peculiaridad que tienes que tener en cuenta. Pero ahora te mostraré. ¿Vale?
No sé si al final lo he instalado con PNPM o lo he instalado con NPM. Creo que con NPM.
Lo digo porque como tardaba tanto. Ah, igual sí que lo he instalado con PNPM. Igual sí que está esto instalado con PNPM.
¿Puede ser que la web la haya instalado con PNPM? Ahora veremos. Si no, no pasa nada. Que PNPM va mucho más rápido.
Sí, sí. PNPM es que va mucho más rápido. Vale. Ya ha instalado la dependencia. ¿Vale?
He puesto PNPM, pero si quieres utilizar NPM, pues NPM. El que tú prefieras.
Vale. Ahora que ya tenemos la dependencia. Vamos a reiniciar esto. Y vamos a ir al código.
Aquí en el código, este description, para renderizarlo, vamos a importar este componente blocksRenderer de Strapi.
BlocksRenderer. Y aquí donde teníamos la description, voy a ponerlo dentro de un div que tiene un poquito más de sentido.
Porque claro, si tiene el párrafo o la descripción, se va a volver loco.
Vamos a poner aquí el componente, blocksRenderer. Y el tema, bueno, en realidad aquí esto lo tenemos que poner así.
Aquí hay que decirle el contenido y es la description. ¿Vale? Description, blocksRenderer.
Y le cerramos aquí la etiqueta y ya está. Vamos a ver que se renderiza. Si vamos por aquí, aquí, no.
Aquí, ¿vale? Debería renderizarse. Vamos a ver. Ahora que tarda más. Ahora tarda más.
Bueno, ya veis que sí que tienen las itálicas, porque las itálicas sí que las está pillando bien, pero las negritas no.
Esto en realidad es por culpa de Tailwind. ¿Vale? Y es porque este div donde se está renderizando, Tailwind le estamos quitando todos los estilos
y tendríamos que indicarle aquí, por ejemplo, que dentro que tengamos un p, si hay un strong, entonces que tenga font bold.
Si no lo he puesto mal, deberíamos ver ahora por aquí. Vale, pues lo he puesto mal. Pero a ver si lo he hecho más o menos bien.
Ah, es que dentro del p, ah, pues sí que lo debería hacer bien, ¿no? Esto es así. Es así. ¿Vale? ¿Ves? Es como... Es así.
Esta es la etiqueta y luego le digo los estilos. ¿Vale? Ahora sí que deberíamos ver la negrita. ¿Vale? Ahí tenemos la negrita.
¿Qué tipo de proyecto será beneficioso usar Strapi en cuanto a escalabilidad?
Es que cualquier proyecto que necesites un content management system, te va a venir bien utilizar Strapi.
Porque si no, manejar contenido es demasiado tedioso. Y esto te simplifica con una interfaz visual el poder hacerlo todo.
Entonces creo que tiene mucho más sentido. ¿Por qué el rich text en modo class, en bloques y no en modo clásico?
El modo clásico te devuelve markdown. Y es un poco más rollo porque el markdown al final lo tienes que transformar.
El rich, lo bueno que tiene es que además de que el editor va mucho mejor que el de markdown, o sea, visualmente en el administrador,
además te devuelve un JSON que está mucho más optimizado para utilizarlo directamente con el componente.
Y ya te olvidas totalmente y ya está. ¿Vale?
¿Qué tipo de selector de Tailwind usaste? Es un selector custom en el que le estoy diciendo elemento actual para el hijo P y de los hijos, o sea, de los P, los hijos Strong,
los vamos a poner en negrita. Es como un custom selector para poder elegir elementos que están de dentro, que aunque no los veamos, realmente están ahí.
Y así podemos estirar los Strong que estarían dentro de los párrafos, aunque no los veamos. ¿Vale?
Muy bien, pues ahí lo tenemos.
Entonces, la imagen, si os dais cuenta, un problema que tenemos es que esta imagen, si miramos en el console.log, es undefined.
Undefined, cuando en realidad en la API nos lo debería devolver.
El problema de la imagen es que por defecto hay ciertos campos que la API de Strapi no te devuelve por temas de rendimiento.
Por ejemplo, la imagen.
Así que, si queremos que nos devuelva la imagen, lo podemos mirar en el REST API, por ejemplo aquí,
fijaos que aquí no me está devolviendo la imagen.
Tenemos un montón de información, el title, la descripción, cuándo se ha creado, bla, bla, un montón de información,
pero no está la imagen.
Si queremos que nos devuelva la imagen, tenemos que pedirle que nos haga un populate, decimos populate image.
¿Vale?
¿Y qué significa esto?
Pues es, oye, quiero que me devuelvas...
Ah, no es image, es cover, perdón.
Queremos que nos devuelvas los campos de title, description y tal.
Y quiero que el campo cover me devuelvas toda la información, porque claro, como podéis ver, el cover, que es la imagen que le hemos puesto con este nombre,
pues tiene un nombre, un texto alternativo, caption, tienes diferentes formatos, o sea que es bastante grande toda la información que te devuelve.
Por defecto, luego veremos cómo optimizarlo.
Pero veis, tenéis de formatos, tenéis un thumbnail, tenéis uno small, tenéis un medium, tenéis diferentes cosas, un montón de información,
que esto lo que hace es que la API pueda ir más lenta porque tiene que devolver más información.
Pero al menos ya sabiendo esto, con esto, ya podríamos volver aquí en nuestro home.
Le podemos pedir que haga el populate y aquí vamos a sacar el title, la descripción, el cover del rest data.
Pero el cover tenemos que transformarlo, tenemos que de alguna forma transformar y recuperar la URL de la imagen completa.
Porque ya hemos visto que nos lo está dando incompleto, solo nos está dando el path.
Así que tenemos que utilizar el Strapi, vamos a importar aquí, Strapi host, ¿vale?
Y con el Strapi host vamos a crear barra cover.url, ¿vale?
Y ahí tendríamos la imagen.
Devolvemos el title, title, description y el image, ¿vale?
Y ahora sí, si vamos al giro, deberíamos ser capaces de ver nuestra imagen, ¿vale?
O sea que ya tenemos, al menos esta, toda esta información ya la tenemos totalmente dinámica.
Saludos desde Colombia. Gracias por todo el contenido.
Miducrack menor que 3.
Un placer, amigo.
Esto es un contenido que digamos que es estático, pero de las colecciones,
como queremos hacer una tienda y no vamos a hacer solo la home,
necesitamos primero categorías de productos y luego los productos.
Así que vamos a crear un nuevo tipo de colección que le vamos a llamar Product Categories.
Importante, el Display Name hay que hacerlo en singular, ¿vale?
El Display Name siempre en singular.
Product Category.
En Advanced Settings esto lo dejamos igual, podríamos poner internacionalización,
pero bueno, eso lo dejaremos más a nivel de, no de toda la colección, sino de campos, ¿vale?
Vamos a darle a Continuum y aquí vamos a poner el Name de la categoría, vamos a poner Name,
vamos a poner que esto sea requerido, que tenga, ahí, le tenía que haber puesto que sí que fuese, perdón, ¿eh?
La he liado porque aquí este Product Category sí que tenemos que poner que tenga internacionalización,
que si no luego no me dejará, no me deja poner que tenga campos que tenga internacionalización, ¿vale?
Venga, vamos, Wait and Restart, vale, ahora, vale, Add New Field.
Venga, vamos a tener el nombre de la categoría, que esto es requerido, no vamos a decir,
podemos decir que sea único, pero bueno, puede haber categorías que se llaman igual,
así que nada, le decimos que Finish, otro campito.
Este sí que queremos un identificador único, así que vamos a utilizar Unique Identifier,
le podemos llamar Slack, por ejemplo, y aquí podemos decir Attach Field.
Bueno, podemos hacer que sea el Name, el Attach Field, o sea, que utilizando el nombre que tenga un Slack único,
puede ser, si no, pues se puede hacer que no tenga Attach, que sea requerido, ¿vale?
Vamos a terminarlo por aquí, vamos con más cositas, una descripción,
en este caso la descripción no hace falta que sea Rich, esto que nos simplifica un poco la vida,
así que vamos a poner que sea más larga, ya está, Description, que se pueda internacionalizar,
requerido, ¿vale? Y también una imagen, vamos a ponerle una imagen,
porque si vamos aquí, en el GIF Shopping, vamos a ver que aquí, ¿ves?
Vamos a intentar hacer esto, así que tiene que tener una imagen, vámonos para acá,
a por la imagen, le decimos que eso tenga una, y ponemos Image, ¿vale?
Requerido que solo pueda subir imágenes, y esto da igual que esté localizado,
siempre vamos a utilizar la misma imagen.
Guardamos, importante que no se nos escape, porque si no lo guardamos se nos escapa,
mientras voy a ir guardando esta imagen, me la voy a copiar, me la voy a robar,
esta imagen, la voy a prestar, la voy a pedir prestada, ¿vale?
Nos vamos por aquí, guardamos esta imagen, y así ahora en el Content Builder,
vamos a poder crear en el Content Manager, en Product Category,
vamos a crear una nueva entrada, y le decimos que es Shirts,
Product Category, bueno, podemos poner Shirts también, le podemos poner Descripción,
pues, The Best Shirts in Town, y le vamos a poner la imagen,
Add More Assets, y le subimos la nueva imagen que acabamos de subir, ¿vale?
Subimos, Finish, publicamos, y ya lo tenemos.
Y aquí, fijaos que ahora, cuando le doy aquí, veis que tengo English,
pero también tengo Create Spanish Locale, o sea, ahora sí que ha detectado
que tengo otro para crear.
Le podría dar, y aquí podríamos crear camisetas, Shirts,
y la descripción, las mejores camisetas del mundo,
y aquí podríamos utilizar la misma imagen, podríamos utilizar la otra.
Aquí es raro, porque la imagen, no le hemos dicho que se pueda, ¿vale?
O sea, que no se pueda, o sea, debería utilizar la misma,
pero bueno, no sé por qué me ha dejado utilizarlo,
no sé si es que se me ha olvidado añadirlo y tal,
pero debería utilizar la misma.
El tema es que ya tenemos aquí como las dos versiones publicadas,
esta sea en español, y esta sea en inglés.
Podemos ver que el nombre y la descripción nos cambia,
que esto es importante porque luego enseñaremos cómo lo podemos hacer.
Y ahora que tenemos al menos una, tenemos una, ¿vale?
A ver, Product Category, ¿vale?
Aquí tenemos Product Category, Create Etat, ¿vale?
Con el name, ¿vale?
Ahora que tenemos una, lo que podemos hacer es renderizarla.
Así que nos vamos a ir aquí, vamos a volver a nuestro proyecto,
voy a cerrarlo todo para volver a empezar.
¿Y dónde lo vamos a renderizar?
Lo vamos a renderizar en el componente Categories.
Este componente Categories, ahora mismo, recibe un array vacío,
y si tiene categorías, la renderiza aquí con un map y tal, ¿no?
Obviamente, si no tiene ninguna categoría, pues no muestra absolutamente nada,
y es aquí donde vamos a tener que pedirle a nuestra API
que devuelva la información.
Para asegurarnos que podemos hacerlo, de nuevo, vamos a la API REST,
vamos a ver, vamos a copiar esto, la petición,
y aquí vamos a poner Category.
Vamos a ver si esto nos lo devuelve, ¿vale?
No dice no found, porque esto creo que sí que es en plural, ¿vale?
Vale, validation, el cover este está mal.
Por eso es importante estas cosas.
¿Veis? Categories.
Y aquí me está devolviendo, ¿vale?
Ah, Categories, pero yo no quiero esto, quiero Product Categories.
Categories, ¿vale?
Ahora no es el...
Ah, es que, ojo que esto no utiliza camelCase, tiene sentido.
Esto utiliza kebabCase, ¿vale?
Ahí lo tenemos.
Esta es la categoría.
Fijaos una cosa muy importante que luego en la paginación lo vamos a ver.
Tenemos por un lado la data y por otro lado tenemos la paginación,
que tenemos información como de metadatos para saber en qué página estamos,
el tamaño de la página, cuántos resultados tenemos en la página
y cuántos hay en total, ¿vale?
Entonces tenemos los datos y los metadatos, que esto los utilizaremos justamente después.
Y aquí ya podemos ver que de nuevo nos falta la imagen, así que vamos a utilizar aquí el populate,
creo que hemos puesto image, así que le damos aquí, ¿ves?
Y aquí tenemos la imagen con todos los datos y tal.
Ahora, para optimizar los datos, una cosa que es interesante es que a veces no queremos todos los datos.
Por ejemplo, aquí me devuelve el create etat, el update etat, el publish etat, o sea, demasiados datos.
Podemos utilizar, gracias a Strapi, ya te viene con un sistema de filtrado, de orden, de un montón de cosas
para que pueda filtrar y optimizar estos datos.
Por ejemplo, le podrías decir, no, es que solo quiero el campo del nombre, ¿vale?
Y fíjate, claro, ahora porque le he puesto el populate, pero si le quito el populate, para que lo veamos más claro,
fíjate que ahora solo me devuelve el nombre.
Si le dices que de los campos que quieres devolver solo es el nombre, por defecto te los devuelve todos,
pero le puedes decir, no, quiero que fills solo me devuelvas el nombre.
Y esto obviamente hace que la API vaya mucho más rápido.
Pero hay veces que quieres que te devuelva más de uno.
Bueno, imagínate que quieres, pues no solo quieres el name, sino que también quieres el slack, obviamente.
El slack y también queremos, de fills, queremos la descripción.
Pero todos los demás nos da igual, porque no nos importa.
Pues podemos hacer esto, el campo 0 que sea el nombre, el 1 que sea el slack, el 2 que sea la descripción.
Pero todos los demás los está ignorando.
Y esto lo que te permite es intentar optimizar las peticiones de tu API sin necesidad de escribir ni una línea de código.
O sea, esto ya lo tendrías hecho.
Ahora, para el populate, también, si ponemos populate de la image, para recuperar toda la información de la imagen,
no sé si se verá, me imagino que sé, ¿no?
Pero bueno, fíjate que tenemos aquí los campos, pero la imagen te devuelve todo el churraco ahí de información,
con además los formatos, un array y tal.
Esto también se puede optimizar.
Y para hacer eso, lo que podéis hacer en el populate, le podéis decir, oye, quiero que me hagas un populate de la imagen
y de los campos, el único que quiero que me saques sea el de la URL.
Y así, con este cambio, fíjate que ahora devuelve mucha menos información.
Aquí en el image, ahora tenemos solo la URL, que es justamente la parte que nos interesa.
En lugar de devolver toda la API, todos los datos, con unos pocos de query params que hagas ahí,
ya te va a estar filtrando un montón los datos, que está mucho mejor.
El churrasco, efectivamente, ¿no?
Así que esta es una de las mejores cosas que tiene Strapi, que es lo potente que tendríamos las queries estas,
que en un momento puedes hacer verdaderas maravillas.
Y ahora que ya tenemos el endpoint que queremos utilizar, nos vamos a ir aquí a la librería,
tendríamos el getCategories y vamos a crear aquí un, vamos a importar la query,
que es el método que hemos creado antes.
Vamos a traernos el Strapi host para la imagen, ¿vale?
ProcessEnf y vamos a exportar una función que sea getCategories,
que podríamos decir que sea asíncrona, pero bueno, da igual.
Y aquí vamos a hacer returnQuery, le pasamos todo el churro que he creado,
que esto es lo que nos va a pedir, y aquí tendríamos la respuesta,
y cuando tenemos la respuesta, aquí ya la podíamos mapear, ¿vale?
Teníamos en el data lo que nos importaba, en el meta, los metadatos,
así que vamos a devolver del data un mapeo, donde vamos a tener la categoría.
Ah, y esto me sobra, ¿eh? Esto me sobra, con razón se ve irregular.
Vale, tendríamos que mapear todos los datos, total, podemos sacar el name, el slack,
el description y la imagen de cada categoría.
La imagen la vamos a renombrar a rowImage,
y de esta forma vamos a poder crear la imagen que realmente queremos devolver
utilizando el Strapi host, que será el localhost1337,
que eso cambiará, como es una variable de entorno, si lo tenéis desplegado,
pues tendréis la URL definitiva,
y aquí sacamos la URL de la imagen, que sería como el path, ¿vale?
Y ya lo podemos devolver, el name, el slack, el description y el image.
Este getCategories, nos vamos a ir a categories,
y vamos, en lugar de tener un array vacío,
hacemos una wait, llamamos al getCategories,
esto, lo importamos,
y volvemos a nuestra home, a ver si le ha gustado.
Vale, pues ya tenemos aquí,
hostia, no sé por qué esto le ha pasado a esto,
todas las categorías.
Bueno, también es verdad que esto diría,
tendría que estar en inglés,
pero no sé por qué sale con error.
Vale, ahora, cada vez que nosotros automáticamente
añadimos una nueva categoría,
lo que deberíamos ver es que aparece aquí.
También es verdad que he puesto aquí en shares,
o sea, he puesto el nombre ahí directamente,
aquí, que tendría mejor que haberlo puesto en mayúscula y tal.
A ver aquí, created that.
Ah, que por cierto, una cosa interesante,
una cosa que está muy chula de Strapi,
fijaos que aquí en product category,
tenemos la ID, created that, updated that,
y es un poco raro cómo se ve.
Pero le podéis dar aquí, a este botoncito,
como para configure view,
y le puedes decir qué es lo que quieres que aparezca aquí.
Entonces, le puedes quitar los campos,
y así le puedes decir,
ostras, tiene sentido que se vea el nombre,
quitamos el update that,
puedes poner la imagen incluso,
para que se vea la imagen,
puedes poner la ID, la descripción,
puedes quitar, yo qué sé,
podrías quitar lo que quieras,
esto es como lo más interesante,
y entonces queda mucho mejor.
O sea, tú puedes determinar de cada content type
cuál es la vista que vas a tener en la tabla,
y esto es increíblemente poderoso,
porque al final lo tienes aquí,
y puedes ver la información que realmente te interesa.
Esto lo podemos hacer también para el segundo,
podríamos poner, pues otro,
vamos a poner otro que es stickers, ¿vale?
Pues podríamos tener aquí, pues los stickers,
que estos sean los stickers,
tenemos que tener el nombre stickers for your laptop.
Y lo mejor de esto, que es lo más interesante,
es que automáticamente,
cada vez que añadáis una nueva categoría,
vais a encontrar,
esto hacemos una imagen,
vamos por aquí,
y aquí le subimos esta imagen,
more assets,
subimos esta imagen,
la actualizamos, borramos,
publicamos, ¿vale?
Y ahora, si nos vamos a nuestro proyecto,
y refrescamos,
tarda un poquito,
ya lo tenemos.
Esto,
esta es la maravilla de Strapi.
Tienes el contenido totalmente separado
de tu página web,
y cualquier usuario puede añadir contenido,
y conforme va añadiendo contenido,
va a aparecer la página web de forma mágica,
¿vale?
Sin necesidad de hacer otro despliegue,
porque es la API la que la tienes totalmente separada
de tu página web,
la página web no la tienes que desplegar,
no tienes que hacer absolutamente nada.
Ahora, obviamente,
cada categoría tendría que tener sus elementos,
igual que vamos aquí en Shop All,
si vas a Shirts,
¿vale?
Pues vamos a ver que tenemos las camisetas,
pues esto tiene,
pues además deberíamos tener diferentes filtros,
esto también se puede hacer con Strapi,
perfectamente,
y además cada uno,
pues tiene sus colores,
tiene su precio,
tiene su stock,
tiene todo esto,
pues lo podemos hacer.
Así que voy a preguntaros,
a ver si lo tenéis claro.
¿Midus y las camisetas tienen categoría camisetas
y también pudieran tener varias marcas,
¿cómo podría hacerse?
Se puede hacer que tenga más de uno,
podrías crear Content Type,
de hecho ahora lo vamos a ver con el tema de las relaciones,
el tema es que podrías tener un Content Type
que fuese marcas,
y puedes hacer que un producto sea de diferentes marcas,
o que una marca tenga diferentes productos,
depende totalmente de,
de el estilo de tu página web,
o sea,
depende de las relaciones que tengas,
se pueden hacer relaciones,
lo vas a ver ahora mismo.
¿Te faltó WTF8 en HTML?
No creo que me haya faltado,
porque en NextEyes lo debería poner por defecto,
o sea,
que yo creo que el tema es,
¿cómo harías un filtro de categorías?
Ahora lo vamos a ver,
porque justamente cuando entremos a una categoría,
¿vale?
O sea,
deberíamos poder entrar a una categoría
y ver los productos,
entonces,
¿qué vamos a hacer?
Vamos a crear ahora,
en el Content Type,
vamos al Content Type Builder,
y vamos a tener Collection Types,
vamos a tener un nuevo tipo de colección,
que va a ser Product,
¿vale?
Los productos,
vamos a poder internacionalizar,
¿vale?
Y de los productos,
¿cuáles son los campos que queremos que tenga?
Bueno,
obviamente los productos deberían tener más campos,
¿no?
Por ejemplo,
tendríamos que tener el Name,
un nombre,
¿vale?
Que esto sí que debería ser requerido,
bueno,
no tiene por qué ser único,
lo añadimos,
podríamos tener el Slack,
obviamente,
Slack,
esto tiene que ser requerido,
podemos añadir a otro,
si,
por ejemplo,
para que veáis,
si está activo,
si ese producto debe aparecer o no,
podéis poder y filtrar por este,
¿vale?
Si está activo,
y podéis poner que por defecto,
está activo,
¿vale?
Otro campo,
podríamos poner el precio,
y esto sería un número,
y el precio,
además,
podéis decir que el formato sea decimal,
¿vale?
Pues ya lo tendríamos,
que sea requerido,
otro campo,
la categoría,
este es interesante,
una relación,
¿vale?
El tema es que cuando hacemos relaciones,
podemos relacionar,
en este caso,
por ejemplo,
podemos llamarle Product Category,
Product Category,
¿vale?
Podemos relacionar diferentes colecciones entre sí,
y depende de la relación que tendrá,
podremos hacer diferentes filtros,
en este caso podemos decirle,
bueno,
aquí ha puesto Article,
pero debemos elegir Product Category,
y aquí en el Product Category,
podríamos decirle,
un producto tiene un Product Category,
un producto tiene y pertenece a una Product Category,
un producto pertenece a diferentes Product Categories,
en este caso,
podríamos decir este,
Product Category tiene diferentes productos,
¿vale?
¿Por qué?
Porque tiene diferentes productos,
o sea,
o podemos decir que un Product,
bueno,
no,
este es el que vamos a hacer,
vamos a hacer que un Product Category tiene diferentes productos,
o sea,
los productos al final,
vamos a hacer,
podría ser diferente,
podría un producto ser de más de una categoría,
lo podríamos hacer,
en nuestro caso vamos a entender que un producto solo puede estar en una categoría,
pero obviamente la categoría Camisetas puede tener diferentes productos,
así que aquí tenemos que hay diferentes relaciones que podríamos hacer,
y dependiendo de la relación que elijamos,
a la hora de filtrar será diferente,
en este caso lo vamos a hacer aquí,
que una categoría de producto tiene diferentes productos,
¿vale?
y lo vamos a añadir,
añadimos este,
vamos a poner otro que podría ser la Description,
Description,
no sé si poner,
vamos a poner en Rich Text otra vez,
Description,
vamos a poner otro campo,
podríais poner el color,
que puede ser una lista,
podríamos tener que esto pueda ser rojo,
negro,
blanco,
gris,
lo que sea,
podéis poner países,
podéis poner lo que queráis,
como enumeración,
y que tengáis que elegir uno en concreto,
obviamente necesitamos imágenes,
pero el tema de los productos,
es que hay más de una imagen,
¿no?
entonces tendría que ser Images,
porque a lo mejor queremos hacer un Slider,
entonces podemos elegir múltiples,
eso sí,
siempre acordaos de aquí,
evitar que si solo salen imágenes,
no permitáis que se puedan subir vídeos,
porque si no,
la podemos liar,
¿vale?
y el Stock,
por ejemplo,
que también podría ser un número,
podemos poner aquí el Stock,
y decir,
bueno,
en este caso es un entero,
y ya está,
vamos a poner que como mínimo tendríamos uno,
que es requerido,
y ya está,
este no tiene localización,
y ya tendríamos todos los campos,
podríamos hacer más campos,
podríamos hacer muy millones de historias,
pero bueno,
solo para que tengamos aquí un ejemplo,
de todos los campos que podemos hacer,
para los productos,
vale,
voy a seleccionar,
pues,
mis camisetas favoritas,
esta me la,
me la conseguí hace poco,
esta me gusta también mucho,
y mi camiseta favorita es esta,
vamos a añadir rápidamente,
tres camisetas,
para que tengamos tres productos,
vamos por aquí,
y así veremos como creamos estos productos,
de nuevo tenemos el Content Manager,
ay,
ay,
me muero,
menos mal,
mira un mail que me ha avisado,
siempre,
siempre,
recordad,
que tenéis que darle al save,
porque como salgáis de la página,
sin darle al save,
perdéis todos los cambios,
y da una rabia,
que no te lo puedes ni imaginar,
así que menos mal,
que tiene este,
este chequeo,
para que si vas a salir de la página,
te avisa,
Dios,
Dios,
porque si no,
vamos,
me tiro los pelos,
bueno,
aquí tenemos ahora el Collection Type,
que es el producto,
y ahora aquí,
pues,
creamos,
podemos decir,
cuál,
a ver,
era este,
Copilot Shirt,
bueno,
podemos llamar Copilot directamente,
Copilot,
el Slack,
vamos a poner Copilot Shirt,
vamos a estar activo,
le ponemos el precio,
25.00,
la categoría,
pues veis,
aquí nos aparece,
qué categorías tenemos,
porque es una relación,
y como hemos creado,
tanto camisetas,
como stickers,
pues ahora,
elegimos que son Shirts,
vale,
y aquí,
en la descripción,
pues le podemos poner,
esta descripción que tenemos por aquí,
esta descripción,
tu, tu, tu, tu, tu, tu, tu,
vale,
esta descripción por aquí,
que, bueno,
la podemos hacer en negrita,
lo que sea,
color,
vamos a poner que sea de color negro,
tenemos 100 de stock,
en imágenes,
vamos a cargar esta imagen,
ah, mirad,
podemos descargarla tal cual,
perfecto,
así que esta imagen,
se supone que se puede hacer drag and drop,
perfecto,
vale,
es que además,
fijaos que rápido,
en la UI,
puedes crear un elemento,
publicarlo,
que ya esté disponible,
que ya te aparezca,
o sea,
es tremendo,
a ver,
vale,
me la he creado aquí,
de nuevo,
esto lo podríamos modificar,
para que se vea la información,
que a nosotros nos interesa,
por ejemplo,
fijaos que aquí,
no aparece la imagen,
le damos aquí,
y digo,
oh,
me gustaría que aparezca,
la imagen,
y el stock,
porque son dos campos importantes para mí,
vale,
pues ahí tenemos el stock,
y la imagen,
tremendo,
además esto,
puedes hacer que,
que desaparezca,
se puede hacer que desaparezca,
para que el usuario,
no lo pueda cambiar,
y así luego no tengas que,
porque si el cliente,
se pone a tocar cositas,
a veces,
ay,
es que ahora no veo esta información,
por favor,
bueno,
pues eso lo puedes,
lo puedes evitar,
lo puedes evitar también,
vale,
32.95,
la categoría es de shirts,
y le ponemos esta descripción,
obviamente,
aquí podríamos estar,
todo el día,
para poner,
todos los campos,
que necesitamos,
para nuestro,
nuestras camisetas,
o sea,
es que le falta un montón de cosas,
pero realmente,
podríamos llegar a hacer,
que tenga un montón de cosas,
de hecho,
podríamos hacer,
que cada tamaño,
de camiseta,
tenga un stock diferente,
porque al final,
como hemos visto,
en los collection types,
podemos hacer,
como agrupar,
entonces,
podríamos agrupar,
que cada uno de los tamaños,
pues que sea un componente,
que además sea un array,
en el que tengas,
diferentes tamaños,
y cada tamaño tenga un stock,
todo eso lo podemos hacer,
pero obviamente,
estaríamos demasiado tiempo,
para hacerlo,
lo mejor,
es que pruebes,
que te pongas ahí a juguetear,
vas a ver,
que es muy,
muy fácil,
de hacer cositas,
y cuando le pilles,
un poco la tónica,
o te equivoques,
unas cuantas veces,
lo vas a ver,
mucho,
mucho más claro,
vale,
InvertoCat,
vamos a ver,
InvertoCat,
esta es mi camiseta favorita,
sin ninguna duda,
de GitHub,
de hecho,
no la llevo ahora,
pero la,
la llevaba,
esta mañana,
pero es que el gatillo,
el gatillo,
me la ha dejado hecha polvo,
vale,
le ponemos el color,
que aquí vamos a decir que sea negra,
vamos a poner un stock de 25,
vamos a subir aquí esta imagen,
y ya está,
estos son los tres que vamos a hacer,
vale,
y vamos a ver cómo se filtra por categoría,
vamos a publicar,
y ya tendríamos aquí,
los tres,
los tres productos,
vale,
entonces,
volvemos otra vez,
un poco con la idea que teníamos antes,
ya tenemos los tres productos,
que puedes verlos aquí,
que bueno,
veo que el producto,
hostia,
no me ha guardado,
no me ha guardado el,
no sé si lo he enseñado,
pero esto debería quedarse por aquí,
vale,
configure this view,
vale,
ah,
es que,
claro,
para guardarlo,
lo tienes que poner aquí,
vale,
lo tienes que guardar aquí,
si no,
no se guarda,
aquí es donde tendríamos que hacer los cambios,
para que siempre se vea,
porque si no,
cuando vuelves,
ya no aparece,
pero para cambiarlo del todo,
aquí en configure the view,
lo tendrías que hacer aquí,
y entonces,
sí que se guardaría del todo,
¿sabes?
O sea,
aquí sí que podrías poner los campos que quieres que se vean,
le das a save,
y entonces,
por defecto,
esos serían los campos que se ven en la tabla,
¿vale?
Pues,
para asegurarnos que todo se ve,
y que todo funciona correctamente,
lo mejor es,
ir a esto del API REST,
vamos a copiarnos esto,
y volvemos a hacer un poco esto de los productos,
por ejemplo,
para ver todos los productos,
vale,
pues,
teníamos barra products,
vamos a hacer la request,
y aquí ya tendríamos los productos que hemos visto,
obviamente los productos los queremos filtrar por categoría,
claro,
ahora mismo,
a ver,
voy a hacer,
en un momento voy a añadir un sticker,
más que nada para que veamos que realmente se está filtrando,
porque si no,
parece que no filtramos,
y es un poco raro,
entonces,
voy a filtrar,
voy a poner el AutoCAD este,
Mon AutoCAD,
AutoCAD,
Sticker,
¿vale?
El precio es 5,00,
la categoría en este caso es Stickers,
y así,
así filtraremos por categoría,
para que veáis cómo funciona el tema de la categoría,
¿vale?
Para cuando hagáis vuestra tiendecita,
vamos a poner que este tiene un montón,
pues,
un sticker,
total,
tenemos 10.000 millones de stickers,
venga,
añadimos este,
y publicamos,
¿vale?
Entonces,
si volvemos aquí a nuestro proyecto,
y hacemos Send Request,
veremos aquí que tenemos la camiseta,
la camiseta,
la camiseta,
y eventualmente,
tenemos el sticker,
¿vale?
Aquí está el sticker,
aquí está el sticker,
¿ves?
Sticker Pack,
de tu favorito,
Mon AutoCAD,
bla, bla, bla,
o sea,
que aparece el sticker,
queremos filtrar por categoría,
así que,
tenemos que aprender cómo funcionan los filtros,
para filtrar,
utilizamos los query params,
y le decimos,
queremos filtrar,
y le decimos el campo por el que queremos filtrar,
en este caso,
sería Product Category,
Product Category,
¿por qué?
Porque es la relación que hemos creado,
¿veis aquí?
Product Category,
cuando hemos creado el Collection Type,
hemos tenido esa ocasión de relacionar,
y ahora que hemos relacionado,
ya podríamos acceder a los campos,
de la categoría del producto,
o sea,
que si vamos a Product Category,
tendríamos por aquí,
por ejemplo,
vamos a mirar,
voy a filtrar este mejor,
porque me pone un poco nervioso,
que no nos aparezca,
¿ves?
Esto no tiene sentido,
tampoco,
tampoco,
vale,
vale,
vamos para atrás,
pues,
tenemos el Slack,
que hemos dicho que es un identificador único,
así que,
por ejemplo,
si quiero filtrar por Shirts,
vamos a utilizar el Slack,
así que le decimos,
vale,
fíltrame,
por el campo Product Category,
y del Product Category,
me filtras por el Slack,
y tiene que ser que contenga,
el de Shirts,
vale,
así que ahora,
me debería devolver,
solo aquellos que sean Shirts,
que sean camisetas,
lo mismo,
si aquí ponemos Stickers,
solo me debería devolver uno,
que es este de aquí,
¿ves?
Solo me devuelve uno,
porque este está,
en la categoría de Stickers,
solo me devuelve uno,
si le pongo Shirts,
me debería devolver tres,
así que damos aquí,
y ¿ves?
Ahora me devuelven más,
porque me está devolviendo las camisetas,
ahora que ya sabemos esto,
pues nada,
ya tenemos trabajo hecho,
para nuestra tienda,
vamos a abrir esto,
Get Products,
y aquí volvemos a hacer un poco,
lo mismo que hemos hecho antes,
importamos la query,
para no repetir,
el Strapi Host,
para crear la imagen,
esto lo podemos haber extraído a una función,
y ser felices,
pero bueno,
total,
no pasa nada,
porque repitamos un poquito de código,
Return Query,
y aquí podemos poner todo esto,
que ya hemos asegurado que funciona,
pero no hace falta,
que pongamos esta parte,
solo esta de aquí,
esta categoría,
que estamos poniendo aquí,
obviamente esta categoría,
vamos a inyectarla,
así que voy a poner aquí,
Category ID,
Category ID,
que esto va a ser,
Category ID,
que es un String,
¿vale?
Y este Category ID,
no será Shares,
sino que será lo que le pasemos nosotros,
por parámetro,
y así,
pues dependiendo de la categoría en la que entremos,
veremos uno u otro,
aquí tendríamos la respuesta,
y aquí,
como vamos a hacer la paginación,
vamos a extraer dos campos,
por un lado,
los datos,
y por otro lado,
los metadatos,
fíjate,
aquí en Apple REST,
cuando hacemos la Send Request,
si miramos los datos,
aquí,
tenemos por un lado,
Data,
que es donde tenemos realmente los datos de los productos,
y por otro lado,
tenemos Meta,
que son los metadatos,
donde tenemos la paginación,
nos dice,
¿en qué página estamos?
¿Cuál es el tamaño de la página que hemos pedido?
¿Cuántas páginas hay?
Y en total,
¿cuántos elementos hay?
Y en este caso,
son tres,
¿vale?
Así que esta información la vamos a necesitar para hacer la paginación después,
así que,
lo mejor es que lo saquemos ya,
y así nos evitamos problemas,
tenemos los productos por un lado,
que vamos a mapear los datos,
muy parecido a lo que estamos haciendo todo el rato,
de recuperar el nombre,
el Slack,
la descripción,
el imagen,
la imagen,
sacamos el row,
¿vale?
El precio,
y aquí tenemos el producto,
creamos la imagen con lo de Strapi Host,
esto es exactamente lo mismo que hemos hecho antes,
y ya devolvemos todos estos datos,
y ahora devolvemos tanto los productos,
como,
bueno,
iba a poner Meta,
Meta,
pero vamos a poner Meta.pagination,
y así accederemos directamente a la paginación,
¿vale?
Con esto,
ya tendríamos,
pues este mapeo,
esta transformación que hacemos de los datos,
y nos vamos a los productos,
aquí tendríamos la página donde mostramos los productos,
pero fijaos que ahora mismo los productos los tenemos vacíos,
esta página,
es la que mostramos cuando entramos,
aquí no,
cuando entramos a una categoría,
entramos a una categoría,
y claro,
ahora me dice que no ha encontrado ningún producto,
¿por qué?
porque tengo aquí un array vacío,
y por eso me aparece aquí que no lo ha encontrado,
me dice no products found,
porque entra aquí,
dice si el length de los productos es cero,
pues entro aquí,
pero si tenemos productos,
que ahora los vamos a ver,
nos los va a mostrar con todo esto de aquí,
entonces,
vamos a evitar este array vacío,
y vamos a utilizar este nuevo método,
get products,
como es un react server component,
podemos utilizar aquí una wait,
y está esperando que le pasemos la categoría ID,
que la sacamos del parámetro,
porque esto,
esto lo tenemos en la URL,
ves aquí que tenemos este shares,
que aparece aquí,
tenemos shares,
esto lo vamos a capturar,
gracias a Next.js,
en Next.js podemos tener rutas dinámicas,
como esta de aquí,
y la ruta dinámica,
la definimos utilizando los corchetes,
le decimos,
oye,
dentro de categorías,
quiero que me captures aquí,
la categoría ID,
porque no sé,
cuál,
qué valor puede ser,
no podemos saber de antemano,
si va a utilizar shares,
stickers,
o si el día de mañana va a ser pepito,
así que,
lo ponemos entre corchetes,
y le decimos que,
sea cual sea,
el parámetro que nos pasa,
nos lo capture,
y nos lo meta,
en el nombre,
categoría ID,
y esto,
lo va a inyectar,
en el componente de página,
category page,
aquí,
en los parámetros,
fíjate que los parámetros,
tenemos la posibilidad de llamar,
category ID,
este category ID,
esto no es casualidad,
es porque,
el nombre que utilicéis aquí,
es el nombre que,
aparecerá aquí,
en el que podréis extraer la información,
¿vale?
o sea,
no es casualidad,
no es que diga,
ah,
porque se llama category ID,
porque yo he decidido que se llama category ID,
si aquí le llamamos,
en lugar de category ID,
le llamamos,
el mejor ID del mundo,
pues aquí deberíamos utilizar,
el mejor ID del mundo,
pero no es el mejor ID del mundo,
es category ID,
así que ahora,
si utilizamos el category ID,
de los parámetros,
este category ID,
se lo pasamos aquí,
y ahora,
vamos a ver,
si con esto,
tenemos los productos,
vale,
me dice que,
la URL,
ah,
porque mira,
se me ha olvidado el populate,
tanto rollo con el populate,
y claro,
la imagen,
no la está encontrando,
porque,
no hemos utilizado,
el populate image,
porque por defecto,
las imágenes,
no,
los tipo media,
no,
no te devuelve los datos,
vale,
vale,
ahora me dice,
vale,
a ver,
espérate,
dice data,
vamos a ver aquí,
que tiene el res,
a ver que se nos está quejando,
vale,
a ver que devuelve por aquí,
ojo,
validation error,
invalid key image,
ah,
porque no es image,
ah,
es que,
ves,
tiene toda la razón del mundo,
cuando vamos aquí,
a los productos,
fijaos,
que yo en realidad,
no le he llamado image,
le hemos llamado,
images,
en plural,
porque hemos dicho,
que podía ser más de una imagen,
por lo tanto,
tenemos que hacer un populate,
de images,
y además aquí,
deberíamos,
esto,
porque voy a utilizar,
una imagen,
pero en realidad,
esto debería ser,
images,
vale,
row images,
y esto debería ser,
accediendo,
a la primera posición,
de la imagen,
vale,
importante,
porque podemos tener,
un campo,
que sea más de una imagen,
y crear un slider,
y devolver todas las imágenes,
claro,
lo podríamos hacer así,
perfectamente,
entonces ahora,
si volvemos por aquí,
vale,
vamos a ver,
vale,
todavía,
alguna cosa no le gusta del todo,
ahora lo vemos,
pero vamos a ver,
si aquí en good products,
vamos a ver con el console log,
entiendo que en el data,
ahora sí que tenemos un array,
vale,
que sí que tenemos aquí,
toda la información,
perfecto,
devolvemos productos,
y paginación,
y si nos vamos,
a la página,
que estamos por aquí,
vale,
ves,
aquí estoy trayendo products así,
pero,
esto tendría que ser así,
porque nos devuelve un objeto,
con la key products,
vale,
y tendríamos por otro lado,
la paginación,
pagination,
y,
ya tendríamos ahí,
nuestros productos,
fíjate,
que tenemos ya los productos,
de nuestra tienda online,
y,
y ya está,
vale,
una cosa muy interesante,
de todo lo que estamos viendo,
y una de las cosas más maravillosas,
que tiene Strapi justamente,
es que,
aparte de generarte una API,
como la que estamos viendo,
una cosa que te puede generar Strapi,
muy fácilmente,
y de lo que no hemos hablado,
es que tienes un marketplace,
maravilloso,
en la que tienes un montón de plugins,
totalmente gratuitos,
que tienes de generación de imágenes,
por inteligencia artificial,
temas de accesibilidad,
temas de,
es increíble,
vale,
tienes incluso para generarte,
los identificadores únicos,
de forma automática,
para,
yo que sé,
es que,
es que es increíble,
la de plugins que tienes,
y uno de ellos,
es el de crearte,
la API de GraphQL,
que,
por si te gustaría utilizar GraphQL,
que es verdad,
que a día de hoy,
ya está un poco más de capa caída,
pero aún así,
creo que,
es una opción muy interesante,
fíjate,
que,
pones GraphQL,
y aquí tienes el Copy Install Command,
le puedes dar un clic,
y esto,
directamente,
te vas para acá,
donde tengas tu proyecto,
y vamos a ejecutar,
en PM Install,
Strapi,
Plugin,
GraphQL,
instalas el plugin,
y una vez que instalas el plugin,
sin hacer absolutamente nada,
te va a generar,
un GraphQL,
ay,
espérate,
ves,
me la he liado,
porque,
bueno,
creo que no pasa nada,
que he utilizado otra versión de Node,
que no era,
pero bueno,
no pasa nada,
creo que no pasa nada,
a ver si me la he reiniciado,
sí que me la he reiniciado,
vale,
pues veréis que todo funciona igual,
pero me pone que esto está instalado,
y solo con este cambio,
podéis ir a localhost,
1,
3,
3,
7,
GraphQL,
y fíjate,
lo que tenéis aquí,
tenéis,
automáticamente,
toda la API,
pero con GraphQL,
directamente,
aquí tenéis un playground,
donde podéis probar,
podéis hacer queries,
por ejemplo,
si queréis sacar la home,
y queréis sacar,
por la,
la cover,
con la URL,
y queréis también sacar el title,
y queréis sacar el description,
vale,
tendremos que pasarle el token,
lo hago en un momento,
porque fijaos,
si hago query,
se queja,
porque no tengo acceso,
en headers,
vamos a ponerle,
el authorization,
vamos a ponerle,
el valor que hemos puesto,
la variable de entorno,
vale,
ponemos esto por aquí,
esto por aquí,
esto por aquí,
vale,
y aquí tenemos ya,
el API token,
y ahora,
con esto,
ay,
se me ha olvidado,
el bearer token,
ahora sí,
ahora sí,
fijaos,
en un momento,
tenemos,
toda la API que habéis visto,
toda la API,
con GraphQL,
que obviamente,
pues está genial,
porque en un momento,
pero en un momento,
podéis optimizar,
y os devuelve la data,
de esta forma,
lo cual,
pues es tremendo,
porque si,
por lo que sea utilizar GraphQL,
o queréis utilizarlo,
por temas de optimización,
lo tenéis así,
perfectamente,
y ya está,
vale,
ahí lo tenéis,
esto,
opcional,
no es obligatorio,
no viene activado por defecto,
tenéis que instalar el plugin,
pero que lo sepáis,
que lo podéis hacer,
ahora que ya hemos mostrado,
nuestros productos,
podemos hacer diferentes cosas,
la localización,
es bastante sencilla,
ahora mismo,
no me va a dar tiempo,
a hacer toda la localización,
de la página,
obviamente,
pero como ya tenemos,
una categoría,
que sí que la hemos localizado,
aquí,
hemos puesto la categoría Shares,
que sea localizada,
la localización,
es tan,
tan,
tan fácil,
como pasarle un parámetro,
a la API,
o sea,
si vamos a Get Categories,
y aquí,
directamente,
entre todos los campos,
le decís,
Locale,
S,
¿vale?
Esto lo que va a hacer,
automáticamente,
es pasarte,
automáticamente,
la localización al español,
¿ves?
Camisetas,
las mejores camisetas del mundo,
el otro,
no nos aparece,
porque ese contenido,
no lo tenemos localizado,
pero podríamos hacerlo,
en un momento,
podríamos ir,
a nuestro Strapi,
¿vale?
aquí,
Content Manager,
nos vamos a Product Category,
nos vamos a los Stickers,
aquí,
creamos la versión español,
ponemos pegatinas,
Stickers,
las mejores pegatinas,
para tu laptop,
teníamos que crearle,
la misma imagen,
que es esta de aquí,
a ver,
aquí hay que darle,
¿vale?
y la relación,
no debería,
bueno,
claro,
no hay ninguna relación,
por aquí,
vale,
y ahora,
con esto,
ya deberíamos ver,
en un momento,
en un momento,
ahí lo tenemos,
pegatinas,
las mejores pegatinas,
para tu laptop,
entonces,
en Next.js,
solo tenéis que,
aquí,
i18n,
locales,
en español,
y en inglés,
default local,
esto para que recupera,
automáticamente,
esto si lo queréis detectar,
lo podríais detectar,
por ejemplo,
si lo detectáis,
debería aparecer,
al principio,
que ahora no sé si,
pero en principio,
debería ser español,
por defecto,
vale,
pero una vez que recuperáis,
la información,
que la podríais recuperar,
a nivel de página,
recuperando tanto,
la url,
o lo que sea,
recuperáis el local,
se lo pasáis,
al get categories,
lo podríais tener aquí,
por ejemplo,
locales,
que voy a poner,
bueno,
locales,
que sea un string,
podemos decir,
que sea,
en por defecto,
esto lo utilizáis aquí,
y ya lo tendríais,
vale,
ahora lo he pasado al inglés,
y por lo tanto,
tenemos el contenido en inglés,
que si lo pasamos en español,
pues nos aparece en español,
o sea,
es tremendo,
porque automáticamente,
solo pasándole,
un campo a la API,
ya tenemos totalmente,
localizada,
nuestra tienda,
con los datos que queremos,
vale,
y lo único que tenemos que hacer,
tanto en Next.js,
como en cualquier framework,
vas a tener la posibilidad,
de crear la localización,
recuperarlo,
en este caso,
con un custom hook,
o por una propiedad,
que te venga,
en las props del componente,
y pasárselo por parámetro,
y ya estaría.
La imaginación,
es muy sencillo,
fijaos que ahora mismo,
claro,
no tengo muchos,
no tengo muchas camisetas,
entonces,
vamos a hacer un poco de trampa,
y vamos a hacer,
que cada resultado,
o sea,
que cada página,
tenga un resultado,
para que tengamos tres páginas,
pero fijaos que yo ya tengo,
un componente de paginación,
que ya lo he preparado,
para no tener que hacerlo desde cero,
que básicamente,
se le pasa,
la página en la que estamos,
el tamaño de cada página,
que sería,
cuántos resultados aparecen,
por cada página,
el page count,
o sea,
cuántas páginas hay,
y el total de elementos,
que se van a mostrar,
o sea,
el total de elementos,
no que se va a mostrar,
el total de elementos,
que hay disponibles,
por eso aquí,
podemos decir,
el total sería,
que hay tres productos,
vale,
en cada página,
ahora por defecto,
estaríamos mostrando,
no sé si eran 25,
por defecto,
y páginas solo tenemos una,
porque caben los 25 aquí,
porque solo tenemos tres,
y ya está,
entonces,
lo primero que tenemos que hacer,
en el get products,
aquí,
sería cambiar,
con la query,
el número de productos,
que queremos filtrar,
igual que tenemos el category ID,
vamos a poner aquí,
tanto el page size,
como el page,
vale,
que el page size,
va a ser un número,
y el page,
va a ser un número,
voy a poner una constante aquí,
con el page size,
que es el número de resultados,
por página,
que queremos mostrar,
voy a decirle uno,
es exagerado,
porque normalmente,
vas a querer mostrar más,
pero es que solo tenemos,
tres camisetas,
y quiero que haya paginación,
entonces,
vamos a cambiar esta URL,
voy a poner aquí,
que esto sea un let URL,
de forma,
que esta URL,
la vamos a poner aquí,
esta URL,
la utilizamos aquí,
y decimos,
oye,
si tenemos un page,
añade a la URL,
vamos a añadir pagination,
que la paginación,
va a ser de esta página,
pagination,
sería el grupo de opciones,
donde Strapi,
indica la información de paginación,
y dentro de la paginación,
le decimos,
la página que es,
vale,
hay diferentes formas,
de hacer paginación en Strapi,
yo creo que esta es la más sencilla,
para no tener que hacer el offset,
el limit y todo esto,
creo que es mucho más fácil,
utilizar el page y el page size,
pero que sepáis,
que también podéis utilizar el limit,
y el offset,
si queréis,
a mí me gusta mucho más esta,
pero si estáis habituados al otro,
pues igual,
utilizáis el otro,
y lo mismo con el page size,
si tenemos el page size,
le vamos a decir,
vale,
pues utiliza del pagination,
me cambias el page size,
vale,
esto,
hay que poner el correcto,
y me utilizas esto,
y con este cambio,
ya deberíamos ser capaces,
de paginar,
pero obviamente,
este get products,
que lo estamos utilizando,
en la página esta,
de page,
aquí,
veis,
nos dice,
que nos falta aquí,
unos campos,
vamos a poner página 1,
y es verdad,
que este page size,
lo he puesto aquí,
lo voy a poner acá,
en el componente,
por si lo queremos cambiar,
a nivel de componente,
más que a nivel de ese método,
y ahí ponemos page size,
que vamos a poner page size,
y ahí lo cambiaremos,
si fuese necesario,
entonces,
solo con esto,
fijaos,
que ya tenemos,
que nos devuelve 1,
esto lo tenemos aquí,
porque estamos en la página 1,
esto en el get products,
le he puesto que es la página 1,
directamente,
pero no está correcto,
porque si no,
siempre me va a devolver la página 1,
ahora veremos,
como realmente debemos,
recuperar la página,
en la que estamos,
para eso,
en la paginación,
el componente de paginación,
que es el que visualmente,
veis aquí abajo,
puede ver que hay un botón next,
ese botón next,
o el previous,
lo único que hace,
lo tenemos aquí,
es un enlace,
que lo que tiene este hrf,
es el next page URL,
que lo que hace,
es crearlo,
que dice,
oye,
si es la última página,
pues no le ponemos nada,
pero si es la siguiente página,
lo que hago es,
añadir el query parent page,
de la siguiente página,
y fíjate,
que cuando le dé,
la url,
me está cambiando,
el elemento no,
ahora os explico por qué,
pero la url,
sí que me está cambiando,
o sea,
debería ir a la siguiente,
bueno,
en este caso,
como siempre estoy pasando page 1,
page 1,
por eso no me cambia,
pero sí que habéis visto,
que en la primera página,
le doy,
y en la url,
me pone page 2,
así que,
esta información de aquí,
es la que tenemos que recuperar,
en nuestra página,
porque fíjate,
ahora siempre decimos,
que en la página 1,
para acceder a esa información,
a los query params,
de una url,
en el app router,
tendríamos que utilizar,
search params,
y aquí,
en los parámetros,
vamos a decir,
que el search params,
hostia,
el search params,
tiene un tipo,
en typescript,
un poco complicado,
porque,
creo que es,
sería así,
bueno,
sí,
lo podemos utilizar así,
o sea,
en realidad,
no es este,
porque también puede ser,
esto debería ser también,
que puede ser un array,
y también,
además,
puede ser undefined,
o sea,
debería ser algo más así,
pero bueno,
lo vamos a dejar,
así,
vale,
lo vamos a dejar,
más bien así,
a ver por qué me dice que este,
ah,
porque esto lo he puesto mal aquí,
esto no va aquí,
esto va aquí,
ahora,
vale,
pues este search params,
es el que me va a permitir,
acceder a la página,
de la url,
y esa página,
de la url,
obviamente,
tendríamos que ponerle,
que sea esta,
si no está,
porque page,
puede ser undefined,
de hecho,
lo vamos a poner aquí,
ves que page,
le he puesto que sea number,
que en realidad,
no en number exactamente,
porque sería string,
de hecho,
se lo voy a poner,
que es o string,
o puede ser undefined,
vale,
que sería lo correcto,
page puede ser string,
o undefined,
porque a lo mejor,
si no viene en los search params,
pues nos devolverá undefined,
vale,
entonces ahora,
sí que vamos a recuperar,
la página correcta,
ves,
estamos en la primera,
si voy a la página 2,
me carga la segunda página,
donde tenemos,
la segunda camiseta,
y en la tercera página,
tenemos la última camiseta,
y ahora podemos ir para atrás,
para ir a la página 2,
a la página 1,
y ya podemos ver,
cómo realmente lo está haciendo,
podemos cambiar el page size,
para que aparezcan,
dos resultados por página,
vale,
aquí tenemos dos resultados por página,
esta sería la primera página,
y en la segunda página,
como solo son tres camisetas,
tendríamos esto,
pero,
ya hemos visto,
que muy fácilmente,
gracias a Strapi,
tenemos la paginación hecha,
simplemente,
utilizando los query params correctos,
podemos utilizar el page,
y el page size,
o podemos utilizar,
el limit,
y el offset,
pero no se pueden mezclar los dos,
o sea,
te tienes que quedar con uno,
yo si me preguntas,
prefiero el de page,
y page size,
donde te dices,
el número de página,
en el que estás,
y el número de resultados,
que tiene que mostrar,
por cada una de las páginas,
vale,
así que ahí tendría,
es el tema,
de la paginación,
y nos queda,
el sorting,
que también es tremendo,
el sorting,
es igual de fácil,
y es que,
es increíble,
el tema del sorting,
se puede,
claro,
ya hemos filtrado,
mira,
tenemos filtros,
hemos hecho filtros,
hemos hecho paginación,
y ahora vamos a hacer,
sorting,
el sorting es,
que vamos a ordenar,
por algún cambio,
por ejemplo,
vamos a añadir un campo sort,
aquí,
y vamos a poner,
que el sort,
sea,
bueno,
voy a poner justo después,
de donde,
para que quede igual,
sea un string,
de forma,
que si le pasamos aquí,
el sort,
vamos a filtrar,
vamos a ordenar,
por el campo que le digamos,
para decirle,
por qué campo queremos ordenar,
simplemente,
tenemos que decirle,
sort,
y el nombre del campo,
ya está,
por ejemplo,
si queremos ordenar,
por el precio,
pues le diríamos sort,
y le diríamos aquí,
price,
y ya está,
y de hecho,
lo podéis ver aquí,
si,
bueno,
voy a hacer que el page size,
sea de 3,
para que veamos los 3,
rápidamente,
vale,
ahora,
en la página 2,
no hay resultados,
obviamente,
pero aquí sí,
bueno,
fíjate,
ah,
ostras,
ah,
claro,
porque no estoy,
digo,
ostras,
qué le pasa,
no,
claro,
esto,
si tiene un if,
no va a funcionar siempre,
vale,
si hacemos esto,
fíjate que ahora me está haciendo el sorting,
me lo está haciendo,
siempre por defecto,
lo hace de forma incremental,
vale,
pero,
el sort,
strappy decremental,
a ver,
acá no me acuerdo del,
de la API,
sort,
sorting,
cómo era la sorting,
además podéis,
es verdad,
podéis ordenar por más de un campo,
podéis utilizar sort 0,
por un campo,
y luego sort 1,
por el otro campo,
lo cual es tremendo,
o sea,
se puede hacer,
se puede hacer un montón de cosas,
y el tema del orden,
no,
cómo se hacía esto,
ahora no me acuerdo,
ahora no me acuerdo,
bueno,
a ver si me lo dice,
ah,
aquí está,
esto,
es que es un poco,
ves,
es que era dos puntos desk,
es que era un poco,
a veces hay que mirar la API,
porque si no es imposible,
entonces,
por defecto,
por defecto es,
es así,
es ascendente,
por eso vemos,
nada más entrar,
que,
hostia,
espérate,
no me ha gustado,
vale,
por eso veis esto,
que aunque yo le cambie esto,
si se lo quito,
sigue siendo ascendente,
si queréis que sea descendiente,
hay que hacer dos puntos desk,
y ahora sí,
sería descendiente,
esto es como se haría,
el cambio de sorting,
de ascendente o descendiente,
no me acordaba que eran dos puntos,
pensaba que era utilizando una cosa aquí,
es que como hay una mezcla a veces de esto,
entonces,
simplemente,
vamos a hacer una cosa,
por defecto vamos a hacer que no tenga sorting,
ves,
que pone aquí default,
pero le he añadido aquí un filtro,
que es by price,
y vamos a hacer que,
cuando se le dé al by price,
vamos a ir aquí a page,
vale,
aquí tenemos los filtros,
aquí short by,
vale,
y fíjate que cuando haces el handle click,
lo que haces,
al darle,
es que cambia la url,
se activa el filtro,
bueno,
se activa como lo va a ordenar,
pero no cambia la API,
tenemos que hacer lo mismo que hemos hecho aquí,
de,
en la página,
vamos a leer de los search params,
vamos a traer el short by,
y este short by,
que en este caso,
nos dice aquí el campo price,
vamos a decirle aquí,
short,
short by,
este short,
debería llegar,
aquí,
get products,
el short,
puede ser string,
o puede ser undefined,
y,
si viene,
le vamos a decir a la API,
que nos lo ordene,
por precio,
y ya está,
así que ahora,
by price,
ahora sí que está ordenado,
de forma ascendente,
por precio,
si le ponemos,
default,
veremos que ahora,
no está ordenado,
de ninguna forma,
pero esto lo podríamos hacer,
que se ordene,
por stock,
por precio,
por nombre,
por colores,
por lo que os dé la gana,
¿vale?
Podrías hacer que el precio,
fuese ascendente,
descendente,
de hecho,
un ejercicio,
pues interesante,
es que,
este proyecto,
que yo te voy a subir,
al repositorio de github,
es que,
le añadas nuevos filtros,
filtros de todo tipo,
y que también,
empieces a jugar más,
con los,
los campos,
que puedes tener,
a nivel de producto,
para ver,
que puedes hacer,
¿vale?
Así que,
nada amigos,
lo vamos a dejar por aquí,
en el caso de ser muchos productos,
recomendado llamarlos por grupos,
por grupos,
no,
por categorías,
o sea,
ya por categorías,
ya lo tendías,
¿no?
Y las categorías,
es que puedes ordenar,
por lo que te dé la gana,
yo tenía una pregunta,
¿se puede traducir los labels,
de los fields?
Los labels,
no,
los labels,
como tanto,
no,
porque el label,
o sea,
el campo tiene que ser el mismo,
siempre,
¿no es mejor usar URL search params?
No sé Adriano,
a qué te refieres,
pero es que esto,
realmente,
viene de search params,
o sea,
viene directamente,
este es search params,
es URL search params,
o sea,
ya te viene aquí,
lo que pasa es que por conveniencia,
lo que está haciendo en XDS,
es que te lo está integrando en el componente,
porque esto funciona en el servidor,
URL search params es una API de cliente,
entonces,
pero es exactamente lo mismo,
el stock lo podemos hacer variable,
es que todos los campos que veis son variables,
no nos da tiempo hoy,
pero que sepáis que todos los campos que tenéis en el CMS,
se pueden modificar a través de la API,
solo hemos visto la parte de la API,
que sería de lectura,
pero es que la API también es de escritura,
por eso,
en los roles y permisos,
fijaos que en el token,
por ejemplo,
que hemos puesto,
solo es de lectura,
pero podríamos tener la home,
product category,
product,
a lo mejor product category,
podríamos hacer que siempre se fuese lectura,
pero se podrían crear,
crear productos,
actualizar productos,
borrar productos,
lo más evidente sería,
pues,
obviamente,
actualizar productos.
¿Qué tan complicado sería agregar carrito de comprar y medio de pago?
¿Harás eso por si acaso?
No sería difícil,
de hecho,
de hecho,
creo que esta tienda que hemos visto,
vamos a añadirle más adelante,
utilizar Stripe,
para que veáis de forma muy fácil,
cómo podríamos añadir carrito y pago,
y lo vamos a hacer,
¿vale?
porque está muy,
muy interesante.
¿Cómo se despliega Stripe en servidor?
Tenéis dos opciones,
¿vale?
Uno sería utilizar Stripe Cloud,
que no está mal de precio,
teniendo en cuenta lo que da,
que son 29 dólares,
es verdad que puede ser más caro de lo normal,
pero bueno,
está bastante bien,
y tenéis ahí,
pues,
29 dólares,
un proyecto al mes,
os olvidáis de todo lo demás,
lo único que tiene limitación,
es que solo es un usuario,
y solo puedes crear mil elementos,
contando categorías,
productos y tal,
pero si no,
podéis utilizar cualquier VPS,
podéis utilizar Render,
que además tenéis un tutorial bastante fácil,
os da un botón,
y entonces lo desplegáis,
¿veis?
Deploy to Render,
y ya lo tenéis,
con el repositorio,
Stripe y todo,
todo,
todo,
o podéis utilizar Fly.io,
también,
que también lo podéis hacer,
Fly.io,
también tiene una guía para hacerlo.