diff --git a/frontend/blog_portal/src/stores/comments.ts b/frontend/blog_portal/src/stores/comments.ts new file mode 100644 index 0000000..de947aa --- /dev/null +++ b/frontend/blog_portal/src/stores/comments.ts @@ -0,0 +1,64 @@ +import { defineStore } from "pinia"; +import { ref } from "vue"; +import { apiDelete, apiGet, apiPost } from "@/api/client"; + +export interface CommentItem { + id: number; + postId: number; + userId: number; + authorDisplayName: string; + body: string; + createdAt: string; +} + +interface CommentListPayload { + comments: CommentItem[]; +} + +interface CommentPayload { + comment: CommentItem; +} + +export const useCommentsStore = defineStore("comments", () => { + const items = ref([]); + const error = ref(null); + + async function fetchForPost(postId: number): Promise { + const result = await apiGet(`/posts/${postId}/comments`); + if (result.ok && result.data) { + items.value = result.data.comments; + } else { + error.value = result.error; + items.value = []; + } + } + + async function create(postId: number, body: string): Promise { + const result = await apiPost(`/posts/${postId}/comments`, { body }); + if (!result.ok || !result.data) { + error.value = result.error; + return false; + } + items.value = [...items.value, result.data.comment]; + return true; + } + + async function remove(id: number): Promise { + const result = await apiDelete(`/comments/${id}`); + if (!result.ok) { + error.value = result.error; + return false; + } + items.value = items.value.filter(function (existing) { + return existing.id !== id; + }); + return true; + } + + function clear(): void { + items.value = []; + error.value = null; + } + + return { items, error, fetchForPost, create, remove, clear }; +}); diff --git a/frontend/blog_portal/src/views/NewPostPage.vue b/frontend/blog_portal/src/views/NewPostPage.vue index a10ef01..2cd7729 100644 --- a/frontend/blog_portal/src/views/NewPostPage.vue +++ b/frontend/blog_portal/src/views/NewPostPage.vue @@ -1,7 +1,103 @@