diff --git a/staff/marti-herms/project/G-HUB/api/handlers/sendMessageHandler.js b/staff/marti-herms/project/G-HUB/api/handlers/sendMessageHandler.js index d6a1bea7b..454fb2091 100644 --- a/staff/marti-herms/project/G-HUB/api/handlers/sendMessageHandler.js +++ b/staff/marti-herms/project/G-HUB/api/handlers/sendMessageHandler.js @@ -9,6 +9,8 @@ export default (req, res, next) => { try { logic.sendMessage(userId, chatId, content) + .then(() => res.status(201).json()) + .catch(error => next(error)) } catch (error) { next(error) } diff --git a/staff/marti-herms/project/G-HUB/app/logic/sendMessage.js b/staff/marti-herms/project/G-HUB/app/logic/sendMessage.js index 347b951d0..0dc3710e7 100644 --- a/staff/marti-herms/project/G-HUB/app/logic/sendMessage.js +++ b/staff/marti-herms/project/G-HUB/app/logic/sendMessage.js @@ -17,7 +17,7 @@ export default (chatId, content) => { .then(response => { const { status } = response - if (status === 200) return + if (status === 201) return return response.json() .then(body => { diff --git a/staff/marti-herms/project/G-HUB/app/src/home/Chat.jsx b/staff/marti-herms/project/G-HUB/app/src/home/Chat.jsx index 140cd15c7..fe31572b1 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/Chat.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/Chat.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useParams } from 'react-router-dom' import { IoIosSend as SendIcon } from 'react-icons/io' @@ -19,15 +19,22 @@ import defaultAvatar from '../../images/defaultAvatar.svg' import logic from '../../logic' export default function Chat({ onOpenChat }) { + const [user, setUser] = useState(null) const [users, setUsers] = useState([]) const [chat, setChat] = useState(null) + const [message, setMessage] = useState('') const [messages, setMessages] = useState([]) + const messageRef = useRef() const { alert } = useContext() const { sub: loggedInUser } = extractPayloadFromToken(sessionStorage.token) const { userId } = useParams() + useEffect(() => { + messageRef.current?.scrollIntoView({ behaviour: 'smooth' }) + }, [messages.length]) + useEffect(() => { try { if (userId === loggedInUser) { @@ -39,7 +46,12 @@ export default function Chat({ onOpenChat }) { alert(error.message) }) } else { - logic.openChat(userId) + logic.getUser(userId) + .then(user => { + setUser(user) + + return logic.openChat(userId) + }) .then(chatId => setChat(chatId)) .catch(error => { console.error(error) @@ -66,6 +78,7 @@ export default function Chat({ onOpenChat }) { if (intervalId) { clearInterval(intervalId) setChat(null) + setMessages([]) } } }, [chat]) @@ -77,11 +90,13 @@ export default function Chat({ onOpenChat }) { const messageInput = form['message-input'] - const message = messageInput.value + setMessage(messageInput.value) try { logic.sendMessage(chat, message) .then(() => { + setMessage('') + loadMessages() }) .catch(error => { @@ -96,6 +111,10 @@ export default function Chat({ onOpenChat }) { } } + const handleInputChange = (e) => { + setMessage(e.target.value) + } + const loadMessages = () => { try { logic.getChatMessages(chat) @@ -119,10 +138,15 @@ export default function Chat({ onOpenChat }) { return {userId !== loggedInUser ? <> + {user && + + {user.username} + } {messages.map(message => )} +
- +
: diff --git a/staff/marti-herms/project/G-HUB/app/src/home/Game.jsx b/staff/marti-herms/project/G-HUB/app/src/home/Game.jsx index c287cf452..7c1c675d1 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/Game.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/Game.jsx @@ -147,8 +147,10 @@ export default function Game({ makeReviewVisibility, onCancel }) { Go to official page } - - {makeReviewVisibility &&
+ + {reviews && reviews.map(review => )} + + {makeReviewVisibility && @@ -163,9 +165,5 @@ export default function Game({ makeReviewVisibility, onCancel }) { } - - - {reviews && reviews.map(review => )} - } \ No newline at end of file diff --git a/staff/marti-herms/project/G-HUB/app/src/home/GameBanner.jsx b/staff/marti-herms/project/G-HUB/app/src/home/GameBanner.jsx index b16d97bd6..670d32a98 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/GameBanner.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/GameBanner.jsx @@ -1,6 +1,12 @@ +import { IoRemoveCircleOutline as RemoveIcon } from 'react-icons/io5' +import { IoIosAddCircleOutline as AddIcon } from 'react-icons/io' +import { MdFavorite as FavIcon, MdFavoriteBorder as NotFavIcon } from "react-icons/md"; + + import Container from '../library/Container' import Image from '../library/Image' import Paragraph from '../library/Paragraph' +import Button from '../library/Button' import useContext from '../context' @@ -46,7 +52,7 @@ export default function GameBanner({ game, onInteraction, onGameClick, collectio } return
- - {collectionType !== 'devGames' && - - {game.inLibrary && } + + {collectionType !== 'devGames' && + + }
} \ No newline at end of file diff --git a/staff/marti-herms/project/G-HUB/app/src/home/Message.jsx b/staff/marti-herms/project/G-HUB/app/src/home/Message.jsx index fd4737460..c40c86594 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/Message.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/Message.jsx @@ -2,21 +2,22 @@ import Container from '../library/Container' import Paragraph from '../library/Paragraph' import extractPayloadFromToken from '../../util/extractPayloadFromToken' +import formatTime from '../../util/formatTime' export default function Message({ message }) { const { sub: userId } = extractPayloadFromToken(sessionStorage.token) return (message.author.id === userId) ? <> - {message.author.username} - - {message.content} + + {message.content} + : <> - {message.author.username} - - {message.content} + + {message.content} + } \ No newline at end of file diff --git a/staff/marti-herms/project/G-HUB/app/src/home/SearchResults.jsx b/staff/marti-herms/project/G-HUB/app/src/home/SearchResults.jsx index 6db03feb7..770594b61 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/SearchResults.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/SearchResults.jsx @@ -8,7 +8,7 @@ import useContext from '../context' import GameBanner from './GameBanner' import UserBanner from './UserBanner' -export default function SearchResults({ onGameClick, onUserClick }) { +export default function SearchResults({ onGameClick, onUserClick, onChatClick }) { const { alert } = useContext() const [searchParams] = useSearchParams() @@ -19,11 +19,14 @@ export default function SearchResults({ onGameClick, onUserClick }) { const [debounceTimer, setDebounceTimer] = useState(null) useEffect(() => { - if (q !== '' || q !== '@') { - debounceSearch() - } else { - clearTimeout(debounceTimer) + if (q === '@' || q === '') { setResults([]) + debounceTimer && clearTimeout(debounceTimer) + } else { + if (debounceTimer) + clearTimeout(debounceTimer) + + debounceSearch() } }, [q]) @@ -60,20 +63,17 @@ export default function SearchResults({ onGameClick, onUserClick }) { } const debounceSearch = () => { - if (debounceTimer) - clearTimeout(debounceTimer) - setDebounceTimer(setTimeout(() => { if (q.startsWith('@')) loadUsers() else loadGames() - }, 1000)) + }, 700)) } return
{results.length > 0 && (q.startsWith('@') ? - results.map(user => ) : + results.map(user => ) : results.map(game => ))}
} diff --git a/staff/marti-herms/project/G-HUB/app/src/home/UserBanner.jsx b/staff/marti-herms/project/G-HUB/app/src/home/UserBanner.jsx index 6be6754d8..58404dfda 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/UserBanner.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/UserBanner.jsx @@ -1,4 +1,6 @@ import { RiUserFollowLine as FollowIcon, RiUserUnfollowLine as UnfollowIcon } from 'react-icons/ri' +import { IoIosSend as SendIcon } from 'react-icons/io' + import Container from '../library/Container' import Avatar from '../library/Avatar' @@ -12,7 +14,7 @@ import logic from '../../logic' import defaultAvatar from '../../images/defaultAvatar.svg' import extractPayloadFromToken from '../../util/extractPayloadFromToken' -export default function UserBanner({ user, onInteraction, onUserClick }) { +export default function UserBanner({ user, onInteraction, onUserClick, onChatClick }) { const { alert } = useContext() const { sub: currentUserId } = extractPayloadFromToken(sessionStorage.token) @@ -37,6 +39,10 @@ export default function UserBanner({ user, onInteraction, onUserClick }) { } } + const handleOpenChat = () => { + onChatClick(user.id) + } + return
- {user.id !== currentUserId && + {user.id !== currentUserId && + }
} \ No newline at end of file diff --git a/staff/marti-herms/project/G-HUB/app/src/home/UserList.jsx b/staff/marti-herms/project/G-HUB/app/src/home/UserList.jsx index e018ad557..ff3351071 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/UserList.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/UserList.jsx @@ -8,7 +8,7 @@ import UserBanner from './UserBanner' import logic from '../../logic' -export default function UserList({ onUserClick }) { +export default function UserList({ onUserClick, onChatClick }) { const { alert } = useContext() const location = useLocation() @@ -20,7 +20,7 @@ export default function UserList({ onUserClick }) { const [users, setUsers] = useState([]) useEffect(() => { - if (listType === 'following' || listType === 'chat') + if (listType === 'following') loadFollowing() else if (listType === 'followers') loadFollowers() @@ -59,7 +59,7 @@ export default function UserList({ onUserClick }) { } return -

{listType.toUpperCase()}

- {users.map(user => )} +

{listType.toUpperCase()}

+ {users.map(user => )}
} \ No newline at end of file diff --git a/staff/marti-herms/project/G-HUB/app/src/home/index.jsx b/staff/marti-herms/project/G-HUB/app/src/home/index.jsx index ccdc12809..fd4f60a1c 100644 --- a/staff/marti-herms/project/G-HUB/app/src/home/index.jsx +++ b/staff/marti-herms/project/G-HUB/app/src/home/index.jsx @@ -77,10 +77,10 @@ export default function Home({ onLogout }) { } /> } /> - } /> - } /> + } /> + } /> } /> - } /> + } /> } /> } /> } /> diff --git a/staff/marti-herms/project/G-HUB/app/util/formatTime.js b/staff/marti-herms/project/G-HUB/app/util/formatTime.js new file mode 100644 index 000000000..b533a62c7 --- /dev/null +++ b/staff/marti-herms/project/G-HUB/app/util/formatTime.js @@ -0,0 +1,44 @@ +function formatTime(date) { + const seconds = Math.floor((Date.now() - date.getTime()) / 1000) + + if (seconds < 60) { + return seconds + ' second' + (seconds === 1 ? '' : 's') + } + + const minutes = Math.round(seconds / 60) + + if (minutes < 60) { + return minutes + ' minute' + (minutes === 1 ? '' : 's') + } + + const hours = Math.round(minutes / 60) + + if (hours < 24) { + return hours + ' hour' + (hours === 1 ? '' : 's') + } + + const days = Math.round(hours / 24) + + if (days < 7) { + return days + ' day' + (days === 1 ? '' : 's') + } + + const weeks = Math.round(days / 7) + + if (weeks < 4) { + return weeks + ' week' + (weeks === 1 ? '' : 's') + } + + const months = Math.round(weeks / 7) + + if (months < 12) { + return months + ' month' + (months === 1 ? '' : 's') + } + + const years = Math.round(months / 7) + + return years + ' year' + (years === 1 ? '' : 's') + +} + +export default formatTime \ No newline at end of file