import React, { useState } from 'react'; import { Header } from '../components/Header'; import { AuthGuard } from '../components/AuthGuard'; import { AuthorFormData } from '../types/auth'; import { useAuthorManagement } from '../hooks/useAuthorManagement'; import { ImagePlus, X, UserPlus, Pencil, Link as LinkIcon, Link2Off as LinkOff, ToggleLeft, ToggleRight, Trash2, ChevronDown, ChevronUp } from 'lucide-react'; import { imageResolutions } from '../config/imageResolutions'; import { useAuthStore } from '../stores/authStore'; import axios from "axios"; const initialFormData: AuthorFormData = { id: '', displayName: '', email: '', bio: '', avatarUrl: '/images/avatar.jpg', order: 0, okUrl: '', vkUrl: '', websiteUrl: '', articlesCount: 0, isActive: true }; export function AuthorManagementPage() { const { authors, users, selectedAuthor, loading, error, setSelectedAuthor, createAuthor, updateAuthor, linkUser, unlinkUser, orderMoveUp, orderMoveDown, toggleActive, deleteAuthor, fetchAuthors, fetchUsers, } = useAuthorManagement(); const { user } = useAuthStore(); const [showCreateModal, setShowCreateModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); const [showLinkUserModal, setShowLinkUserModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(null); const [formData, setFormData] = useState(initialFormData); const [formError, setFormError] = useState(null); const [selectedUserId, setSelectedUserId] = useState(''); const handleAvatarUpload = async (event: React.ChangeEvent, authorId: string) => { const file = event.target.files?.[0]; if (!file) return; try { const resolution = imageResolutions.find(r => r.id === 'thumbnail'); if (!resolution) throw new Error('Invalid resolution'); const formData = new FormData(); formData.append('file', file); formData.append('resolutionId', resolution.id); formData.append('folder', 'authors/' + authorId); const response = await axios.post('/api/images/upload-url', formData, { headers: { 'Content-Type': 'multipart/form-data', 'Authorization': `Bearer ${localStorage.getItem('token')}`, // Передача токена аутентификации }, }); setFormData(prev => ({ ...prev, avatarUrl: response.data?.fileUrl })); } catch (error) { setFormError('Ошибка загрузки аватара. Повторите попытку.'); console.error('Ошибка загрузки:', error); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setFormError(null); try { if (showCreateModal) { await createAuthor(formData); setShowCreateModal(false); } else if (showEditModal && selectedAuthor) { await updateAuthor(selectedAuthor.id, formData); setShowEditModal(false); await fetchAuthors(); } setFormData(initialFormData); } catch (error) { setFormError(error instanceof Error ? error.message : 'An error occurred'); } }; const handleLinkUser = async (authorId: string, userId: string) => { if (!selectedAuthor || !selectedUserId) return; try { await linkUser(authorId, userId); setShowLinkUserModal(false); setSelectedUserId(''); await fetchAuthors(); await fetchUsers(); } catch { setFormError('Failed to link user to author'); } }; const handleUnlinkUser = async (authorId: string) => { try { await unlinkUser(authorId); await fetchAuthors(); await fetchUsers(); } catch { setFormError('Failed to unlink user from author'); } }; const handleMoveUp = async (authorId: string) => { await orderMoveUp(authorId); fetchAuthors(); }; const handleMoveDown = async (authorId: string) => { await orderMoveDown(authorId); fetchAuthors(); }; const handleToggleActive = async (authorId: string, isActive: boolean) => { try { await toggleActive(authorId, isActive); await fetchAuthors(); } catch { setFormError('Failed to toggle author status'); } }; const handleDeleteAuthor = async (authorId: string) => { try { await deleteAuthor(authorId); setShowDeleteModal(null) } catch { setFormError('Failed to delete author'); } }; if (loading) { return (
); } return (

Управление авторами

{error && (
{error}
)}
    {authors.map((author, index) => (
  • {author.displayName}

    {author.displayName} {author.userId ? `=> пользователь ${author.displayName}` : ``}

    {author.bio}

    {author.okUrl && ( Одноклассники )} {author.vkUrl && ( Вконтакте )} {author.websiteUrl && ( Website )}
    {author.userId ? ( ) : ( )}
  • ))}
{/* Create/Edit Author Modal */} {((showCreateModal || showEditModal) && user?.permissions.isAdmin ) && (

{showCreateModal ? 'Новый автор' : 'Изменить автора'}

{formError && (
{formError}
)}
Author avatar
setFormData(prev => ({ ...prev, displayName: e.target.value }))} className="px-2 py-1 mt-1 block w-full rounded-lg border border-gray-300 shadow-sm hover:border-blue-300 focus:border-blue-500 focus:ring-4 focus:ring-blue-100 transition-all duration-200" required />