source: frontend/src/pages/Blogs.tsx@ 700e2f9

main
Last change on this file since 700e2f9 was 700e2f9, checked in by 186079 <matej.milevski@…>, 5 days ago

Init

  • Property mode set to 100644
File size: 4.7 KB
Line 
1import {
2 type Component,
3 createEffect,
4 createSignal,
5 createResource,
6 Show,
7} from "solid-js";
8import { useNavigate } from "@solidjs/router";
9import { useAuth } from "@/context/AuthContext";
10import { blogApi, type BlogPost } from "@/api/blog";
11import BlogList from "@/components/BlogList";
12import BlogModal from "@/components/BlogModal";
13import CreateBlogForm from "@/components/CreateBlogForm";
14import { UserType } from "@/enums/UserType";
15
16const Blogs: Component = () => {
17 const { user, isAuthenticated } = useAuth();
18 const navigate = useNavigate();
19 const [showCreateForm, setShowCreateForm] = createSignal(false);
20 const [selectedBlogId, setSelectedBlogId] = createSignal<number | null>(null);
21 const [editMode, setEditMode] = createSignal(false);
22
23 const [blogs, { refetch: refetchBlogs }] = createResource(async () => {
24 if (!isAuthenticated()) return [];
25 return await blogApi.getAllBlogs();
26 });
27
28 const [selectedBlog, { refetch: refetchSelectedBlog }] = createResource(
29 selectedBlogId,
30 async (id) => {
31 if (!id) return null;
32 return await blogApi.getBlog(id);
33 },
34 );
35
36 createEffect(() => {
37 if (!isAuthenticated()) {
38 navigate("/login", { replace: true });
39 return;
40 }
41
42 const currentUser = user();
43 if (currentUser?.userType !== UserType.PATIENT) {
44 navigate("/", { replace: true });
45 }
46 });
47
48 const handleCreateBlog = async (title: string, content: string) => {
49 await blogApi.createBlog({ title, content });
50 setShowCreateForm(false);
51 refetchBlogs();
52 };
53
54 const handleLike = async (blogId: number) => {
55 try {
56 await blogApi.toggleLike(blogId);
57 } finally {
58 refetchBlogs();
59 if (selectedBlogId() === blogId) {
60 refetchSelectedBlog();
61 }
62 }
63 };
64
65 const handleAddComment = async (content: string) => {
66 const blog = selectedBlog();
67 if (!blog) return;
68
69 await blogApi.addComment(blog.idBlog, content);
70 refetchBlogs();
71 refetchSelectedBlog();
72 };
73
74 const handleUpdateBlog = async (
75 blogId: number,
76 title: string,
77 content: string,
78 ) => {
79 await blogApi.updateBlog(blogId, { title, content });
80 refetchBlogs();
81 if (selectedBlogId() === blogId) {
82 refetchSelectedBlog();
83 }
84 };
85
86 const handleDeleteBlog = async (blogId: number) => {
87 await blogApi.deleteBlog(blogId);
88 if (selectedBlogId() === blogId) {
89 closeBlog();
90 }
91 refetchBlogs();
92 };
93
94 const handleUpdateComment = async (commentId: number, content: string) => {
95 await blogApi.updateComment(commentId, content);
96 refetchBlogs();
97 refetchSelectedBlog();
98 };
99
100 const handleDeleteComment = async (commentId: number) => {
101 await blogApi.deleteComment(commentId);
102 refetchBlogs();
103 refetchSelectedBlog();
104 };
105
106 const openBlog = (blog: BlogPost) => {
107 setSelectedBlogId(blog.idBlog);
108 setEditMode(false);
109 };
110
111 const openBlogInEditMode = (blog: BlogPost) => {
112 setSelectedBlogId(blog.idBlog);
113 setEditMode(true);
114 };
115
116 const handleQuickDelete = async (blogId: number) => {
117 await blogApi.deleteBlog(blogId);
118 refetchBlogs();
119 };
120
121 const closeBlog = () => {
122 setSelectedBlogId(null);
123 setEditMode(false);
124 };
125
126 return (
127 <div class="max-w-4xl mx-auto px-4 py-8">
128 <div class="flex justify-between items-center mb-8">
129 <h1 class="text-3xl font-bold text-gray-900">Community Blogs</h1>
130 <button
131 onClick={() => setShowCreateForm(!showCreateForm())}
132 class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors cursor-pointer"
133 >
134 {showCreateForm() ? "Cancel" : "Create Post"}
135 </button>
136 </div>
137
138 <Show when={blogs.error}>
139 <div class="mb-4 p-4 bg-red-50 border border-red-200 text-red-700 rounded-md">
140 {blogs.error instanceof Error
141 ? blogs.error.message
142 : "Failed to load blogs"}
143 </div>
144 </Show>
145
146 <Show when={showCreateForm()}>
147 <CreateBlogForm
148 onSubmit={handleCreateBlog}
149 onCancel={() => setShowCreateForm(false)}
150 />
151 </Show>
152
153 <BlogList
154 blogs={blogs() || []}
155 loading={blogs.loading}
156 openBlog={openBlog}
157 onLike={handleLike}
158 onEdit={openBlogInEditMode}
159 onDelete={handleQuickDelete}
160 />
161
162 <Show when={selectedBlogId() && selectedBlog()}>
163 <BlogModal
164 blog={selectedBlog()!}
165 onClose={closeBlog}
166 onLike={handleLike}
167 onAddComment={handleAddComment}
168 onUpdateBlog={handleUpdateBlog}
169 onDeleteBlog={handleDeleteBlog}
170 onUpdateComment={handleUpdateComment}
171 onDeleteComment={handleDeleteComment}
172 initialEditMode={editMode()}
173 />
174 </Show>
175 </div>
176 );
177};
178
179export default Blogs;
Note: See TracBrowser for help on using the repository browser.