| @@ -11,6 +11,7 @@ import { useTranslation } from "react-i18next"; | |||
| import { isInRoute, routeMatches } from "../../../../util/helpers/routeHelpers"; | |||
| import { ADMIN_HOME_PAGE, ADMIN_USERS_PAGE } from "../../../../constants/pages"; | |||
| import { ADMIN_NAVIGATION } from "../../../../constants/adminNavigation"; | |||
| import history from "../../../../store/utils/history"; | |||
| const SidebarNavigation = () => { | |||
| const { t } = useTranslation(); | |||
| @@ -1,5 +1,5 @@ | |||
| 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 { IconButton } from "../IconButton/IconButton"; | |||
| @@ -11,9 +11,9 @@ export const ArrowIcon = styled(DownArrow)` | |||
| `} | |||
| width: 18px; | |||
| height: 18px; | |||
| /* position: relative; | |||
| position: relative; | |||
| top: 1px; | |||
| left: 1px; */ | |||
| left: 1px; | |||
| & path { | |||
| ${(props) => | |||
| props.disabled && | |||
| @@ -46,7 +46,7 @@ export const ArrowContainer = styled(IconButton)` | |||
| } | |||
| ${(props) => | |||
| props.disabled && | |||
| ` | |||
| css` | |||
| border 1px solid ${selectedTheme.colors.iconStrokeDisabledColor} !important; | |||
| &:hover { | |||
| background-color: inherit; | |||
| @@ -18,7 +18,7 @@ export const IconButton = (props) => { | |||
| onClick={props.onClick} | |||
| sx={props.style} | |||
| iconcolor={props.iconColor} | |||
| {...props} | |||
| // {...props} | |||
| > | |||
| {props.children} | |||
| </IconButtonStyled> | |||
| @@ -12,42 +12,50 @@ import MobileOfferDetails from "./MobileOfferDetails/MobileOfferDetails"; | |||
| import useIsMobile from "../../../hooks/useIsMobile"; | |||
| import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | |||
| 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) | |||
| const ChatCard = (props) => { | |||
| const { isMobile } = useIsMobile(); | |||
| const userId = useSelector(selectUserId); | |||
| const chat = useMemo(() => { | |||
| return props.chat; | |||
| }, [props.chat]); | |||
| 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 ( | |||
| <ChatCardContainer onClick={routeToItem}> | |||
| <UserImgWrapper> | |||
| <UserImage | |||
| src={getImageUrl( | |||
| chat?.interlocutorData?.image, | |||
| chat?.participants[interlocutor].image, | |||
| variants.chatCard, | |||
| isMobile | |||
| )} | |||
| /> | |||
| </UserImgWrapper> | |||
| <ChatInfo isBlocked={props.chat.interlocutorData?._blocked}> | |||
| <ChatInfo isBlocked={props.chat.participants[interlocutor]?._blocked}> | |||
| <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 | |||
| redText | |||
| chatCard | |||
| shortText | |||
| aboveTitle | |||
| hideIcon | |||
| deleted={props.chat.interlocutorData?._deleted} | |||
| deleted={props.chat?.participants[interlocutor]?._deleted} | |||
| /> | |||
| )} | |||
| </ProfileNameContainer> | |||
| @@ -12,7 +12,7 @@ const MobileOfferDetails = (props) => { | |||
| return ( | |||
| <OfferCardContainerMobile> | |||
| <OfferTextMobile>{t("messages.cardProduct")}</OfferTextMobile> | |||
| <OfferTitleMobile>{props.chat?.offerData?.name}</OfferTitleMobile> | |||
| <OfferTitleMobile>{props.chat?.offer?.name}</OfferTitleMobile> | |||
| </OfferCardContainerMobile> | |||
| ); | |||
| }; | |||
| @@ -21,6 +21,7 @@ const CategoryChoser = forwardRef((props, ref) => { | |||
| const handleSelectCategory = (category) => { | |||
| filters.category.setSelectedCategory(category); | |||
| filters.subcategory.setSelectedSubcategory({}); | |||
| console.log("category 1") | |||
| props.offers.applyFilters(); | |||
| }; | |||
| console.log(props); | |||
| @@ -32,8 +32,14 @@ const SubcategoryChoser = forwardRef((props, ref) => { | |||
| }, | |||
| })); | |||
| const handleSelectSubcategory = (subcategory) => { | |||
| filters.subcategory.setSelectedSubcategory(subcategory, !props.myOffers); | |||
| console.log("props.offers") | |||
| // if (props.myOffers) props.offers?.applyFilters(); | |||
| }; | |||
| useEffect(() => { | |||
| if (props?.queryStringHook?.isInitiallyLoaded || props.isMyOffers) { | |||
| if (props?.queryStringHook?.isInitiallyLoaded || props.myOffers) { | |||
| if ( | |||
| !filters.category.selectedCategoryLocally || | |||
| filters.category.selectedCategoryLocally?._id === 0 | |||
| @@ -74,7 +80,7 @@ const SubcategoryChoser = forwardRef((props, ref) => { | |||
| : t("filters.subcategories.title") | |||
| } | |||
| searchPlaceholder={t("filters.subcategories.placeholder")} | |||
| setSelected={filters.subcategory.setSelectedSubcategory} | |||
| setSelected={handleSelectSubcategory} | |||
| selected={filters.subcategory.selectedSubcategoryLocally} | |||
| open={isOpened} | |||
| disabled={isDisabled} | |||
| @@ -91,7 +97,7 @@ SubcategoryChoser.propTypes = { | |||
| filters: PropTypes.any, | |||
| categoryOpened: PropTypes.bool, | |||
| queryStringHook: PropTypes.any, | |||
| isMyOffers: PropTypes.bool, | |||
| myOffers: PropTypes.bool, | |||
| offers: PropTypes.any, | |||
| }; | |||
| @@ -50,7 +50,7 @@ const FilterCard = (props) => { | |||
| queryStringHook={offers.queryStringHook} | |||
| ref={subcategoryRef} | |||
| categoryOpened={categoryRef.current?.isOpened} | |||
| isMyOffers={props.myOffers} | |||
| myOffers={props.myOffers} | |||
| offers={offers} | |||
| /> | |||
| @@ -17,6 +17,7 @@ const CheckboxDropdownList = (props) => { | |||
| const [isOpened, setIsOpened] = useState(false); | |||
| const handleDelete = (item) => { | |||
| props.setItemsSelected([...props.filters.filter((p) => p !== item)]); | |||
| console.log("dropdown 1") | |||
| props.offers.applyFilters(); | |||
| }; | |||
| const handleOpen = () => { | |||
| @@ -55,6 +55,7 @@ const FilterCheckboxDropdown = (props) => { | |||
| props.setItemsSelected([...props.filters, item]); | |||
| props.offers.applyFilters(); | |||
| } | |||
| console.log("filter checkbox 1"); | |||
| } | |||
| }; | |||
| const handleOpen = () => { | |||
| @@ -55,6 +55,7 @@ const FilterSmallDropdown = (props) => { | |||
| props.offers.applyFilters(); | |||
| } | |||
| } | |||
| console.log("dropdown 2") | |||
| }; | |||
| const setDropdownHandler = () => { | |||
| @@ -37,7 +37,7 @@ const ImagesCarousel = (props) => { | |||
| <CloseButtonIcon /> | |||
| </CloseButton> | |||
| <Scroller isCarousel> | |||
| {props?.offer?.offer?.images.map((image) => { | |||
| {props?.images.map((image) => { | |||
| if (!image) return; | |||
| return ( | |||
| <OfferImage | |||
| @@ -48,7 +48,7 @@ const ImagesCarousel = (props) => { | |||
| })} | |||
| </Scroller> | |||
| <Offer> | |||
| {t("carousel.offer")} <OfferSpan>{props.offer.offer.name}</OfferSpan> | |||
| {t("carousel.offer")} <OfferSpan>{props.offer.name}</OfferSpan> | |||
| </Offer> | |||
| </ImagesCarouselContainer> | |||
| </> | |||
| @@ -59,6 +59,7 @@ ImagesCarousel.propTypes = { | |||
| offer: PropTypes.any, | |||
| onModalClose: PropTypes.any, | |||
| createOffer: PropTypes.bool, | |||
| images: PropTypes.array | |||
| }; | |||
| export default ImagesCarousel; | |||
| @@ -49,12 +49,10 @@ const ItemDetailsCard = (props) => { | |||
| const dispatch = useDispatch(); | |||
| const offer = useMemo(() => { | |||
| 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; | |||
| } | |||
| if (props.createOffer) return props.offer.offer; | |||
| } | |||
| return itemDetailsData; | |||
| }, [props.offer, props.createOffer, routeMatch.params]); | |||
| @@ -66,21 +64,21 @@ const ItemDetailsCard = (props) => { | |||
| }, []); | |||
| useEffect(() => { | |||
| if (offer?.offer?._id) { | |||
| increaseOfferCounter(offer?.offer?._id); | |||
| if (offer?._id) { | |||
| increaseOfferCounter(offer?._id); | |||
| } | |||
| }, [offer]); | |||
| const date = formatDateLocale(new Date(offer?.offer?._created)); | |||
| const date = formatDateLocale(new Date(offer?._created)); | |||
| const startExchange = () => { | |||
| startChat(chats, offer?.offer, userId); | |||
| startChat(chats, offer, userId); | |||
| }; | |||
| const showDeleteOfferModalHandler = () => { | |||
| dispatch( | |||
| toggleDeleteOfferModal({ | |||
| offer: offer.offer, | |||
| offer: offer, | |||
| isAdmin: props.isAdmin, | |||
| }) | |||
| ); | |||
| @@ -90,18 +88,18 @@ const ItemDetailsCard = (props) => { | |||
| dispatch( | |||
| toggleEditOfferModal({ | |||
| editOffer: true, | |||
| offer: offer?.offer, | |||
| offer: offer, | |||
| isAdmin: props.isAdmin, | |||
| customUserId: offer?.offer?.userId, | |||
| customUserId: offer?.user?._id, | |||
| }) | |||
| ); | |||
| }; | |||
| const showPinOfferModalHandler = () => { | |||
| dispatch( | |||
| toggleDeleteOfferModal({ | |||
| offer: offer?.offer, | |||
| offer: offer, | |||
| pin: true, | |||
| pinnedOffer: offer?.offer?.pinned, | |||
| pinnedOffer: offer?.pinned, | |||
| deleteOffer: false, | |||
| }) | |||
| ); | |||
| @@ -120,21 +118,15 @@ const ItemDetailsCard = (props) => { | |||
| <Info> | |||
| <Information | |||
| icon={<CategoryIcon />} | |||
| value={offer?.offer?.category?.name} | |||
| value={offer?.category?.name} | |||
| /> | |||
| <Information | |||
| icon={<SubcategoryIcon />} | |||
| value={offer?.offer?.subcategory} | |||
| /> | |||
| <Information | |||
| icon={<QuantityIcon />} | |||
| value={offer?.offer?.condition} | |||
| value={offer?.subcategory} | |||
| /> | |||
| <Information icon={<QuantityIcon />} value={offer?.condition} /> | |||
| {!props.hideViews && ( | |||
| <Information | |||
| icon={<EyeIcon />} | |||
| value={offer?.offer?.views?.count} | |||
| /> | |||
| <Information icon={<EyeIcon />} value={offer?.views?.count} /> | |||
| )} | |||
| </Info> | |||
| <PostDate previewCard={props.previewCard}>{date}</PostDate> | |||
| @@ -154,7 +146,7 @@ const ItemDetailsCard = (props) => { | |||
| {props.isMyOffer && ( | |||
| <ButtonsContainer> | |||
| <PinIconContainer onClick={showPinOfferModalHandler}> | |||
| {offer?.offer?.pinned ? <UnpinIcon /> : <PinIcon />} | |||
| {offer?.pinned ? <UnpinIcon /> : <PinIcon />} | |||
| </PinIconContainer> | |||
| <EditIconContainer onClick={showEditOfferModalHandler}> | |||
| <EditIcon /> | |||
| @@ -27,9 +27,11 @@ const OfferDetails = (props) => { | |||
| const [images, setImages] = useState([]); | |||
| const [imagesCarouselModal, setImagesCarouselModal] = useState(false); | |||
| console.log(offer); | |||
| useEffect(() => { | |||
| if (props?.offer?.offer?.images) { | |||
| props.offer.offer.images.map((file) => { | |||
| if (props?.offer?.images) { | |||
| props.offer.images.map((file) => { | |||
| if (file) { | |||
| if (typeof file !== "string") { | |||
| var reader = new FileReader(); | |||
| @@ -41,19 +43,18 @@ const OfferDetails = (props) => { | |||
| console.log("Error: ", error); | |||
| }; | |||
| } 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 = () => { | |||
| setImagesCarouselModal(false); | |||
| }; | |||
| console.log(props); | |||
| return ( | |||
| <> | |||
| <Details | |||
| @@ -64,7 +65,7 @@ const OfferDetails = (props) => { | |||
| > | |||
| {!isMobile && props.singleOffer && ( | |||
| <ScrollerVertical> | |||
| {props?.offer?.offer?.images.map((item, index) => ( | |||
| {images.map((item, index) => ( | |||
| <OfferImage | |||
| src={ | |||
| props.createOffer | |||
| @@ -85,12 +86,10 @@ const OfferDetails = (props) => { | |||
| singleOffer={props.singleOffer} | |||
| previewCard={props.previewCard} | |||
| > | |||
| <OfferTitle singleOffer={props.singleOffer}> | |||
| {offer?.offer?.name} | |||
| </OfferTitle> | |||
| <OfferTitle singleOffer={props.singleOffer}>{offer?.name}</OfferTitle> | |||
| {isMobile && ( | |||
| <ScrollerHorizontal> | |||
| {props?.offer?.offer?.images.map((item, index) => { | |||
| {images.map((item, index) => { | |||
| if (!item) return; | |||
| return ( | |||
| <OfferImage | |||
| @@ -117,7 +116,7 @@ const OfferDetails = (props) => { | |||
| {t("itemDetailsCard.description")} | |||
| </OfferDescriptionTitle> | |||
| <OfferDescriptionText showBarterButton={props.showExchangeButton}> | |||
| {offer?.offer?.description} | |||
| {offer?.description} | |||
| </OfferDescriptionText> | |||
| <DesciprtionPostDate previewCard={props.previewCard}> | |||
| {date} | |||
| @@ -126,7 +125,7 @@ const OfferDetails = (props) => { | |||
| </OfferInfoContainer> | |||
| </Details> | |||
| {imagesCarouselModal && ( | |||
| <ImagesCarousel offer={props.offer} onModalClose={onModalClose} /> | |||
| <ImagesCarousel offer={props.offer} images={images} onModalClose={onModalClose} /> | |||
| )} | |||
| </> | |||
| ); | |||
| @@ -16,40 +16,46 @@ import history from "../../../store/utils/history"; | |||
| import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | |||
| import { DIRECT_CHAT_PAGE } from "../../../constants/pages"; | |||
| 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 { t } = useTranslation(); | |||
| const { isMobile } = useIsMobile(); | |||
| const userId = useSelector(selectUserId); | |||
| const changeChat = () => { | |||
| history.push( | |||
| 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 ( | |||
| <MiniChatCardContainer selected={props.selected} onClick={changeChat}> | |||
| <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> | |||
| <ProfileName selected={props.selected}> | |||
| {props?.chat?.interlocutorData?.name} | |||
| {interlocutorData?.company?.name} | |||
| </ProfileName> | |||
| {(props.chat.interlocutorData?._blocked || | |||
| props.chat.interlocutorData?._deleted) && ( | |||
| {(interlocutorData?._blocked || interlocutorData?._deleted) && ( | |||
| <BlockedProfile | |||
| redText | |||
| chatCard | |||
| shortText | |||
| aboveTitle | |||
| hideIcon | |||
| deleted={props.chat.interlocutorData?._deleted} | |||
| deleted={interlocutorData?._deleted} | |||
| /> | |||
| )} | |||
| </ProfileNameContainer> | |||
| @@ -57,7 +63,7 @@ const MiniChatCard = (props) => { | |||
| {t("messages.cardProduct")} | |||
| </ProfileProduct> | |||
| <ProfileProductName selected={props.selected}> | |||
| {props?.chat?.offerData?.name} | |||
| {props?.chat?.offer?.name} | |||
| </ProfileProductName> | |||
| </ProfileDetails> | |||
| </MiniChatCardContainer> | |||
| @@ -33,7 +33,7 @@ const RequestExchangeCard = (props) => { | |||
| () => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted), | |||
| [amIBuyer, exchange] | |||
| ); | |||
| const interlucatorUserId = useMemo( | |||
| const interlocutorUserId = useMemo( | |||
| () => (amIBuyer ? exchange?.seller?.userId : exchange?.buyer?.userId), | |||
| [exchange, amIBuyer] | |||
| ); | |||
| @@ -52,18 +52,18 @@ const RequestExchangeCard = (props) => { | |||
| </MessageText> | |||
| ); | |||
| } | |||
| } else if (requester === requesterStatus.INTERLUCATOR) { | |||
| } else if (requester === requesterStatus.interlocutor) { | |||
| return ( | |||
| <RequestExchangeMessage | |||
| haveIAccepted={haveIAccepted} | |||
| chatId={props.chatId} | |||
| userId={userId} | |||
| interlucatorUserId={interlucatorUserId} | |||
| interlocutorUserId={interlocutorUserId} | |||
| /> | |||
| ); | |||
| } | |||
| return ""; | |||
| }, [requester, t, haveIAccepted, interlucatorUserId, userId, exchange]); | |||
| }, [requester, t, haveIAccepted, interlocutorUserId, userId, exchange]); | |||
| return ( | |||
| <RequestExchangeCardContainer ismymessage={props.isMyMessage}> | |||
| <InfoIcon /> | |||
| @@ -25,7 +25,7 @@ const RequestExchangeMessage = (props) => { | |||
| acceptExchangeSocket( | |||
| props.chatId, | |||
| props.userId, | |||
| props.interlucatorUserId, | |||
| props.interlocutorUserId, | |||
| () => { | |||
| dispatch( | |||
| acceptExchange({ | |||
| @@ -76,7 +76,7 @@ RequestExchangeMessage.propTypes = { | |||
| children: PropTypes.node, | |||
| chatId: PropTypes.string, | |||
| userId: PropTypes.string, | |||
| interlucatorUserId: PropTypes.string, | |||
| interlocutorUserId: PropTypes.string, | |||
| haveIAccepted: PropTypes.any, | |||
| }; | |||
| @@ -24,7 +24,7 @@ import { | |||
| fetchChats, | |||
| } from "../../store/actions/chat/chatActions"; | |||
| 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 { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants"; | |||
| import SkeletonChatColumn from "./SkeletonChatColumn/SkeletonChatColumn"; | |||
| @@ -60,7 +60,7 @@ export const ChatColumn = (props) => { | |||
| history.goBack(); | |||
| return; | |||
| } | |||
| addMesageListener(({ succeed, data }) => { | |||
| addMessageListener(({ succeed, data }) => { | |||
| if (succeed) { | |||
| dispatch( | |||
| addNewMessage({ | |||
| @@ -24,7 +24,7 @@ import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants"; | |||
| import { selectUserId } from "../../store/selectors/loginSelectors"; | |||
| import { | |||
| acceptExchangeSocket, | |||
| addMesageListener, | |||
| addMessageListener, | |||
| removeMessageListener, | |||
| } from "../../socket/socket"; | |||
| import { makeErrorToastMessage } from "../../store/utils/makeToastMessage"; | |||
| @@ -59,9 +59,9 @@ const DirectChat = () => { | |||
| const offerObject = useMemo(() => { | |||
| if (location?.state?.offerId) { | |||
| return offer?.offer; | |||
| return offer; | |||
| } | |||
| return chat?.offer?.offer; | |||
| return chat?.offer; | |||
| }, [chat, location.state, offer]); | |||
| const chatObject = useMemo(() => { | |||
| @@ -81,14 +81,14 @@ const DirectChat = () => { | |||
| let haveIAccepted = amIBuyer | |||
| ? exchange.buyer?.accepted | |||
| : exchange.seller?.accepted; | |||
| let haveInterlucatorAccepted = amIBuyer | |||
| let haveinterlocutorAccepted = amIBuyer | |||
| ? exchange.seller?.accepted | |||
| : exchange.buyer?.accepted; | |||
| let haveIReviewed = amIBuyer | |||
| ? exchange.buyer.givenReview | |||
| : exchange.seller.givenReview; | |||
| if (haveIAccepted) { | |||
| if (haveInterlucatorAccepted) { | |||
| if (haveinterlocutorAccepted) { | |||
| if (haveIReviewed) { | |||
| return exchangeStatus.REVIEWED; | |||
| } else { | |||
| @@ -98,7 +98,7 @@ const DirectChat = () => { | |||
| return exchangeStatus.I_OFFERED; | |||
| } | |||
| } else { | |||
| if (haveInterlucatorAccepted) { | |||
| if (haveinterlocutorAccepted) { | |||
| return exchangeStatus.I_AM_OFFERED; | |||
| } else { | |||
| return exchangeStatus.INITIAL; | |||
| @@ -109,22 +109,15 @@ const DirectChat = () => { | |||
| }, [exchange, amIBuyer]); | |||
| const interlocutorObject = useMemo(() => { | |||
| console.log(offer); | |||
| 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]); | |||
| // Fetch chat after it is created | |||
| @@ -137,11 +130,11 @@ const DirectChat = () => { | |||
| // Listener to socket.IO chat | |||
| useEffect(() => { | |||
| addMesageListener(({ succeed, data }) => { | |||
| addMessageListener(({ succeed, data }) => { | |||
| if (succeed) { | |||
| if ( | |||
| [...allChats].find((item) => { | |||
| return item.chat._id === data.chatId; | |||
| return item._id === data.chatId; | |||
| }) | |||
| ) { | |||
| dispatch( | |||
| @@ -154,7 +147,7 @@ const DirectChat = () => { | |||
| data.message?.isAcceptRequest && | |||
| requester === requesterStatus.NOONE | |||
| ) { | |||
| dispatch(setRequester(requesterStatus.INTERLUCATOR)); | |||
| dispatch(setRequester(requesterStatus.interlocutor)); | |||
| } | |||
| } else { | |||
| dispatch(fetchChats()); | |||
| @@ -168,7 +161,6 @@ const DirectChat = () => { | |||
| return () => removeMessageListener(); | |||
| }, [allChats, routeMatch]); | |||
| const refreshChat = () => { | |||
| if (routeMatch.params?.chatId === "newMessage") { | |||
| dispatch(fetchOneOffer(location.state.offerId)); | |||
| @@ -178,8 +170,9 @@ const DirectChat = () => { | |||
| } | |||
| }; | |||
| const handleAcceptExchange = () => { | |||
| console.log(chat) | |||
| acceptExchangeSocket( | |||
| chat?.chat?._id, | |||
| chat?._id, | |||
| userId, | |||
| chat?.interlocutor?._id, | |||
| () => { | |||
| @@ -190,7 +183,7 @@ const DirectChat = () => { | |||
| ); | |||
| dispatch( | |||
| addNewMessage({ | |||
| _id: chat?.chat?._id, | |||
| _id: chat?._id, | |||
| message: { | |||
| userId, | |||
| isAcceptRequest: true, | |||
| @@ -224,7 +217,7 @@ const DirectChat = () => { | |||
| <DirectChatContent | |||
| chat={chatObject} | |||
| exchangeState={exchangeState} | |||
| interlucator={interlocutorObject} | |||
| interlocutor={interlocutorObject} | |||
| refreshChat={refreshChat} | |||
| /> | |||
| </DirectChatContainer> | |||
| @@ -23,11 +23,11 @@ const DirectChatContent = (props) => { | |||
| const myProfileImage = useSelector(selectMineProfilePicture); | |||
| const messagesRef = useRef(null); | |||
| const requester = useSelector(selectRequester); | |||
| const interlucatorProfileImage = props?.interlucator?.image; | |||
| const interlocutorProfileImage = props?.interlocutor?.image; | |||
| const isLoadingChatContent = useSelector( | |||
| selectIsLoadingByActionType(CHAT_SCOPE) | |||
| ); | |||
| const messages = props?.chat?.chat?.messages; | |||
| const messages = props?.chat?.messages; | |||
| useEffect(() => { | |||
| messagesRef.current?.scrollTo({ | |||
| top: messagesRef.current.scrollHeight, | |||
| @@ -39,6 +39,7 @@ const DirectChatContent = (props) => { | |||
| const handleRefresh = () => { | |||
| props.refreshChat(); | |||
| }; | |||
| console.log(props); | |||
| return ( | |||
| <> | |||
| {isLoadingChatContent || isLoadingChatContent === undefined ? ( | |||
| @@ -46,7 +47,7 @@ const DirectChatContent = (props) => { | |||
| ) : ( | |||
| <DirectChatContentContainer> | |||
| <DirectChatContentHeader | |||
| interlucator={props?.interlucator} | |||
| interlocutor={props?.interlocutor} | |||
| exchangeState={props.exchangeState} | |||
| /> | |||
| <MessagesList ref={messagesRef} exchangeState={props?.exchangeState}> | |||
| @@ -54,8 +55,12 @@ const DirectChatContent = (props) => { | |||
| const isMyMessage = userId === item.userId; | |||
| const image = isMyMessage | |||
| ? myProfileImage | |||
| : interlucatorProfileImage; | |||
| if (requester === requesterStatus.INTERLUCATOR && isMyMessage && item?.isAcceptRequest) | |||
| : interlocutorProfileImage; | |||
| if ( | |||
| requester === requesterStatus.interlocutor && | |||
| isMyMessage && | |||
| item?.isAcceptRequest | |||
| ) | |||
| return; | |||
| return ( | |||
| <MessageContainer key={item?._id || item?._created}> | |||
| @@ -63,7 +68,7 @@ const DirectChatContent = (props) => { | |||
| <RequestExchangeCard | |||
| isMyMessage={isMyMessage} | |||
| message={item} | |||
| chatId={props?.chat?.chat?._id} | |||
| chatId={props?.chat?._id} | |||
| /> | |||
| ) : ( | |||
| <MessageCard | |||
| @@ -79,7 +84,7 @@ const DirectChatContent = (props) => { | |||
| <DirectChatNewMessage | |||
| chat={props?.chat} | |||
| refreshChat={handleRefresh} | |||
| interlucator={props.interlucator} | |||
| interlocutor={props.interlocutor} | |||
| /> | |||
| </DirectChatContentContainer> | |||
| )} | |||
| @@ -90,7 +95,7 @@ const DirectChatContent = (props) => { | |||
| DirectChatContent.propTypes = { | |||
| children: PropTypes.node, | |||
| chat: PropTypes.any, | |||
| interlucator: PropTypes.any, | |||
| interlocutor: PropTypes.any, | |||
| refreshChat: PropTypes.func, | |||
| exchangeState: PropTypes.any, | |||
| }; | |||
| @@ -32,9 +32,9 @@ const DirectChatContentHeader = (props) => { | |||
| const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null); | |||
| const { isMobile } = useIsMobile(); | |||
| const mineProfileBlocked = useSelector(selectAmIBlocked); | |||
| console.log(props) | |||
| const togglePhonePopover = (event) => { | |||
| if (props.interlucator?.telephone) { | |||
| if (props.interlocutor?.company?.contacts?.telephone) { | |||
| setShowPhonePopover((prevState) => !prevState); | |||
| setPhonePopoverAnchorEl((prevState) => { | |||
| if (prevState) return null; | |||
| @@ -43,13 +43,14 @@ const DirectChatContentHeader = (props) => { | |||
| } | |||
| }; | |||
| const routeToUser = () => { | |||
| if (!props?.interlucator?._blocked) | |||
| if (!props?.interlocutor?._blocked) | |||
| history.push( | |||
| replaceInRoute(PROFILE_PAGE, { | |||
| profileId: props?.interlucator?.userId, | |||
| profileId: props?.interlocutor?._id, | |||
| }) | |||
| ); | |||
| }; | |||
| console.log("in", props); | |||
| return ( | |||
| <> | |||
| <DirectChatContentHeaderContainer> | |||
| @@ -57,19 +58,19 @@ const DirectChatContentHeader = (props) => { | |||
| <ProfileImage | |||
| onClick={routeToUser} | |||
| src={getImageUrl( | |||
| props?.interlucator?.image, | |||
| props?.interlocutor?.image, | |||
| variants.chatHeader, | |||
| isMobile | |||
| )} | |||
| /> | |||
| <ProfileDetails> | |||
| <ProfileName onClick={routeToUser}> | |||
| {props?.interlucator?.name} | |||
| {props?.interlocutor?.company?.name} | |||
| </ProfileName> | |||
| <ProfileLocation> | |||
| <ProfileLocationIcon /> | |||
| <ProfileLocationText> | |||
| {props?.interlucator?.location} | |||
| {props?.interlocutor?.company?.contacts?.location} | |||
| </ProfileLocationText> | |||
| </ProfileLocation> | |||
| </ProfileDetails> | |||
| @@ -78,8 +79,8 @@ const DirectChatContentHeader = (props) => { | |||
| <PhoneIconContainer | |||
| disabled={ | |||
| mineProfileBlocked || | |||
| props?.interlucator?._blocked || | |||
| !props.interlucator?.telephone | |||
| props?.interlocutor?._blocked || | |||
| !props.interlocutor?.company?.contacts?.telephone | |||
| } | |||
| onClick={togglePhonePopover} | |||
| > | |||
| @@ -91,7 +92,11 @@ const DirectChatContentHeader = (props) => { | |||
| open={showPhonePopover} | |||
| anchorRight | |||
| onClose={togglePhonePopover} | |||
| content={<PhonePopover phoneNumber={props.interlucator?.telephone} />} | |||
| content={ | |||
| <PhonePopover | |||
| phoneNumber={props.interlocutor?.company?.contacts?.telephone} | |||
| /> | |||
| } | |||
| /> | |||
| </DirectChatContentHeaderContainer> | |||
| {(props.exchangeState === exchangeStatus.I_OFFERED || | |||
| @@ -111,7 +116,7 @@ const DirectChatContentHeader = (props) => { | |||
| DirectChatContentHeader.propTypes = { | |||
| children: PropTypes.node, | |||
| interlucator: PropTypes.any, | |||
| interlocutor: PropTypes.any, | |||
| exchangeState: PropTypes.bool, | |||
| }; | |||
| @@ -17,8 +17,8 @@ const DirectChatHeader = (props) => { | |||
| const chat = useSelector(selectSelectedChat); | |||
| useEffect(() => { | |||
| if (chat?.chat?.exchangeId) refetchExchange(); | |||
| }, [chat]); | |||
| if (chat?.exchange?._id) refetchExchange(); | |||
| }, [chat?.exchange]); | |||
| const isDisabledReviews = useMemo(() => { | |||
| if (!exchange.valid) return true; | |||
| @@ -40,7 +40,7 @@ const DirectChatHeader = (props) => { | |||
| }; | |||
| const refetchExchange = () => { | |||
| dispatch(fetchExchange(chat.chat.exchangeId)); | |||
| dispatch(fetchExchange(chat.exchange?._id)); | |||
| }; | |||
| const acceptExchange = () => { | |||
| @@ -32,11 +32,14 @@ const DirectChatNewMessage = (props) => { | |||
| const location = useLocation(); | |||
| const history = useHistory(); | |||
| const userId = useSelector(selectUserId); | |||
| console.log(props) | |||
| const handleSend = useCallback( | |||
| (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( | |||
| addNewMessage({ | |||
| _id: chatId, | |||
| @@ -47,8 +50,8 @@ const DirectChatNewMessage = (props) => { | |||
| }, | |||
| }) | |||
| ); | |||
| 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)); | |||
| } | |||
| } | |||
| @@ -57,8 +60,9 @@ const DirectChatNewMessage = (props) => { | |||
| } | |||
| setTypedValue(""); | |||
| }, | |||
| [typedValue, props.chat?.chat?._id, userId, props.interlucator.userId] | |||
| [typedValue, props.chat?._id, userId, props.interlocutor] | |||
| ); | |||
| console.log(exchange); | |||
| const handleMessageSendSuccess = (newChatId) => { | |||
| history.replace(`${newChatId}`); | |||
| }; | |||
| @@ -82,7 +86,7 @@ const DirectChatNewMessage = (props) => { | |||
| startNewChat({ | |||
| offerId, | |||
| message: typedValue, | |||
| interlucatorUserId: props.interlucator.userId, | |||
| interlocutorUserId: props.interlocutor.userId, | |||
| handleMessageSendSuccess, | |||
| }) | |||
| ); | |||
| @@ -127,7 +131,7 @@ DirectChatNewMessage.propTypes = { | |||
| children: PropTypes.node, | |||
| chatId: PropTypes.any, | |||
| refreshChat: PropTypes.func, | |||
| interlucator: PropTypes.any, | |||
| interlocutor: PropTypes.any, | |||
| chat: PropTypes.any, | |||
| }; | |||
| @@ -36,12 +36,16 @@ const MiniChatColumn = () => { | |||
| const newChat = useMemo(() => { | |||
| if (location.state?.offerId) { | |||
| 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, | |||
| }, | |||
| }; | |||
| } | |||
| @@ -72,7 +76,7 @@ const MiniChatColumn = () => { | |||
| <MiniChatCard | |||
| key={Date.now() * Math.random()} | |||
| chat={item} | |||
| selected={item?.chat?._id === selectedChat?.chat?._id} | |||
| selected={item?._id === selectedChat?._id} | |||
| /> | |||
| ); | |||
| })} | |||
| @@ -107,7 +107,7 @@ const Header = () => { | |||
| logo: true, | |||
| }, | |||
| }); | |||
| searchRef.current.value = ""; | |||
| if (searchRef?.current) searchRef.current.value = ""; | |||
| } | |||
| }; | |||
| @@ -26,7 +26,7 @@ const ItemDetails = (props) => { | |||
| ); | |||
| let isMyProfile = useMemo(() => { | |||
| if ( | |||
| offer?.offer?.userId?.toString() === userId?.toString() || | |||
| offer?.user?._id?.toString() === userId?.toString() || | |||
| props.isAdmin | |||
| ) | |||
| return true; | |||
| @@ -25,6 +25,8 @@ import { useMemo } from "react"; | |||
| import itemDetailsData from "../../../notFoundData/itemDetailsData"; | |||
| import { Tooltip } from "@mui/material"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | |||
| import { DIRECT_CHAT_PAGE, PROFILE_PAGE } from "../../../constants/pages"; | |||
| const ItemDetailsHeaderCard = (props) => { | |||
| const history = useHistory(); | |||
| @@ -33,7 +35,8 @@ const ItemDetailsHeaderCard = (props) => { | |||
| const { t } = useTranslation(); | |||
| const offer = useMemo(() => { | |||
| 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; | |||
| } | |||
| } | |||
| @@ -43,18 +46,22 @@ const ItemDetailsHeaderCard = (props) => { | |||
| const { isMobile } = useIsMobile(); | |||
| const handleGoProfile = () => { | |||
| history.push(`/profile/${offer?.offer?.userId}`); | |||
| history.push(replaceInRoute(PROFILE_PAGE, { | |||
| profileId: props?.offer?.user?._id | |||
| })); | |||
| }; | |||
| const messageUser = (offer) => { | |||
| const chatItem = chats.find( | |||
| (item) => item.chat.offerId === offer?.offer?._id | |||
| (item) => item.chat.offerId === offer?._id | |||
| ); | |||
| if (chatItem !== undefined) { | |||
| history.push(`/messages/${chatItem.chat._id}`); | |||
| history.push(DIRECT_CHAT_PAGE, { | |||
| chatId: chatItem.chat._id | |||
| }); | |||
| } else { | |||
| if (offer?.offer?.userId !== userId) { | |||
| if (offer?.userId !== userId) { | |||
| history.push(`/messages/newMessage`, { | |||
| offerId: offer?.offer?._id, | |||
| offerId: offer?._id, | |||
| }); | |||
| } | |||
| } | |||
| @@ -67,14 +74,14 @@ const ItemDetailsHeaderCard = (props) => { | |||
| <HeaderTop> | |||
| <OfferImage | |||
| src={getImageUrl( | |||
| offer?.companyData?.image ? offer.companyData.image : "", | |||
| offer?.user?.image ? offer.user.image : "", | |||
| variants.profileImage, | |||
| isMobile | |||
| )} | |||
| /> | |||
| <OfferDetails> | |||
| <OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}> | |||
| {offer?.companyData?.company?.name} | |||
| {offer?.user?.company?.name} | |||
| </OfferTitle> | |||
| <PIBDetail offer={offer} isMyProfile={props.isMyProfile} /> | |||
| <CategoryDetail offer={offer} isMyProfile={props.isMyProfile} /> | |||
| @@ -16,7 +16,7 @@ const CategoryDetail = (props) => { | |||
| <LocationIcon /> | |||
| </DetailIcon> | |||
| <DetailText ismyprofile={props.isMyProfile}> | |||
| {offer.offer?.location?.city} | |||
| {offer?.location?.city} | |||
| </DetailText> | |||
| </DetailContainer> | |||
| ); | |||
| @@ -15,7 +15,7 @@ const PIBDetail = (props) => { | |||
| <PIB /> | |||
| </PIBIcon> | |||
| <DetailText isMyProfile={props.isMyProfile}> | |||
| {`${t("itemDetailsCard.PIB")}${offer?.companyData?.company?.PIB}`} | |||
| {`${t("itemDetailsCard.PIB")}${offer?.user?.company?.PIB}`} | |||
| </DetailText> | |||
| </DetailContainer> | |||
| ); | |||
| @@ -12,13 +12,13 @@ const StatisticDetails = (props) => { | |||
| const { t } = useTranslation(); | |||
| const offer = props.offer; | |||
| const percentOfSucceededExchanges = useMemo(() => { | |||
| if (offer?.companyData?.statistics?.exchanges?.succeeded === 0) { | |||
| if (offer?.user?.statistics?.exchanges?.succeeded === 0) { | |||
| return 0 + "%"; | |||
| } else { | |||
| return ( | |||
| Math.ceil( | |||
| (offer?.companyData?.statistics?.exchanges?.total / | |||
| offer?.companyData?.statistics?.exchanges?.succeeded) * | |||
| (offer?.user?.statistics?.exchanges?.total / | |||
| offer?.user?.statistics?.exchanges?.succeeded) * | |||
| 100 | |||
| ) + "%" | |||
| ); | |||
| @@ -30,13 +30,13 @@ const StatisticDetails = (props) => { | |||
| <BottomDetails> | |||
| <StatusText> | |||
| <StatusValue> | |||
| {offer?.companyData?.statistics?.publishes?.count} | |||
| {offer?.user?.statistics?.publishes?.count} | |||
| </StatusValue> | |||
| {t("itemDetailsCard.offers")} | |||
| </StatusText> | |||
| <StatusText> | |||
| <StatusValue> | |||
| {offer?.companyData?.statistics?.views?.count} | |||
| {offer?.user?.statistics?.views?.count} | |||
| </StatusValue> | |||
| {t("itemDetailsCard.totalViews")} | |||
| </StatusText> | |||
| @@ -31,10 +31,12 @@ const TooltipHeader = (props) => { | |||
| const handleClickCategory = () => { | |||
| props?.offers?.filters?.locations.clear(); | |||
| props?.offers?.filters?.subcategory.clear(); | |||
| console.log("tooltip 1") | |||
| props?.offers?.applyFilters(); | |||
| }; | |||
| const handleClickSubcategory = () => { | |||
| props?.offers?.filters?.locations.clear(); | |||
| console.log("tooltip 2") | |||
| props?.offers?.applyFilters(); | |||
| }; | |||
| const goBack = () => { | |||
| @@ -21,6 +21,7 @@ const Offers = (props) => { | |||
| isGrid={props?.isGrid} | |||
| isUsers={props?.isUsers} | |||
| users={props?.users} | |||
| myOffers={props?.myOffers} | |||
| /> | |||
| {props?.skeleton && | |||
| arrayForMapping.map((item, index) => ( | |||
| @@ -9,6 +9,8 @@ import HeaderPopover from "../HeaderPopover/HeaderPopover"; | |||
| import PropTypes from "prop-types"; | |||
| import { makeErrorToastMessage } from "../../../store/utils/makeToastMessage"; | |||
| import { EyeIcon } from "./MyMessages.styled"; | |||
| import { DIRECT_CHAT_PAGE } from "../../../constants/pages"; | |||
| import { replaceInRoute } from "../../../util/helpers/routeHelpers"; | |||
| export const MyMessages = (props) => { | |||
| const { t } = useTranslation(); | |||
| @@ -20,13 +22,16 @@ export const MyMessages = (props) => { | |||
| const convertMessages = (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); | |||
| }; | |||
| @@ -36,6 +41,7 @@ export const MyMessages = (props) => { | |||
| } | |||
| }, [userId]); | |||
| useEffect(() => { | |||
| console.log(chats); | |||
| if (chats?.length > 0) { | |||
| setLastChats([...convertMessages(chats)]); | |||
| } | |||
| @@ -50,7 +56,11 @@ export const MyMessages = (props) => { | |||
| } | |||
| }; | |||
| const goToMessage = (chatId) => { | |||
| history.push(`/messages/${chatId}`); | |||
| history.push( | |||
| replaceInRoute(DIRECT_CHAT_PAGE, { | |||
| chatId, | |||
| }) | |||
| ); | |||
| props.closePopover(); | |||
| }; | |||
| return ( | |||
| @@ -11,6 +11,7 @@ const SearchField = (props) => { | |||
| // Event keycode 13 = ENTER keycode | |||
| if (event.keyCode === 13) { | |||
| event.preventDefault(); | |||
| console.log("iz search1") | |||
| handleSearch(); | |||
| } | |||
| }, | |||
| @@ -26,6 +27,7 @@ const SearchField = (props) => { | |||
| searchRef.current.removeEventListener("keyup", listener); | |||
| }; | |||
| const handleSearch = () => { | |||
| console.log("iz search 2") | |||
| if (props.isAdmin) { | |||
| if (props.handleSearch) props.handleSearch(searchRef.current.value); | |||
| else search.searchOffersImmediately(searchRef.current.value); | |||
| @@ -1,5 +1,5 @@ | |||
| export default { | |||
| NOONE: 0, | |||
| ME: 1, | |||
| INTERLUCATOR: 2 | |||
| interlocutor: 2 | |||
| } | |||
| @@ -17,15 +17,16 @@ const useCategoryFilter = () => { | |||
| useEffect(() => { | |||
| setSelectedCategoryLocally(selectedCategory); | |||
| console.log("sleectedCat") | |||
| }, [selectedCategory]); | |||
| // Set selected category locally in state | |||
| // If second argument is true, then selected category is also updated in redux | |||
| const setSelectedCategory = (category, immediateApply = false) => { | |||
| const setSelectedCategory = (category) => { | |||
| setSelectedCategoryLocally(category); | |||
| if (immediateApply) { | |||
| dispatch(setFilteredCategory(category)); | |||
| } | |||
| // if (immediateApply) { | |||
| // dispatch(setFilteredCategory(category)); | |||
| // } | |||
| }; | |||
| // Find category object by providing its name | |||
| @@ -4,7 +4,7 @@ import useCompaniesFilter from "./useCompanyFilter"; | |||
| import useLocationsFilter from "./useLocationsFilter"; | |||
| import useSubcategoryFilter from "./useSubcategoryFilter"; | |||
| const useFilters = (clearAll = false, applyFilters) => { | |||
| const useFilters = (clearAll = false, applyFilters = () => {}) => { | |||
| const category = useCategoryFilter(); | |||
| const subcategory = useSubcategoryFilter(applyFilters); | |||
| const locations = useLocationsFilter(); | |||
| @@ -21,6 +21,7 @@ const useFilters = (clearAll = false, applyFilters) => { | |||
| if (category.selectedCategoryLocally?._id) sumOfFiltersChosen++; | |||
| if (subcategory.selectedSubcategoryLocally?._id) sumOfFiltersChosen++; | |||
| sumOfFiltersChosen += locations.selectedLocationsLocally.length; | |||
| console.log("numOfFiltersChosen"); | |||
| return sumOfFiltersChosen; | |||
| }, [ | |||
| category.selectedCategoryLocally, | |||
| @@ -20,6 +20,10 @@ const useMyOffers = () => { | |||
| useEffect(() => { | |||
| dispatch(fetchMineOffers()); | |||
| return () => { | |||
| filters.clear(); | |||
| } | |||
| }, []); | |||
| const clear = () => { | |||
| @@ -27,7 +31,7 @@ const useMyOffers = () => { | |||
| setAppliedFilters(false); | |||
| } | |||
| const apply = () => { | |||
| const applyFilters = () => { | |||
| paging.changePage(1); | |||
| setAppliedFilters(false); | |||
| }; | |||
| @@ -35,6 +39,7 @@ const useMyOffers = () => { | |||
| // Filter, search and sort all mine offers | |||
| const allOffersToShow = useMemo(() => { | |||
| let mineOffersFiltered = [...mineOffers]; | |||
| console.log(filters) | |||
| // Filter mine offers by category | |||
| if (filters.category.selectedCategoryLocally?.name) | |||
| mineOffersFiltered = mineOffersFiltered.filter( | |||
| @@ -100,7 +105,7 @@ const useMyOffers = () => { | |||
| search, | |||
| allOffersToShow, | |||
| totalOffers, | |||
| apply, | |||
| applyFilters, | |||
| clear, | |||
| }; | |||
| }; | |||
| @@ -46,6 +46,7 @@ const useOffers = () => { | |||
| sorting | |||
| ); | |||
| dispatch(setQueryString(convertQueryStringForBackend(newQueryString))); | |||
| console.log("useoff apply") | |||
| }; | |||
| const filters = useFilters(false, apply); | |||
| @@ -70,6 +71,7 @@ const useOffers = () => { | |||
| dispatch(setHeaderString(makeHeaderStringHelper({}))); | |||
| history.location.state = {}; | |||
| } | |||
| console.log("history.log"); | |||
| }, [history.location]); | |||
| // On every change of query string, new header string should be created | |||
| @@ -77,10 +79,12 @@ const useOffers = () => { | |||
| useEffect(() => { | |||
| const headerStringLocal = makeHeaderStringHelper(filters); | |||
| dispatch(setHeaderString(headerStringLocal)); | |||
| console.log("queryStringHook.queryString, filtersCleared") | |||
| }, [queryStringHook.queryString, filtersCleared]); | |||
| // Initially set category, location and subcategory based on query string | |||
| useEffect(() => { | |||
| console.log("!!!!!!!!!!queryStringHook.isInitiallyLoaded") | |||
| if (queryStringHook.isInitiallyLoaded) { | |||
| const queryObject = queryStringHook.queryObject; | |||
| if (KEY_CATEGORY in queryObject) { | |||
| @@ -135,23 +139,28 @@ const useOffers = () => { | |||
| setFiltersCleared(false); | |||
| apply(); | |||
| } | |||
| console.log("filtersCleared") | |||
| }, [filtersCleared]); | |||
| const applyFilters = () => { | |||
| console.log("applyfilters") | |||
| setFiltersCleared(true); | |||
| }; | |||
| const clearFiltersAndApply = () => { | |||
| console.log("applyfilters") | |||
| clear(); | |||
| setFiltersCleared(true); | |||
| }; | |||
| const applySorting = () => { | |||
| console.log("applyfilters") | |||
| paging.changePage(1); | |||
| setFiltersCleared(true); | |||
| }; | |||
| const applySearch = () => { | |||
| console.log("applyfilters") | |||
| paging.changePage(1); | |||
| setFiltersCleared(true); | |||
| }; | |||
| @@ -166,14 +175,15 @@ const useOffers = () => { | |||
| if (queryStringHook.isInitiallyLoaded) { | |||
| search.searchOffers(search.searchString); | |||
| } | |||
| console.log("search log") | |||
| }, [search.searchString]); | |||
| // Clears only filters(does not clear sorting and search) | |||
| const clearOnlyFiltersAndApply = () => { | |||
| filters.clear(); | |||
| paging.changePage(1); | |||
| setFiltersCleared(true); | |||
| console.log("clear log") | |||
| }; | |||
| const clear = () => { | |||
| @@ -8,6 +8,7 @@ const usePaging = (applyAllFilters, disableScroll) => { | |||
| // except on initial load | |||
| useEffect(() => { | |||
| if (isInitallyLoaded && applyAllFilters) { | |||
| console.log("paging apply") | |||
| applyAllFilters(); | |||
| } | |||
| if (!disableScroll) { | |||
| @@ -33,6 +33,7 @@ const useQueryString = () => { | |||
| } else { | |||
| setHistoryStateCleared(true); | |||
| } | |||
| console.log("history location querystr") | |||
| }, [history.location]); | |||
| // Set initially loaded to true on initial load | |||
| @@ -44,6 +45,7 @@ const useQueryString = () => { | |||
| ) { | |||
| setIsInitallyLoaded(true); | |||
| } | |||
| console.log("querystr") | |||
| }, [queryString]); | |||
| // Updating offers on query string change | |||
| @@ -57,6 +59,7 @@ const useQueryString = () => { | |||
| search: convertQueryStringForFrontend(queryString), | |||
| }); | |||
| } | |||
| console.log("querystr, isinit") | |||
| }, [queryString, isInitiallyLoaded]); | |||
| return { | |||
| @@ -3,7 +3,7 @@ import { useDispatch, useSelector } from "react-redux"; | |||
| import { setFilteredSubcategory } from "../../store/actions/filters/filtersActions"; | |||
| import { selectSelectedSubcategory } from "../../store/selectors/filtersSelectors"; | |||
| const useSubcategoryFilter = (applyFilters) => { | |||
| const useSubcategoryFilter = (applyFilters = () => {}) => { | |||
| const selectedSubcategory = useSelector(selectSelectedSubcategory); | |||
| const dispatch = useDispatch(); | |||
| const initialOption = { | |||
| @@ -31,15 +31,24 @@ const useSubcategoryFilter = (applyFilters) => { | |||
| const setSelectedSubcategory = (subcategory) => { | |||
| setSelectedSubcategoryLocally(subcategory); | |||
| // if (immediateApply) { | |||
| dispatch(setFilteredSubcategory(subcategory)); | |||
| dispatch(setFilteredSubcategory(subcategory)); | |||
| // } | |||
| console.log("funk"); | |||
| }; | |||
| 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 = () => { | |||
| console.log("clear"); | |||
| setSelectedSubcategoryLocally(initialOption); | |||
| dispatch(setFilteredSubcategory(initialOption)); | |||
| }; | |||
| @@ -1,19 +0,0 @@ | |||
| // 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, | |||
| }; | |||
| }; | |||
| @@ -2,28 +2,6 @@ import i18next from "i18next"; | |||
| import defaultImage from "../constants/defaultImage"; | |||
| 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: { | |||
| name: i18next.t("notFoundData.categoryName") | |||
| }, | |||
| @@ -43,5 +21,4 @@ export default { | |||
| count: 0 | |||
| }, | |||
| _created: new Date().toString() | |||
| } | |||
| } | |||
| @@ -17,7 +17,7 @@ const HomePage = () => { | |||
| const toggleFilters = () => { | |||
| setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened); | |||
| }; | |||
| console.log("rerender") | |||
| return ( | |||
| <HomePageContainer> | |||
| <MainLayout | |||
| @@ -182,7 +182,7 @@ export default { | |||
| }, | |||
| chat: { | |||
| getChat: "chats", | |||
| getUserChats: "users/{userId}/chat", | |||
| getUserChats: "users/{userId}/chats", | |||
| getOneChat: "users/{userId}/chats/{chatId}", | |||
| createChat: "users/{userId}/offers/{offerId}/chat", | |||
| sendMessage: "chats", | |||
| @@ -38,7 +38,7 @@ export const acceptExchangeSocket = (chatId, userId, receiverUserId, callbackFn) | |||
| callbackFn(); | |||
| }; | |||
| export const addMesageListener = (listener) => { | |||
| export const addMessageListener = (listener) => { | |||
| socket.on("private_message", (data) => | |||
| listener({ | |||
| succeed: true, | |||
| @@ -33,7 +33,7 @@ function setChats(state, action) { | |||
| function setChatsTotal(state, action) { | |||
| return { | |||
| ...state, | |||
| total: action.payload | |||
| total: action.payload, | |||
| }; | |||
| } | |||
| function setOneChat(state, action) { | |||
| @@ -47,23 +47,21 @@ function clearChats() { | |||
| } | |||
| function addNewMessage(state, { payload }) { | |||
| 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) { | |||
| 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]; | |||
| } | |||
| let newSelectedChat = {}; | |||
| if (state.selectedChat.chat) { | |||
| 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 { | |||
| newSelectedChat = { ...chat }; | |||
| } | |||
| @@ -60,8 +60,8 @@ function* fetchChats({ payload }) { | |||
| queryString: queryString, | |||
| }); | |||
| 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()); | |||
| } catch (e) { | |||
| yield put(fetchChatsError()); | |||
| @@ -73,7 +73,7 @@ function* fetchHeaderChats() { | |||
| try { | |||
| const userId = yield select(selectUserId); | |||
| const data = yield call(attemptFetchHeaderChats, userId); | |||
| yield put(setChats([...data.data.chatsWithData])); | |||
| yield put(setChats([...data.data.chats])); | |||
| yield put(fetchHeaderChatsSuccess()); | |||
| } catch (e) { | |||
| yield put(fetchHeaderChatsError()); | |||
| @@ -88,22 +88,15 @@ function* fetchOneChat(payload) { | |||
| userId, | |||
| }); | |||
| let requester = requesterStatus.NOONE; | |||
| chatData.data.chat.messages.forEach((item) => { | |||
| chatData.data.messages.forEach((item) => { | |||
| if (requester !== requesterStatus.NOONE) return; | |||
| if (item.isAcceptRequest) { | |||
| 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(setOneChat(chat)); | |||
| yield put(setOneChat(chatData.data)); | |||
| yield put(fetchOneChatSuccess()); | |||
| } catch (e) { | |||
| yield put(fetchOneChatError()); | |||
| @@ -142,8 +135,8 @@ function* startNewChat(payload) { | |||
| }); | |||
| const queryString = yield select(selectQueryString); | |||
| 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; | |||
| yield put(startNewChatSuccess()); | |||
| yield call( | |||
| @@ -151,7 +144,7 @@ function* startNewChat(payload) { | |||
| newChatData.data.chatId, | |||
| userId, | |||
| payload.payload.message, | |||
| payload.payload.interlucatorUserId | |||
| payload.payload.interlocutorUserId | |||
| ); | |||
| yield put( | |||
| addNewMessage({ | |||
| @@ -172,7 +172,14 @@ function* createOffer(payload) { | |||
| const offerData = payload.payload.offerData; | |||
| const formData = new FormData(); | |||
| 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("file", JSON.stringify(offerData.images)) | |||
| for (var i = 0; i < offerData.images.length; i++) { | |||
| @@ -214,6 +221,7 @@ function* fetchMineOffers() { | |||
| const userId = yield select(selectUserId); | |||
| const data = yield call(attemptFetchProfileOffers, userId); | |||
| yield put(setMineOffers(data.data.offers)); | |||
| yield put(setTotalOffers(data.data.total)); | |||
| yield put(fetchMineOffersSuccess()); | |||
| } catch (e) { | |||
| yield put(fetchMineOffersError()); | |||
| @@ -1,13 +1,15 @@ | |||
| import { DIRECT_CHAT_PAGE } from "../../constants/pages"; | |||
| import history from "../../store/utils/history"; | |||
| import { replaceInRoute } from "./routeHelpers"; | |||
| export const startChat = (chats, offer, userId) => { | |||
| 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) { | |||
| history.push(`/messages/${chatItem.chat._id}`); | |||
| history.push(replaceInRoute(DIRECT_CHAT_PAGE, { chatId: chatItem?._id })); | |||
| } else { | |||
| if (offer?.userId !== userId) { | |||
| if (offer?.user?._id !== userId) { | |||
| history.push(`/messages/newMessage`, { | |||
| offerId: offer?._id, | |||
| }); | |||