import React, { useState } from 'react' import { router, useForm, usePage } from '@inertiajs/react' import StudioLayout from '../../Layouts/StudioLayout' function SearchResultList({ items, onSelect, emptyLabel = 'No matches yet.' }) { if (!Array.isArray(items) || items.length === 0) { return
{emptyLabel}
} return (
{items.map((item) => ( ))}
) } function RelationCard({ relation, index, onChange, onRemove, onSearch, results, relationTypeOptions }) { return (
{relation.preview ? (
Linked: {relation.preview.title}
{relation.preview.subtitle ?
{relation.preview.subtitle}
: null}
) : null}
onChange(index, { ...relation, entity_id: item.id, preview: item, query: item.title })} emptyLabel="Search to attach a related entity." />
) } export default function StudioNewsEditor() { const { props } = usePage() const article = props.article || {} const [authorResults, setAuthorResults] = useState([]) const [authorQuery, setAuthorQuery] = useState(article.author?.title || article.author?.subtitle?.replace(/^@/, '') || '') const [selectedAuthor, setSelectedAuthor] = useState(article.author || props.defaultAuthor || null) const [relationResults, setRelationResults] = useState({}) const form = useForm({ title: article.title || '', slug: article.slug || '', excerpt: article.excerpt || '', content: article.content || '', cover_image: article.cover_image || '', type: article.type || (props.typeOptions?.[0]?.value || 'announcement'), category_id: article.category_id || '', author_id: article.author_id || props.defaultAuthor?.id || '', editorial_status: article.editorial_status || 'draft', published_at: article.published_at ? String(article.published_at).slice(0, 16) : '', is_featured: Boolean(article.is_featured), is_pinned: Boolean(article.is_pinned), tag_ids: Array.isArray(article.tag_ids) ? article.tag_ids : [], meta_title: article.meta_title || '', meta_description: article.meta_description || '', meta_keywords: article.meta_keywords || '', canonical_url: article.canonical_url || '', og_title: article.og_title || '', og_description: article.og_description || '', og_image: article.og_image || '', relations: Array.isArray(article.relations) ? article.relations.map((relation) => ({ entity_type: relation.entity_type || 'group', entity_id: relation.entity_id || '', context_label: relation.context_label || '', preview: relation.preview || null, query: relation.preview?.title || '', })) : [], }) const submit = (event) => { event.preventDefault() if (props.updateUrl) { form.patch(props.updateUrl) return } form.post(props.storeUrl) } const searchEntities = async (type, query) => { const url = new URL(props.entitySearchUrl, window.location.origin) url.searchParams.set('type', type) url.searchParams.set('q', query) const response = await fetch(url.toString(), { headers: { Accept: 'application/json', }, credentials: 'same-origin', }) if (!response.ok) { return [] } const payload = await response.json() return Array.isArray(payload.items) ? payload.items : [] } const runAuthorSearch = async () => { const items = await searchEntities('user', authorQuery) setAuthorResults(items) } const addRelation = () => { form.setData('relations', [ ...form.data.relations, { entity_type: props.relationTypeOptions?.[0]?.value || 'group', entity_id: '', context_label: '', preview: null, query: '', }, ]) } const updateRelation = (index, nextRelation) => { form.setData('relations', form.data.relations.map((relation, relationIndex) => (relationIndex === index ? nextRelation : relation))) } const removeRelation = (index) => { form.setData('relations', form.data.relations.filter((_, relationIndex) => relationIndex !== index)) setRelationResults((current) => { const next = { ...current } delete next[index] return next }) } const runRelationSearch = async (index) => { const relation = form.data.relations[index] if (!relation) return const items = await searchEntities(relation.entity_type, relation.query || '') setRelationResults((current) => ({ ...current, [index]: items })) } return (