diff --git a/client/src/components/chat/chatArea/AnimatedMessage.tsx b/client/src/components/chat/chatArea/AnimatedMessage.tsx deleted file mode 100644 index 8a59f93..0000000 --- a/client/src/components/chat/chatArea/AnimatedMessage.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { useContext, useState } from 'react'; -import { Trash2 } from 'lucide-react'; -import AttachmentPreview from './AttachmentPreview.tsx'; -import { ChatMessagesProps } from '@/types/types.ts'; -import { useChat } from '@/context/chat/useChat.ts'; -import { AuthContext } from '@/utils/AuthProvider.tsx'; - -type AnimatedMessageProps = { - message: ChatMessagesProps; - onDelete: (messageId: number) => void; -}; - -const AnimatedMessage = ({ onDelete, message }: AnimatedMessageProps) => { - const { user } = useContext(AuthContext); - const { me, groupOwner } = useChat(); - const [isRemoving, setIsRemoving] = useState(false); - - const handleDelete = () => { - setIsRemoving(true); - setTimeout(() => { - onDelete(message.message_id); - }, 300); - }; - - return ( -
  • -
    -
    - - {message.sender}: {message.message} - - {message.attachment_urls && ( -
    - {message.attachment_urls?.length > 0 - ? message.attachment_urls.map((url, index) => ( - - )) - : null} -
    - )} -
    - {me.isGroupOwner || - message.sender == user?.username || - (me.isGroupAdmin && - me.isGroupOwner && - message.sender_id !== groupOwner) ? ( - - ) : null} -
    -
  • - ); -}; - -export default AnimatedMessage; diff --git a/client/src/components/chat/chatArea/MessageElement.tsx b/client/src/components/chat/chatArea/MessageElement.tsx new file mode 100644 index 0000000..bbaf8de --- /dev/null +++ b/client/src/components/chat/chatArea/MessageElement.tsx @@ -0,0 +1,89 @@ +import { useContext, useState } from 'react'; +import { Trash2 } from 'lucide-react'; +import AttachmentPreview from './AttachmentPreview.tsx'; +import { ChatMessagesProps } from '@/types/types.ts'; +import { useChat } from '@/context/chat/useChat.ts'; +import { AuthContext } from '@/utils/AuthProvider.tsx'; +import { format, isToday, isYesterday, formatDistanceToNow } from 'date-fns'; +import { pl } from 'date-fns/locale'; + +type AnimatedMessageProps = { + message: ChatMessagesProps; + onDelete: (messageId: number) => void; +}; + +const MessageElement = ({ onDelete, message }: AnimatedMessageProps) => { + const { user } = useContext(AuthContext); + const { me, groupOwner } = useChat(); + const [isRemoving, setIsRemoving] = useState(false); + + const handleDelete = () => { + setIsRemoving(true); + setTimeout(() => { + onDelete(message.message_id); + }, 300); + }; + + const formatMessageDate = (date: Date) => { + if (isToday(date)) { + return `Dzisiaj o ${format(date, 'HH:mm')}`; + } + if (isYesterday(date)) { + return `Wczoraj o ${format(date, 'HH:mm')}`; + } + return format(date, "d MMMM yyyy 'o' HH:mm", { locale: pl }); + }; + + const messageDate = new Date(message.sent_at); + const formattedDate = formatMessageDate(messageDate); + const fullDate = format(messageDate, "d MMMM yyyy 'o' HH:mm", { locale: pl }); + const timeAgo = formatDistanceToNow(messageDate, { + addSuffix: true, + locale: pl, + }); + + const canDelete = + me.isGroupOwner || + message.sender === user?.username || + (me.isGroupAdmin && me.isGroupOwner && message.sender_id !== groupOwner); + + return ( +
  • +
    +
    +
    + {message.sender} + + {formattedDate} + +
    +
    {message.message}
    + {message.attachment_urls && message.attachment_urls.length > 0 && ( +
    + {message.attachment_urls.map((url, index) => ( + + ))} +
    + )} +
    + {canDelete && ( + + )} +
    +
  • + ); +}; + +export default MessageElement; diff --git a/client/src/components/chat/chatArea/MessagesArea.tsx b/client/src/components/chat/chatArea/MessagesArea.tsx index 8221eb3..57b0836 100644 --- a/client/src/components/chat/chatArea/MessagesArea.tsx +++ b/client/src/components/chat/chatArea/MessagesArea.tsx @@ -2,7 +2,7 @@ import { useContext, useEffect, useRef, useState } from 'react'; import { socket } from '@/socket/socket.ts'; import { sendContact } from '@/api/contactsApi.tsx'; import LoadingWheel from '../LoadingWheel.tsx'; -import AnimatedMessage from '@/components/chat/chatArea/AnimatedMessage.tsx'; +import AnimatedMessage from '@/components/chat/chatArea/MessageElement.tsx'; import { ChatMessagesProps } from '@/types/types.ts'; import { useChat } from '@/context/chat/useChat.ts'; import { AuthContext } from '@/utils/AuthProvider.tsx'; @@ -56,7 +56,7 @@ function MessagesArea() { const isAtBottom = container.scrollHeight - container.scrollTop <= - container.clientHeight + 100; + container.clientHeight + 200; setShouldScrollToBottom(isAtBottom); }; diff --git a/client/src/pages/Chat.tsx b/client/src/pages/Chat.tsx index c1e0cba..1a296d2 100644 --- a/client/src/pages/Chat.tsx +++ b/client/src/pages/Chat.tsx @@ -32,7 +32,7 @@ function Chat() { }, []); return ( -
    +
    {/* Left Sidebar */}