import { createEffect, createSignal, For, Show, on } from 'solid-js' import { Topic, useData } from '../context/data' import { query } from '../graphql' import { ADMIN_UPDATE_TOPIC_MUTATION } from '../graphql/mutations' import styles from '../styles/Form.module.css' import Modal from '../ui/Modal' import TopicPillsCloud, { type TopicPill } from '../ui/TopicPillsCloud' import HTMLEditor from '../ui/HTMLEditor' interface TopicEditModalProps { topic: Topic isOpen: boolean onClose: () => void onSave: (updatedTopic: Topic) => void onError?: (message: string) => void } export default function TopicEditModal(props: TopicEditModalProps) { const { communities, topics, getCommunityName, selectedCommunity } = useData() // Состояние формы const [formData, setFormData] = createSignal({ id: 0, title: '', slug: '', body: '', community: 0, parent_ids: [] as number[] }) // Состояние для выбора родителей const [availableParents, setAvailableParents] = createSignal([]) const [saving, setSaving] = createSignal(false) // Инициализация формы при открытии createEffect(() => { if (props.isOpen && props.topic) { const topicCommunity = props.topic.community || selectedCommunity() || 0 setFormData({ id: props.topic.id, title: props.topic.title || '', slug: props.topic.slug || '', body: props.topic.body || '', community: topicCommunity, parent_ids: props.topic.parent_ids || [] }) updateAvailableParents(topicCommunity, props.topic.id) } }) // Обновление доступных родителей при изменении сообщества в форме createEffect(on(() => formData().community, (communityId) => { if (communityId > 0) { updateAvailableParents(communityId) } })) // Обновление доступных родителей при смене сообщества const updateAvailableParents = (communityId: number, excludeTopicId?: number) => { const allTopics = topics() const currentTopicId = excludeTopicId || formData().id // Фильтруем топики того же сообщества, исключая текущий топик const filteredTopics = allTopics.filter( (topic) => topic.community === communityId && topic.id !== currentTopicId ) setAvailableParents(filteredTopics) } /** * Преобразование Topic в TopicPill для компонента TopicPillsCloud */ const convertTopicsToTopicPills = (topics: Topic[]): TopicPill[] => { return topics.map(topic => ({ id: topic.id.toString(), title: topic.title || '', slug: topic.slug || '', community: getCommunityName(topic.community), parent_ids: (topic.parent_ids || []).map(id => id.toString()), })) } /** * Обработка изменения выбора родительских топиков из таблеточек */ const handleParentSelectionChange = (selectedIds: string[]) => { const parentIds = selectedIds.map(id => Number.parseInt(id)) setFormData((prev) => ({ ...prev, parent_ids: parentIds })) } // Сообщество топика изменить нельзя, поэтому обработчик не нужен // Обработка изменения полей формы const handleFieldChange = (field: string, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })) } // Сохранение изменений const handleSave = async () => { try { setSaving(true) const topicData = formData() // Вызываем админскую мутацию для сохранения const result = await query<{ adminUpdateTopic: { success: boolean error?: string topic?: Topic } }>(`${location.origin}/graphql`, ADMIN_UPDATE_TOPIC_MUTATION, { topic: { id: topicData.id, title: topicData.title, slug: topicData.slug, body: topicData.body, community: topicData.community, parent_ids: topicData.parent_ids } }) if (result.adminUpdateTopic.success && result.adminUpdateTopic.topic) { console.log('[TopicEditModal] Topic saved successfully:', result.adminUpdateTopic.topic) props.onSave(result.adminUpdateTopic.topic) props.onClose() } else { const errorMessage = result.adminUpdateTopic.error || 'Неизвестная ошибка' throw new Error(errorMessage) } } catch (error) { console.error('[TopicEditModal] Error saving topic:', error) props.onError?.(error instanceof Error ? error.message : 'Ошибка сохранения топика') } finally { setSaving(false) } } return ( <> } >
{/* Основная информация */}
📍 Сообщество топика нельзя изменить после создания
{/* Содержимое */}
{/* Родительские топики */} 0}>
{/* Компонент с таблеточками для выбора родителей */}
id.toString())} onSelectionChange={handleParentSelectionChange} excludeTopics={[formData().id.toString()]} showSearch={true} searchPlaceholder="Задайте родительские темы..." hideSelectedInHeader={true} />
) }