import React, { useEffect, useMemo } from "react"; import PropTypes from "prop-types"; import { DirectChatContainer } from "./DirectChat.styled"; import DirectChatHeaderTitle from "./DirectChatHeaderTitle/DirectChatHeaderTitle"; import DirectChatHeader from "./DirectChatHeader/DirectChatHeader"; import { useDispatch, useSelector } from "react-redux"; import { useLocation, useRouteMatch } from "react-router-dom"; import { addNewMessage, fetchChats, fetchOneChat, setOneChat, } from "../../store/actions/chat/chatActions"; import { selectLatestChats, selectSelectedChat, } from "../../store/selectors/chatSelectors"; import DirectChatContent from "./DirectChatContent/DirectChatContent"; import { selectOffer } from "../../store/selectors/offersSelectors"; import { fetchOneOffer } from "../../store/actions/offers/offersActions"; import SkeletonDirectChat from "./SkeletonDirectChat/SkeletonDirectChat"; import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants"; import { selectUserId } from "../../store/selectors/loginSelectors"; import { acceptExchangeSocket, addMesageListener, removeMessageListener, } from "../../socket/socket"; import { makeErrorToastMessage } from "../../store/utils/makeToastMessage"; import { useTranslation } from "react-i18next"; import { selectExchange, selectRequester, } from "../../store/selectors/exchangeSelector"; import { acceptExchange, setRequester, } from "../../store/actions/exchange/exchangeActions"; import { convertLocalDateToUTCDate } from "../../util/helpers/dateHelpers"; import requesterStatus from "../../constants/requesterStatus"; import exchangeStatus from "../../constants/exchangeStatus"; const DirectChat = () => { const chat = useSelector(selectSelectedChat); const allChats = useSelector(selectLatestChats); const offer = useSelector(selectOffer); const routeMatch = useRouteMatch(); const location = useLocation(); const dispatch = useDispatch(); const { t } = useTranslation(); const exchange = useSelector(selectExchange); const requester = useSelector(selectRequester); const userId = useSelector(selectUserId); const isLoadingDirectChat = useSelector( selectIsLoadingByActionType(CHAT_SCOPE) ); const offerObject = useMemo(() => { if (location?.state?.offerId) { return offer?.offer; } return chat?.offer?.offer; }, [chat, location.state, offer]); const chatObject = useMemo(() => { if (location?.state?.offerId) { return {}; } return chat; }, [chat, location.state]); const amIBuyer = useMemo( () => exchange.buyer?.userId === userId, [exchange, userId] ); const exchangeState = useMemo(() => { if (exchange?.buyer) { let haveIAccepted = amIBuyer ? exchange.buyer?.accepted : exchange.seller?.accepted; let haveInterlucatorAccepted = amIBuyer ? exchange.seller?.accepted : exchange.buyer?.accepted; let haveIReviewed = amIBuyer ? exchange.buyer.givenReview : exchange.seller.givenReview; if (haveIAccepted) { if (haveInterlucatorAccepted) { if (haveIReviewed) { return exchangeStatus.REVIEWED; } else { return exchangeStatus.ACCEPTED; } } else { return exchangeStatus.I_OFFERED; } } else { if (haveInterlucatorAccepted) { return exchangeStatus.I_AM_OFFERED; } else { return exchangeStatus.INITIAL; } } } return exchangeStatus.INITIAL; }, [exchange, amIBuyer]); const interlocutorObject = useMemo(() => { if (location?.state?.offerId) { return { image: offer?.companyData?.image, name: offer?.companyData?.company?.name, location: offer?.companyData?.company?.contacts?.location, userId: offer?.offer?.userId, telephone: offer?.companyData?.company?.contacts?.telephone, }; } return { ...chat?.interlocutor, userId: chat?.chat?.participants[0] === userId ? chat?.chat?.participants[1] : chat?.chat?.participants[0], }; }, [chat, location.state, offer]); // Fetch chat after it is created // (renders after state of location changes) useEffect(() => { if (routeMatch.params.idChat) { refreshChat(); } }, [routeMatch.params.idChat, location.state?.offerId]); // Listener to socket.IO chat useEffect(() => { addMesageListener(({ succeed, data }) => { if (succeed) { if ( [...allChats].find((item) => { return item.chat._id === data.chatId; }) ) { dispatch( addNewMessage({ _id: data.chatId, message: data.message, }) ); if ( data.message?.isAcceptRequest && requester === requesterStatus.NOONE ) { dispatch(setRequester(requesterStatus.INTERLUCATOR)); } } else { dispatch(fetchChats()); } } else { dispatch(fetchChats()); dispatch(fetchOneChat(routeMatch.params.idChat)); makeErrorToastMessage(t("apiErrors.somethingWentWrong")); } }); return () => removeMessageListener(); }, [allChats, routeMatch]); const refreshChat = () => { if (routeMatch.params.idChat === "newMessage") { dispatch(fetchOneOffer(location.state.offerId)); dispatch(setOneChat({})); } else { dispatch(fetchOneChat(routeMatch.params.idChat)); } }; const handleAcceptExchange = () => { acceptExchangeSocket( chat?.chat?._id, userId, chat?.interlocutor?._id, () => { dispatch( acceptExchange({ exchangeId: exchange._id, }) ); dispatch( addNewMessage({ _id: chat?.chat?._id, message: { userId, isAcceptRequest: true, text: "", _created: convertLocalDateToUTCDate(new Date()), }, }) ); if (requester === requesterStatus.NOONE) { dispatch(setRequester(requesterStatus.ME)); } } ); }; return ( {isLoadingDirectChat || isLoadingDirectChat === undefined ? ( ) : ( <> )} ); }; DirectChat.propTypes = { children: PropTypes.node, }; export default DirectChat;