import React from 'react' import { Head, Link, usePage } from '@inertiajs/react' function requestJson(url, { method = 'GET', body } = {}) { return fetch(url, { method, credentials: 'same-origin', headers: { Accept: 'application/json', 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '', 'X-Requested-With': 'XMLHttpRequest', }, body: body ? JSON.stringify(body) : undefined, }).then(async (response) => { const payload = await response.json().catch(() => ({})) if (!response.ok) throw new Error(payload?.message || 'Request failed') return payload }) } export default function NovaCardsAssetPackAdmin() { const { props } = usePage() const [packs, setPacks] = React.useState(props.packs || []) const [selectedId, setSelectedId] = React.useState(null) const [form, setForm] = React.useState({ slug: '', name: '', description: '', type: 'asset', preview_image: '', manifest_json: {}, official: true, active: true, order_num: 0 }) const endpoints = props.endpoints || {} function loadPack(pack) { setSelectedId(pack.id) setForm({ slug: pack.slug, name: pack.name, description: pack.description || '', type: pack.type || 'asset', preview_image: pack.preview_image || '', manifest_json: pack.manifest_json || {}, official: Boolean(pack.official), active: Boolean(pack.active), order_num: pack.order_num || 0, }) } function resetForm() { setSelectedId(null) setForm({ slug: '', name: '', description: '', type: 'asset', preview_image: '', manifest_json: {}, official: true, active: true, order_num: packs.length }) } async function savePack() { const isExisting = Boolean(selectedId) const url = isExisting ? String(endpoints.updatePattern || '').replace('__PACK__', String(selectedId)) : endpoints.store const response = await requestJson(url, { method: isExisting ? 'PATCH' : 'POST', body: form }) if (isExisting) { setPacks((current) => current.map((pack) => (pack.id === selectedId ? response.pack : pack))) } else { setPacks((current) => [...current, response.pack]) setSelectedId(response.pack.id) } } return (

V2 pack system

Official asset and template packs

Control the official packs exposed in the v2 editor and public pack directories.

Back to cards
Existing packs
{packs.map((pack) => ( ))}
Pack editor
setForm((current) => ({ ...current, name: event.target.value }))} placeholder="Pack name" className="rounded-2xl border border-white/10 bg-[#0d1726] px-4 py-3 text-white" /> setForm((current) => ({ ...current, slug: event.target.value }))} placeholder="Slug" className="rounded-2xl border border-white/10 bg-[#0d1726] px-4 py-3 text-white" />