Skip to content

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 TarjetaDescripción
CardsBuyTarjetas de compra
CardsConsultativeTarjetas consultivas
CardsDirectTarjetas para contenido en directo
CardsEpisodeTarjetas de episodios
CardsFileTarjetas para archivos (PDFs)
CardsOndemandTarjetas para contenido bajo demanda
CardsPackProductsTarjetas para paquetes de productos
CardsSerieTarjetas de series
CardsVideoTarjetas 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

  1. 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;
}
});
  1. 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",
    };
  2. 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.

  1. Agrega el nuevo componente al tipo ComponentNameType con su tipo correspondiente.

  2. Añade la nueva entrada en propNameMap con la clave esperada para el componente.

  3. Incluye la nueva opción en el switchde componentToRender.

  4. Añade el tipado de la nueva carta en el tipo CardEntry si es necesario.

Para eliminar una tarjeta el proceso sería el contrario