76 lines
3.1 KiB
JavaScript
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>
|
|
)
|
|
} |