diff --git a/worklenz-frontend/src/pages/projects/project-view-1/updates/project-view-updates.tsx b/worklenz-frontend/src/pages/projects/project-view-1/updates/project-view-updates.tsx index 684cb5f9..dbf66036 100644 --- a/worklenz-frontend/src/pages/projects/project-view-1/updates/project-view-updates.tsx +++ b/worklenz-frontend/src/pages/projects/project-view-1/updates/project-view-updates.tsx @@ -1,5 +1,5 @@ import { Button, ConfigProvider, Flex, Form, Mentions, Skeleton, Space, Tooltip, Typography } from 'antd'; -import { useEffect, useState, useCallback } from 'react'; +import { useEffect, useState, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import DOMPurify from 'dompurify'; import { useParams } from 'react-router-dom'; @@ -68,7 +68,7 @@ const ProjectViewUpdates = () => { } }, [projectId]); - const handleAddComment = async () => { + const handleAddComment = useCallback(async () => { if (!projectId || characterLength === 0) return; try { @@ -96,15 +96,13 @@ const ProjectViewUpdates = () => { } finally { setIsSubmitting(false); setCommentValue(''); - - } - }; + }, [projectId, characterLength, commentValue, selectedMembers, getComments]); useEffect(() => { void getMembers(); void getComments(); - }, [getMembers, getComments,refreshTimestamp]); + }, [getMembers, getComments, refreshTimestamp]); const handleCancel = useCallback(() => { form.resetFields(['comment']); @@ -113,14 +111,16 @@ const ProjectViewUpdates = () => { setSelectedMembers([]); }, [form]); - const mentionsOptions = + const mentionsOptions = useMemo(() => members?.map(member => ({ value: member.id, label: member.name, - })) ?? []; + })) ?? [], [members] + ); const memberSelectHandler = useCallback((member: IMentionMemberSelectOption) => { if (!member?.value || !member?.label) return; + setSelectedMembers(prev => prev.some(mention => mention.id === member.value) ? prev @@ -131,13 +131,11 @@ const ProjectViewUpdates = () => { const parts = prev.split('@'); const lastPart = parts[parts.length - 1]; const mentionText = member.label; - // Keep only the part before the @ and add the new mention return prev.slice(0, prev.length - lastPart.length) + mentionText; }); }, []); const handleCommentChange = useCallback((value: string) => { - // Only update the value without trying to replace mentions setCommentValue(value); setCharacterLength(value.trim().length); }, []); @@ -157,56 +155,69 @@ const ProjectViewUpdates = () => { [getComments] ); + const configProviderTheme = useMemo(() => ({ + components: { + Button: { + defaultColor: colors.lightGray, + defaultHoverColor: colors.darkGray, + }, + }, + }), []); + + const renderComment = useCallback((comment: IProjectUpdateCommentViewModel) => { + const sanitizedContent = DOMPurify.sanitize(comment.content || ''); + const timeDifference = calculateTimeDifference(comment.created_at || ''); + const themeClass = theme === 'dark' ? 'dark' : 'light'; + + return ( + + + + + + {comment.created_by || ''} + + + + {timeDifference} + + + + +
+ + +