Files
SkinbaseNova/resources/js/Pages/Studio/StudioWorldsIndex.jsx
2026-04-18 17:02:56 +02:00

71 lines
4.7 KiB
JavaScript

import React from 'react'
import { router, usePage } from '@inertiajs/react'
import StudioLayout from '../../Layouts/StudioLayout'
export default function StudioWorldsIndex() {
const { props } = usePage()
const listing = props.listing || {}
const items = Array.isArray(listing.items) ? listing.items : []
const filters = listing.filters || {}
const updateFilter = (name, value) => {
router.get('/studio/worlds', { ...filters, [name]: value }, { preserveState: true, replace: true })
}
return (
<StudioLayout title={props.title} subtitle={props.description}>
<div className="grid gap-6">
<section className="rounded-[28px] border border-white/10 bg-white/[0.03] p-5">
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_12rem_12rem_auto] lg:items-end">
<label className="grid gap-2 text-sm text-slate-300">
<span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Search</span>
<input value={filters.q || ''} onChange={(event) => updateFilter('q', event.target.value)} placeholder="Search title, slug, or summary" className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none" />
</label>
<label className="grid gap-2 text-sm text-slate-300">
<span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Status</span>
<select value={filters.status || ''} onChange={(event) => updateFilter('status', event.target.value)} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none">
<option value="">All statuses</option>
{(props.statusOptions || []).map((option) => <option key={option.value} value={option.value}>{option.label}</option>)}
</select>
</label>
<label className="grid gap-2 text-sm text-slate-300">
<span className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Type</span>
<select value={filters.type || ''} onChange={(event) => updateFilter('type', event.target.value)} className="rounded-2xl border border-white/10 bg-black/20 px-4 py-3 text-white outline-none">
<option value="">All types</option>
{(props.typeOptions || []).map((option) => <option key={option.value} value={option.value}>{option.label}</option>)}
</select>
</label>
<a href={props.createUrl} className="inline-flex items-center justify-center gap-2 rounded-2xl border border-sky-300/20 bg-sky-400/10 px-5 py-3 text-sm font-semibold text-sky-100 transition hover:bg-sky-400/15"><i className="fa-solid fa-plus" />New world</a>
</div>
</section>
<section className="grid gap-4 xl:grid-cols-2">
{items.length > 0 ? items.map((world) => (
<a key={world.id} href={world.edit_url} className="rounded-[28px] border border-white/10 bg-white/[0.03] p-5 transition hover:-translate-y-1 hover:border-white/20 hover:bg-white/[0.05]">
<div className="flex flex-wrap items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.18em] text-slate-500">
<span className="rounded-full border border-white/10 bg-black/20 px-3 py-1">{world.status}</span>
<span className="rounded-full border border-white/10 bg-black/20 px-3 py-1">{world.type}</span>
{world.is_featured ? <span className="rounded-full border border-amber-300/20 bg-amber-400/10 px-3 py-1 text-amber-100">Featured</span> : null}
</div>
<h2 className="mt-4 text-2xl font-semibold tracking-[-0.03em] text-white">{world.title}</h2>
<div className="mt-2 text-sm text-slate-500">/{world.slug}</div>
{world.summary ? <p className="mt-4 text-sm leading-6 text-slate-300">{world.summary}</p> : null}
<div className="mt-5 flex flex-wrap gap-4 text-sm text-slate-400">
{world.timeframe_label ? <span>{world.timeframe_label}</span> : null}
<span>{world.relation_count} relations</span>
{world.theme_key ? <span>{world.theme_key}</span> : null}
</div>
<div className="mt-5 flex flex-wrap gap-3 text-sm font-semibold">
<span className="text-sky-100">Edit</span>
<span className="text-slate-500">Preview</span>
{world.public_url ? <span className="text-slate-500">Public</span> : null}
</div>
</a>
)) : (
<div className="rounded-[28px] border border-dashed border-white/10 bg-white/[0.02] p-6 text-sm text-slate-400">No worlds match this filter yet.</div>
)}
</section>
</div>
</StudioLayout>
)
}