Files
SkinbaseNova/resources/js/components/worlds/UploadWorldHighlightCard.jsx

76 lines
3.1 KiB
JavaScript

import React, { useEffect, useRef } from 'react'
import WorldCampaignMeta from './WorldCampaignMeta'
import WorldStatusBadge from './WorldStatusBadge'
import { trackWorldSourceImpression } from '../../lib/worldAnalytics'
export default function UploadWorldHighlightCard({ world, sourceSurface = '', sourceDetail = '' }) {
const cardRef = useRef(null)
useEffect(() => {
if (!sourceSurface || !world?.id || typeof window === 'undefined') {
return undefined
}
const node = cardRef.current
if (!node) {
return undefined
}
if (typeof window.IntersectionObserver !== 'function') {
trackWorldSourceImpression({
worldId: world.id,
worldTitle: world.title,
sourceSurface,
sourceDetail,
sectionKey: 'upload_highlight',
})
return undefined
}
const observer = new window.IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting || entry.intersectionRatio < 0.5) {
return
}
trackWorldSourceImpression({
worldId: world.id,
worldTitle: world.title,
sourceSurface,
sourceDetail,
sectionKey: 'upload_highlight',
})
observer.disconnect()
})
}, { threshold: [0.5] })
observer.observe(node)
return () => observer.disconnect()
}, [sourceDetail, sourceSurface, world?.id, world?.title])
if (!world) {
return null
}
return (
<div ref={cardRef} className="overflow-hidden rounded-[24px] border border-emerald-300/20 bg-[linear-gradient(135deg,rgba(16,185,129,0.14),rgba(15,23,42,0.84))] p-5">
<div className="grid gap-4 md:grid-cols-[9rem_minmax(0,1fr)] md:items-center">
<div className="h-28 overflow-hidden rounded-[20px] border border-white/12 bg-slate-950/80">
{(world.teaser_image_url || world.cover_url) ? <img src={world.teaser_image_url || world.cover_url} alt={world.title} className="h-full w-full object-cover" /> : <div className="flex h-full items-center justify-center text-slate-500"><i className="fa-solid fa-globe" /></div>}
</div>
<div>
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-emerald-100/80">Upload spotlight</div>
<div className="mt-3 flex flex-wrap gap-2">
{(Array.isArray(world.status_badges) ? world.status_badges : []).map((badge) => <WorldStatusBadge key={badge.label} badge={badge} />)}
{world.campaign_label ? <WorldStatusBadge badge={{ label: world.campaign_label, tone: 'slate' }} /> : null}
</div>
<h3 className="mt-4 text-xl font-semibold tracking-[-0.03em] text-white">{world.teaser_title || world.title}</h3>
{world.teaser_title && world.teaser_title !== world.title ? <div className="mt-1 text-xs uppercase tracking-[0.16em] text-white/55">{world.title}</div> : null}
{(world.teaser_summary || world.summary) ? <p className="mt-3 text-sm leading-6 text-slate-200/85">{world.teaser_summary || world.summary}</p> : null}
<WorldCampaignMeta world={world} className="mt-4" />
</div>
</div>
</div>
)
}