Skip to content

Commit

Permalink
Added Message UI
Browse files Browse the repository at this point in the history
  • Loading branch information
debojitsaha committed Nov 3, 2022
1 parent c868fa6 commit 1d1821e
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 6 deletions.
53 changes: 53 additions & 0 deletions frontend/src/components/ScrollableChat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Avatar, Tooltip } from "@chakra-ui/react";
import React from "react";
import {
isLastMessage,
isSameSender,
isSameSenderMargin,
isSameUser,
} from "../config/ChatLogics";
import { ChatState } from "../Context/ChatProvider";

const ScrollableChat = ({ messages }) => {
const { user } = ChatState();

return (
<div style={{ overflowX: "hidden", overflowY: "auto" }}>
{messages &&
messages.map((m, i) => (
<div style={{ display: "flex" }} key={m._id}>
{(isSameSender(messages, m, i, user._id) ||
isLastMessage(messages, i, user._id)) && (
<Tooltip label={m.sender.name} placement="bottom-start" hasArrow>
<Avatar
mt="7px"
mr={1}
size="sm"
cursor="pointer"
name={m.sender.name}
src={m.sender.pic}
/>
</Tooltip>
)}

<span
style={{
backgroundColor: `${
m.sender._id === user._id ? "#BEE3F8" : "#20f099b7"
}`,
borderRadius: "20px",
padding: "5px 15px",
maxWidth: "75%",
marginLeft: isSameSenderMargin(messages, m, i, user._id),
marginTop: isSameUser(messages, m, i) ? 3 : 10,
}}
>
{m.content}
</span>
</div>
))}
</div>
);
};

export default ScrollableChat;
131 changes: 126 additions & 5 deletions frontend/src/components/SingleChat.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,108 @@
import { Box, IconButton, Text } from "@chakra-ui/react";
import {
Box,
FormControl,
IconButton,
Input,
Spinner,
Text,
useToast,
} from "@chakra-ui/react";
import { ArrowBackIcon } from "@chakra-ui/icons";
import React from "react";
import React, { useEffect, useState } from "react";
import { ChatState } from "../Context/ChatProvider";
import { getSender, getSenderFull } from "../config/ChatLogics";
import ProfileModal from "./miscellaneous/ProfileModal";
import UpdateGroupChatModal from "./miscellaneous/UpdateGroupChatModal";
import axios from "axios";
import "./style.css";
import ScrollableChat from "./ScrollableChat";

const SingleChat = ({ fetchAgain, setFetchAgain }) => {
const { user, selectedChat, setSelectedChat } = ChatState();

const toast = useToast();

const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState();
const [loading, setLoading] = useState(false);

const fetchMessages = async () => {
if (!selectedChat) return;

try {
setLoading(true);

const config = {
headers: {
Authorization: `Bearer ${user.token}`,
},
};

const { data } = await axios.get(
`/api/message/${selectedChat._id}`,
config
);
setMessages(data);
// console.log(data);
setLoading(false);
} catch (error) {
toast({
title: "Error Occured",
description: "Failed to load the messages",
duration: 2000,
status: "error",
isClosable: true,
position: "bottom",
});
setLoading(false);
}
};

useEffect(() => {
fetchMessages();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedChat]);

const sendMessage = async (e) => {
if (e.key === "Enter" && newMessage) {
try {
const config = {
headers: {
Authorization: `Bearer ${user.token}`,
},
};

setNewMessage("");
const { data } = await axios.post(
"api/message",
{
content: newMessage,
chatId: selectedChat._id,
},
config
);

// console.log(data);
setMessages([...messages, data]);
} catch (error) {
toast({
title: "Error Occured",
description: "Failed to send the message",
duration: 2000,
status: "error",
isClosable: true,
position: "bottom",
});
}
}
};

const typingHandler = (e) => {
setNewMessage(e.target.value);

// Typing indicator Logic
};

return (
<>
{selectedChat ? (
Expand All @@ -30,8 +124,12 @@ const SingleChat = ({ fetchAgain, setFetchAgain }) => {
/>
{selectedChat.isGroupChat ? (
<>
{selectedChat.chatName}
<UpdateGroupChatModal fetchAgain={fetchAgain} setFetchAgain={setFetchAgain} />
{selectedChat.chatName}
<UpdateGroupChatModal
fetchAgain={fetchAgain}
setFetchAgain={setFetchAgain}
fetchMessages={fetchMessages}
/>
</>
) : (
<>
Expand All @@ -50,7 +148,30 @@ const SingleChat = ({ fetchAgain, setFetchAgain }) => {
bg="#E8E8E8"
borderRadius="lg"
overflowY="hidden"
></Box>
>
{loading ? (
<Spinner
size="xl"
w={20}
h={20}
alignSelf="center"
margin="auto"
/>
) : (
<div className="messages">
<ScrollableChat messages={messages} />
</div>
)}
<FormControl onKeyDown={sendMessage} mt={3} isRequired>
<Input
variant="filled"
bg="#E0E0E0"
placeholder="Enter new message.."
value={newMessage}
onChange={typingHandler}
/>
</FormControl>
</Box>
</>
) : (
<Box
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import UserBadgeItem from "../UserAvatar/UserBadgeItem";
import axios from "axios";
import UserListItem from "../UserAvatar/UserListItem";

const UpdateGroupChatModal = ({ fetchAgain, setFetchAgain }) => {
const UpdateGroupChatModal = ({ fetchAgain, setFetchAgain, fetchMessages }) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const { user, selectedChat, setSelectedChat } = ChatState();

Expand Down Expand Up @@ -66,6 +66,7 @@ const UpdateGroupChatModal = ({ fetchAgain, setFetchAgain }) => {

userToRemove._id === user._id ? setSelectedChat() : setSelectedChat(data);
setFetchAgain(!fetchAgain);
fetchMessages()
setLoading(false);
} catch (error) {
toast({
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/components/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.messages{
display: flex;
flex-direction: column;
overflow-y: scroll;
scrollbar-width: none;
/* background-color: #20f099b7; */
}
38 changes: 38 additions & 0 deletions frontend/src/config/ChatLogics.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,41 @@ export const getSender = (loggedUser, users) => {
export const getSenderFull = (loggedUser, users) => {
return users[0]._id === loggedUser._id ? users[1] : users[0];
};

export const isSameSender = (messages, m, i, userId) => {
return (
i < messages.length - 1 &&
(messages[i + 1].sender._id !== m.sender._id ||
messages[i + 1].sender._id === undefined) &&
messages[i].sender._id !== userId
);
};

export const isLastMessage = (messages, i, userId) => {
return (
i === messages.length - 1 &&
messages[messages.length - 1].sender._id !== userId &&
messages[messages.length - 1].sender._id
);
};

export const isSameSenderMargin = (messages, m, i, userId) => {
if (
i < messages.length - 1 &&
messages[i + 1].sender._id === m.sender._id &&
messages[i].sender._id !== userId
)
return 33;
else if (
(i < messages.length - 1 &&
messages[i + 1].sender._id !== m.sender._id &&
messages[i].sender._id !== userId) ||
(i === messages.length - 1 && messages[i].sender._id !== userId)
)
return 0;
else return "auto";
};

export const isSameUser = (messages, m, i) => {
return i > 0 && messages[i - 1].sender._id === m.sender._id;
};

0 comments on commit 1d1821e

Please sign in to comment.