Skip to content

Commit 561ff76

Browse files
committed
feat: add CommentSectionProvider for improved comment management and state handling
1 parent 6ba0c31 commit 561ff76

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

.dev.vars

Whitespace-only changes.

src/app/[username]/[articleHandle]/page.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ import HomeLeftSidebar from "@/app/(home)/_components/HomeLeftSidebar";
22
import { persistenceRepository } from "@/backend/persistence/persistence-repositories";
33
import * as articleActions from "@/backend/services/article.actions";
44
import AppImage from "@/components/AppImage";
5-
import { CommentSection } from "@/components/comment-section";
5+
import {
6+
CommentSection,
7+
CommentSectionProvider,
8+
} from "@/components/comment-section";
69
import HomepageLayout from "@/components/layout/HomepageLayout";
10+
import ResourceReaction from "@/components/ResourceReaction";
711
import { readingTime, removeMarkdownSyntax } from "@/lib/utils";
812
import getFileUrl from "@/utils/getFileUrl";
913
import { markdocParser } from "@/utils/markdoc-parser";
@@ -13,9 +17,7 @@ import Link from "next/link";
1317
import { notFound } from "next/navigation";
1418
import type { Article, WithContext } from "schema-dts";
1519
import { eq } from "sqlkit";
16-
import ArticleReaction from "./_components/ArticleReaction";
1720
import ArticleSidebar from "./_components/ArticleSidebar";
18-
import ResourceReaction from "@/components/ResourceReaction";
1921

2022
interface ArticlePageProps {
2123
params: Promise<{
@@ -158,7 +160,9 @@ const Page: NextPage<ArticlePageProps> = async ({ params }) => {
158160
<div className="mx-auto content-typography">{parsedHTML}</div>
159161
</div>
160162

161-
<CommentSection resource_type="ARTICLE" resource_id={article.id} />
163+
<CommentSectionProvider>
164+
<CommentSection resource_type="ARTICLE" resource_id={article.id} />
165+
</CommentSectionProvider>
162166
</HomepageLayout>
163167
</>
164168
);

src/components/comment-section.tsx

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,40 @@ import { useLoginPopup } from "./app-login-popup";
1313
import ResourceReaction from "./ResourceReaction";
1414
import { Textarea } from "./ui/textarea";
1515

16+
const Context = React.createContext<
17+
{ mutatingId?: string; setMutatingId: (id?: string) => void } | undefined
18+
>(undefined);
19+
20+
export const CommentSectionProvider = ({
21+
children,
22+
}: {
23+
children: React.ReactNode;
24+
}) => {
25+
const [mutatingId, setMutatingId] = useState<string | undefined>(undefined);
26+
return (
27+
<Context.Provider value={{ mutatingId, setMutatingId }}>
28+
{children}
29+
</Context.Provider>
30+
);
31+
};
32+
export const useCommentSection = () => {
33+
const context = React.useContext(Context);
34+
if (!context) {
35+
throw new Error(
36+
"useCommentSectionContext must be used within a CommentSectionProvider"
37+
);
38+
}
39+
return context;
40+
};
41+
1642
export const CommentSection = (props: {
1743
resource_id: string;
1844
resource_type: "ARTICLE" | "COMMENT";
1945
}) => {
2046
const { _t } = useTranslation();
2147
const queryClient = useQueryClient();
2248
const appLoginPopup = useLoginPopup();
49+
const { setMutatingId } = useCommentSection();
2350
const session = useSession();
2451
const mutation = useMutation({
2552
mutationFn: (payload: { body: string; comment_id: string }) =>
@@ -34,6 +61,7 @@ export const CommentSection = (props: {
3461
appLoginPopup.show();
3562
return;
3663
}
64+
setMutatingId(payload.comment_id);
3765

3866
// Optimistically update the UI by adding the new comment to the list
3967
await queryClient.cancelQueries({
@@ -82,7 +110,7 @@ export const CommentSection = (props: {
82110
refetchOnReconnect: false,
83111
});
84112

85-
const generated_comment_id = useMemo(() => crypto.randomUUID(), []);
113+
const generated_comment_id = () => crypto.randomUUID();
86114
return (
87115
<div className="max-w-4xl mx-auto p-4">
88116
<div className="mb-6">
@@ -91,7 +119,7 @@ export const CommentSection = (props: {
91119
{/* New Comment Box */}
92120
<CommentEditor
93121
onSubmit={(body) => {
94-
mutation.mutate({ body, comment_id: generated_comment_id });
122+
mutation.mutate({ body, comment_id: generated_comment_id() });
95123
}}
96124
isLoading={mutation.isPending}
97125
placeholder={_t("What are your thoughts?")}
@@ -170,19 +198,19 @@ const CommentEditor = (props: {
170198
const CommentItem = (props: {
171199
comment: CommentPresentation;
172200
mutating?: boolean;
173-
mutatingId?: string;
174201
}) => {
175202
const { _t } = useTranslation();
176203
const session = useSession();
177204
const appLoginPopup = useLoginPopup();
178205
const [isCollapsed, setIsCollapsed] = useState(false);
179206
const [showReplyBox, setShowReplyBox] = useState(false);
207+
const { mutatingId, setMutatingId } = useCommentSection();
180208
const [replies, setReplies] = useImmer<CommentPresentation[]>(
181209
props.comment.replies ?? []
182210
);
183211

184212
const level = useMemo(() => props.comment.level ?? 0, [props.comment]);
185-
const generated_comment_id = useMemo(() => crypto.randomUUID(), []);
213+
const generated_comment_id = () => crypto.randomUUID();
186214
const mutation = useMutation({
187215
mutationFn: (payload: { body: string; comment_id: string }) =>
188216
commentActions.createMyComment({
@@ -212,6 +240,9 @@ const CommentItem = (props: {
212240
created_at: new Date(),
213241
} satisfies CommentPresentation);
214242
});
243+
console.log("Mutating comment with ID:", payload.comment_id);
244+
245+
setMutatingId(payload.comment_id);
215246
},
216247
onError: (error) => {
217248
// reverse the optimistic update if there's an error
@@ -256,7 +287,7 @@ const CommentItem = (props: {
256287

257288
{/* Comment Actions */}
258289

259-
{props.mutating && props.mutatingId == props.comment.id ? (
290+
{props.mutating && mutatingId == props.comment.id ? (
260291
<p className="text-muted-foreground text-sm mb-3">
261292
{_t("Pending")}...
262293
</p>
@@ -285,7 +316,7 @@ const CommentItem = (props: {
285316
onSubmit={(value) => {
286317
mutation.mutate({
287318
body: value,
288-
comment_id: generated_comment_id,
319+
comment_id: generated_comment_id(),
289320
});
290321
setShowReplyBox(false);
291322
}}
@@ -301,7 +332,6 @@ const CommentItem = (props: {
301332
key={reply.id}
302333
comment={reply}
303334
mutating={mutation.isPending}
304-
mutatingId={mutation.isPending ? reply.id : undefined}
305335
/>
306336
))}
307337
</>

0 commit comments

Comments
 (0)