| import { isInRoute, routeMatches } from "../../../../util/helpers/routeHelpers"; | import { isInRoute, routeMatches } from "../../../../util/helpers/routeHelpers"; | ||||
| import { ADMIN_HOME_PAGE, ADMIN_USERS_PAGE } from "../../../../constants/pages"; | import { ADMIN_HOME_PAGE, ADMIN_USERS_PAGE } from "../../../../constants/pages"; | ||||
| import { ADMIN_NAVIGATION } from "../../../../constants/adminNavigation"; | import { ADMIN_NAVIGATION } from "../../../../constants/adminNavigation"; | ||||
| import history from "../../../../store/utils/history"; | |||||
| const SidebarNavigation = () => { | const SidebarNavigation = () => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); |
| import { ReactComponent as DownArrow } from "../../../assets/images/svg/arrow-down.svg"; | import { ReactComponent as DownArrow } from "../../../assets/images/svg/arrow-down.svg"; | ||||
| import styled from "styled-components"; | |||||
| import styled, { css } from "styled-components"; | |||||
| import selectedTheme from "../../../themes"; | import selectedTheme from "../../../themes"; | ||||
| import { IconButton } from "../IconButton/IconButton"; | import { IconButton } from "../IconButton/IconButton"; | ||||
| `} | `} | ||||
| width: 18px; | width: 18px; | ||||
| height: 18px; | height: 18px; | ||||
| /* position: relative; | |||||
| position: relative; | |||||
| top: 1px; | top: 1px; | ||||
| left: 1px; */ | |||||
| left: 1px; | |||||
| & path { | & path { | ||||
| ${(props) => | ${(props) => | ||||
| props.disabled && | props.disabled && | ||||
| } | } | ||||
| ${(props) => | ${(props) => | ||||
| props.disabled && | props.disabled && | ||||
| ` | |||||
| css` | |||||
| border 1px solid ${selectedTheme.colors.iconStrokeDisabledColor} !important; | border 1px solid ${selectedTheme.colors.iconStrokeDisabledColor} !important; | ||||
| &:hover { | &:hover { | ||||
| background-color: inherit; | background-color: inherit; |
| onClick={props.onClick} | onClick={props.onClick} | ||||
| sx={props.style} | sx={props.style} | ||||
| iconcolor={props.iconColor} | iconcolor={props.iconColor} | ||||
| {...props} | |||||
| // {...props} | |||||
| > | > | ||||
| {props.children} | {props.children} | ||||
| </IconButtonStyled> | </IconButtonStyled> |
| import useIsMobile from "../../../hooks/useIsMobile"; | import useIsMobile from "../../../hooks/useIsMobile"; | ||||
| import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | ||||
| import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile"; | import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile"; | ||||
| import { useSelector } from "react-redux"; | |||||
| import { selectUserId } from "../../../store/selectors/loginSelectors"; | |||||
| // Chat card is shown only on mobile phones (route /messages) | // Chat card is shown only on mobile phones (route /messages) | ||||
| const ChatCard = (props) => { | const ChatCard = (props) => { | ||||
| const { isMobile } = useIsMobile(); | const { isMobile } = useIsMobile(); | ||||
| const userId = useSelector(selectUserId); | |||||
| const chat = useMemo(() => { | const chat = useMemo(() => { | ||||
| return props.chat; | return props.chat; | ||||
| }, [props.chat]); | }, [props.chat]); | ||||
| const routeToItem = () => { | const routeToItem = () => { | ||||
| props.navigateToChat(chat?.chat?._id); | |||||
| props.navigateToChat(chat?._id); | |||||
| }; | }; | ||||
| console.log(chat) | |||||
| const interlocutor = useMemo(() => { | |||||
| return userId === chat?.participants[0]._id ? 1 : 0; | |||||
| }, [userId, chat]); | |||||
| return ( | return ( | ||||
| <ChatCardContainer onClick={routeToItem}> | <ChatCardContainer onClick={routeToItem}> | ||||
| <UserImgWrapper> | <UserImgWrapper> | ||||
| <UserImage | <UserImage | ||||
| src={getImageUrl( | src={getImageUrl( | ||||
| chat?.interlocutorData?.image, | |||||
| chat?.participants[interlocutor].image, | |||||
| variants.chatCard, | variants.chatCard, | ||||
| isMobile | isMobile | ||||
| )} | )} | ||||
| /> | /> | ||||
| </UserImgWrapper> | </UserImgWrapper> | ||||
| <ChatInfo isBlocked={props.chat.interlocutorData?._blocked}> | |||||
| <ChatInfo isBlocked={props.chat.participants[interlocutor]?._blocked}> | |||||
| <ProfileNameContainer> | <ProfileNameContainer> | ||||
| <UserName>{chat?.interlocutorData?.name}</UserName> | |||||
| {(props.chat.interlocutorData?._blocked || | |||||
| props.chat.interlocutorData?._deleted) && ( | |||||
| <UserName>{chat?.participants[interlocutor]?.company?.name}</UserName> | |||||
| {(props.chat?.participants[interlocutor]?._blocked || | |||||
| props.chat?.participants[interlocutor]?._deleted) && ( | |||||
| <BlockedProfile | <BlockedProfile | ||||
| redText | redText | ||||
| chatCard | chatCard | ||||
| shortText | shortText | ||||
| aboveTitle | aboveTitle | ||||
| hideIcon | hideIcon | ||||
| deleted={props.chat.interlocutorData?._deleted} | |||||
| deleted={props.chat?.participants[interlocutor]?._deleted} | |||||
| /> | /> | ||||
| )} | )} | ||||
| </ProfileNameContainer> | </ProfileNameContainer> |
| return ( | return ( | ||||
| <OfferCardContainerMobile> | <OfferCardContainerMobile> | ||||
| <OfferTextMobile>{t("messages.cardProduct")}</OfferTextMobile> | <OfferTextMobile>{t("messages.cardProduct")}</OfferTextMobile> | ||||
| <OfferTitleMobile>{props.chat?.offerData?.name}</OfferTitleMobile> | |||||
| <OfferTitleMobile>{props.chat?.offer?.name}</OfferTitleMobile> | |||||
| </OfferCardContainerMobile> | </OfferCardContainerMobile> | ||||
| ); | ); | ||||
| }; | }; |
| const handleSelectCategory = (category) => { | const handleSelectCategory = (category) => { | ||||
| filters.category.setSelectedCategory(category); | filters.category.setSelectedCategory(category); | ||||
| filters.subcategory.setSelectedSubcategory({}); | filters.subcategory.setSelectedSubcategory({}); | ||||
| console.log("category 1") | |||||
| props.offers.applyFilters(); | props.offers.applyFilters(); | ||||
| }; | }; | ||||
| console.log(props); | console.log(props); |
| }, | }, | ||||
| })); | })); | ||||
| const handleSelectSubcategory = (subcategory) => { | |||||
| filters.subcategory.setSelectedSubcategory(subcategory, !props.myOffers); | |||||
| console.log("props.offers") | |||||
| // if (props.myOffers) props.offers?.applyFilters(); | |||||
| }; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (props?.queryStringHook?.isInitiallyLoaded || props.isMyOffers) { | |||||
| if (props?.queryStringHook?.isInitiallyLoaded || props.myOffers) { | |||||
| if ( | if ( | ||||
| !filters.category.selectedCategoryLocally || | !filters.category.selectedCategoryLocally || | ||||
| filters.category.selectedCategoryLocally?._id === 0 | filters.category.selectedCategoryLocally?._id === 0 | ||||
| : t("filters.subcategories.title") | : t("filters.subcategories.title") | ||||
| } | } | ||||
| searchPlaceholder={t("filters.subcategories.placeholder")} | searchPlaceholder={t("filters.subcategories.placeholder")} | ||||
| setSelected={filters.subcategory.setSelectedSubcategory} | |||||
| setSelected={handleSelectSubcategory} | |||||
| selected={filters.subcategory.selectedSubcategoryLocally} | selected={filters.subcategory.selectedSubcategoryLocally} | ||||
| open={isOpened} | open={isOpened} | ||||
| disabled={isDisabled} | disabled={isDisabled} | ||||
| filters: PropTypes.any, | filters: PropTypes.any, | ||||
| categoryOpened: PropTypes.bool, | categoryOpened: PropTypes.bool, | ||||
| queryStringHook: PropTypes.any, | queryStringHook: PropTypes.any, | ||||
| isMyOffers: PropTypes.bool, | |||||
| myOffers: PropTypes.bool, | |||||
| offers: PropTypes.any, | offers: PropTypes.any, | ||||
| }; | }; | ||||
| queryStringHook={offers.queryStringHook} | queryStringHook={offers.queryStringHook} | ||||
| ref={subcategoryRef} | ref={subcategoryRef} | ||||
| categoryOpened={categoryRef.current?.isOpened} | categoryOpened={categoryRef.current?.isOpened} | ||||
| isMyOffers={props.myOffers} | |||||
| myOffers={props.myOffers} | |||||
| offers={offers} | offers={offers} | ||||
| /> | /> | ||||
| const [isOpened, setIsOpened] = useState(false); | const [isOpened, setIsOpened] = useState(false); | ||||
| const handleDelete = (item) => { | const handleDelete = (item) => { | ||||
| props.setItemsSelected([...props.filters.filter((p) => p !== item)]); | props.setItemsSelected([...props.filters.filter((p) => p !== item)]); | ||||
| console.log("dropdown 1") | |||||
| props.offers.applyFilters(); | props.offers.applyFilters(); | ||||
| }; | }; | ||||
| const handleOpen = () => { | const handleOpen = () => { |
| props.setItemsSelected([...props.filters, item]); | props.setItemsSelected([...props.filters, item]); | ||||
| props.offers.applyFilters(); | props.offers.applyFilters(); | ||||
| } | } | ||||
| console.log("filter checkbox 1"); | |||||
| } | } | ||||
| }; | }; | ||||
| const handleOpen = () => { | const handleOpen = () => { |
| props.offers.applyFilters(); | props.offers.applyFilters(); | ||||
| } | } | ||||
| } | } | ||||
| console.log("dropdown 2") | |||||
| }; | }; | ||||
| const setDropdownHandler = () => { | const setDropdownHandler = () => { |
| <CloseButtonIcon /> | <CloseButtonIcon /> | ||||
| </CloseButton> | </CloseButton> | ||||
| <Scroller isCarousel> | <Scroller isCarousel> | ||||
| {props?.offer?.offer?.images.map((image) => { | |||||
| {props?.images.map((image) => { | |||||
| if (!image) return; | if (!image) return; | ||||
| return ( | return ( | ||||
| <OfferImage | <OfferImage | ||||
| })} | })} | ||||
| </Scroller> | </Scroller> | ||||
| <Offer> | <Offer> | ||||
| {t("carousel.offer")} <OfferSpan>{props.offer.offer.name}</OfferSpan> | |||||
| {t("carousel.offer")} <OfferSpan>{props.offer.name}</OfferSpan> | |||||
| </Offer> | </Offer> | ||||
| </ImagesCarouselContainer> | </ImagesCarouselContainer> | ||||
| </> | </> | ||||
| offer: PropTypes.any, | offer: PropTypes.any, | ||||
| onModalClose: PropTypes.any, | onModalClose: PropTypes.any, | ||||
| createOffer: PropTypes.bool, | createOffer: PropTypes.bool, | ||||
| images: PropTypes.array | |||||
| }; | }; | ||||
| export default ImagesCarousel; | export default ImagesCarousel; |
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| const offer = useMemo(() => { | const offer = useMemo(() => { | ||||
| if (props.offer) { | if (props.offer) { | ||||
| if ( | |||||
| props.offer.offer._id === routeMatch.params?.offerId || | |||||
| props.createOffer | |||||
| ) { | |||||
| if (props.offer._id === routeMatch.params?.offerId && !props?.createOffer) { | |||||
| return props.offer; | return props.offer; | ||||
| } | } | ||||
| if (props.createOffer) return props.offer.offer; | |||||
| } | } | ||||
| return itemDetailsData; | return itemDetailsData; | ||||
| }, [props.offer, props.createOffer, routeMatch.params]); | }, [props.offer, props.createOffer, routeMatch.params]); | ||||
| }, []); | }, []); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| if (offer?.offer?._id) { | |||||
| increaseOfferCounter(offer?.offer?._id); | |||||
| if (offer?._id) { | |||||
| increaseOfferCounter(offer?._id); | |||||
| } | } | ||||
| }, [offer]); | }, [offer]); | ||||
| const date = formatDateLocale(new Date(offer?.offer?._created)); | |||||
| const date = formatDateLocale(new Date(offer?._created)); | |||||
| const startExchange = () => { | const startExchange = () => { | ||||
| startChat(chats, offer?.offer, userId); | |||||
| startChat(chats, offer, userId); | |||||
| }; | }; | ||||
| const showDeleteOfferModalHandler = () => { | const showDeleteOfferModalHandler = () => { | ||||
| dispatch( | dispatch( | ||||
| toggleDeleteOfferModal({ | toggleDeleteOfferModal({ | ||||
| offer: offer.offer, | |||||
| offer: offer, | |||||
| isAdmin: props.isAdmin, | isAdmin: props.isAdmin, | ||||
| }) | }) | ||||
| ); | ); | ||||
| dispatch( | dispatch( | ||||
| toggleEditOfferModal({ | toggleEditOfferModal({ | ||||
| editOffer: true, | editOffer: true, | ||||
| offer: offer?.offer, | |||||
| offer: offer, | |||||
| isAdmin: props.isAdmin, | isAdmin: props.isAdmin, | ||||
| customUserId: offer?.offer?.userId, | |||||
| customUserId: offer?.user?._id, | |||||
| }) | }) | ||||
| ); | ); | ||||
| }; | }; | ||||
| const showPinOfferModalHandler = () => { | const showPinOfferModalHandler = () => { | ||||
| dispatch( | dispatch( | ||||
| toggleDeleteOfferModal({ | toggleDeleteOfferModal({ | ||||
| offer: offer?.offer, | |||||
| offer: offer, | |||||
| pin: true, | pin: true, | ||||
| pinnedOffer: offer?.offer?.pinned, | |||||
| pinnedOffer: offer?.pinned, | |||||
| deleteOffer: false, | deleteOffer: false, | ||||
| }) | }) | ||||
| ); | ); | ||||
| <Info> | <Info> | ||||
| <Information | <Information | ||||
| icon={<CategoryIcon />} | icon={<CategoryIcon />} | ||||
| value={offer?.offer?.category?.name} | |||||
| value={offer?.category?.name} | |||||
| /> | /> | ||||
| <Information | <Information | ||||
| icon={<SubcategoryIcon />} | icon={<SubcategoryIcon />} | ||||
| value={offer?.offer?.subcategory} | |||||
| /> | |||||
| <Information | |||||
| icon={<QuantityIcon />} | |||||
| value={offer?.offer?.condition} | |||||
| value={offer?.subcategory} | |||||
| /> | /> | ||||
| <Information icon={<QuantityIcon />} value={offer?.condition} /> | |||||
| {!props.hideViews && ( | {!props.hideViews && ( | ||||
| <Information | |||||
| icon={<EyeIcon />} | |||||
| value={offer?.offer?.views?.count} | |||||
| /> | |||||
| <Information icon={<EyeIcon />} value={offer?.views?.count} /> | |||||
| )} | )} | ||||
| </Info> | </Info> | ||||
| <PostDate previewCard={props.previewCard}>{date}</PostDate> | <PostDate previewCard={props.previewCard}>{date}</PostDate> | ||||
| {props.isMyOffer && ( | {props.isMyOffer && ( | ||||
| <ButtonsContainer> | <ButtonsContainer> | ||||
| <PinIconContainer onClick={showPinOfferModalHandler}> | <PinIconContainer onClick={showPinOfferModalHandler}> | ||||
| {offer?.offer?.pinned ? <UnpinIcon /> : <PinIcon />} | |||||
| {offer?.pinned ? <UnpinIcon /> : <PinIcon />} | |||||
| </PinIconContainer> | </PinIconContainer> | ||||
| <EditIconContainer onClick={showEditOfferModalHandler}> | <EditIconContainer onClick={showEditOfferModalHandler}> | ||||
| <EditIcon /> | <EditIcon /> |
| const [images, setImages] = useState([]); | const [images, setImages] = useState([]); | ||||
| const [imagesCarouselModal, setImagesCarouselModal] = useState(false); | const [imagesCarouselModal, setImagesCarouselModal] = useState(false); | ||||
| console.log(offer); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (props?.offer?.offer?.images) { | |||||
| props.offer.offer.images.map((file) => { | |||||
| if (props?.offer?.images) { | |||||
| props.offer.images.map((file) => { | |||||
| if (file) { | if (file) { | ||||
| if (typeof file !== "string") { | if (typeof file !== "string") { | ||||
| var reader = new FileReader(); | var reader = new FileReader(); | ||||
| console.log("Error: ", error); | console.log("Error: ", error); | ||||
| }; | }; | ||||
| } else { | } else { | ||||
| setImages((prevImages) => [ | |||||
| ...prevImages, | |||||
| getImageUrl(file, variants.offerCard, isMobile), | |||||
| ]); | |||||
| setImages((prevImages) => [...prevImages, file]); | |||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| }, [props?.offer?.offer?.images]); | |||||
| const date = formatDateLocale(new Date(offer?.offer?._created)); | |||||
| }, [props?.offer?.images]); | |||||
| console.log(images); | |||||
| const date = formatDateLocale(new Date(offer?._created)); | |||||
| const onModalClose = () => { | const onModalClose = () => { | ||||
| setImagesCarouselModal(false); | setImagesCarouselModal(false); | ||||
| }; | }; | ||||
| console.log(props); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <Details | <Details | ||||
| > | > | ||||
| {!isMobile && props.singleOffer && ( | {!isMobile && props.singleOffer && ( | ||||
| <ScrollerVertical> | <ScrollerVertical> | ||||
| {props?.offer?.offer?.images.map((item, index) => ( | |||||
| {images.map((item, index) => ( | |||||
| <OfferImage | <OfferImage | ||||
| src={ | src={ | ||||
| props.createOffer | props.createOffer | ||||
| singleOffer={props.singleOffer} | singleOffer={props.singleOffer} | ||||
| previewCard={props.previewCard} | previewCard={props.previewCard} | ||||
| > | > | ||||
| <OfferTitle singleOffer={props.singleOffer}> | |||||
| {offer?.offer?.name} | |||||
| </OfferTitle> | |||||
| <OfferTitle singleOffer={props.singleOffer}>{offer?.name}</OfferTitle> | |||||
| {isMobile && ( | {isMobile && ( | ||||
| <ScrollerHorizontal> | <ScrollerHorizontal> | ||||
| {props?.offer?.offer?.images.map((item, index) => { | |||||
| {images.map((item, index) => { | |||||
| if (!item) return; | if (!item) return; | ||||
| return ( | return ( | ||||
| <OfferImage | <OfferImage | ||||
| {t("itemDetailsCard.description")} | {t("itemDetailsCard.description")} | ||||
| </OfferDescriptionTitle> | </OfferDescriptionTitle> | ||||
| <OfferDescriptionText showBarterButton={props.showExchangeButton}> | <OfferDescriptionText showBarterButton={props.showExchangeButton}> | ||||
| {offer?.offer?.description} | |||||
| {offer?.description} | |||||
| </OfferDescriptionText> | </OfferDescriptionText> | ||||
| <DesciprtionPostDate previewCard={props.previewCard}> | <DesciprtionPostDate previewCard={props.previewCard}> | ||||
| {date} | {date} | ||||
| </OfferInfoContainer> | </OfferInfoContainer> | ||||
| </Details> | </Details> | ||||
| {imagesCarouselModal && ( | {imagesCarouselModal && ( | ||||
| <ImagesCarousel offer={props.offer} onModalClose={onModalClose} /> | |||||
| <ImagesCarousel offer={props.offer} images={images} onModalClose={onModalClose} /> | |||||
| )} | )} | ||||
| </> | </> | ||||
| ); | ); |
| import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | ||||
| import { DIRECT_CHAT_PAGE } from "../../../constants/pages"; | import { DIRECT_CHAT_PAGE } from "../../../constants/pages"; | ||||
| import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile"; | import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile"; | ||||
| import { useMemo } from "react"; | |||||
| import { useSelector } from "react-redux"; | |||||
| import { selectUserId } from "../../../store/selectors/loginSelectors"; | |||||
| const MiniChatCard = (props) => { | const MiniChatCard = (props) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { isMobile } = useIsMobile(); | const { isMobile } = useIsMobile(); | ||||
| const userId = useSelector(selectUserId); | |||||
| const changeChat = () => { | const changeChat = () => { | ||||
| history.push( | history.push( | ||||
| replaceInRoute(DIRECT_CHAT_PAGE, { | replaceInRoute(DIRECT_CHAT_PAGE, { | ||||
| chatId: props?.chat?.chat?._id, | |||||
| chatId: props?.chat?._id, | |||||
| }) | }) | ||||
| ); | ); | ||||
| }; | }; | ||||
| const interlocutorData = useMemo(() => { | |||||
| if (props?.chat?.participants) { | |||||
| let interlocutor = props?.chat?.participants[0]._id === userId ? 1 : 0; | |||||
| return props?.chat?.participants[interlocutor]; | |||||
| } | |||||
| return {}; | |||||
| }, [props?.chat]); | |||||
| return ( | return ( | ||||
| <MiniChatCardContainer selected={props.selected} onClick={changeChat}> | <MiniChatCardContainer selected={props.selected} onClick={changeChat}> | ||||
| <ProfileImage | <ProfileImage | ||||
| src={getImageUrl( | |||||
| props?.chat?.interlocutorData?.image, | |||||
| variants.chatCard, | |||||
| isMobile | |||||
| )} | |||||
| src={getImageUrl(interlocutorData?.image, variants.chatCard, isMobile)} | |||||
| /> | /> | ||||
| <ProfileDetails isBlocked={props.chat.interlocutorData?._blocked}> | |||||
| <ProfileDetails isBlocked={interlocutorData?._blocked}> | |||||
| <ProfileNameContainer> | <ProfileNameContainer> | ||||
| <ProfileName selected={props.selected}> | <ProfileName selected={props.selected}> | ||||
| {props?.chat?.interlocutorData?.name} | |||||
| {interlocutorData?.company?.name} | |||||
| </ProfileName> | </ProfileName> | ||||
| {(props.chat.interlocutorData?._blocked || | |||||
| props.chat.interlocutorData?._deleted) && ( | |||||
| {(interlocutorData?._blocked || interlocutorData?._deleted) && ( | |||||
| <BlockedProfile | <BlockedProfile | ||||
| redText | redText | ||||
| chatCard | chatCard | ||||
| shortText | shortText | ||||
| aboveTitle | aboveTitle | ||||
| hideIcon | hideIcon | ||||
| deleted={props.chat.interlocutorData?._deleted} | |||||
| deleted={interlocutorData?._deleted} | |||||
| /> | /> | ||||
| )} | )} | ||||
| </ProfileNameContainer> | </ProfileNameContainer> | ||||
| {t("messages.cardProduct")} | {t("messages.cardProduct")} | ||||
| </ProfileProduct> | </ProfileProduct> | ||||
| <ProfileProductName selected={props.selected}> | <ProfileProductName selected={props.selected}> | ||||
| {props?.chat?.offerData?.name} | |||||
| {props?.chat?.offer?.name} | |||||
| </ProfileProductName> | </ProfileProductName> | ||||
| </ProfileDetails> | </ProfileDetails> | ||||
| </MiniChatCardContainer> | </MiniChatCardContainer> |
| () => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted), | () => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted), | ||||
| [amIBuyer, exchange] | [amIBuyer, exchange] | ||||
| ); | ); | ||||
| const interlucatorUserId = useMemo( | |||||
| const interlocutorUserId = useMemo( | |||||
| () => (amIBuyer ? exchange?.seller?.userId : exchange?.buyer?.userId), | () => (amIBuyer ? exchange?.seller?.userId : exchange?.buyer?.userId), | ||||
| [exchange, amIBuyer] | [exchange, amIBuyer] | ||||
| ); | ); | ||||
| </MessageText> | </MessageText> | ||||
| ); | ); | ||||
| } | } | ||||
| } else if (requester === requesterStatus.INTERLUCATOR) { | |||||
| } else if (requester === requesterStatus.interlocutor) { | |||||
| return ( | return ( | ||||
| <RequestExchangeMessage | <RequestExchangeMessage | ||||
| haveIAccepted={haveIAccepted} | haveIAccepted={haveIAccepted} | ||||
| chatId={props.chatId} | chatId={props.chatId} | ||||
| userId={userId} | userId={userId} | ||||
| interlucatorUserId={interlucatorUserId} | |||||
| interlocutorUserId={interlocutorUserId} | |||||
| /> | /> | ||||
| ); | ); | ||||
| } | } | ||||
| return ""; | return ""; | ||||
| }, [requester, t, haveIAccepted, interlucatorUserId, userId, exchange]); | |||||
| }, [requester, t, haveIAccepted, interlocutorUserId, userId, exchange]); | |||||
| return ( | return ( | ||||
| <RequestExchangeCardContainer ismymessage={props.isMyMessage}> | <RequestExchangeCardContainer ismymessage={props.isMyMessage}> | ||||
| <InfoIcon /> | <InfoIcon /> |
| acceptExchangeSocket( | acceptExchangeSocket( | ||||
| props.chatId, | props.chatId, | ||||
| props.userId, | props.userId, | ||||
| props.interlucatorUserId, | |||||
| props.interlocutorUserId, | |||||
| () => { | () => { | ||||
| dispatch( | dispatch( | ||||
| acceptExchange({ | acceptExchange({ | ||||
| children: PropTypes.node, | children: PropTypes.node, | ||||
| chatId: PropTypes.string, | chatId: PropTypes.string, | ||||
| userId: PropTypes.string, | userId: PropTypes.string, | ||||
| interlucatorUserId: PropTypes.string, | |||||
| interlocutorUserId: PropTypes.string, | |||||
| haveIAccepted: PropTypes.any, | haveIAccepted: PropTypes.any, | ||||
| }; | }; | ||||
| fetchChats, | fetchChats, | ||||
| } from "../../store/actions/chat/chatActions"; | } from "../../store/actions/chat/chatActions"; | ||||
| import useSorting from "../../hooks/useOffers/useSorting"; | import useSorting from "../../hooks/useOffers/useSorting"; | ||||
| import { addMesageListener, removeMessageListener } from "../../socket/socket"; | |||||
| import { addMessageListener, removeMessageListener } from "../../socket/socket"; | |||||
| import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; | import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; | ||||
| import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants"; | import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants"; | ||||
| import SkeletonChatColumn from "./SkeletonChatColumn/SkeletonChatColumn"; | import SkeletonChatColumn from "./SkeletonChatColumn/SkeletonChatColumn"; | ||||
| history.goBack(); | history.goBack(); | ||||
| return; | return; | ||||
| } | } | ||||
| addMesageListener(({ succeed, data }) => { | |||||
| addMessageListener(({ succeed, data }) => { | |||||
| if (succeed) { | if (succeed) { | ||||
| dispatch( | dispatch( | ||||
| addNewMessage({ | addNewMessage({ |
| import { selectUserId } from "../../store/selectors/loginSelectors"; | import { selectUserId } from "../../store/selectors/loginSelectors"; | ||||
| import { | import { | ||||
| acceptExchangeSocket, | acceptExchangeSocket, | ||||
| addMesageListener, | |||||
| addMessageListener, | |||||
| removeMessageListener, | removeMessageListener, | ||||
| } from "../../socket/socket"; | } from "../../socket/socket"; | ||||
| import { makeErrorToastMessage } from "../../store/utils/makeToastMessage"; | import { makeErrorToastMessage } from "../../store/utils/makeToastMessage"; | ||||
| const offerObject = useMemo(() => { | const offerObject = useMemo(() => { | ||||
| if (location?.state?.offerId) { | if (location?.state?.offerId) { | ||||
| return offer?.offer; | |||||
| return offer; | |||||
| } | } | ||||
| return chat?.offer?.offer; | |||||
| return chat?.offer; | |||||
| }, [chat, location.state, offer]); | }, [chat, location.state, offer]); | ||||
| const chatObject = useMemo(() => { | const chatObject = useMemo(() => { | ||||
| let haveIAccepted = amIBuyer | let haveIAccepted = amIBuyer | ||||
| ? exchange.buyer?.accepted | ? exchange.buyer?.accepted | ||||
| : exchange.seller?.accepted; | : exchange.seller?.accepted; | ||||
| let haveInterlucatorAccepted = amIBuyer | |||||
| let haveinterlocutorAccepted = amIBuyer | |||||
| ? exchange.seller?.accepted | ? exchange.seller?.accepted | ||||
| : exchange.buyer?.accepted; | : exchange.buyer?.accepted; | ||||
| let haveIReviewed = amIBuyer | let haveIReviewed = amIBuyer | ||||
| ? exchange.buyer.givenReview | ? exchange.buyer.givenReview | ||||
| : exchange.seller.givenReview; | : exchange.seller.givenReview; | ||||
| if (haveIAccepted) { | if (haveIAccepted) { | ||||
| if (haveInterlucatorAccepted) { | |||||
| if (haveinterlocutorAccepted) { | |||||
| if (haveIReviewed) { | if (haveIReviewed) { | ||||
| return exchangeStatus.REVIEWED; | return exchangeStatus.REVIEWED; | ||||
| } else { | } else { | ||||
| return exchangeStatus.I_OFFERED; | return exchangeStatus.I_OFFERED; | ||||
| } | } | ||||
| } else { | } else { | ||||
| if (haveInterlucatorAccepted) { | |||||
| if (haveinterlocutorAccepted) { | |||||
| return exchangeStatus.I_AM_OFFERED; | return exchangeStatus.I_AM_OFFERED; | ||||
| } else { | } else { | ||||
| return exchangeStatus.INITIAL; | return exchangeStatus.INITIAL; | ||||
| }, [exchange, amIBuyer]); | }, [exchange, amIBuyer]); | ||||
| const interlocutorObject = useMemo(() => { | const interlocutorObject = useMemo(() => { | ||||
| console.log(offer); | |||||
| if (location?.state?.offerId) { | 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 offer?.user; | |||||
| } | } | ||||
| return { | |||||
| ...chat?.interlocutor, | |||||
| userId: | |||||
| chat?.chat?.participants[0] === userId | |||||
| ? chat?.chat?.participants[1] | |||||
| : chat?.chat?.participants[0], | |||||
| }; | |||||
| if (chat?.participants) { | |||||
| let interlocutor = userId === chat?.participants[0]._id ? 1 : 0; | |||||
| return chat?.participants[interlocutor]; | |||||
| } | |||||
| return {}; | |||||
| }, [chat, location.state, offer]); | }, [chat, location.state, offer]); | ||||
| // Fetch chat after it is created | // Fetch chat after it is created | ||||
| // Listener to socket.IO chat | // Listener to socket.IO chat | ||||
| useEffect(() => { | useEffect(() => { | ||||
| addMesageListener(({ succeed, data }) => { | |||||
| addMessageListener(({ succeed, data }) => { | |||||
| if (succeed) { | if (succeed) { | ||||
| if ( | if ( | ||||
| [...allChats].find((item) => { | [...allChats].find((item) => { | ||||
| return item.chat._id === data.chatId; | |||||
| return item._id === data.chatId; | |||||
| }) | }) | ||||
| ) { | ) { | ||||
| dispatch( | dispatch( | ||||
| data.message?.isAcceptRequest && | data.message?.isAcceptRequest && | ||||
| requester === requesterStatus.NOONE | requester === requesterStatus.NOONE | ||||
| ) { | ) { | ||||
| dispatch(setRequester(requesterStatus.INTERLUCATOR)); | |||||
| dispatch(setRequester(requesterStatus.interlocutor)); | |||||
| } | } | ||||
| } else { | } else { | ||||
| dispatch(fetchChats()); | dispatch(fetchChats()); | ||||
| return () => removeMessageListener(); | return () => removeMessageListener(); | ||||
| }, [allChats, routeMatch]); | }, [allChats, routeMatch]); | ||||
| const refreshChat = () => { | const refreshChat = () => { | ||||
| if (routeMatch.params?.chatId === "newMessage") { | if (routeMatch.params?.chatId === "newMessage") { | ||||
| dispatch(fetchOneOffer(location.state.offerId)); | dispatch(fetchOneOffer(location.state.offerId)); | ||||
| } | } | ||||
| }; | }; | ||||
| const handleAcceptExchange = () => { | const handleAcceptExchange = () => { | ||||
| console.log(chat) | |||||
| acceptExchangeSocket( | acceptExchangeSocket( | ||||
| chat?.chat?._id, | |||||
| chat?._id, | |||||
| userId, | userId, | ||||
| chat?.interlocutor?._id, | chat?.interlocutor?._id, | ||||
| () => { | () => { | ||||
| ); | ); | ||||
| dispatch( | dispatch( | ||||
| addNewMessage({ | addNewMessage({ | ||||
| _id: chat?.chat?._id, | |||||
| _id: chat?._id, | |||||
| message: { | message: { | ||||
| userId, | userId, | ||||
| isAcceptRequest: true, | isAcceptRequest: true, | ||||
| <DirectChatContent | <DirectChatContent | ||||
| chat={chatObject} | chat={chatObject} | ||||
| exchangeState={exchangeState} | exchangeState={exchangeState} | ||||
| interlucator={interlocutorObject} | |||||
| interlocutor={interlocutorObject} | |||||
| refreshChat={refreshChat} | refreshChat={refreshChat} | ||||
| /> | /> | ||||
| </DirectChatContainer> | </DirectChatContainer> |
| const myProfileImage = useSelector(selectMineProfilePicture); | const myProfileImage = useSelector(selectMineProfilePicture); | ||||
| const messagesRef = useRef(null); | const messagesRef = useRef(null); | ||||
| const requester = useSelector(selectRequester); | const requester = useSelector(selectRequester); | ||||
| const interlucatorProfileImage = props?.interlucator?.image; | |||||
| const interlocutorProfileImage = props?.interlocutor?.image; | |||||
| const isLoadingChatContent = useSelector( | const isLoadingChatContent = useSelector( | ||||
| selectIsLoadingByActionType(CHAT_SCOPE) | selectIsLoadingByActionType(CHAT_SCOPE) | ||||
| ); | ); | ||||
| const messages = props?.chat?.chat?.messages; | |||||
| const messages = props?.chat?.messages; | |||||
| useEffect(() => { | useEffect(() => { | ||||
| messagesRef.current?.scrollTo({ | messagesRef.current?.scrollTo({ | ||||
| top: messagesRef.current.scrollHeight, | top: messagesRef.current.scrollHeight, | ||||
| const handleRefresh = () => { | const handleRefresh = () => { | ||||
| props.refreshChat(); | props.refreshChat(); | ||||
| }; | }; | ||||
| console.log(props); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| {isLoadingChatContent || isLoadingChatContent === undefined ? ( | {isLoadingChatContent || isLoadingChatContent === undefined ? ( | ||||
| ) : ( | ) : ( | ||||
| <DirectChatContentContainer> | <DirectChatContentContainer> | ||||
| <DirectChatContentHeader | <DirectChatContentHeader | ||||
| interlucator={props?.interlucator} | |||||
| interlocutor={props?.interlocutor} | |||||
| exchangeState={props.exchangeState} | exchangeState={props.exchangeState} | ||||
| /> | /> | ||||
| <MessagesList ref={messagesRef} exchangeState={props?.exchangeState}> | <MessagesList ref={messagesRef} exchangeState={props?.exchangeState}> | ||||
| const isMyMessage = userId === item.userId; | const isMyMessage = userId === item.userId; | ||||
| const image = isMyMessage | const image = isMyMessage | ||||
| ? myProfileImage | ? myProfileImage | ||||
| : interlucatorProfileImage; | |||||
| if (requester === requesterStatus.INTERLUCATOR && isMyMessage && item?.isAcceptRequest) | |||||
| : interlocutorProfileImage; | |||||
| if ( | |||||
| requester === requesterStatus.interlocutor && | |||||
| isMyMessage && | |||||
| item?.isAcceptRequest | |||||
| ) | |||||
| return; | return; | ||||
| return ( | return ( | ||||
| <MessageContainer key={item?._id || item?._created}> | <MessageContainer key={item?._id || item?._created}> | ||||
| <RequestExchangeCard | <RequestExchangeCard | ||||
| isMyMessage={isMyMessage} | isMyMessage={isMyMessage} | ||||
| message={item} | message={item} | ||||
| chatId={props?.chat?.chat?._id} | |||||
| chatId={props?.chat?._id} | |||||
| /> | /> | ||||
| ) : ( | ) : ( | ||||
| <MessageCard | <MessageCard | ||||
| <DirectChatNewMessage | <DirectChatNewMessage | ||||
| chat={props?.chat} | chat={props?.chat} | ||||
| refreshChat={handleRefresh} | refreshChat={handleRefresh} | ||||
| interlucator={props.interlucator} | |||||
| interlocutor={props.interlocutor} | |||||
| /> | /> | ||||
| </DirectChatContentContainer> | </DirectChatContentContainer> | ||||
| )} | )} | ||||
| DirectChatContent.propTypes = { | DirectChatContent.propTypes = { | ||||
| children: PropTypes.node, | children: PropTypes.node, | ||||
| chat: PropTypes.any, | chat: PropTypes.any, | ||||
| interlucator: PropTypes.any, | |||||
| interlocutor: PropTypes.any, | |||||
| refreshChat: PropTypes.func, | refreshChat: PropTypes.func, | ||||
| exchangeState: PropTypes.any, | exchangeState: PropTypes.any, | ||||
| }; | }; |
| const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null); | const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null); | ||||
| const { isMobile } = useIsMobile(); | const { isMobile } = useIsMobile(); | ||||
| const mineProfileBlocked = useSelector(selectAmIBlocked); | const mineProfileBlocked = useSelector(selectAmIBlocked); | ||||
| console.log(props) | |||||
| const togglePhonePopover = (event) => { | const togglePhonePopover = (event) => { | ||||
| if (props.interlucator?.telephone) { | |||||
| if (props.interlocutor?.company?.contacts?.telephone) { | |||||
| setShowPhonePopover((prevState) => !prevState); | setShowPhonePopover((prevState) => !prevState); | ||||
| setPhonePopoverAnchorEl((prevState) => { | setPhonePopoverAnchorEl((prevState) => { | ||||
| if (prevState) return null; | if (prevState) return null; | ||||
| } | } | ||||
| }; | }; | ||||
| const routeToUser = () => { | const routeToUser = () => { | ||||
| if (!props?.interlucator?._blocked) | |||||
| if (!props?.interlocutor?._blocked) | |||||
| history.push( | history.push( | ||||
| replaceInRoute(PROFILE_PAGE, { | replaceInRoute(PROFILE_PAGE, { | ||||
| profileId: props?.interlucator?.userId, | |||||
| profileId: props?.interlocutor?._id, | |||||
| }) | }) | ||||
| ); | ); | ||||
| }; | }; | ||||
| console.log("in", props); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <DirectChatContentHeaderContainer> | <DirectChatContentHeaderContainer> | ||||
| <ProfileImage | <ProfileImage | ||||
| onClick={routeToUser} | onClick={routeToUser} | ||||
| src={getImageUrl( | src={getImageUrl( | ||||
| props?.interlucator?.image, | |||||
| props?.interlocutor?.image, | |||||
| variants.chatHeader, | variants.chatHeader, | ||||
| isMobile | isMobile | ||||
| )} | )} | ||||
| /> | /> | ||||
| <ProfileDetails> | <ProfileDetails> | ||||
| <ProfileName onClick={routeToUser}> | <ProfileName onClick={routeToUser}> | ||||
| {props?.interlucator?.name} | |||||
| {props?.interlocutor?.company?.name} | |||||
| </ProfileName> | </ProfileName> | ||||
| <ProfileLocation> | <ProfileLocation> | ||||
| <ProfileLocationIcon /> | <ProfileLocationIcon /> | ||||
| <ProfileLocationText> | <ProfileLocationText> | ||||
| {props?.interlucator?.location} | |||||
| {props?.interlocutor?.company?.contacts?.location} | |||||
| </ProfileLocationText> | </ProfileLocationText> | ||||
| </ProfileLocation> | </ProfileLocation> | ||||
| </ProfileDetails> | </ProfileDetails> | ||||
| <PhoneIconContainer | <PhoneIconContainer | ||||
| disabled={ | disabled={ | ||||
| mineProfileBlocked || | mineProfileBlocked || | ||||
| props?.interlucator?._blocked || | |||||
| !props.interlucator?.telephone | |||||
| props?.interlocutor?._blocked || | |||||
| !props.interlocutor?.company?.contacts?.telephone | |||||
| } | } | ||||
| onClick={togglePhonePopover} | onClick={togglePhonePopover} | ||||
| > | > | ||||
| open={showPhonePopover} | open={showPhonePopover} | ||||
| anchorRight | anchorRight | ||||
| onClose={togglePhonePopover} | onClose={togglePhonePopover} | ||||
| content={<PhonePopover phoneNumber={props.interlucator?.telephone} />} | |||||
| content={ | |||||
| <PhonePopover | |||||
| phoneNumber={props.interlocutor?.company?.contacts?.telephone} | |||||
| /> | |||||
| } | |||||
| /> | /> | ||||
| </DirectChatContentHeaderContainer> | </DirectChatContentHeaderContainer> | ||||
| {(props.exchangeState === exchangeStatus.I_OFFERED || | {(props.exchangeState === exchangeStatus.I_OFFERED || | ||||
| DirectChatContentHeader.propTypes = { | DirectChatContentHeader.propTypes = { | ||||
| children: PropTypes.node, | children: PropTypes.node, | ||||
| interlucator: PropTypes.any, | |||||
| interlocutor: PropTypes.any, | |||||
| exchangeState: PropTypes.bool, | exchangeState: PropTypes.bool, | ||||
| }; | }; | ||||
| const chat = useSelector(selectSelectedChat); | const chat = useSelector(selectSelectedChat); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| if (chat?.chat?.exchangeId) refetchExchange(); | |||||
| }, [chat]); | |||||
| if (chat?.exchange?._id) refetchExchange(); | |||||
| }, [chat?.exchange]); | |||||
| const isDisabledReviews = useMemo(() => { | const isDisabledReviews = useMemo(() => { | ||||
| if (!exchange.valid) return true; | if (!exchange.valid) return true; | ||||
| }; | }; | ||||
| const refetchExchange = () => { | const refetchExchange = () => { | ||||
| dispatch(fetchExchange(chat.chat.exchangeId)); | |||||
| dispatch(fetchExchange(chat.exchange?._id)); | |||||
| }; | }; | ||||
| const acceptExchange = () => { | const acceptExchange = () => { |
| const location = useLocation(); | const location = useLocation(); | ||||
| const history = useHistory(); | const history = useHistory(); | ||||
| const userId = useSelector(selectUserId); | const userId = useSelector(selectUserId); | ||||
| console.log(props) | |||||
| const handleSend = useCallback( | const handleSend = useCallback( | ||||
| (newChatId = undefined) => { | (newChatId = undefined) => { | ||||
| if (props.chat?.chat?._id) { | |||||
| const chatId = props.chat?.chat?._id || newChatId; | |||||
| sendMessage(chatId, userId, typedValue, props.interlucator.userId); | |||||
| console.log(props?.chat?._id); | |||||
| if (typedValue?.length === 0) return; | |||||
| if (props?.chat?._id) { | |||||
| const chatId = props.chat?._id || newChatId; | |||||
| sendMessage(chatId, userId, typedValue, props.interlocutor._id); | |||||
| dispatch( | dispatch( | ||||
| addNewMessage({ | addNewMessage({ | ||||
| _id: chatId, | _id: chatId, | ||||
| }, | }, | ||||
| }) | }) | ||||
| ); | ); | ||||
| if (props.chat?.chat?._id) { | |||||
| if (!exchange.valid && exchange.seller.userId === userId) { | |||||
| if (props.chat?._id) { | |||||
| if (!exchange.valid && exchange.seller.user._id === userId) { | |||||
| dispatch(validateExchange(exchange._id)); | dispatch(validateExchange(exchange._id)); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| setTypedValue(""); | setTypedValue(""); | ||||
| }, | }, | ||||
| [typedValue, props.chat?.chat?._id, userId, props.interlucator.userId] | |||||
| [typedValue, props.chat?._id, userId, props.interlocutor] | |||||
| ); | ); | ||||
| console.log(exchange); | |||||
| const handleMessageSendSuccess = (newChatId) => { | const handleMessageSendSuccess = (newChatId) => { | ||||
| history.replace(`${newChatId}`); | history.replace(`${newChatId}`); | ||||
| }; | }; | ||||
| startNewChat({ | startNewChat({ | ||||
| offerId, | offerId, | ||||
| message: typedValue, | message: typedValue, | ||||
| interlucatorUserId: props.interlucator.userId, | |||||
| interlocutorUserId: props.interlocutor.userId, | |||||
| handleMessageSendSuccess, | handleMessageSendSuccess, | ||||
| }) | }) | ||||
| ); | ); | ||||
| children: PropTypes.node, | children: PropTypes.node, | ||||
| chatId: PropTypes.any, | chatId: PropTypes.any, | ||||
| refreshChat: PropTypes.func, | refreshChat: PropTypes.func, | ||||
| interlucator: PropTypes.any, | |||||
| interlocutor: PropTypes.any, | |||||
| chat: PropTypes.any, | chat: PropTypes.any, | ||||
| }; | }; | ||||
| const newChat = useMemo(() => { | const newChat = useMemo(() => { | ||||
| if (location.state?.offerId) { | if (location.state?.offerId) { | ||||
| return { | return { | ||||
| interlocutorData: { | |||||
| image: offer?.companyData?.image, | |||||
| name: offer?.companyData?.company?.name, | |||||
| }, | |||||
| offerData: { | |||||
| name: offer?.offer?.name, | |||||
| participants: [ | |||||
| { | |||||
| image: offer?.user?.image, | |||||
| company: { | |||||
| name: offer?.user?.company?.name, | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| offer: { | |||||
| name: offer?.name, | |||||
| }, | }, | ||||
| }; | }; | ||||
| } | } | ||||
| <MiniChatCard | <MiniChatCard | ||||
| key={Date.now() * Math.random()} | key={Date.now() * Math.random()} | ||||
| chat={item} | chat={item} | ||||
| selected={item?.chat?._id === selectedChat?.chat?._id} | |||||
| selected={item?._id === selectedChat?._id} | |||||
| /> | /> | ||||
| ); | ); | ||||
| })} | })} |
| logo: true, | logo: true, | ||||
| }, | }, | ||||
| }); | }); | ||||
| searchRef.current.value = ""; | |||||
| if (searchRef?.current) searchRef.current.value = ""; | |||||
| } | } | ||||
| }; | }; | ||||
| ); | ); | ||||
| let isMyProfile = useMemo(() => { | let isMyProfile = useMemo(() => { | ||||
| if ( | if ( | ||||
| offer?.offer?.userId?.toString() === userId?.toString() || | |||||
| offer?.user?._id?.toString() === userId?.toString() || | |||||
| props.isAdmin | props.isAdmin | ||||
| ) | ) | ||||
| return true; | return true; |
| import itemDetailsData from "../../../notFoundData/itemDetailsData"; | import itemDetailsData from "../../../notFoundData/itemDetailsData"; | ||||
| import { Tooltip } from "@mui/material"; | import { Tooltip } from "@mui/material"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | |||||
| import { DIRECT_CHAT_PAGE, PROFILE_PAGE } from "../../../constants/pages"; | |||||
| const ItemDetailsHeaderCard = (props) => { | const ItemDetailsHeaderCard = (props) => { | ||||
| const history = useHistory(); | const history = useHistory(); | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const offer = useMemo(() => { | const offer = useMemo(() => { | ||||
| if (props.offer) { | if (props.offer) { | ||||
| if (props.offer.offer._id === routeMatch.params.offerId) { | |||||
| console.log("itemDetailsHeader: ", props.offer) | |||||
| if (props.offer._id === routeMatch.params.offerId) { | |||||
| return props.offer; | return props.offer; | ||||
| } | } | ||||
| } | } | ||||
| const { isMobile } = useIsMobile(); | const { isMobile } = useIsMobile(); | ||||
| const handleGoProfile = () => { | const handleGoProfile = () => { | ||||
| history.push(`/profile/${offer?.offer?.userId}`); | |||||
| history.push(replaceInRoute(PROFILE_PAGE, { | |||||
| profileId: props?.offer?.user?._id | |||||
| })); | |||||
| }; | }; | ||||
| const messageUser = (offer) => { | const messageUser = (offer) => { | ||||
| const chatItem = chats.find( | const chatItem = chats.find( | ||||
| (item) => item.chat.offerId === offer?.offer?._id | |||||
| (item) => item.chat.offerId === offer?._id | |||||
| ); | ); | ||||
| if (chatItem !== undefined) { | if (chatItem !== undefined) { | ||||
| history.push(`/messages/${chatItem.chat._id}`); | |||||
| history.push(DIRECT_CHAT_PAGE, { | |||||
| chatId: chatItem.chat._id | |||||
| }); | |||||
| } else { | } else { | ||||
| if (offer?.offer?.userId !== userId) { | |||||
| if (offer?.userId !== userId) { | |||||
| history.push(`/messages/newMessage`, { | history.push(`/messages/newMessage`, { | ||||
| offerId: offer?.offer?._id, | |||||
| offerId: offer?._id, | |||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| <HeaderTop> | <HeaderTop> | ||||
| <OfferImage | <OfferImage | ||||
| src={getImageUrl( | src={getImageUrl( | ||||
| offer?.companyData?.image ? offer.companyData.image : "", | |||||
| offer?.user?.image ? offer.user.image : "", | |||||
| variants.profileImage, | variants.profileImage, | ||||
| isMobile | isMobile | ||||
| )} | )} | ||||
| /> | /> | ||||
| <OfferDetails> | <OfferDetails> | ||||
| <OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}> | <OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}> | ||||
| {offer?.companyData?.company?.name} | |||||
| {offer?.user?.company?.name} | |||||
| </OfferTitle> | </OfferTitle> | ||||
| <PIBDetail offer={offer} isMyProfile={props.isMyProfile} /> | <PIBDetail offer={offer} isMyProfile={props.isMyProfile} /> | ||||
| <CategoryDetail offer={offer} isMyProfile={props.isMyProfile} /> | <CategoryDetail offer={offer} isMyProfile={props.isMyProfile} /> |
| <LocationIcon /> | <LocationIcon /> | ||||
| </DetailIcon> | </DetailIcon> | ||||
| <DetailText ismyprofile={props.isMyProfile}> | <DetailText ismyprofile={props.isMyProfile}> | ||||
| {offer.offer?.location?.city} | |||||
| {offer?.location?.city} | |||||
| </DetailText> | </DetailText> | ||||
| </DetailContainer> | </DetailContainer> | ||||
| ); | ); |
| <PIB /> | <PIB /> | ||||
| </PIBIcon> | </PIBIcon> | ||||
| <DetailText isMyProfile={props.isMyProfile}> | <DetailText isMyProfile={props.isMyProfile}> | ||||
| {`${t("itemDetailsCard.PIB")}${offer?.companyData?.company?.PIB}`} | |||||
| {`${t("itemDetailsCard.PIB")}${offer?.user?.company?.PIB}`} | |||||
| </DetailText> | </DetailText> | ||||
| </DetailContainer> | </DetailContainer> | ||||
| ); | ); |
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const offer = props.offer; | const offer = props.offer; | ||||
| const percentOfSucceededExchanges = useMemo(() => { | const percentOfSucceededExchanges = useMemo(() => { | ||||
| if (offer?.companyData?.statistics?.exchanges?.succeeded === 0) { | |||||
| if (offer?.user?.statistics?.exchanges?.succeeded === 0) { | |||||
| return 0 + "%"; | return 0 + "%"; | ||||
| } else { | } else { | ||||
| return ( | return ( | ||||
| Math.ceil( | Math.ceil( | ||||
| (offer?.companyData?.statistics?.exchanges?.total / | |||||
| offer?.companyData?.statistics?.exchanges?.succeeded) * | |||||
| (offer?.user?.statistics?.exchanges?.total / | |||||
| offer?.user?.statistics?.exchanges?.succeeded) * | |||||
| 100 | 100 | ||||
| ) + "%" | ) + "%" | ||||
| ); | ); | ||||
| <BottomDetails> | <BottomDetails> | ||||
| <StatusText> | <StatusText> | ||||
| <StatusValue> | <StatusValue> | ||||
| {offer?.companyData?.statistics?.publishes?.count} | |||||
| {offer?.user?.statistics?.publishes?.count} | |||||
| </StatusValue> | </StatusValue> | ||||
| {t("itemDetailsCard.offers")} | {t("itemDetailsCard.offers")} | ||||
| </StatusText> | </StatusText> | ||||
| <StatusText> | <StatusText> | ||||
| <StatusValue> | <StatusValue> | ||||
| {offer?.companyData?.statistics?.views?.count} | |||||
| {offer?.user?.statistics?.views?.count} | |||||
| </StatusValue> | </StatusValue> | ||||
| {t("itemDetailsCard.totalViews")} | {t("itemDetailsCard.totalViews")} | ||||
| </StatusText> | </StatusText> |
| const handleClickCategory = () => { | const handleClickCategory = () => { | ||||
| props?.offers?.filters?.locations.clear(); | props?.offers?.filters?.locations.clear(); | ||||
| props?.offers?.filters?.subcategory.clear(); | props?.offers?.filters?.subcategory.clear(); | ||||
| console.log("tooltip 1") | |||||
| props?.offers?.applyFilters(); | props?.offers?.applyFilters(); | ||||
| }; | }; | ||||
| const handleClickSubcategory = () => { | const handleClickSubcategory = () => { | ||||
| props?.offers?.filters?.locations.clear(); | props?.offers?.filters?.locations.clear(); | ||||
| console.log("tooltip 2") | |||||
| props?.offers?.applyFilters(); | props?.offers?.applyFilters(); | ||||
| }; | }; | ||||
| const goBack = () => { | const goBack = () => { |
| isGrid={props?.isGrid} | isGrid={props?.isGrid} | ||||
| isUsers={props?.isUsers} | isUsers={props?.isUsers} | ||||
| users={props?.users} | users={props?.users} | ||||
| myOffers={props?.myOffers} | |||||
| /> | /> | ||||
| {props?.skeleton && | {props?.skeleton && | ||||
| arrayForMapping.map((item, index) => ( | arrayForMapping.map((item, index) => ( |
| import PropTypes from "prop-types"; | import PropTypes from "prop-types"; | ||||
| import { makeErrorToastMessage } from "../../../store/utils/makeToastMessage"; | import { makeErrorToastMessage } from "../../../store/utils/makeToastMessage"; | ||||
| import { EyeIcon } from "./MyMessages.styled"; | import { EyeIcon } from "./MyMessages.styled"; | ||||
| import { DIRECT_CHAT_PAGE } from "../../../constants/pages"; | |||||
| import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | |||||
| export const MyMessages = (props) => { | export const MyMessages = (props) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const convertMessages = (messages) => { | const convertMessages = (messages) => { | ||||
| return messages | return messages | ||||
| .map((item) => ({ | |||||
| src: item.interlocutorData.image, | |||||
| title: item.interlocutorData.name, | |||||
| onClick: () => goToMessage(item?.chat?._id), | |||||
| text: "Proizvod: ", | |||||
| bigText: item.offerData.name, | |||||
| })) | |||||
| .map((item) => { | |||||
| let interlocutor = userId === item.participants[0]._id ? 1 : 0; | |||||
| return { | |||||
| src: item.participants[interlocutor]?.image, | |||||
| title: item.participants[interlocutor]?.company?.name, | |||||
| onClick: () => goToMessage(item?._id), | |||||
| text: "Proizvod: ", | |||||
| bigText: item.offer.name, | |||||
| }; | |||||
| }) | |||||
| .slice(0, 2); | .slice(0, 2); | ||||
| }; | }; | ||||
| } | } | ||||
| }, [userId]); | }, [userId]); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| console.log(chats); | |||||
| if (chats?.length > 0) { | if (chats?.length > 0) { | ||||
| setLastChats([...convertMessages(chats)]); | setLastChats([...convertMessages(chats)]); | ||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| const goToMessage = (chatId) => { | const goToMessage = (chatId) => { | ||||
| history.push(`/messages/${chatId}`); | |||||
| history.push( | |||||
| replaceInRoute(DIRECT_CHAT_PAGE, { | |||||
| chatId, | |||||
| }) | |||||
| ); | |||||
| props.closePopover(); | props.closePopover(); | ||||
| }; | }; | ||||
| return ( | return ( |
| // Event keycode 13 = ENTER keycode | // Event keycode 13 = ENTER keycode | ||||
| if (event.keyCode === 13) { | if (event.keyCode === 13) { | ||||
| event.preventDefault(); | event.preventDefault(); | ||||
| console.log("iz search1") | |||||
| handleSearch(); | handleSearch(); | ||||
| } | } | ||||
| }, | }, | ||||
| searchRef.current.removeEventListener("keyup", listener); | searchRef.current.removeEventListener("keyup", listener); | ||||
| }; | }; | ||||
| const handleSearch = () => { | const handleSearch = () => { | ||||
| console.log("iz search 2") | |||||
| if (props.isAdmin) { | if (props.isAdmin) { | ||||
| if (props.handleSearch) props.handleSearch(searchRef.current.value); | if (props.handleSearch) props.handleSearch(searchRef.current.value); | ||||
| else search.searchOffersImmediately(searchRef.current.value); | else search.searchOffersImmediately(searchRef.current.value); |
| export default { | export default { | ||||
| NOONE: 0, | NOONE: 0, | ||||
| ME: 1, | ME: 1, | ||||
| INTERLUCATOR: 2 | |||||
| interlocutor: 2 | |||||
| } | } |
| useEffect(() => { | useEffect(() => { | ||||
| setSelectedCategoryLocally(selectedCategory); | setSelectedCategoryLocally(selectedCategory); | ||||
| console.log("sleectedCat") | |||||
| }, [selectedCategory]); | }, [selectedCategory]); | ||||
| // Set selected category locally in state | // Set selected category locally in state | ||||
| // If second argument is true, then selected category is also updated in redux | // If second argument is true, then selected category is also updated in redux | ||||
| const setSelectedCategory = (category, immediateApply = false) => { | |||||
| const setSelectedCategory = (category) => { | |||||
| setSelectedCategoryLocally(category); | setSelectedCategoryLocally(category); | ||||
| if (immediateApply) { | |||||
| dispatch(setFilteredCategory(category)); | |||||
| } | |||||
| // if (immediateApply) { | |||||
| // dispatch(setFilteredCategory(category)); | |||||
| // } | |||||
| }; | }; | ||||
| // Find category object by providing its name | // Find category object by providing its name |
| import useLocationsFilter from "./useLocationsFilter"; | import useLocationsFilter from "./useLocationsFilter"; | ||||
| import useSubcategoryFilter from "./useSubcategoryFilter"; | import useSubcategoryFilter from "./useSubcategoryFilter"; | ||||
| const useFilters = (clearAll = false, applyFilters) => { | |||||
| const useFilters = (clearAll = false, applyFilters = () => {}) => { | |||||
| const category = useCategoryFilter(); | const category = useCategoryFilter(); | ||||
| const subcategory = useSubcategoryFilter(applyFilters); | const subcategory = useSubcategoryFilter(applyFilters); | ||||
| const locations = useLocationsFilter(); | const locations = useLocationsFilter(); | ||||
| if (category.selectedCategoryLocally?._id) sumOfFiltersChosen++; | if (category.selectedCategoryLocally?._id) sumOfFiltersChosen++; | ||||
| if (subcategory.selectedSubcategoryLocally?._id) sumOfFiltersChosen++; | if (subcategory.selectedSubcategoryLocally?._id) sumOfFiltersChosen++; | ||||
| sumOfFiltersChosen += locations.selectedLocationsLocally.length; | sumOfFiltersChosen += locations.selectedLocationsLocally.length; | ||||
| console.log("numOfFiltersChosen"); | |||||
| return sumOfFiltersChosen; | return sumOfFiltersChosen; | ||||
| }, [ | }, [ | ||||
| category.selectedCategoryLocally, | category.selectedCategoryLocally, |
| useEffect(() => { | useEffect(() => { | ||||
| dispatch(fetchMineOffers()); | dispatch(fetchMineOffers()); | ||||
| return () => { | |||||
| filters.clear(); | |||||
| } | |||||
| }, []); | }, []); | ||||
| const clear = () => { | const clear = () => { | ||||
| setAppliedFilters(false); | setAppliedFilters(false); | ||||
| } | } | ||||
| const apply = () => { | |||||
| const applyFilters = () => { | |||||
| paging.changePage(1); | paging.changePage(1); | ||||
| setAppliedFilters(false); | setAppliedFilters(false); | ||||
| }; | }; | ||||
| // Filter, search and sort all mine offers | // Filter, search and sort all mine offers | ||||
| const allOffersToShow = useMemo(() => { | const allOffersToShow = useMemo(() => { | ||||
| let mineOffersFiltered = [...mineOffers]; | let mineOffersFiltered = [...mineOffers]; | ||||
| console.log(filters) | |||||
| // Filter mine offers by category | // Filter mine offers by category | ||||
| if (filters.category.selectedCategoryLocally?.name) | if (filters.category.selectedCategoryLocally?.name) | ||||
| mineOffersFiltered = mineOffersFiltered.filter( | mineOffersFiltered = mineOffersFiltered.filter( | ||||
| search, | search, | ||||
| allOffersToShow, | allOffersToShow, | ||||
| totalOffers, | totalOffers, | ||||
| apply, | |||||
| applyFilters, | |||||
| clear, | clear, | ||||
| }; | }; | ||||
| }; | }; |
| sorting | sorting | ||||
| ); | ); | ||||
| dispatch(setQueryString(convertQueryStringForBackend(newQueryString))); | dispatch(setQueryString(convertQueryStringForBackend(newQueryString))); | ||||
| console.log("useoff apply") | |||||
| }; | }; | ||||
| const filters = useFilters(false, apply); | const filters = useFilters(false, apply); | ||||
| dispatch(setHeaderString(makeHeaderStringHelper({}))); | dispatch(setHeaderString(makeHeaderStringHelper({}))); | ||||
| history.location.state = {}; | history.location.state = {}; | ||||
| } | } | ||||
| console.log("history.log"); | |||||
| }, [history.location]); | }, [history.location]); | ||||
| // On every change of query string, new header string should be created | // On every change of query string, new header string should be created | ||||
| useEffect(() => { | useEffect(() => { | ||||
| const headerStringLocal = makeHeaderStringHelper(filters); | const headerStringLocal = makeHeaderStringHelper(filters); | ||||
| dispatch(setHeaderString(headerStringLocal)); | dispatch(setHeaderString(headerStringLocal)); | ||||
| console.log("queryStringHook.queryString, filtersCleared") | |||||
| }, [queryStringHook.queryString, filtersCleared]); | }, [queryStringHook.queryString, filtersCleared]); | ||||
| // Initially set category, location and subcategory based on query string | // Initially set category, location and subcategory based on query string | ||||
| useEffect(() => { | useEffect(() => { | ||||
| console.log("!!!!!!!!!!queryStringHook.isInitiallyLoaded") | |||||
| if (queryStringHook.isInitiallyLoaded) { | if (queryStringHook.isInitiallyLoaded) { | ||||
| const queryObject = queryStringHook.queryObject; | const queryObject = queryStringHook.queryObject; | ||||
| if (KEY_CATEGORY in queryObject) { | if (KEY_CATEGORY in queryObject) { | ||||
| setFiltersCleared(false); | setFiltersCleared(false); | ||||
| apply(); | apply(); | ||||
| } | } | ||||
| console.log("filtersCleared") | |||||
| }, [filtersCleared]); | }, [filtersCleared]); | ||||
| const applyFilters = () => { | const applyFilters = () => { | ||||
| console.log("applyfilters") | |||||
| setFiltersCleared(true); | setFiltersCleared(true); | ||||
| }; | }; | ||||
| const clearFiltersAndApply = () => { | const clearFiltersAndApply = () => { | ||||
| console.log("applyfilters") | |||||
| clear(); | clear(); | ||||
| setFiltersCleared(true); | setFiltersCleared(true); | ||||
| }; | }; | ||||
| const applySorting = () => { | const applySorting = () => { | ||||
| console.log("applyfilters") | |||||
| paging.changePage(1); | paging.changePage(1); | ||||
| setFiltersCleared(true); | setFiltersCleared(true); | ||||
| }; | }; | ||||
| const applySearch = () => { | const applySearch = () => { | ||||
| console.log("applyfilters") | |||||
| paging.changePage(1); | paging.changePage(1); | ||||
| setFiltersCleared(true); | setFiltersCleared(true); | ||||
| }; | }; | ||||
| if (queryStringHook.isInitiallyLoaded) { | if (queryStringHook.isInitiallyLoaded) { | ||||
| search.searchOffers(search.searchString); | search.searchOffers(search.searchString); | ||||
| } | } | ||||
| console.log("search log") | |||||
| }, [search.searchString]); | }, [search.searchString]); | ||||
| // Clears only filters(does not clear sorting and search) | // Clears only filters(does not clear sorting and search) | ||||
| const clearOnlyFiltersAndApply = () => { | const clearOnlyFiltersAndApply = () => { | ||||
| filters.clear(); | filters.clear(); | ||||
| paging.changePage(1); | paging.changePage(1); | ||||
| setFiltersCleared(true); | setFiltersCleared(true); | ||||
| console.log("clear log") | |||||
| }; | }; | ||||
| const clear = () => { | const clear = () => { |
| // except on initial load | // except on initial load | ||||
| useEffect(() => { | useEffect(() => { | ||||
| if (isInitallyLoaded && applyAllFilters) { | if (isInitallyLoaded && applyAllFilters) { | ||||
| console.log("paging apply") | |||||
| applyAllFilters(); | applyAllFilters(); | ||||
| } | } | ||||
| if (!disableScroll) { | if (!disableScroll) { |
| } else { | } else { | ||||
| setHistoryStateCleared(true); | setHistoryStateCleared(true); | ||||
| } | } | ||||
| console.log("history location querystr") | |||||
| }, [history.location]); | }, [history.location]); | ||||
| // Set initially loaded to true on initial load | // Set initially loaded to true on initial load | ||||
| ) { | ) { | ||||
| setIsInitallyLoaded(true); | setIsInitallyLoaded(true); | ||||
| } | } | ||||
| console.log("querystr") | |||||
| }, [queryString]); | }, [queryString]); | ||||
| // Updating offers on query string change | // Updating offers on query string change | ||||
| search: convertQueryStringForFrontend(queryString), | search: convertQueryStringForFrontend(queryString), | ||||
| }); | }); | ||||
| } | } | ||||
| console.log("querystr, isinit") | |||||
| }, [queryString, isInitiallyLoaded]); | }, [queryString, isInitiallyLoaded]); | ||||
| return { | return { |
| import { setFilteredSubcategory } from "../../store/actions/filters/filtersActions"; | import { setFilteredSubcategory } from "../../store/actions/filters/filtersActions"; | ||||
| import { selectSelectedSubcategory } from "../../store/selectors/filtersSelectors"; | import { selectSelectedSubcategory } from "../../store/selectors/filtersSelectors"; | ||||
| const useSubcategoryFilter = (applyFilters) => { | |||||
| const useSubcategoryFilter = (applyFilters = () => {}) => { | |||||
| const selectedSubcategory = useSelector(selectSelectedSubcategory); | const selectedSubcategory = useSelector(selectSelectedSubcategory); | ||||
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| const initialOption = { | const initialOption = { | ||||
| const setSelectedSubcategory = (subcategory) => { | const setSelectedSubcategory = (subcategory) => { | ||||
| setSelectedSubcategoryLocally(subcategory); | setSelectedSubcategoryLocally(subcategory); | ||||
| // if (immediateApply) { | // if (immediateApply) { | ||||
| dispatch(setFilteredSubcategory(subcategory)); | |||||
| dispatch(setFilteredSubcategory(subcategory)); | |||||
| // } | // } | ||||
| console.log("funk"); | |||||
| }; | }; | ||||
| const apply = () => { | const apply = () => { | ||||
| dispatch(setFilteredSubcategory(selectedSubcategoryLocally)); | |||||
| console.log("apply"); | |||||
| console.log("SELECTED SUB", selectedSubcategory); | |||||
| console.log("SELECTED SUBLOCALLY", selectedSubcategoryLocally); | |||||
| if ( | |||||
| Number(selectedSubcategory?._id) !== | |||||
| Number(selectedSubcategoryLocally?._id) | |||||
| ) | |||||
| dispatch(setFilteredSubcategory(selectedSubcategoryLocally)); | |||||
| }; | }; | ||||
| const clear = () => { | const clear = () => { | ||||
| console.log("clear"); | |||||
| setSelectedSubcategoryLocally(initialOption); | setSelectedSubcategoryLocally(initialOption); | ||||
| dispatch(setFilteredSubcategory(initialOption)); | dispatch(setFilteredSubcategory(initialOption)); | ||||
| }; | }; |
| // import useQueryString from "./useOffers/useQueryString"; | |||||
| export const useSearch = () => { | |||||
| // const queryStringHook = useQueryString(); | |||||
| const searchOffers = () => { | |||||
| // if (searchString?.length !== 0) { | |||||
| // queryStringHook.appendToQueryString("oname", searchString); | |||||
| // } else { | |||||
| // const newQueryString = new URLSearchParams(queryStringHook.queryString); | |||||
| // if (newQueryString.has("oname")) { | |||||
| // queryStringHook.deleteFromQueryString("oname"); | |||||
| // } | |||||
| // } | |||||
| }; | |||||
| return { | |||||
| searchOffers, | |||||
| }; | |||||
| }; |
| import defaultImage from "../constants/defaultImage"; | import defaultImage from "../constants/defaultImage"; | ||||
| export default { | export default { | ||||
| companyData: { | |||||
| company: { | |||||
| PIB: i18next.t("notFoundData.PIB"), | |||||
| name: i18next.t("notFoundData.companyName") | |||||
| }, | |||||
| image: defaultImage, | |||||
| lastThreeReviews: [], | |||||
| statistics: { | |||||
| exchanges: { | |||||
| failed: 0, | |||||
| succeeded: 0, | |||||
| total: 0, | |||||
| }, | |||||
| publishes: { | |||||
| count: 0, | |||||
| }, | |||||
| views: { | |||||
| count: 0, | |||||
| } | |||||
| } | |||||
| }, | |||||
| offer: { | |||||
| category: { | category: { | ||||
| name: i18next.t("notFoundData.categoryName") | name: i18next.t("notFoundData.categoryName") | ||||
| }, | }, | ||||
| count: 0 | count: 0 | ||||
| }, | }, | ||||
| _created: new Date().toString() | _created: new Date().toString() | ||||
| } | |||||
| } | } |
| const toggleFilters = () => { | const toggleFilters = () => { | ||||
| setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened); | setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened); | ||||
| }; | }; | ||||
| console.log("rerender") | |||||
| return ( | return ( | ||||
| <HomePageContainer> | <HomePageContainer> | ||||
| <MainLayout | <MainLayout |
| }, | }, | ||||
| chat: { | chat: { | ||||
| getChat: "chats", | getChat: "chats", | ||||
| getUserChats: "users/{userId}/chat", | |||||
| getUserChats: "users/{userId}/chats", | |||||
| getOneChat: "users/{userId}/chats/{chatId}", | getOneChat: "users/{userId}/chats/{chatId}", | ||||
| createChat: "users/{userId}/offers/{offerId}/chat", | createChat: "users/{userId}/offers/{offerId}/chat", | ||||
| sendMessage: "chats", | sendMessage: "chats", |
| callbackFn(); | callbackFn(); | ||||
| }; | }; | ||||
| export const addMesageListener = (listener) => { | |||||
| export const addMessageListener = (listener) => { | |||||
| socket.on("private_message", (data) => | socket.on("private_message", (data) => | ||||
| listener({ | listener({ | ||||
| succeed: true, | succeed: true, |
| function setChatsTotal(state, action) { | function setChatsTotal(state, action) { | ||||
| return { | return { | ||||
| ...state, | ...state, | ||||
| total: action.payload | |||||
| total: action.payload, | |||||
| }; | }; | ||||
| } | } | ||||
| function setOneChat(state, action) { | function setOneChat(state, action) { | ||||
| } | } | ||||
| function addNewMessage(state, { payload }) { | function addNewMessage(state, { payload }) { | ||||
| let allChats = [...state.latestChats]; | let allChats = [...state.latestChats]; | ||||
| let chat = allChats.find((item) => item.chat._id === payload._id); | |||||
| console.log(state); | |||||
| let chat = allChats.find((item) => item._id === payload._id); | |||||
| if (chat) { | if (chat) { | ||||
| chat = { | chat = { | ||||
| ...chat, | ...chat, | ||||
| chat: { | |||||
| ...chat.chat, | |||||
| messages: [...chat.chat.messages, payload.message], | |||||
| }, | |||||
| messages: [...chat.messages, payload.message], | |||||
| }; | }; | ||||
| allChats = allChats.filter((item) => item.chat._id !== chat.chat._id); | |||||
| allChats = allChats.filter((item) => item._id !== chat._id); | |||||
| allChats = [chat, ...allChats]; | allChats = [chat, ...allChats]; | ||||
| } | } | ||||
| let newSelectedChat = {}; | let newSelectedChat = {}; | ||||
| if (state.selectedChat.chat) { | if (state.selectedChat.chat) { | ||||
| newSelectedChat = { ...state.selectedChat }; | newSelectedChat = { ...state.selectedChat }; | ||||
| if (newSelectedChat.chat._id === chat.chat._id) | |||||
| newSelectedChat = { ...newSelectedChat, chat: chat.chat }; | |||||
| if (newSelectedChat._id === chat._id) | |||||
| newSelectedChat = { ...newSelectedChat, chat: chat }; | |||||
| } else { | } else { | ||||
| newSelectedChat = { ...chat }; | newSelectedChat = { ...chat }; | ||||
| } | } |
| queryString: queryString, | queryString: queryString, | ||||
| }); | }); | ||||
| yield call(console.dir, data); | yield call(console.dir, data); | ||||
| yield put(setChats([...data.data.chatsWithData])); | |||||
| yield put(setChatsTotal(data.data.total)) | |||||
| yield put(setChats([...data.data.chats])); | |||||
| yield put(setChatsTotal(data.data.total)); | |||||
| yield put(fetchChatsSuccess()); | yield put(fetchChatsSuccess()); | ||||
| } catch (e) { | } catch (e) { | ||||
| yield put(fetchChatsError()); | yield put(fetchChatsError()); | ||||
| try { | try { | ||||
| const userId = yield select(selectUserId); | const userId = yield select(selectUserId); | ||||
| const data = yield call(attemptFetchHeaderChats, userId); | const data = yield call(attemptFetchHeaderChats, userId); | ||||
| yield put(setChats([...data.data.chatsWithData])); | |||||
| yield put(setChats([...data.data.chats])); | |||||
| yield put(fetchHeaderChatsSuccess()); | yield put(fetchHeaderChatsSuccess()); | ||||
| } catch (e) { | } catch (e) { | ||||
| yield put(fetchHeaderChatsError()); | yield put(fetchHeaderChatsError()); | ||||
| userId, | userId, | ||||
| }); | }); | ||||
| let requester = requesterStatus.NOONE; | let requester = requesterStatus.NOONE; | ||||
| chatData.data.chat.messages.forEach((item) => { | |||||
| chatData.data.messages.forEach((item) => { | |||||
| if (requester !== requesterStatus.NOONE) return; | if (requester !== requesterStatus.NOONE) return; | ||||
| if (item.isAcceptRequest) { | if (item.isAcceptRequest) { | ||||
| if (item.userId === userId) requester = requesterStatus.ME; | if (item.userId === userId) requester = requesterStatus.ME; | ||||
| else requester = requesterStatus.INTERLUCATOR; | |||||
| else requester = requesterStatus.interlocutor; | |||||
| } | } | ||||
| }); | }); | ||||
| const chat = { | |||||
| chat: chatData.data.chat, | |||||
| offer: { | |||||
| offer: { ...chatData.data.offer, images: [chatData.data.offer.image] }, | |||||
| }, | |||||
| interlocutor: chatData.data.interlocutorData, | |||||
| }; | |||||
| yield put(setRequester(requester)); | yield put(setRequester(requester)); | ||||
| yield put(setOneChat(chat)); | |||||
| yield put(setOneChat(chatData.data)); | |||||
| yield put(fetchOneChatSuccess()); | yield put(fetchOneChatSuccess()); | ||||
| } catch (e) { | } catch (e) { | ||||
| yield put(fetchOneChatError()); | yield put(fetchOneChatError()); | ||||
| }); | }); | ||||
| const queryString = yield select(selectQueryString); | const queryString = yield select(selectQueryString); | ||||
| const data = yield call(attemptFetchChats, { userId, queryString }); | const data = yield call(attemptFetchChats, { userId, queryString }); | ||||
| yield put(setChats([...data.data.chatsWithData])); | |||||
| yield put(setChatsTotal(data.data.total)) | |||||
| yield put(setChats([...data.data.chats])); | |||||
| yield put(setChatsTotal(data.data.total)); | |||||
| const newChatId = newChatData.data.chatId; | const newChatId = newChatData.data.chatId; | ||||
| yield put(startNewChatSuccess()); | yield put(startNewChatSuccess()); | ||||
| yield call( | yield call( | ||||
| newChatData.data.chatId, | newChatData.data.chatId, | ||||
| userId, | userId, | ||||
| payload.payload.message, | payload.payload.message, | ||||
| payload.payload.interlucatorUserId | |||||
| payload.payload.interlocutorUserId | |||||
| ); | ); | ||||
| yield put( | yield put( | ||||
| addNewMessage({ | addNewMessage({ |
| const offerData = payload.payload.offerData; | const offerData = payload.payload.offerData; | ||||
| const formData = new FormData(); | const formData = new FormData(); | ||||
| formData.append("category[name]", offerData.category.name); | formData.append("category[name]", offerData.category.name); | ||||
| formData.append("condition", offerData.condition); | |||||
| formData.append( | |||||
| "condition", | |||||
| offerData.condition === "Novo" | |||||
| ? "novo" | |||||
| : offerData.condition === "Polovno" | |||||
| ? "polovno" | |||||
| : "kao novo" | |||||
| ); | |||||
| formData.append("description", offerData.description); | formData.append("description", offerData.description); | ||||
| // formData.append("file", JSON.stringify(offerData.images)) | // formData.append("file", JSON.stringify(offerData.images)) | ||||
| for (var i = 0; i < offerData.images.length; i++) { | for (var i = 0; i < offerData.images.length; i++) { | ||||
| const userId = yield select(selectUserId); | const userId = yield select(selectUserId); | ||||
| const data = yield call(attemptFetchProfileOffers, userId); | const data = yield call(attemptFetchProfileOffers, userId); | ||||
| yield put(setMineOffers(data.data.offers)); | yield put(setMineOffers(data.data.offers)); | ||||
| yield put(setTotalOffers(data.data.total)); | |||||
| yield put(fetchMineOffersSuccess()); | yield put(fetchMineOffersSuccess()); | ||||
| } catch (e) { | } catch (e) { | ||||
| yield put(fetchMineOffersError()); | yield put(fetchMineOffersError()); |
| import { DIRECT_CHAT_PAGE } from "../../constants/pages"; | |||||
| import history from "../../store/utils/history"; | import history from "../../store/utils/history"; | ||||
| import { replaceInRoute } from "./routeHelpers"; | |||||
| export const startChat = (chats, offer, userId) => { | export const startChat = (chats, offer, userId) => { | ||||
| const chatItem = chats.find( | const chatItem = chats.find( | ||||
| (item) => item.chat.offerId === offer?._id && offer?.userId !== userId | |||||
| (item) => item.offer?._id === offer?._id && offer?.user?._id !== userId | |||||
| ); | ); | ||||
| if (chatItem !== undefined) { | if (chatItem !== undefined) { | ||||
| history.push(`/messages/${chatItem.chat._id}`); | |||||
| history.push(replaceInRoute(DIRECT_CHAT_PAGE, { chatId: chatItem?._id })); | |||||
| } else { | } else { | ||||
| if (offer?.userId !== userId) { | |||||
| if (offer?.user?._id !== userId) { | |||||
| history.push(`/messages/newMessage`, { | history.push(`/messages/newMessage`, { | ||||
| offerId: offer?._id, | offerId: offer?._id, | ||||
| }); | }); |