110 lines
8.1 KiB
JavaScript
110 lines
8.1 KiB
JavaScript
import React from 'react'
|
|
import { usePage } from '@inertiajs/react'
|
|
import SeoHead from '../../components/seo/SeoHead'
|
|
|
|
function ArtworkGrid({ artworks }) {
|
|
if (!Array.isArray(artworks) || artworks.length === 0) {
|
|
return <p className="mt-4 text-sm text-slate-400">No linked artworks yet.</p>
|
|
}
|
|
|
|
return (
|
|
<div className="mt-4 grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
|
|
{artworks.map((artwork) => (
|
|
<a key={artwork.id} href={artwork.url} className="overflow-hidden rounded-[24px] border border-white/10 bg-black/20 transition hover:border-white/20">
|
|
{artwork.thumb ? <img src={artwork.thumb} alt={artwork.title} className="aspect-[4/3] w-full object-cover" /> : null}
|
|
<div className="p-4">
|
|
<h3 className="text-base font-semibold text-white">{artwork.title}</h3>
|
|
<p className="mt-1 text-sm text-slate-400">{artwork.author || 'Artwork'}</p>
|
|
</div>
|
|
</a>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default function GroupReleaseShow() {
|
|
const { props } = usePage()
|
|
const group = props.group || {}
|
|
const release = props.release || {}
|
|
const contributors = Array.isArray(release.contributors) ? release.contributors : []
|
|
const milestones = Array.isArray(release.milestones) ? release.milestones : []
|
|
|
|
return (
|
|
<main className="min-h-screen bg-[radial-gradient(circle_at_top_left,_rgba(56,189,248,0.16),_transparent_28%),linear-gradient(180deg,_#020617_0%,_#02040a_100%)] px-4 py-10 sm:px-6 lg:px-8">
|
|
<SeoHead seo={props.seo || {}} title={`${release.title || group.name} - Skinbase`} description={release.summary || release.description || group.headline || 'Group release'} />
|
|
<div className="mx-auto max-w-6xl space-y-8">
|
|
<section className="overflow-hidden rounded-[32px] border border-white/10 bg-white/[0.03]">
|
|
{release.cover_url ? <img src={release.cover_url} alt={release.title} className="h-64 w-full object-cover" /> : <div className="h-44 bg-white/[0.03]" />}
|
|
<div className="p-6">
|
|
<div className="flex flex-wrap items-center gap-3">
|
|
<a href={group.urls?.public} className="text-sm font-semibold text-sky-200">{group.name}</a>
|
|
{release.status ? <span className="rounded-full border border-white/10 bg-white/[0.04] px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-300">{release.status}</span> : null}
|
|
{release.current_stage ? <span className="rounded-full border border-white/10 bg-white/[0.04] px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-300">{release.current_stage}</span> : null}
|
|
</div>
|
|
<h1 className="mt-4 text-4xl font-semibold text-white">{release.title}</h1>
|
|
{release.summary ? <p className="mt-4 max-w-3xl text-sm leading-7 text-slate-300">{release.summary}</p> : null}
|
|
<div className="mt-5 flex flex-wrap gap-4 text-xs text-slate-400">
|
|
{release.released_at ? <span>Released {new Date(release.released_at).toLocaleDateString()}</span> : null}
|
|
{release.planned_release_at ? <span>Planned {new Date(release.planned_release_at).toLocaleDateString()}</span> : null}
|
|
{release.lead?.name || release.lead?.username ? <span>Lead: {release.lead?.name || release.lead?.username}</span> : null}
|
|
<span>{release.counts?.artworks || 0} artworks</span>
|
|
<span>{release.counts?.contributors || 0} contributors</span>
|
|
<span>{release.counts?.milestones || 0} milestones</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<div className="grid gap-8 xl:grid-cols-[minmax(0,1.15fr)_minmax(0,0.85fr)]">
|
|
<section className="rounded-[30px] border border-white/10 bg-white/[0.03] p-6">
|
|
<h2 className="text-2xl font-semibold text-white">Overview</h2>
|
|
<p className="mt-4 text-sm leading-7 text-slate-300">{release.description || 'No long-form release description yet.'}</p>
|
|
{release.release_notes ? <div className="mt-6 rounded-[24px] border border-white/10 bg-black/20 p-4"><div className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Release notes</div><div className="mt-3 whitespace-pre-wrap text-sm leading-7 text-slate-300">{release.release_notes}</div></div> : null}
|
|
<ArtworkGrid artworks={release.artworks} />
|
|
</section>
|
|
|
|
<div className="space-y-8">
|
|
<section className="rounded-[30px] border border-white/10 bg-white/[0.03] p-6">
|
|
<h2 className="text-2xl font-semibold text-white">Links</h2>
|
|
<div className="mt-4 space-y-3">
|
|
{release.linked_project?.url ? <a href={release.linked_project.url} className="block rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-sm text-white"><div className="font-semibold">{release.linked_project.title}</div><div className="mt-1 text-xs uppercase tracking-[0.16em] text-slate-400">Linked project</div></a> : null}
|
|
{release.linked_collection?.url ? <a href={release.linked_collection.url} className="block rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-sm text-white"><div className="font-semibold">{release.linked_collection.title}</div><div className="mt-1 text-xs uppercase tracking-[0.16em] text-slate-400">Linked collection</div></a> : null}
|
|
{release.featured_artwork ? <div className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-sm text-white"><div className="font-semibold">{release.featured_artwork.title}</div><div className="mt-1 text-xs uppercase tracking-[0.16em] text-slate-400">Featured artwork</div></div> : null}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="rounded-[30px] border border-white/10 bg-white/[0.03] p-6">
|
|
<h2 className="text-2xl font-semibold text-white">Contributors</h2>
|
|
<div className="mt-4 space-y-3">
|
|
{contributors.length > 0 ? contributors.map((contributor) => (
|
|
<div key={contributor.id} className="flex items-center gap-3 rounded-2xl border border-white/10 bg-black/20 px-4 py-3">
|
|
{contributor.avatar_url ? <img src={contributor.avatar_url} alt={contributor.name || contributor.username} className="h-11 w-11 rounded-2xl object-cover" /> : <div className="flex h-11 w-11 items-center justify-center rounded-2xl border border-white/10 bg-white/[0.03] text-slate-400"><i className="fa-solid fa-user" /></div>}
|
|
<div className="min-w-0">
|
|
<div className="truncate font-semibold text-white">{contributor.name || contributor.username}</div>
|
|
<div className="text-xs uppercase tracking-[0.16em] text-slate-400">{contributor.role_label || 'Contributor'}</div>
|
|
</div>
|
|
</div>
|
|
)) : <p className="text-sm text-slate-400">No contributor credits yet.</p>}
|
|
</div>
|
|
</section>
|
|
|
|
<section className="rounded-[30px] border border-white/10 bg-white/[0.03] p-6">
|
|
<h2 className="text-2xl font-semibold text-white">Milestones</h2>
|
|
<div className="mt-4 space-y-3">
|
|
{milestones.length > 0 ? milestones.map((milestone) => (
|
|
<div key={milestone.id} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-4">
|
|
<div className="flex items-center justify-between gap-3">
|
|
<div className="font-semibold text-white">{milestone.title}</div>
|
|
<span className="rounded-full border border-white/10 bg-white/[0.04] px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-300">{milestone.status}</span>
|
|
</div>
|
|
{milestone.summary ? <p className="mt-2 text-sm text-slate-400">{milestone.summary}</p> : null}
|
|
<div className="mt-2 text-xs text-slate-500">{milestone.owner?.name || milestone.owner?.username || 'No owner'}{milestone.due_date ? ` • due ${milestone.due_date}` : ''}</div>
|
|
</div>
|
|
)) : <p className="text-sm text-slate-400">No milestones defined yet.</p>}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
)
|
|
} |