Lecciones del curso
Aprende Remix construyendo un Blog con MongoDB y Netlify
Vista de lista
Vamos a la ruta /blog
., y escribamos el código necesario para mostrar un mensaje y todos nuestros posts.
Esta será la ruta para mostrar nuestros posts en una lista atractiva. También contendrá un saludo amistoso, junto con nuestros datos si es un blog personal o los de marca. ®️
Para ello necesitaremos algunos datos de cada post, pero no todos, solo los necesarios.
Por eso, vamos a escribir el loader primero.
Escribiendo el loader
¿Qué datos necesitamos? Depende del diseño del componente <BlogCard>
, pero por ahora pediremos tres: title
, createdAt
y author
.
export const loader: LoaderFunction = async () => { const posts = await db.posts.findMany({ where: { published: true }, select: { title: true, createdAt: true, author: true, }, }); return { posts }; };
Toma nota de que he aplicado un filtro, pues solo queremos los posts que posean la llave published
como true
.
👀 También observa que al pedir
author:true
estamos haciendo uso de la relación uno a muchos definida en el schema de Prisma. — Puedes revisar la lección Conectando con la base de datos ✅ para recordar esto.
Escribiendo el cliente
Ahora coloquemos el JSX de nuestro cliente, que ofrecerá un saludo y la lista de los posts. Pero comencemos con el saludo:
// app/routes/blog.tsx export default function Blog() { return ( <> <h2>¡Hola! 👋🏼 Bienvenid@ a mi blog.</h2> <p> Soy @blissmo 🤓 y me gusta compartir lo que aprendo sobre desarrollo web. </p> </> ); }
👋🏼 ¡Hola! Disfruto de programar, igual que tu. 🤓
Agregando una imagen y un mejor “copy”
Me gustan las versiones minimalistas que a veces me resultan en estos cursos, disfruto de imaginar la mínima interfaz posible. No, no importa si no tiene todas las recomendaciones de diseño, buenas prácticas y espaciados, me preocupo de la accesibilidad claro, pero la estética queda subordinada a la usabilidad.
Es bonito construir un app que funcione, sin la presión de hacerlo todo perfecto o estético.
Por eso no he agregado más, que un par de párrafos y una imagen:
<> <main className="max-w-3xl mx-auto py-20 px-4 flex justify-between gap-4 items-center"> <div> <h2 className="font-medium text-4xl text-white"> ¡Hola! 👋🏼 Bienvenid@ a mi jardín digital. 🪴 </h2> <p className="text-2xl font-thin my-4 text-gray-200"> Soy @blissmo 🤓 y me gusta compartir lo que aprendo sobre desarrollo web independiente. </p> <p className="text-2xl my-4 text-gray-200"> Ultimamente intento escribir y narrar bien. ✍🏼 </p> </div> <img className="rounded-3xl max-w-xs hover:rotate-3 hover:scale-105 transition-all" src="https://i.imgur.com/OtuQ5J8.png" alt="Chilango at Prague" /> </main> <section> {posts.map((post) => ( <BlogCard {...post} key={post.id} /> ))} </section> {posts.length < 1 && ( <p className="bg-gray-600 text-gray-200 text-center py-12 max-w-3xl mx-auto block rounded-2xl text-xl font-thin hover:scale-95 transition-all"> {" "} No he escrito nada aún 😥{" "} </p> )} </>
¡Tú puedes crear tu propia versión, por su puesto! 👩🏻🎨
Pero por ahora con este <section>
vamos a contener todos nuestros posts, utilizando el componente <BlogCard>
que escribiremos en un momento.
Ahora, vamos a trabajar con <BlogCard>
para que muestre el título de cada posts con un buen tamaño, junto a una pequeña imagen como thumbnail.
Finalizando el maquetado
Hay un montón de diseños hermosos allá afuera, pero este curso está pensado para construir un app funcional, real, lista para producción. Así que tengo que repetir que, puedes mejorar el diseño de esta tarjeta. Pero yo me conformo, este componente es suficientemente bello y muy útil, nos sirve para mostrar nuestros posts, así que nos gusta. 🌀
Vamos a crear esta tarjeta para usarla en nuestra ruta /blog.tsx
y poder mostrar todos nuestros posts.
Escribiendo <BlogCard>
Este componente es el responsable de mostrar nuestros posts de manera vistosa, además de colocar un enlace para llevar a nuestro usuario al detalle, mismo que escribiremos en la siguiente lección.
// app/components/BlogCard.tsx import { Link } from "@remix-run/react"; import relativeTime from "dayjs/plugin/relativeTime"; import dayjs from "dayjs"; // Mi biblioteca favorita para fechas import "dayjs/locale/es-mx"; dayjs.extend(relativeTime); dayjs.locale("es-mx"); export const BlogCard = ({ title, slug, cover, createdAt, }: { createdAt: string | Date; cover?: string; slug: string; title: string | null; }) => { return ( <Link to={`${slug}`} className="bg-gradient-to-r from-slate-600 to-slate-800 text-white p-4 rounded-md hover:ring-indigo-500 hover:ring transition-all w-full flex items-center gap-4" > <img src={cover} alt="cover" className="rounded-sm object-cover max-w-xs" /> <div> <h3 className="text-3xl"> {title}</h3> <span className="font-thin text-sm text-gray-300"> {dayjs(createdAt).from(new Date())} // @Reto: este dato debería venir del modelo </span> </div> </Link> ); };
toma nota de que usamos dayjs
para no perder tiempo con los formatos de fecha.
dayjs
necesita más configuración que momentjs
(1 línea más 😅) pero pesa menos de 2kb y tiene herramientas bien buenas, como la que estoy usando. 😎
Agrega un par de posts desde tu dashboard, y hazlos públicos
Agrega dos post a tu blog para poder trabajar en la ruta dinámica que sigue.
Necesitamos una vista de detalle, que será el espacio de lectura de nuestro usuario, y necesitamos que sea lo más agradable posible.
Vayamos pues a construir la ruta dinámica para el detalle. 🚀