From a7cfcf88f03862f198a61fcf439bc1290645c209 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Sat, 14 Feb 2026 19:43:27 +0530 Subject: [PATCH] feat(comments): implement mergeCommentsById function for comment deduplication and sorting --- frontend/src/app/boards/[boardId]/page.tsx | 68 ++++++++++------------ 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/frontend/src/app/boards/[boardId]/page.tsx b/frontend/src/app/boards/[boardId]/page.tsx index 0836ec8..e1a0cd0 100644 --- a/frontend/src/app/boards/[boardId]/page.tsx +++ b/frontend/src/app/boards/[boardId]/page.tsx @@ -243,6 +243,32 @@ const toLiveFeedFromComment = (comment: TaskCommentRead): LiveFeedItem => ({ event_type: "task.comment", }); +const mergeCommentsById = (...collections: TaskComment[][]): TaskComment[] => { + const byId = new Map(); + for (const collection of collections) { + for (const comment of collection) { + const existing = byId.get(comment.id); + if (!existing) { + byId.set(comment.id, comment); + continue; + } + const existingTime = apiDatetimeToMs(existing.created_at) ?? 0; + const incomingTime = apiDatetimeToMs(comment.created_at) ?? 0; + byId.set( + comment.id, + incomingTime >= existingTime + ? { ...existing, ...comment } + : { ...comment, ...existing }, + ); + } + } + return [...byId.values()].sort((a, b) => { + const aTime = apiDatetimeToMs(a.created_at) ?? 0; + const bTime = apiDatetimeToMs(b.created_at) ?? 0; + return bTime - aTime; + }); +}; + const toLiveFeedFromBoardChat = (memory: BoardChatMessage): LiveFeedItem => { const content = (memory.content ?? "").trim(); const actorName = resolveHumanActorName(memory.source, DEFAULT_HUMAN_LABEL); @@ -1694,35 +1720,9 @@ export default function BoardDetailPage() { ) { return prev; } - const exists = prev.some( - (item) => item.id === payload.comment?.id, - ); - if (exists) { - return prev; - } - const createdMs = apiDatetimeToMs( - payload.comment?.created_at, - ); - if (prev.length === 0 || createdMs === null) { - return [payload.comment as TaskComment, ...prev]; - } - const first = prev[0]; - const firstMs = apiDatetimeToMs(first?.created_at); - if (firstMs !== null && createdMs >= firstMs) { - return [payload.comment as TaskComment, ...prev]; - } - const last = prev[prev.length - 1]; - const lastMs = apiDatetimeToMs(last?.created_at); - if (lastMs !== null && createdMs <= lastMs) { - return [...prev, payload.comment as TaskComment]; - } - const next = [...prev, payload.comment as TaskComment]; - next.sort((a, b) => { - const aTime = apiDatetimeToMs(a.created_at) ?? 0; - const bTime = apiDatetimeToMs(b.created_at) ?? 0; - return bTime - aTime; - }); - return next; + return mergeCommentsById(prev, [ + payload.comment as TaskComment, + ]); }); } else if (payload.task) { const incomingTask = payload.task; @@ -2337,13 +2337,7 @@ export default function BoardDetailPage() { taskId, ); if (result.status !== 200) throw new Error("Unable to load comments."); - const items = [...(result.data.items ?? [])]; - items.sort((a, b) => { - const aTime = apiDatetimeToMs(a.created_at) ?? 0; - const bTime = apiDatetimeToMs(b.created_at) ?? 0; - return bTime - aTime; - }); - setComments(items); + setComments(mergeCommentsById(result.data.items ?? [])); } catch (err) { setCommentsError( err instanceof Error ? err.message : "Something went wrong.", @@ -2515,7 +2509,7 @@ export default function BoardDetailPage() { ); if (result.status !== 200) throw new Error("Unable to send message."); const created = result.data; - setComments((prev) => [created, ...prev]); + setComments((prev) => mergeCommentsById([created], prev)); return true; } catch (err) { const message = formatActionError(err, "Unable to send message.");