import { useNavigate } from 'react-router-dom'; import Header from '../views/articleeditor/Header'; import MarkdownEditor from '../views/articleeditor/Editor'; import { useEffect, useState } from 'react'; import { PrimaryButton } from '../components/button/PrimaryButton'; import MarkdownPreview from '../views/articleeditor/MarckDownPreview'; import { Input } from '../components/input/Input'; import { useAppDispatch, useAppSelector } from '../redux/hooks'; import { createArticle, deleteArticle, fetchArticleById, setArticlesStatus, updateArticle, } from '../redux/slices/articles'; import { useQuery } from '../hooks/useQuery'; import { ReverseButton } from '../components/button/ReverseButton'; import { cn } from '../lib/cn'; const ArticleEditor = () => { const navigate = useNavigate(); const dispatch = useAppDispatch(); const query = useQuery(); const back = query.get('back') ?? undefined; const articleId = Number(query.get('articleId') ?? undefined); const refactor = articleId && !isNaN(articleId); const [clickSubmit, setClickSubmit] = useState(false); // Достаём данные из redux const article = useAppSelector( (state) => state.articles.fetchArticleById.article, ); const statusCreate = useAppSelector( (state) => state.articles.createArticle.status, ); const statusUpdate = useAppSelector( (state) => state.articles.updateArticle.status, ); const statusDelete = useAppSelector( (state) => state.articles.deleteArticle.status, ); // Локальные состояния const [code, setCode] = useState(article?.content || ''); const [name, setName] = useState(article?.name || ''); const [tagInput, setTagInput] = useState(''); const [tags, setTags] = useState(article?.tags || []); const [activeEditor, setActiveEditor] = useState(false); // ========================== // Теги // ========================== const addTag = () => { const newTag = tagInput.trim(); if (newTag && !tags.includes(newTag)) { setTags([...tags, newTag]); setTagInput(''); } }; const removeTag = (tagToRemove: string) => { setTags(tags.filter((tag) => tag !== tagToRemove)); }; // ========================== // Эффекты по статусам // ========================== useEffect(() => { if (statusCreate === 'successful') { dispatch( setArticlesStatus({ key: 'createArticle', status: 'idle' }), ); navigate(back ?? '/home/articles'); } }, [statusCreate]); useEffect(() => { if (statusUpdate === 'successful') { dispatch( setArticlesStatus({ key: 'updateArticle', status: 'idle' }), ); navigate(back ?? '/home/articles'); } }, [statusUpdate]); useEffect(() => { if (statusDelete === 'successful') { dispatch( setArticlesStatus({ key: 'deleteArticle', status: 'idle' }), ); navigate(back ?? '/home/articles'); } }, [statusDelete]); // ========================== // Получение статьи // ========================== useEffect(() => { setClickSubmit(false); if (articleId) { dispatch(fetchArticleById(articleId)); } }, [articleId]); // Обновление локального состояния после загрузки статьи useEffect(() => { if (article && refactor) { setCode(article.content || ''); setName(article.name || ''); setTags(article.tags || []); } }, [article]); const getNameErrorMessage = (): string => { if (!clickSubmit) return ''; if (name == '') return 'Поле не может быть пустым'; return ''; }; const getContentErrorMessage = (): string => { if (!clickSubmit) return ''; if (code == '') return 'Поле не может быть пустым'; return ''; }; // ========================== // Рендер // ========================== return (
{activeEditor ? (
setActiveEditor(false)} /> ) : (
navigate(back ?? '/home/articles')} /> )} {activeEditor ? ( ) : (
{refactor ? `Редактирование статьи: \"${article?.name}\"` : 'Создание статьи'}
{/* Кнопки действий */}
{refactor ? (
{ setClickSubmit(true); dispatch( updateArticle({ articleId, name, tags, content: code, }), ); }} text="Обновить" className="mt-[20px]" disabled={statusUpdate === 'loading'} /> dispatch(deleteArticle(articleId)) } color="error" text="Удалить" className="mt-[20px]" disabled={statusDelete === 'loading'} />
) : ( { setClickSubmit(true); dispatch( createArticle({ name, tags, content: code, }), ); }} text="Опубликовать" className="mt-[20px]" disabled={statusCreate === 'loading'} /> )}
{/* Название */} {/* Теги */}
{ if (e.key === 'Enter') addTag(); }} />
{tags.map((tag) => (
{tag}
))}
{/* Просмотр и переход в редактор */} setActiveEditor(true)} text="Редактировать текст" className="mt-[20px]" />
{getContentErrorMessage()}
)}
); }; export default ArticleEditor;