Replace native selects with NovaSelect

This commit is contained in:
2026-05-01 07:45:37 +02:00
parent 67be537c86
commit 35011001ba
55 changed files with 3136 additions and 1662 deletions

View File

@@ -1,6 +1,9 @@
import React from 'react'
import { router, usePage } from '@inertiajs/react'
import StudioLayout from '../../Layouts/StudioLayout'
import WorldStatusBadge from '../../components/worlds/WorldStatusBadge'
import WorldAnalyticsPortfolioPanel from '../../components/worlds/editor/analytics/WorldAnalyticsPortfolioPanel'
import NovaSelect from '../../components/ui/NovaSelect'
export default function StudioWorldsIndex() {
const { props } = usePage()
@@ -15,26 +18,22 @@ export default function StudioWorldsIndex() {
return (
<StudioLayout title={props.title} subtitle={props.description}>
<div className="grid gap-6">
<WorldAnalyticsPortfolioPanel analytics={props.analytics} />
<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">
<div 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">
<NovaSelect value={filters.status || ''} onChange={(val) => updateFilter('status', val)} options={[{ value: '', label: 'All statuses' }, ...(props.statusOptions || [])]} searchable={false} />
</div>
<div 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>
<NovaSelect value={filters.type || ''} onChange={(val) => updateFilter('type', val)} options={[{ value: '', label: 'All types' }, ...(props.typeOptions || [])]} searchable={false} />
</div>
<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>
@@ -43,16 +42,18 @@ export default function StudioWorldsIndex() {
{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}
<WorldStatusBadge badge={{ label: world.status, tone: 'slate' }} />
<WorldStatusBadge badge={{ label: world.type, tone: 'slate' }} />
{(Array.isArray(world.status_badges) ? world.status_badges : []).map((badge) => <WorldStatusBadge key={`${world.id}-${badge.label}`} badge={badge} />)}
</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}
{world.promotion_window_label ? <span>{world.promotion_window_label}</span> : null}
<span>{world.relation_count} relations</span>
{world.live_submission_count > 0 ? <span>{world.live_submission_count} live submissions</span> : null}
{world.theme_key ? <span>{world.theme_key}</span> : null}
</div>
<div className="mt-5 flex flex-wrap gap-3 text-sm font-semibold">