diff --git a/src/blog/BlogEditor.tsx b/src/blog/BlogEditor.tsx
index 58eea01..987a8fe 100644
--- a/src/blog/BlogEditor.tsx
+++ b/src/blog/BlogEditor.tsx
@@ -1,4 +1,5 @@
import { LexicalComposer } from '@lexical/react/LexicalComposer';
+import type { InitialConfigType } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
@@ -15,7 +16,7 @@ import { LinkNode, AutoLinkNode } from '@lexical/link';
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin';
import { HashtagNode } from '@lexical/hashtag';
-import { forwardRef, useImperativeHandle, useEffect } from 'react';
+import { forwardRef, useImperativeHandle, useEffect, useRef } from 'react';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { ImageNode } from './nodes/ImageNode';
@@ -66,7 +67,7 @@ const MATCHERS = [
},
];
-const editorConfig = {
+const editorConfig: InitialConfigType = {
namespace: 'BlogEditor',
theme: editorTheme,
onError(error: Error) {
@@ -95,6 +96,10 @@ export interface BlogEditorRef {
getEditorState: () => string;
}
+interface BlogEditorProps {
+ initialContent?: string;
+}
+
// Plugin to expose editor instance via ref
function EditorRefPlugin({ editorRef }: { editorRef: React.Ref }) {
const [editor] = useLexicalComposerContext();
@@ -108,7 +113,30 @@ function EditorRefPlugin({ editorRef }: { editorRef: React.Ref })
return null;
}
-const BlogEditor = forwardRef((_, ref) => {
+function InitialContentPlugin({ initialContent }: { initialContent?: string }) {
+ const [editor] = useLexicalComposerContext();
+ const appliedContent = useRef(undefined);
+
+ useEffect(() => {
+ if (initialContent === undefined || initialContent === appliedContent.current) {
+ return;
+ }
+
+ try {
+ const editorState = initialContent
+ ? editor.parseEditorState(initialContent)
+ : editor.parseEditorState('{"root":{"children":[],"direction":null,"format":"","indent":0,"type":"root","version":1}}');
+ editor.setEditorState(editorState);
+ appliedContent.current = initialContent;
+ } catch (error) {
+ console.error('Failed to set initial editor content:', error);
+ }
+ }, [editor, initialContent]);
+
+ return null;
+}
+
+const BlogEditor = forwardRef(({ initialContent }, ref) => {
const { toasts, removeToast, success, error } = useToast();
// Setup toast handler for drag/drop plugin
@@ -150,6 +178,7 @@ const BlogEditor = forwardRef((_, ref) => {
+
diff --git a/src/blog/api.ts b/src/blog/api.ts
index bfd7445..021f8b7 100644
--- a/src/blog/api.ts
+++ b/src/blog/api.ts
@@ -11,6 +11,8 @@ import type {
ListPostsResponse,
ListTagsResponse,
GetPostResponse,
+ UpdatePostPayload,
+ UpdatePostResponse,
} from './types';
const API_BASE = '/api/blog';
@@ -113,6 +115,19 @@ export async function createBlogPost(
return response.json();
}
+/**
+ * Update an existing blog post
+ */
+export async function updateBlogPost(payload: UpdatePostPayload): Promise {
+ const response = await apiPost(`${API_BASE}/post/update`, payload);
+
+ if (!response.ok) {
+ throw new Error(`Failed to update post: ${response.statusText}`);
+ }
+
+ return response.json();
+}
+
/**
* Fetch a paginated list of blog posts
*/
diff --git a/src/blog/types.ts b/src/blog/types.ts
index 6f74c06..7e02f58 100644
--- a/src/blog/types.ts
+++ b/src/blog/types.ts
@@ -31,6 +31,7 @@ export interface BlogPostSummary {
postId: string;
title: string;
coverImageUrl?: string;
+ coverImageKey?: string;
createdAt: number;
updatedAt: number;
}
@@ -39,6 +40,17 @@ export interface BlogPost extends BlogPostSummary {
content: string;
}
+export interface UpdatePostPayload {
+ postId: string;
+ title: string;
+ content: string;
+ coverImageKey?: string;
+}
+
+export interface UpdatePostResponse {
+ postId: string;
+}
+
export interface ListPostsRequest {
page: number;
pageSize: number;
diff --git a/src/main.tsx b/src/main.tsx
index 6fca237..51c67d7 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -17,6 +17,7 @@ import Forum from './pages/Forum.tsx'
import AuthCallback from './pages/AuthCallback.tsx'
import EditorDemo from './pages/EditorDemo.tsx'
import BlogPost from './pages/BlogPost.tsx'
+import EditPost from './pages/EditPost.tsx'
createRoot(document.getElementById('root')!).render(
@@ -31,6 +32,7 @@ createRoot(document.getElementById('root')!).render(
} />
} />
} />
+ } />
} />
} />
} />
diff --git a/src/pages/Blog.tsx b/src/pages/Blog.tsx
index 6807a07..3931aa4 100644
--- a/src/pages/Blog.tsx
+++ b/src/pages/Blog.tsx
@@ -162,31 +162,6 @@ function Blog() {
{t('blog.subtitle')}
-
{
- event.currentTarget.style.transform = 'translateY(-2px)';
- event.currentTarget.style.boxShadow = '0 6px 18px var(--accent-shadow)';
- }}
- onMouseLeave={(event) => {
- event.currentTarget.style.transform = 'translateY(0)';
- event.currentTarget.style.boxShadow = 'none';
- }}
- >
- {t('blog.readMore')}
-
{selectedTags.length > 0 && (