107 lines
4.1 KiB
JavaScript
107 lines
4.1 KiB
JavaScript
import React from 'react'
|
|
|
|
function GroupSpotlightCard({ group }) {
|
|
if (!group) return null
|
|
|
|
const stats = [
|
|
{ key: 'artworks', label: 'artworks', value: Number(group.counts?.artworks || 0) },
|
|
{ key: 'members', label: 'members', value: Number(group.counts?.members || 0) },
|
|
{ key: 'followers', label: 'followers', value: Number(group.counts?.followers || 0) },
|
|
].filter((item) => item.value > 0)
|
|
|
|
return (
|
|
<article className="group relative flex flex-col overflow-hidden rounded-xl bg-panel p-5 shadow-sm transition hover:ring-1 hover:ring-nova-500">
|
|
{group.banner_url ? (
|
|
<>
|
|
<img
|
|
src={group.banner_url}
|
|
alt=""
|
|
aria-hidden="true"
|
|
className="pointer-events-none absolute inset-0 h-full w-full object-cover opacity-40 transition duration-500 group-hover:scale-105 group-hover:opacity-20"
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-panel via-panel/85 to-panel/70" />
|
|
</>
|
|
) : null}
|
|
|
|
<a href={group.urls?.public || '/groups'} className="relative block">
|
|
<div className="flex h-16 w-16 items-center justify-center overflow-hidden rounded-2xl bg-nova-800/80 ring-4 ring-nova-800">
|
|
{group.avatar_url ? (
|
|
<img
|
|
src={group.avatar_url}
|
|
alt={group.name}
|
|
className="h-full w-full object-cover"
|
|
loading="lazy"
|
|
decoding="async"
|
|
/>
|
|
) : (
|
|
<i className="fa-solid fa-people-group text-2xl text-white" aria-hidden="true" />
|
|
)}
|
|
</div>
|
|
<h3 className="mt-3 text-base font-semibold text-white">{group.name}</h3>
|
|
</a>
|
|
|
|
<p className="relative mt-2 line-clamp-3 text-sm text-soft">
|
|
{group.headline || group.bio_excerpt || 'Shared publishing identity for collaborative releases and artwork.'}
|
|
</p>
|
|
|
|
<div className="relative mt-3 flex flex-wrap gap-2 text-xs text-soft">
|
|
{group.is_recruiting ? <span className="rounded-full bg-emerald-400/15 px-2.5 py-1 font-semibold text-emerald-200">Recruiting</span> : null}
|
|
{group.is_verified ? <span className="rounded-full bg-sky-400/15 px-2.5 py-1 font-semibold text-sky-200">Verified</span> : null}
|
|
{group.owner?.username || group.owner?.name ? <span>Led by {group.owner?.username || group.owner?.name}</span> : null}
|
|
</div>
|
|
|
|
{stats.length > 0 ? (
|
|
<div className="relative mt-4 flex flex-wrap gap-3 text-xs text-soft">
|
|
{stats.map((item) => (
|
|
<span key={item.key}>
|
|
{item.value.toLocaleString()} {item.label}
|
|
</span>
|
|
))}
|
|
</div>
|
|
) : null}
|
|
|
|
<a
|
|
href={group.urls?.public || '/groups'}
|
|
className="relative mt-4 inline-flex w-fit rounded-lg bg-nova-700 px-4 py-1.5 text-xs font-semibold text-white transition hover:bg-nova-600"
|
|
>
|
|
View Group
|
|
</a>
|
|
</article>
|
|
)
|
|
}
|
|
|
|
export default function HomeGroups({ groups }) {
|
|
const spotlightGroups = [
|
|
groups?.spotlight,
|
|
...(Array.isArray(groups?.featured) ? groups.featured : []),
|
|
...(Array.isArray(groups?.recruiting) ? groups.recruiting : []),
|
|
...(Array.isArray(groups?.rising) ? groups.rising : []),
|
|
].filter(Boolean)
|
|
|
|
const uniqueGroups = spotlightGroups.filter((group, index, items) => (
|
|
items.findIndex((candidate) => candidate?.id === group?.id) === index
|
|
)).slice(0, 4)
|
|
|
|
if (uniqueGroups.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">Group Spotlight</h2>
|
|
<a href="/groups" className="text-sm text-nova-300 transition hover:text-white">
|
|
All groups ->
|
|
</a>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
{uniqueGroups.map((group) => (
|
|
<GroupSpotlightCard key={group.id} group={group} />
|
|
))}
|
|
</div>
|
|
</section>
|
|
)
|
|
} |