Customizar tarjeta producto

La tarjeta de producto es uno de los componentes que hay que customizar mƔs a menudo cuando arrancamos un proyecto en Mercury.

Variantes

Si lo que necesitamos es realizar ajustes de diseño bÔsicos, la primera opción es ver si podemos conseguirlo con las variantes del componente original.

Ver componente en Storybook

Sobreescritura

Cuando no es posible conseguir, con los estilos y las variantes del componente original, que la tarjeta de producto del proyecto cumpla con los requerimientos funcionales o de diseƱo del proyecto, deberemos sobreescribr el componente.

Con la sobreescritura del componente tendremos total libertad para implementar todo lo que se necesite.

1. Crear un Custom Component

Los componentes propios del proyecto se crearƔn dentro del directorio mercury/src/component/CustomTheme.

Podemos coger como base el componente original y a partir de ahĆ­ adaptarlo. En nuestro ejemplo usaremos el componente. En nuestro ejemplo copiaremos el componente node_modules/@mercury/theme/src/components/BaseTheme/CardProduct/CardProduct.tsx para crear nuestro CustomCard:

mercury/src/component/CustomTheme/CustomCard.tsx
import { useI18n } from '@mercury/i18n'
import { useProductPrice } from '@mercury/service-adobe-commerce'
import { AddToCart, CardProductProps, Price, addToFormatClasses } from '@mercury/theme/components'
import { Badge, Card, Typography } from '@mercury/ui'
import Image from 'next/image'
import { useEffect, useState } from 'react'

export default function CustomCard ({
  product,
  addToFormat = 'vertical',
  border = 'none',
  buttonSize,
  hover = 'border',
  nameSize = 'h6',
  nameWeight = 'bold',
  radius = 'none',
  shadow = 'lg',
  showBadge = false,
  size = 'sm',
  ...props
}: CardProductProps) {
  const { t } = useI18n()
  const { sku, name, image, urlKey } = product
  const { price, loading: priceLoading } = useProductPrice({ sku })
  const [badge, setBadge] = useState<{text: string, color: string, variant?: string}>()

  useEffect(() => {
    if (showBadge && price && price.finalPrice < price.regularPrice) {
      setBadge({
        text: t('productPage.sale'),
        color: 'green'
      })
    }
  }, [price, setBadge, showBadge, t])

  return (
    <>
      <Card
        size={size}
        border={border}
        radius={radius}
        shadow={shadow}
        hover={hover}
        className='px-3 py-2 bg-white md:px-4'
        {...props}
      >
        <div>
          <div className='relative w-full aspect-square md:mb-4 lg:mb-6'>
            { badge &&
              <Badge variant={badge.variant ? badge.variant : 'default'}
                     color={badge.color ? badge.color : 'default'}
                     style={ { position: 'absolute', zIndex: 1 } }>
                {badge.text}
              </Badge>
            }
            <a href={`/product/${urlKey}`} className='relative block w-full h-full'>
              <Image
                  src={image.src}
                  alt={name}
                  placeholder='blur'
                  blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mPcXA8AAesBNGQg4IAAAAAASUVORK5CYII="
                  quality={60}
                  className='object-contain'
                  fill
                />
            </a>

          </div>

          { sku && <h6 className='hidden mb-2 text-gray-400 text'>{t('productPage.ref')}: {sku}</h6> }
          <Typography htmlTag='h6' variant={nameSize} weight={nameWeight} customClass='mb-4 line-clamp-3'>
            <a href={`/product/${urlKey}`}>{name}</a>
          </Typography>

        </div>

        <div>
          <div className={addToFormatClasses[addToFormat]}>
            <div className='md:min-h-[30px] md:overflow-hidden price-wrapper price-carousel'>
              <Price variants='h5 h6' price={price?.finalPrice} regularPrice={price?.regularPrice} loading={priceLoading} />
            </div>

            <div className='mt-4'>
              <AddToCart
                buttonVariant='primary'
                buttonSize={buttonSize}
                nextJSLinkHref={{
                  pathname: `/product/${urlKey}`,
                  query: product.variants ? null : { added: 'true' }
                }}
              >
                <span className='hidden md:inline'>{t('cart.add')}</span>
                <span className='inline md:hidden'>{t('cart.addMobile')}</span>
              </AddToCart>
            </div>
          </div>
        </div>
      </Card>
    </>
  )
}

2. Configurar sobreescritura

La tarjeta de producto es un componente que se usa en mĆŗltiples sitio en Mercury. Para facilitar que el componente se sobreescriba en todos los sitios donde aparece se debe configurar.

Para configurar la sobreescritura deberemos aƱadir las siguientes lƭneas en:

mercury/src/pages/_app.tsx
...

// Importamos MercuryConfigType para poder sobrescribir la configuración por defecto.
import { MercuryConfigType } from '@mercury/theme/src/features/MercuryContext'

// Importamos nuestro Custom Component.
import CustomCard from '@/components/CustomTheme/CustomCard'

// Inidicamos el componente que queremos substituir con el nuestro.
const mercuryConfig: MercuryConfigType = {
  ProductCardComponent: CustomCard
}

...