Cards Renderer Component
Descripción
Componente dinámico que renderiza diferentes tipos de tarjetas (Cards) según las props proporcionadas. Funciona como un wrapper inteligente que selecciona y muestra el componente de tarjeta adecuado con sus propiedades correspondientes.
Cómo usar
Importación
<script setup> import CardsRenderer from "@/components/ui/cards/CardsRenderer.vue";</script>Se puede usar el autoimport de Nuxt también
Uso básico
<template> <CardsRenderer component="CardsBuy" :data="buyCardData" /></template>Props
Tipado Principal
export type ComponentNameType = { CardsFile: FileCardItem; CardsBuy: BuyCardItem; CardsDirect: DirectCardItem; CardsConsultative: ConsultativeCardItem; CardsSerie: Serie; CardsEpisode: EpisodeCardItem; CardsPackProducts: ProductCardPackItem; CardsOndemand: OndemandCardItem; CardsVideo: VideoCardItem;};ComponentNameType es el tipo principal del componente. Permite validar que los datos proporcionados a CardsRenderer son compatibles con el tipo de tarjeta que se quiere renderizar.
Tipado de los datos a la hora de renderizar
export type CardEntry = { list: | FileCardItem[] | BuyCardItem[] | EpisodeCardItem[] | ConsultativeCardItem[] | ProductCardPackItem[] | DirectCardItem[] | OndemandCardItem[] | Serie[] | Testimonials[]; buttonLogic?: () => void;};CardEntry es el tipo de datos que se espera recibir a la hora de renderizar muchos componentes. El tipo list tiene que ser de uno de esos tipos. Que son los que tipan los datos de cada tarjeta.
Propiedades
-
component: (key of ComponentNameType) en String, es el nombre de tarjeta a renderizar. -
data: (ComponentNameType[T]), datos específicos para el tipo de tarjeta seleccionado. -
handleClick: (opcional) (function), función que se ejecutará cuando se haga clic en la tarjeta.
Tipos de tarjetas soportadas
El componente soporta los siguientes tipos de tarjetas:
| Tipo de Tarjeta | Descripción |
|---|---|
CardsBuy | Tarjetas de compra |
CardsConsultative | Tarjetas consultivas |
CardsDirect | Tarjetas para contenido en directo |
CardsEpisode | Tarjetas de episodios |
CardsFile | Tarjetas para archivos (PDFs) |
CardsOndemand | Tarjetas para contenido bajo demanda |
CardsPackProducts | Tarjetas para paquetes de productos |
CardsSerie | Tarjetas de series |
CardsVideo | Tarjetas de video |
Ejemplo completo
<script setup>import { ref } from "vue";
const cards = ref<Partial<Record<keyof ComponentNameType, CardEntry>>>({ CardsBuy: { list: buyCardList, buttonLogic: () => console.log('buy') }, CardsDirect: { list: directCardList },})</script>
<template> <UiCardsRenderer v-for="[componentName, cardData] in Object.entries(cards)" :component="componentName as keyof ComponentNameType" :data="cardData.list[0]" :handleClick="cardData.buttonLogic" /></template>Se usa el Partial para que no sea obligatorio usar todos los tipos. Y con el tipado de CardEntry puedes especificar los datos y la funcionalidad de cada Card
Flujo de trabajo interno
-
Seleccion del componente:-
Recibe el nombre del componente mediante la prop
component. -
Utiliza un switch para seleccionar el componente correcto a renderizar.
-
const componentToRender = computed(() => { switch (props.component) { case "CardsConsultative": return CardsConsultative; case "CardsFile": return CardsFile; case "CardsBuy": return CardsBuy; case "CardsDirect": return CardsDirect; case "CardsSerie": return CardsSerie; case "CardsEpisode": return CardsEpisode; case "CardsPackProducts": return CardsPackProducts; case "CardsOndemand": return CardsOndemand; case "CardsVideo": return CardsVideo; default: return null; }});-
Mapeo de propiedades:-
Algunos componentes hijos no esperan la prop como
data, sino con nombres personalizados. -
Para resolver esto se utiliza el objeto
propNameMap.
const propNameMap: Record<keyof ComponentNameType, string> = {CardsConsultative: "consultativeList",CardsFile: "fileCardItem",CardsBuy: "cardBuyList",CardsDirect: "directList",CardsSerie: "serie",CardsEpisode: "episode",CardsPackProducts: "cardProductList",CardsOndemand: "ondemandList",CardsVideo: "videoCardItem",}; -
-
Renderizado:-
Se usa el componente dinámico
<component :is="componentToRender"> -
Se pasan las propiedades mapeadas al componente hijo
Este el propNameMap mencionado previamente
-
Añadir una card nueva
Para añadir soporte a una nueva tarjeta.
-
Agrega el nuevo componente al tipo
ComponentNameTypecon su tipo correspondiente. -
Añade la nueva entrada en
propNameMapcon la clave esperada para el componente. -
Incluye la nueva opción en el
switchdecomponentToRender. -
Añade el tipado de la nueva carta en el tipo
CardEntrysi es necesario.
Para eliminar una tarjeta el proceso sería el contrario