teqo-backup/src/components/conteudos/ContentCatalogCardItem.tsx

111 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Image from 'next/image'
import Link from 'next/link'
import { sendCardOpeningEvent } from '@/lib/contentEvents'
import { contentPieceTypeLabels } from '@/lib/contentPiece'
import { CONTENT_PIECE_ASPECT_CLASS, type CardCatalogItem } from '@/lib/contentPieceCatalog'
import { cn } from '@/lib/utils'
import {
CONTENT_PIECE_CARD,
CONTENT_PIECE_FOCUS,
CONTENT_PIECE_OUTLINE_BUTTON,
CONTENT_PIECE_TAG,
} from './contentPieceClasses'
/**
* S38 — the art of a model item (artefato: cenas 01–03): the model's real file
* whole in the 3:4 vertical slot (S45 — the art is never cropped), or the
* neutral dashed placeholder of the photo models, whose master is only the
* frame with a transparent photo window. The `NOVO` badge of the newest model
* sits on the art.
*/
const CardItemArt = ({ item }: { item: CardCatalogItem }) => (
<span
className={cn(
'relative grid place-items-center overflow-hidden',
CONTENT_PIECE_ASPECT_CLASS.model,
item.art.kind === 'placeholder'
? 'bg-[linear-gradient(145deg,#eee9e5,#fff)]'
: 'bg-[linear-gradient(145deg,#184e92,#0876ac)]',
)}
>
{item.art.kind === 'placeholder' ? (
<span
aria-hidden="true"
className={cn(
'relative grid place-items-center border-2 border-dashed border-[#a21c1c]/40 text-3xl text-[#a21c1c]',
item.art.shape === 'square' ? 'size-20 rounded-full' : 'h-24 w-16 rounded-lg',
)}
>
◎
</span>
) : (
<Image
src={item.art.src}
alt=""
fill
sizes="(min-width: 1024px) 260px, (min-width: 640px) 45vw, 112px"
className="object-contain"
/>
)}
{item.badge ? (
<span className="absolute top-2 right-2 hidden rounded-full bg-white px-2 py-1 text-[9px] font-black text-[#184e92] sm:block">
{item.badge}
</span>
) : null}
</span>
)
/**
* S38 — one card model as an item of the board (artefato: cenas 01–05). The
* whole item is a single link to the studio with the model chosen — a bigger
* tap target on the phone and no second selection contract. It is NOT a piece:
* no download, no share, no detail page; the item is an invite to `/cards`.
* The click feeds the anonymous opening event of the model (C213/S32
* mechanism), never a piece event.
*/
export const ContentCatalogCardItem = ({ item }: { item: CardCatalogItem }) => (
<Link
href={item.href}
data-card-model={item.modelId}
onClick={() => sendCardOpeningEvent(item.modelId)}
className={cn(
CONTENT_PIECE_CARD,
'grid grid-cols-[112px_minmax(0,1fr)] text-black no-underline sm:block',
item.badge ? 'border-2 border-[#e4102f]' : null,
CONTENT_PIECE_FOCUS,
)}
>
<CardItemArt item={item} />
<div className="p-4">
<span className={CONTENT_PIECE_TAG}>
{contentPieceTypeLabels.card}
{/* Artefato (cena 02): no celular o selo vive na tag, não sobre a arte. */}
{item.badge ? <span className="sm:hidden"> · {item.badge}</span> : null}
</span>
<h3 className="mt-2 font-[family-name:var(--font-exo2)] text-sm font-extrabold sm:text-base">
{item.title}
</h3>
<p className="mt-1 text-xs text-(--campaign-muted)">{item.description}</p>
{item.aliases.length > 0 ? (
<div className="mt-2 flex flex-wrap gap-1">
{item.aliases.map((alias) => (
<span
key={alias}
className="inline-flex rounded-full border border-black/10 bg-white px-[7px] py-[3px] text-[10px] font-bold text-(--campaign-muted)"
>
{alias}
</span>
))}
</div>
) : null}
<span className={cn(CONTENT_PIECE_OUTLINE_BUTTON, 'mt-4 hidden w-full sm:inline-flex')}>
Escolher este modelo →
</span>
<span className="mt-3 block text-xs font-bold text-(--pt-red) sm:hidden">Escolher →</span>
</div>
</Link>
)