import { useEffect, useRef, useState } from 'react'; import { Navigate, useNavigate, useParams } from 'react-router-dom'; import Layout from '../components/Layout'; import BlogEditor, { type BlogEditorRef } from '../blog/BlogEditor'; import { getBlogPost, updateBlogPost, uploadImage } from '../blog/api'; import { Toast } from '../components/Toast'; import { useToast } from '../hooks/useToast'; import { useAuth } from '../contexts/AuthContext'; import '../App.css'; function EditPost() { const { postId } = useParams<{ postId: string }>(); const navigate = useNavigate(); const editorRef = useRef(null); const fileInputRef = useRef(null); const { toasts, removeToast, success, error } = useToast(); const { isAuthenticated } = useAuth(); const [isLoading, setIsLoading] = useState(true); const [loadError, setLoadError] = useState(null); const [title, setTitle] = useState(''); const [initialContent, setInitialContent] = useState(undefined); const [coverImage, setCoverImage] = useState(null); const [coverImageKey, setCoverImageKey] = useState(''); const [uploadProgress, setUploadProgress] = useState(0); const [isUploading, setIsUploading] = useState(false); const [uploadError, setUploadError] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); useEffect(() => { if (!postId) { setLoadError('Post not found.'); setIsLoading(false); return; } (async () => { try { const fetched = await getBlogPost(postId); setTitle(fetched.title); setInitialContent(fetched.content); setCoverImage(fetched.coverImageUrl ?? null); setCoverImageKey(fetched.coverImageKey ?? ''); } catch (err) { const message = err instanceof Error ? err.message : 'Failed to load post.'; setLoadError(message); console.error('Failed to load blog post for editing:', err); } finally { setIsLoading(false); } })(); }, [postId]); const handleCoverImageChange = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) { return; } if (!file.type.startsWith('image/')) { setUploadError('Please select an image file'); return; } const reader = new FileReader(); reader.onload = (e) => { setCoverImage(e.target?.result as string); }; reader.readAsDataURL(file); setIsUploading(true); setUploadError(''); setUploadProgress(0); try { const { fileKey, url } = await uploadImage(file, (progress) => { setUploadProgress(progress); }); setCoverImageKey(fileKey); setCoverImage(url); setUploadProgress(100); success('Cover image uploaded successfully!', 2000); } catch (err) { const message = err instanceof Error ? err.message : 'Upload failed'; setUploadError(message); error(`Cover image upload failed: ${message}`); } finally { setIsUploading(false); } }; const handleSubmit = async () => { if (!postId) { error('Invalid post identifier.'); return; } if (!title.trim()) { error('Please enter a title'); return; } if (!editorRef.current) { error('Editor not initialized'); return; } const content = editorRef.current.getEditorState(); if (!coverImageKey) { error('Please upload a cover image'); return; } setIsSubmitting(true); try { await updateBlogPost({ postId, title: title.trim(), content, coverImageKey, }); success('Blog post updated successfully!', 2000); setTimeout(() => { navigate(`/blog/${postId}`); }, 1500); } catch (err) { const message = err instanceof Error ? err.message : 'Failed to update blog post'; error(`Failed to update post: ${message}`); } finally { setIsSubmitting(false); } }; if (!isAuthenticated) { return ; } return (
{isLoading ? (
Loading post...
) : loadError ? (
{loadError}
) : ( <>

Edit Post

Update your article content and cover image

setTitle(e.target.value)} placeholder="Enter your blog post title..." style={{ width: '100%', padding: '1rem', fontSize: '1.2rem', border: '2px solid var(--border-color)', borderRadius: '8px', background: 'var(--bg-card)', color: 'var(--text-primary)', outline: 'none', transition: 'border-color 0.3s ease', }} onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--accent-color)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = 'var(--border-color)'; }} />
fileInputRef.current?.click()} onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--accent-color)'; }} onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--border-color)'; }} > {coverImage ? (
Cover {isUploading && (
Uploading... {Math.round(uploadProgress)}%
)}
) : (
📷

Click to upload cover image

PNG, JPG, GIF up to 10MB

)}
{uploadError && (
❌ {uploadError}
)}
)}
); } export default EditPost;