87 lines
4.4 KiB
JavaScript
87 lines
4.4 KiB
JavaScript
import React from 'react'
|
|
|
|
function formatDate(dateStr) {
|
|
if (!dateStr) return ''
|
|
try {
|
|
return new Date(dateStr).toLocaleDateString('en-US', {
|
|
year: 'numeric', month: 'short', day: 'numeric',
|
|
})
|
|
} catch {
|
|
return ''
|
|
}
|
|
}
|
|
|
|
export default function HomeNews({ items }) {
|
|
if (!Array.isArray(items) || items.length === 0) return null
|
|
|
|
return (
|
|
<section className="mt-14 px-4 sm:px-6 lg:px-8">
|
|
<div className="mb-5 flex items-center justify-between">
|
|
<h2 className="text-xl font-bold text-white">News & Updates</h2>
|
|
<a href="/news" className="text-sm text-nova-300 hover:text-white transition">
|
|
All news →
|
|
</a>
|
|
</div>
|
|
|
|
<div className="mt-5 grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
|
{items.map((item) => (
|
|
<article
|
|
key={item.id}
|
|
className="group relative overflow-hidden rounded-[28px] border border-white/[0.06] bg-[linear-gradient(180deg,rgba(11,16,26,0.94),rgba(7,11,19,0.92))] shadow-[0_18px_45px_rgba(0,0,0,0.22)] transition hover:-translate-y-0.5 hover:border-white/[0.12]"
|
|
>
|
|
<a href={item.url} className="block">
|
|
<div className="relative aspect-[16/9] overflow-hidden bg-black/20">
|
|
{item.cover_url ? (
|
|
<img
|
|
src={item.cover_mobile_url || item.cover_url}
|
|
srcSet={item.cover_srcset || undefined}
|
|
sizes={item.cover_srcset ? '(max-width: 767px) 100vw, (max-width: 1279px) 50vw, 390px' : undefined}
|
|
alt={item.title}
|
|
className="h-full w-full object-cover transition duration-300 group-hover:scale-[1.04]"
|
|
/>
|
|
) : (
|
|
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(56,189,248,0.14),transparent_45%),linear-gradient(180deg,rgba(15,23,42,0.92),rgba(2,6,23,0.98))]" />
|
|
)}
|
|
<div className="absolute inset-0 bg-gradient-to-t from-[#020611cc] via-transparent to-transparent" />
|
|
</div>
|
|
</a>
|
|
|
|
<div className="flex h-full flex-col p-5">
|
|
<div className="flex flex-wrap items-center gap-2">
|
|
{item.type_label ? (
|
|
<span className="inline-flex items-center rounded-full border border-white/[0.08] bg-white/[0.04] px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-white/70 transition group-hover:border-white/20 group-hover:text-white">{item.type_label}</span>
|
|
) : null}
|
|
{item.category?.name ? (
|
|
<span className="inline-flex items-center rounded-full border border-sky-400/20 bg-sky-500/10 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-sky-200">{item.category.name}</span>
|
|
) : null}
|
|
{item.is_pinned ? (
|
|
<span className="inline-flex items-center rounded-full border border-amber-300/20 bg-amber-400/10 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-amber-100">Pinned</span>
|
|
) : item.is_featured ? (
|
|
<span className="inline-flex items-center rounded-full border border-emerald-300/20 bg-emerald-400/10 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-emerald-100">Featured</span>
|
|
) : null}
|
|
{item.date ? <span className="text-[11px] uppercase tracking-[0.16em] text-white/30">{formatDate(item.date)}</span> : null}
|
|
</div>
|
|
|
|
<h3 className="mt-3 text-xl font-semibold leading-tight text-white/95">
|
|
<a href={item.url} className="transition hover:text-sky-200">{item.title}</a>
|
|
</h3>
|
|
|
|
{item.excerpt ? <p className="mt-3 flex-1 text-sm leading-7 text-white/55">{item.excerpt}</p> : null}
|
|
|
|
<div className="mt-4 flex items-center justify-between gap-3 text-sm text-white/40">
|
|
<span className="truncate">{item.author?.name || 'Skinbase'}</span>
|
|
{typeof item.views === 'number' ? (
|
|
<span className="shrink-0 inline-flex items-center gap-1.5">
|
|
<i className="fa-regular fa-eye text-[11px]" />
|
|
{Number(item.views).toLocaleString()}
|
|
</span>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|