'use client'; import { useState, useEffect } from 'react'; import { useParams, useRouter } from 'next/navigation'; import Image from 'next/image'; import { authorApi, getImageUrl } from '../../../../lib/api'; import { Author } from '../../../../types/api'; import AppLayout from '../../../../components/layout/AppLayout'; import { Input, Textarea } from '../../../../components/ui/Input'; import Button from '../../../../components/ui/Button'; import ImageUpload from '../../../../components/ui/ImageUpload'; import LoadingSpinner from '../../../../components/ui/LoadingSpinner'; export default function EditAuthorPage() { const params = useParams(); const router = useRouter(); const authorId = params.id as string; const [author, setAuthor] = useState(null); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [errors, setErrors] = useState>({}); const [formData, setFormData] = useState({ name: '', notes: '', authorRating: 0, urls: [] as string[], }); const [avatarImage, setAvatarImage] = useState(null); useEffect(() => { const loadAuthor = async () => { try { setLoading(true); const authorData = await authorApi.getAuthor(authorId); setAuthor(authorData); // Initialize form with author data setFormData({ name: authorData.name, notes: authorData.notes || '', authorRating: authorData.authorRating || 0, urls: authorData.urls || [], }); } catch (error) { console.error('Failed to load author:', error); router.push('/authors'); } finally { setLoading(false); } }; if (authorId) { loadAuthor(); } }, [authorId, router]); const handleInputChange = (field: string) => ( e: React.ChangeEvent ) => { setFormData(prev => ({ ...prev, [field]: e.target.value })); // Clear error when user starts typing if (errors[field]) { setErrors(prev => ({ ...prev, [field]: '' })); } }; const handleRatingChange = (rating: number) => { setFormData(prev => ({ ...prev, authorRating: rating })); }; const addUrl = () => { setFormData(prev => ({ ...prev, urls: [...prev.urls, ''] })); }; const updateUrl = (index: number, value: string) => { setFormData(prev => ({ ...prev, urls: prev.urls.map((url, i) => i === index ? value : url) })); }; const removeUrl = (index: number) => { setFormData(prev => ({ ...prev, urls: prev.urls.filter((_, i) => i !== index) })); }; const validateForm = () => { const newErrors: Record = {}; if (!formData.name.trim()) { newErrors.name = 'Author name is required'; } // Validate URLs formData.urls.forEach((url, index) => { if (url.trim() && !url.match(/^https?:\/\/.+/)) { newErrors[`url_${index}`] = 'Please enter a valid URL'; } }); setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!validateForm() || !author) { return; } setSaving(true); try { // Prepare form data for multipart upload const updateFormData = new FormData(); updateFormData.append('name', formData.name); updateFormData.append('notes', formData.notes); if (formData.authorRating > 0) { updateFormData.append('authorRating', formData.authorRating.toString()); } // Add URLs as multiple parameters with same name const validUrls = formData.urls.filter(url => url.trim()); validUrls.forEach((url) => { updateFormData.append('urls', url); }); // Add avatar if selected if (avatarImage) { updateFormData.append('avatarImage', avatarImage); } await authorApi.updateAuthor(authorId, updateFormData); router.push(`/authors/${authorId}`); } catch (error: any) { console.error('Failed to update author:', error); const errorMessage = error.response?.data?.message || 'Failed to update author'; setErrors({ submit: errorMessage }); } finally { setSaving(false); } }; const handleAvatarUpload = async () => { if (!avatarImage || !author) return; try { setSaving(true); await authorApi.uploadAvatar(authorId, avatarImage); setAvatarImage(null); // Reload to show new avatar window.location.reload(); } catch (error) { console.error('Failed to upload avatar:', error); setErrors({ submit: 'Failed to upload avatar' }); } finally { setSaving(false); } }; const handleRemoveAvatar = async () => { if (!author?.avatarImagePath) return; if (!confirm('Are you sure you want to remove the current avatar?')) return; try { setSaving(true); await authorApi.removeAvatar(authorId); // Reload to show removed avatar window.location.reload(); } catch (error) { console.error('Failed to remove avatar:', error); setErrors({ submit: 'Failed to remove avatar' }); } finally { setSaving(false); } }; if (loading) { return (
); } if (!author) { return (

Author Not Found

); } return (

Edit Author

Make changes to {author.name}

{/* Left Column - Avatar and Basic Info */}
{/* Current Avatar */}
{author.avatarImagePath ? ( {author.name} ) : (
👤
)}
{author.avatarImagePath && ( )}
{/* New Avatar Upload */}
{avatarImage && (
)}
{/* Rating */}
{[1, 2, 3, 4, 5].map((star) => ( ))}
{formData.authorRating > 0 && (

{formData.authorRating}/5 stars

)}
{/* Right Column - Details */}
{/* Name */} {/* Notes */}