Selaa lähdekoodia

Merge branch 'bugfix/app-changes' of https://git.dilig.net/selenaaasi/trampa-frontend into bugfix/1758

bugfix/1758
jovan.cirkovic 3 vuotta sitten
vanhempi
commit
f2ac94f9c3
71 muutettua tiedostoa jossa 25317 lisäystä ja 411 poistoa
  1. 24800
    42
      package-lock.json
  2. 0
    1
      src/App.js
  3. 1
    0
      src/components/Admin/Sidebar/MarketplaceButton/MarketplaceButton.js
  4. 1
    0
      src/components/Admin/Sidebar/SidebarNavigation/SidebarNavigation.js
  5. 4
    4
      src/components/Buttons/ArrowButton/ArrowButton.styled.js
  6. 1
    1
      src/components/Buttons/IconButton/IconButton.js
  7. 13
    7
      src/components/Cards/ChatCard/ChatCard.js
  8. 1
    1
      src/components/Cards/ChatCard/MobileOfferDetails/MobileOfferDetails.js
  9. 2
    2
      src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.js
  10. 14
    1
      src/components/Cards/FilterCard/Choser/CompanyChoser/CompanyChoser.js
  11. 14
    3
      src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.js
  12. 14
    6
      src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.js
  13. 1
    1
      src/components/Cards/FilterCard/FilterCard.js
  14. 3
    2
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/CheckboxDropdownList/CheckboxDropdownList.js
  15. 0
    1
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js
  16. 1
    0
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown.js
  17. 4
    1
      src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js
  18. 3
    2
      src/components/Cards/ItemDetailsCard/ImagesCarousel/ImagesCarousel.js
  19. 21
    24
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.js
  20. 17
    15
      src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js
  21. 18
    12
      src/components/Cards/MiniChatCard/MiniChatCard.js
  22. 6
    3
      src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.js
  23. 7
    1
      src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.styled.js
  24. 7
    4
      src/components/Cards/OfferCard/OfferCard.js
  25. 6
    2
      src/components/Cards/ProfileCard/ProfileControl/ProfileControl.js
  26. 6
    6
      src/components/Cards/RequestExchangeCard/RequestExchangeCard.js
  27. 28
    12
      src/components/Cards/RequestExchangeCard/RequestExchangeMessage/RequestExchangeMessage.js
  28. 3
    2
      src/components/ChatColumn/ChatColumn.js
  29. 4
    8
      src/components/CreateReview/CreateReview.js
  30. 6
    0
      src/components/CreateReview/ThirdStep/ThirdStepCreateReview.js
  31. 40
    41
      src/components/DirectChat/DirectChat.js
  32. 14
    10
      src/components/DirectChat/DirectChatContent/DirectChatContent.js
  33. 14
    11
      src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.js
  34. 17
    6
      src/components/DirectChat/DirectChatHeader/DirectChatHeader.js
  35. 12
    9
      src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js
  36. 11
    7
      src/components/DirectChat/MiniChatColumn/MiniChatColumn.js
  37. 1
    1
      src/components/Header/Header.js
  38. 1
    1
      src/components/ItemDetails/ItemDetails.js
  39. 14
    8
      src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js
  40. 1
    1
      src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/Category/CategoryDetail.js
  41. 1
    1
      src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/PIB/PIBDetail.js
  42. 5
    5
      src/components/ItemDetails/ItemDetailsHeaderCard/StatisticDetails/StatisticDetails.js
  43. 2
    0
      src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.js
  44. 4
    1
      src/components/MarketPlace/Offers/Offers.js
  45. 6
    2
      src/components/MarketPlace/Offers/OffersList/OffersList.js
  46. 2
    0
      src/components/Modals/EditCategory/EditCategory.js
  47. 17
    8
      src/components/Popovers/MyMessages/MyMessages.js
  48. 11
    4
      src/components/Profile/ProfileOffers/ProfileOffers.js
  49. 1
    7
      src/components/UserReviews/UserReviews.js
  50. 1
    1
      src/constants/requesterStatus.js
  51. 4
    4
      src/hooks/useOffers/useCategoryFilter.js
  52. 1
    1
      src/hooks/useOffers/useFilters.js
  53. 9
    6
      src/hooks/useOffers/useMyOffers.js
  54. 3
    4
      src/hooks/useOffers/useOffers.js
  55. 7
    3
      src/hooks/useOffers/useSubcategoryFilter.js
  56. 0
    19
      src/hooks/useSearch.js
  57. 6
    1
      src/initialValues/createOfferInitialValues/secondPartCreateOfferInitialValues.js
  58. 0
    23
      src/notFoundData/itemDetailsData.js
  59. 0
    1
      src/pages/HomePage/HomePage.js
  60. 4
    1
      src/pages/ItemDetailsPage/ItemDetailsPageMUI.js
  61. 4
    3
      src/request/apiEndpoints.js
  62. 3
    3
      src/request/index.js
  63. 13
    2
      src/request/offersRequest.js
  64. 16
    7
      src/socket/socket.js
  65. 1
    0
      src/store/middleware/accessTokensMiddleware.js
  66. 6
    14
      src/store/reducers/chat/chatReducer.js
  67. 14
    19
      src/store/saga/chatSaga.js
  68. 3
    0
      src/store/saga/exchangeSaga.js
  69. 36
    8
      src/store/saga/offersSaga.js
  70. 1
    1
      src/store/saga/reviewSaga.js
  71. 5
    3
      src/util/helpers/chatHelper.js

+ 24800
- 42
package-lock.json
File diff suppressed because it is too large
Näytä tiedosto


+ 0
- 1
src/App.js Näytä tiedosto

useEffect(() => { useEffect(() => {
socketInit(userId); socketInit(userId);
}, [userId]); }, [userId]);

return ( return (
<Router history={history}> <Router history={history}>
<Helmet> <Helmet>

+ 1
- 0
src/components/Admin/Sidebar/MarketplaceButton/MarketplaceButton.js Näytä tiedosto

MarketplaceIcon, MarketplaceIcon,
} from "./MarketplaceButton.styled"; } from "./MarketplaceButton.styled";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import history from "../../../../store/utils/history";


const MarketplaceButton = () => { const MarketplaceButton = () => {
const { t } = useTranslation(); const { t } = useTranslation();

+ 1
- 0
src/components/Admin/Sidebar/SidebarNavigation/SidebarNavigation.js Näytä tiedosto

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();

+ 4
- 4
src/components/Buttons/ArrowButton/ArrowButton.styled.js Näytä tiedosto

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;

+ 1
- 1
src/components/Buttons/IconButton/IconButton.js Näytä tiedosto

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>

+ 13
- 7
src/components/Cards/ChatCard/ChatCard.js Näytä tiedosto

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);
}; };
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>

+ 1
- 1
src/components/Cards/ChatCard/MobileOfferDetails/MobileOfferDetails.js Näytä tiedosto

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>
); );
}; };

+ 2
- 2
src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.js Näytä tiedosto

filters.subcategory.setSelectedSubcategory({}); filters.subcategory.setSelectedSubcategory({});
props.offers.applyFilters(); props.offers.applyFilters();
}; };
console.log(props);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
closeSection: () => { closeSection: () => {
setIsOpened(false); setIsOpened(false);


useEffect(() => { useEffect(() => {
if ( if (
!filters.category.selectedCategoryLocally ||
(filters.category.selectedCategoryLocally &&
!("_id" in filters.category.selectedCategoryLocally)) ||
(filters.category.selectedCategoryLocally?._id === 0 && !isOpened) (filters.category.selectedCategoryLocally?._id === 0 && !isOpened)
) { ) {
setIsOpened(false); setIsOpened(false);

+ 14
- 1
src/components/Cards/FilterCard/Choser/CompanyChoser/CompanyChoser.js Näytä tiedosto



const CompanyChoser = forwardRef((props, ref) => { const CompanyChoser = forwardRef((props, ref) => {
const [isOpened, setIsOpened] = useState(false); const [isOpened, setIsOpened] = useState(false);
const [appliedFilters, setAppliedFilters] = useState(false);
const filters = props.filters; const filters = props.filters;
const { t } = useTranslation(); const { t } = useTranslation();


} }
}, [filters.companies.selectedCompaniesLocally]); }, [filters.companies.selectedCompaniesLocally]);


useEffect(() => {
if (appliedFilters) {
props?.offers?.apply();
setAppliedFilters(false);
}
}, [filters.companies.selectedCompaniesLocally]);

const handleSetItemsSelected = (items) => {
filters.companies.setSelectedCompanies(items);
setAppliedFilters(true);
};

return ( return (
<FilterSubDropdown <FilterSubDropdown
searchPlaceholder={t("filters.company.placeholder")} searchPlaceholder={t("filters.company.placeholder")}
handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)} handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)}
icon={<CompanyIcon />} icon={<CompanyIcon />}
title={t("filters.company.title")} title={t("filters.company.title")}
setItemsSelected={filters.companies.setSelectedCompanies}
setItemsSelected={handleSetItemsSelected}
companies companies
offers={props.offers} offers={props.offers}
/> />

+ 14
- 3
src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.js Näytä tiedosto



const LocationChoser = forwardRef((props, ref) => { const LocationChoser = forwardRef((props, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [appliedFilters, setAppliedFilters] = useState(false);
const [isOpened, setIsOpened] = useState(false); const [isOpened, setIsOpened] = useState(false);
const filters = props.filters; const filters = props.filters;


console.log(props);

const allLocations = useMemo( const allLocations = useMemo(
() => filters.locations.allLocations || [], () => filters.locations.allLocations || [],
[filters.locations] [filters.locations]
setIsOpened(true); setIsOpened(true);
} }
}, [filters.locations.selectedLocationsLocally]); }, [filters.locations.selectedLocationsLocally]);

useEffect(() => {
if (appliedFilters) {
props?.offers?.apply();
setAppliedFilters(false);
}
}, [appliedFilters]);

const handleSetItemsSelected = (items) => {
filters.locations.setSelectedLocations(items);
setAppliedFilters(true);
};
return ( return (
<FilterCheckboxDropdown <FilterCheckboxDropdown
searchPlaceholder={t("filters.location.placeholder")} searchPlaceholder={t("filters.location.placeholder")}
handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)} handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)}
icon={<LocationIcon />} icon={<LocationIcon />}
title={t("filters.location.title")} title={t("filters.location.title")}
setItemsSelected={filters.locations.setSelectedLocations}
setItemsSelected={handleSetItemsSelected}
offers={props.offers} offers={props.offers}
/> />
); );

+ 14
- 6
src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.js Näytä tiedosto

}, },
})); }));


const handleSelectSubcategory = (subcategory) => {
filters.subcategory.setSelectedSubcategory(subcategory, !props.myOffers);
// 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 &&
!("_id" in filters.category.selectedCategoryLocally)) ||
filters.category.selectedCategoryLocally?._id === 0 filters.category.selectedCategoryLocally?._id === 0
) { ) {
setIsOpened(false); setIsOpened(false);
} }
} else { } else {
if ( if (
!filters.subcategory.selectedSubcategoryLocally ||
(filters.subcategory.selectedSubcategoryLocally &&
!("_id" in filters.subcategory.selectedSubcategoryLocally)) ||
filters.subcategory.selectedSubcategoryLocally?._id === 0 filters.subcategory.selectedSubcategoryLocally?._id === 0
) { ) {
setIsOpened(false); setIsOpened(false);
if ( if (
!filters.category.selectedCategoryLocally ||
(filters.category.selectedCategoryLocally &&
!("_id" in filters.category.selectedCategoryLocally)) ||
filters.category.selectedCategoryLocally?._id === 0 filters.category.selectedCategoryLocally?._id === 0
) { ) {
setIsDisabled(true); setIsDisabled(true);
: 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,
}; };



+ 1
- 1
src/components/Cards/FilterCard/FilterCard.js Näytä tiedosto

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}
/> />



+ 3
- 2
src/components/Cards/FilterCard/FilterDropdown/Checkbox/CheckboxDropdownList/CheckboxDropdownList.js Näytä tiedosto

const data = props.data; const data = props.data;
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.offers.applyFilters();
console.log(item);
console.log(props.filters)
props.setItemsSelected([...props.filters.filter((p) => p?._id !== item?._id)]);
}; };
const handleOpen = () => { const handleOpen = () => {
setIsOpened((prevState) => !prevState); setIsOpened((prevState) => !prevState);

+ 0
- 1
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js Näytä tiedosto

const [isOpened, setIsOpened] = useState(false); const [isOpened, setIsOpened] = useState(false);
const [toSearch, setToSearch] = useState(""); const [toSearch, setToSearch] = useState("");
const { data } = props; const { data } = props;
console.log(props);


useEffect(() => { useEffect(() => {
setDataToShow([...data]); setDataToShow([...data]);

+ 1
- 0
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown.js Näytä tiedosto

filters={props.filters} filters={props.filters}
icon={props.icon} icon={props.icon}
data={data} data={data}
offers={props?.offers}
searchPlaceholder={props.searchPlaceholder} searchPlaceholder={props.searchPlaceholder}
open={props?.open !== undefined ? props.open : isOpened} open={props?.open !== undefined ? props.open : isOpened}
handleOpen={handleOpen} handleOpen={handleOpen}

+ 4
- 1
src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js Näytä tiedosto

label={props.firstOption.label} label={props.firstOption.label}
// number={item.numberOfProducts} // number={item.numberOfProducts}
fullWidth fullWidth
checked={!props.selected || props.selected._id === 0}
checked={
(props?.selected && !("_id" in props?.selected)) ||
props?.selected?._id === 0
}
onChange={props.setSelected} onChange={props.setSelected}
/> />
</DropdownItem> </DropdownItem>

+ 3
- 2
src/components/Cards/ItemDetailsCard/ImagesCarousel/ImagesCarousel.js Näytä tiedosto

<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;

+ 21
- 24
src/components/Cards/ItemDetailsCard/ItemDetailsCard.js Näytä tiedosto

const offer = useMemo(() => { const offer = useMemo(() => {
if (props.offer) { if (props.offer) {
if ( if (
props.offer.offer._id === routeMatch.params?.offerId ||
props.createOffer
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>
<DateButtonsContainer> <DateButtonsContainer>
{props.isMyOffer && ( {props.isMyOffer && (
<ButtonsContainer> <ButtonsContainer>
<PinIconContainer onClick={showPinOfferModalHandler}>
{offer?.offer?.pinned ? <UnpinIcon /> : <PinIcon />}
</PinIconContainer>
{props?.isAdmin && (
<PinIconContainer onClick={showPinOfferModalHandler}>
{offer?.pinned ? <UnpinIcon /> : <PinIcon />}
</PinIconContainer>
)}
<EditIconContainer onClick={showEditOfferModalHandler}> <EditIconContainer onClick={showEditOfferModalHandler}>
<EditIcon /> <EditIcon />
</EditIconContainer> </EditIconContainer>

+ 17
- 15
src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js Näytä tiedosto

const [imagesCarouselModal, setImagesCarouselModal] = useState(false); const [imagesCarouselModal, setImagesCarouselModal] = useState(false);


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));
return () => {
setImages([]);
};
}, [props?.offer?.images]);
const date = formatDateLocale(new Date(offer?._created));
const onModalClose = () => { const onModalClose = () => {
setImagesCarouselModal(false); setImagesCarouselModal(false);
}; };
> >
{!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}
/>
)} )}
</> </>
); );

+ 18
- 12
src/components/Cards/MiniChatCard/MiniChatCard.js Näytä tiedosto

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>

+ 6
- 3
src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.js Näytä tiedosto

import { import {
CategoryIcon, CategoryIcon,
CategoryIconContainer, CategoryIconContainer,
OfferCategoryContainer,
OfferDescriptionCategory, OfferDescriptionCategory,
OfferDescriptionContainer, OfferDescriptionContainer,
OfferDescriptionTitle, OfferDescriptionTitle,
return ( return (
<OfferDescriptionContainer> <OfferDescriptionContainer>
<OfferDescriptionTitle>{props.offerName}</OfferDescriptionTitle> <OfferDescriptionTitle>{props.offerName}</OfferDescriptionTitle>
<OfferDescriptionCategory>
<OfferCategoryContainer>
<CategoryIconContainer <CategoryIconContainer
color={selectedTheme.colors.iconStrokeDisabledColor} color={selectedTheme.colors.iconStrokeDisabledColor}
component="span" component="span"
> >
<CategoryIcon /> <CategoryIcon />
</CategoryIconContainer> </CategoryIconContainer>
{props.categoryName}
</OfferDescriptionCategory>
<OfferDescriptionCategory>
{props.categoryName}
</OfferDescriptionCategory>
</OfferCategoryContainer>
</OfferDescriptionContainer> </OfferDescriptionContainer>
); );
}; };

+ 7
- 1
src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.styled.js Näytä tiedosto

font-family: ${selectedTheme.fonts.textFont}; font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryDarkText}; color: ${selectedTheme.colors.primaryDarkText};
`; `;
export const OfferCategoryContainer = styled(Box)`
display: flex;
flex-direction: row;
white-space: nowrap;
`


export const CategoryIconContainer = styled(Icon)` export const CategoryIconContainer = styled(Icon)`
margin-right: 4px; margin-right: 4px;
position: relative; position: relative;
top: 2px; top: 2px;
display: inline;
& svg { & svg {
width: 14px; width: 14px;
position: relative; position: relative;
top: -6px;
top: -4px;
} }
`; `;
export const CategoryIcon = styled(Category)``; export const CategoryIcon = styled(Category)``;

+ 7
- 4
src/components/Cards/OfferCard/OfferCard.js Näytä tiedosto

}) })
); );
} else { } else {
history.push(
replaceInRoute(ITEM_DETAILS_PAGE, {
history.push({
pathname: replaceInRoute(ITEM_DETAILS_PAGE, {
offerId: itemId, offerId: itemId,
})
);
}),
state: {
view: true,
},
});
} }
} }
}; };

+ 6
- 2
src/components/Cards/ProfileCard/ProfileControl/ProfileControl.js Näytä tiedosto

); );
}; };
const handleEditProfile = () => { const handleEditProfile = () => {
if (!props.profile?._blocked) {
console.log("edit")
console.log(props)
if (!props.profile?._blocked || props?.isAdmin) {
console.log("edit2")
dispatch( dispatch(
toggleEditProfileModal({ toggleEditProfileModal({
userId: props.profile._id, userId: props.profile._id,
); );
} }
}; };
console.log(props)
return ( return (
<ButtonsContainer> <ButtonsContainer>
{props.profile?._blocked && !props.isMobile && <BlockedProfile />}
{props.profile?._blocked && !props.isMobile && !props?.isAdmin && <BlockedProfile />}
{props.isAdmin && ( {props.isAdmin && (
<> <>
{props.profile?._blocked ? ( {props.profile?._blocked ? (

+ 6
- 6
src/components/Cards/RequestExchangeCard/RequestExchangeCard.js Näytä tiedosto

const requester = useSelector(selectRequester); const requester = useSelector(selectRequester);
const exchange = useSelector(selectExchange); const exchange = useSelector(selectExchange);
const amIBuyer = useMemo( const amIBuyer = useMemo(
() => exchange?.buyer?.userId === userId,
() => exchange?.buyer?.user?._id === userId,
[exchange, userId] [exchange, userId]
); );
const haveIAccepted = useMemo( const haveIAccepted = useMemo(
() => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted), () => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted),
[amIBuyer, exchange] [amIBuyer, exchange]
); );
const interlucatorUserId = useMemo(
() => (amIBuyer ? exchange?.seller?.userId : exchange?.buyer?.userId),
const interlocutorUserId = useMemo(
() => (amIBuyer ? exchange?.seller?.user?._id : exchange?.buyer?.user?._id),
[exchange, amIBuyer] [exchange, amIBuyer]
); );
const message = useMemo(() => { const message = useMemo(() => {
</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 />

+ 28
- 12
src/components/Cards/RequestExchangeCard/RequestExchangeMessage/RequestExchangeMessage.js Näytä tiedosto

import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { acceptExchangeSocket } from "../../../../socket/socket"; import { acceptExchangeSocket } from "../../../../socket/socket";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { selectExchange, selectRequester } from "../../../../store/selectors/exchangeSelector";
import { acceptExchange, setRequester } from "../../../../store/actions/exchange/exchangeActions";
import {
selectExchange,
selectRequester,
} from "../../../../store/selectors/exchangeSelector";
import {
acceptExchange,
setRequester,
} from "../../../../store/actions/exchange/exchangeActions";
import { addNewMessage } from "../../../../store/actions/chat/chatActions"; import { addNewMessage } from "../../../../store/actions/chat/chatActions";
import { convertLocalDateToUTCDate } from "../../../../util/helpers/dateHelpers"; import { convertLocalDateToUTCDate } from "../../../../util/helpers/dateHelpers";
import requesterStatus from "../../../../constants/requesterStatus"; import requesterStatus from "../../../../constants/requesterStatus";
const exchange = useSelector(selectExchange); const exchange = useSelector(selectExchange);
const requester = useSelector(selectRequester); const requester = useSelector(selectRequester);


const handleAcceptExchange = () => {
const handleAcceptExchangeSuccess = () => {
console.log("accept salje i prima 3 POZVANA RESPONSE FUNKCIJA");
acceptExchangeSocket( acceptExchangeSocket(
props.chatId, props.chatId,
props.userId, props.userId,
props.interlucatorUserId,
props.interlocutorUserId,
() => { () => {
dispatch(
acceptExchange({
exchangeId: exchange._id,
})
);
console.log("accept salje i prima 4 SOCKET FUNKCIJA");
dispatch( dispatch(
addNewMessage({ addNewMessage({
_id: props.chatId, _id: props.chatId,
message: { message: {
userId: props.userId,
user: {
_id: props.userId,
},
text: "", text: "",
isAcceptRequest: true, isAcceptRequest: true,
_created: convertLocalDateToUTCDate(new Date()), _created: convertLocalDateToUTCDate(new Date()),
} }
); );
}; };
const handleAcceptExchange = () => {
console.log("accept salje i prima 1 POZVANA FUNKCIJA");
dispatch(
acceptExchange({
exchangeId: exchange._id,
handleApiResponseSuccess: handleAcceptExchangeSuccess,
})
);
};
return ( return (
<RequestExchangeMessageContainer> <RequestExchangeMessageContainer>
<RequestExchangeMessageText> <RequestExchangeMessageText>
onClick={handleAcceptExchange} onClick={handleAcceptExchange}
disabled={props.haveIAccepted} disabled={props.haveIAccepted}
> >
{props.haveIAccepted ? t("messages.acceptedRequest") : t("messages.acceptRequest")}
{props.haveIAccepted
? t("messages.acceptedRequest")
: t("messages.acceptRequest")}
</RequestExchangeMessageButton> </RequestExchangeMessageButton>
</RequestExchangeMessageButtonsContainer> </RequestExchangeMessageButtonsContainer>
</RequestExchangeMessageContainer> </RequestExchangeMessageContainer>
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,
}; };



+ 3
- 2
src/components/ChatColumn/ChatColumn.js Näytä tiedosto

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({

+ 4
- 8
src/components/CreateReview/CreateReview.js Näytä tiedosto

import FirstStepCreateReview from "./FirstStep/FirstStepCreateReview"; import FirstStepCreateReview from "./FirstStep/FirstStepCreateReview";
import SecondStepCreateReview from "./SecondStep/SecondStepCreateReview"; import SecondStepCreateReview from "./SecondStep/SecondStepCreateReview";
import ThirdStepCreateReview from "./ThirdStep/ThirdStepCreateReview"; import ThirdStepCreateReview from "./ThirdStep/ThirdStepCreateReview";
import { useDispatch, useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { giveReview } from "../../store/actions/review/reviewActions"; import { giveReview } from "../../store/actions/review/reviewActions";
import { selectUserId } from "../../store/selectors/loginSelectors";
import { reviewEnum } from "../../enums/reviewEnum"; import { reviewEnum } from "../../enums/reviewEnum";
import { fetchExchange } from "../../store/actions/exchange/exchangeActions"; import { fetchExchange } from "../../store/actions/exchange/exchangeActions";
import { closeModal } from "../../store/actions/modal/modalActions"; import { closeModal } from "../../store/actions/modal/modalActions";
const [informations, setInformations] = useState({}); const [informations, setInformations] = useState({});
const [currentStep, setCurrentStep] = useState(1); const [currentStep, setCurrentStep] = useState(1);
const dispatch = useDispatch(); const dispatch = useDispatch();
const userId = useSelector(selectUserId);
const closeModalHandler = () => { const closeModalHandler = () => {
dispatch(closeModal()); dispatch(closeModal());
}; };
setTimeout(() => {
dispatch(closeModal());
}, 3000);
const handleApiResponseSuccess = () => { const handleApiResponseSuccess = () => {
dispatch(fetchExchange(props.exchange._id)); dispatch(fetchExchange(props.exchange._id));
}; };
dispatch( dispatch(
giveReview({ giveReview({
review: { review: {
exchangeId: props.exchange._id,
userId: userId,
exchange: {
_id: props.exchange._id,
},
succeeded, succeeded,
communication, communication,
message: informations.comment, message: informations.comment,

+ 6
- 0
src/components/CreateReview/ThirdStep/ThirdStepCreateReview.js Näytä tiedosto

ThirdStepCreateReviewContainer, ThirdStepCreateReviewContainer,
} from "./ThirdStepCreateReview.styled"; } from "./ThirdStepCreateReview.styled";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useDispatch } from "react-redux";
import { closeModal } from "../../../store/actions/modal/modalActions";


const ThirdStepCreateReview = () => { const ThirdStepCreateReview = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useDispatch();
setTimeout(() => {
dispatch(closeModal());
}, 3000);
return ( return (
<ThirdStepCreateReviewContainer> <ThirdStepCreateReviewContainer>
<LogoImage /> <LogoImage />

+ 40
- 41
src/components/DirectChat/DirectChat.js Näytä tiedosto

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";
} from "../../store/selectors/exchangeSelector"; } from "../../store/selectors/exchangeSelector";
import { import {
acceptExchange, acceptExchange,
fetchExchange,
setRequester, setRequester,
} from "../../store/actions/exchange/exchangeActions"; } from "../../store/actions/exchange/exchangeActions";
import { convertLocalDateToUTCDate } from "../../util/helpers/dateHelpers"; import { convertLocalDateToUTCDate } from "../../util/helpers/dateHelpers";


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(() => {
}, [chat, location.state]); }, [chat, location.state]);


const amIBuyer = useMemo( const amIBuyer = useMemo(
() => exchange.buyer?.userId === userId,
() => exchange.buyer?.user?._id === userId,
[exchange, userId] [exchange, userId]
); );


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;


const interlocutorObject = useMemo(() => { const interlocutorObject = useMemo(() => {
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(
message: data.message, message: data.message,
}) })
); );
if (
data.message?.isAcceptRequest &&
requester === requesterStatus.NOONE
) {
dispatch(setRequester(requesterStatus.INTERLUCATOR));
if (data.message?.isAcceptRequest) {
dispatch(fetchExchange(exchange?._id));
if (requester === requesterStatus.NOONE) {
dispatch(setRequester(requesterStatus.interlocutor));
}
} }
} else { } else {
dispatch(fetchChats()); dispatch(fetchChats());
} }
}); });
return () => removeMessageListener(); return () => removeMessageListener();
}, [allChats, routeMatch]);

}, [allChats, routeMatch, requester]);


const refreshChat = () => { const refreshChat = () => {
if (routeMatch.params?.chatId === "newMessage") { if (routeMatch.params?.chatId === "newMessage") {
dispatch(fetchOneChat(routeMatch.params?.chatId)); dispatch(fetchOneChat(routeMatch.params?.chatId));
} }
}; };
const handleAcceptExchange = () => {
const handleAcceptExchangeSuccess = () => {
let interlocutor = userId === chat?.participants[0]._id ? 1 : 0;
acceptExchangeSocket( acceptExchangeSocket(
chat?.chat?._id,
chat?._id,
userId, userId,
chat?.interlocutor?._id,
chat?.participants[interlocutor]._id,
() => { () => {
dispatch(
acceptExchange({
exchangeId: exchange._id,
})
);
dispatch( dispatch(
addNewMessage({ addNewMessage({
_id: chat?.chat?._id,
_id: chat?._id,
message: { message: {
userId,
user: {
_id: userId,
},
isAcceptRequest: true, isAcceptRequest: true,
text: "", text: "",
_created: convertLocalDateToUTCDate(new Date()), _created: convertLocalDateToUTCDate(new Date()),
} }
); );
}; };
const handleAcceptExchange = () => {
console.log("accept salje i prima 1 POZVANA FUNKCIJA")
dispatch(
acceptExchange({
exchangeId: exchange._id,
handleApiResponseSuccess: handleAcceptExchangeSuccess,
})
);
};
return ( return (
<DirectChatContainer> <DirectChatContainer>
{isLoadingDirectChat || isLoadingDirectChat === undefined ? ( {isLoadingDirectChat || isLoadingDirectChat === undefined ? (
<DirectChatContent <DirectChatContent
chat={chatObject} chat={chatObject}
exchangeState={exchangeState} exchangeState={exchangeState}
interlucator={interlocutorObject}
interlocutor={interlocutorObject}
refreshChat={refreshChat} refreshChat={refreshChat}
/> />
</DirectChatContainer> </DirectChatContainer>

+ 14
- 10
src/components/DirectChat/DirectChatContent/DirectChatContent.js Näytä tiedosto

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,
behaviour: "smooth", behaviour: "smooth",
}); });
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" }); window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
}, [props?.chat?.chat?.messages, messagesRef, isLoadingChatContent]);
}, [props?.chat?.messages, messagesRef, isLoadingChatContent]);


const handleRefresh = () => { const handleRefresh = () => {
props.refreshChat(); props.refreshChat();
) : ( ) : (
<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}>
{messages?.map((item) => { {messages?.map((item) => {
const isMyMessage = userId === item.userId;
const isMyMessage = userId === item.user?._id;
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,
}; };

+ 14
- 11
src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.js Näytä tiedosto

const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null); const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null);
const { isMobile } = useIsMobile(); const { isMobile } = useIsMobile();
const mineProfileBlocked = useSelector(selectAmIBlocked); const mineProfileBlocked = useSelector(selectAmIBlocked);

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,
}) })
); );
}; };
<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,
}; };



+ 17
- 6
src/components/DirectChat/DirectChatHeader/DirectChatHeader.js Näytä tiedosto

import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { selectExchange } from "../../../store/selectors/exchangeSelector"; import { selectExchange } from "../../../store/selectors/exchangeSelector";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { fetchExchange } from "../../../store/actions/exchange/exchangeActions";
import {
fetchExchange,
setExchange,
} from "../../../store/actions/exchange/exchangeActions";
import { selectSelectedChat } from "../../../store/selectors/chatSelectors"; import { selectSelectedChat } from "../../../store/selectors/chatSelectors";
import { selectUserId } from "../../../store/selectors/loginSelectors"; import { selectUserId } from "../../../store/selectors/loginSelectors";
import { toggleCreateReviewModal } from "../../../store/actions/modal/modalActions"; import { toggleCreateReviewModal } from "../../../store/actions/modal/modalActions";
import { setOneChat } from "../../../store/actions/chat/chatActions";


const DirectChatHeader = (props) => { const DirectChatHeader = (props) => {
const exchange = useSelector(selectExchange); const exchange = useSelector(selectExchange);
const chat = useSelector(selectSelectedChat); const chat = useSelector(selectSelectedChat);


useEffect(() => { useEffect(() => {
if (chat?.chat?.exchangeId) refetchExchange();
}, [chat]);
return () => {
dispatch(setExchange({}));
dispatch(setOneChat({}));
};
}, []);

useEffect(() => {
if (chat?.exchange?._id) refetchExchange();
}, [chat?.exchange]);


const isDisabledReviews = useMemo(() => { const isDisabledReviews = useMemo(() => {
if (!exchange.valid) return true; if (!exchange.valid) return true;
if (exchange.seller?.userId === userId && exchange.seller?.givenReview)
if (exchange.seller?.user._id === userId && exchange.seller?.givenReview)
return true; return true;
if (exchange.buyer?.userId === userId && exchange.buyer?.givenReview)
if (exchange.buyer?.user._id === userId && exchange.buyer?.givenReview)
return true; return true;
return false; return false;
}, [exchange, userId]); }, [exchange, userId]);
}; };


const refetchExchange = () => { const refetchExchange = () => {
dispatch(fetchExchange(chat.chat.exchangeId));
dispatch(fetchExchange(chat.exchange?._id));
}; };


const acceptExchange = () => { const acceptExchange = () => {

+ 12
- 9
src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js Näytä tiedosto

const userId = useSelector(selectUserId); const userId = useSelector(selectUserId);
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);
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,
message: { message: {
userId,
user: {
_id: userId,
},
text: typedValue, text: typedValue,
_created: convertLocalDateToUTCDate(new Date()), _created: convertLocalDateToUTCDate(new Date()),
}, },
}) })
); );
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]
); );
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._id,
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,
}; };



+ 11
- 7
src/components/DirectChat/MiniChatColumn/MiniChatColumn.js Näytä tiedosto

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}
/> />
); );
})} })}

+ 1
- 1
src/components/Header/Header.js Näytä tiedosto

logo: true, logo: true,
}, },
}); });
searchRef.current.value = "";
if (searchRef?.current) searchRef.current.value = "";
} }
}; };



+ 1
- 1
src/components/ItemDetails/ItemDetails.js Näytä tiedosto

); );
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;

+ 14
- 8
src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js Näytä tiedosto

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) {
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.offer._id === offer?._id
); );
if (chatItem !== undefined) { if (chatItem !== undefined) {
history.push(`/messages/${chatItem.chat._id}`);
history.push(DIRECT_CHAT_PAGE, {
chatId: chatItem._id
});
} else { } else {
if (offer?.offer?.userId !== userId) {
if (offer?.user?._id !== 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} />

+ 1
- 1
src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/Category/CategoryDetail.js Näytä tiedosto

<LocationIcon /> <LocationIcon />
</DetailIcon> </DetailIcon>
<DetailText ismyprofile={props.isMyProfile}> <DetailText ismyprofile={props.isMyProfile}>
{offer.offer?.location?.city}
{offer?.location?.city}
</DetailText> </DetailText>
</DetailContainer> </DetailContainer>
); );

+ 1
- 1
src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/PIB/PIBDetail.js Näytä tiedosto

<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>
); );

+ 5
- 5
src/components/ItemDetails/ItemDetailsHeaderCard/StatisticDetails/StatisticDetails.js Näytä tiedosto

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>

+ 2
- 0
src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.js Näytä tiedosto

const handleClickCategory = () => { const handleClickCategory = () => {
props?.offers?.filters?.locations.clear(); props?.offers?.filters?.locations.clear();
props?.offers?.filters?.subcategory.clear(); props?.offers?.filters?.subcategory.clear();
props?.offers?.filters?.companies?.clear();
props?.offers?.applyFilters(); props?.offers?.applyFilters();
}; };
const handleClickSubcategory = () => { const handleClickSubcategory = () => {
props?.offers?.filters?.locations.clear(); props?.offers?.filters?.locations.clear();
props?.offers?.filters?.companies?.clear();
props?.offers?.applyFilters(); props?.offers?.applyFilters();
}; };
const goBack = () => { const goBack = () => {

+ 4
- 1
src/components/MarketPlace/Offers/Offers.js Näytä tiedosto

const Offers = (props) => { const Offers = (props) => {
const offers = props?.offers; const offers = props?.offers;
const arrayForMapping = Array.apply(null, Array(4)).map(() => {}); const arrayForMapping = Array.apply(null, Array(4)).map(() => {});
console.log("rerender")

return ( return (
<> <>
<OffersFilterButton /> <OffersFilterButton />
<OffersSearchField /> <OffersSearchField />
<OffersNotFound />
<OffersNotFound skeleton={props?.skeleton} />
<OffersList <OffersList
loading={props?.skeleton} loading={props?.skeleton}
offers={offers} offers={offers}
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) => (

+ 6
- 2
src/components/MarketPlace/Offers/OffersList/OffersList.js Näytä tiedosto

import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useSelector } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { selectTotalOffers } from "../../../../store/selectors/offersSelectors"; import { selectTotalOffers } from "../../../../store/selectors/offersSelectors";
import { OffersContainer } from "./OffersList.styled"; import { OffersContainer } from "./OffersList.styled";
import BigProfileCard from "../../../Cards/ProfileCard/BigProfileCard/BigProfileCard"; import BigProfileCard from "../../../Cards/ProfileCard/BigProfileCard/BigProfileCard";
import { startChat } from "../../../../util/helpers/chatHelper"; import { startChat } from "../../../../util/helpers/chatHelper";
import { selectLatestChats } from "../../../../store/selectors/chatSelectors"; import { selectLatestChats } from "../../../../store/selectors/chatSelectors";
import { selectUserId } from "../../../../store/selectors/loginSelectors"; import { selectUserId } from "../../../../store/selectors/loginSelectors";
import { setRequester } from "../../../../store/actions/exchange/exchangeActions";
import requesterStatus from "../../../../constants/requesterStatus";


const OffersList = (props) => { const OffersList = (props) => {
const totalOffers = useSelector(selectTotalOffers); const totalOffers = useSelector(selectTotalOffers);
const chats = useSelector(selectLatestChats); const chats = useSelector(selectLatestChats);
const userId = useSelector(selectUserId); const userId = useSelector(selectUserId);
const dispatch = useDispatch();
const offers = props?.offers; const offers = props?.offers;
const messageOneUser = (offer) => { const messageOneUser = (offer) => {
dispatch(setRequester(requesterStatus.NOONE));
startChat(chats, offer, userId); startChat(chats, offer, userId);
}; };
return ( return (
offer={item} offer={item}
halfwidth={props?.isGrid} halfwidth={props?.isGrid}
messageUser={messageOneUser} messageUser={messageOneUser}
isMyOffer={item?.userId === userId || props?.isAdmin}
isMyOffer={item?.user._id === userId || props?.isAdmin}
isAdmin={props?.isAdmin} isAdmin={props?.isAdmin}
/> />
); );

+ 2
- 0
src/components/Modals/EditCategory/EditCategory.js Näytä tiedosto

// }; // };


const closeModalHandler = () => { const closeModalHandler = () => {
console.log("closed")
dispatch(closeModal()); dispatch(closeModal());
}; };


const handleApiResponseSuccess = () => { const handleApiResponseSuccess = () => {
console.log("succes")
if (clickedOnNext) { if (clickedOnNext) {
formik.resetForm(); formik.resetForm();
inputRef.current.focus(); inputRef.current.focus();

+ 17
- 8
src/components/Popovers/MyMessages/MyMessages.js Näytä tiedosto

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);
}; };


} }
}; };
const goToMessage = (chatId) => { const goToMessage = (chatId) => {
history.push(`/messages/${chatId}`);
history.push(
replaceInRoute(DIRECT_CHAT_PAGE, {
chatId,
})
);
props.closePopover(); props.closePopover();
}; };
return ( return (

+ 11
- 4
src/components/Profile/ProfileOffers/ProfileOffers.js Näytä tiedosto

const dispatch = useDispatch(); const dispatch = useDispatch();
const searchRef = useRef(null); const searchRef = useRef(null);


useEffect(() => {
return () => {
dispatch(setProfileOffers([]));
};
}, []);

useEffect(() => { useEffect(() => {
dispatch( dispatch(
fetchProfileOffers({ fetchProfileOffers({
sortOption: sortOption, sortOption: sortOption,
append: isMobile && append, append: isMobile && append,
page: paging.currentPage, page: paging.currentPage,
isAdmin: props?.isAdmin,
}) })
); );
setAppend(true); setAppend(true);
<ProfileOffersHeaderSkeleton /> <ProfileOffersHeaderSkeleton />
{isMobile ? ( {isMobile ? (
<SkeletonContainer> <SkeletonContainer>
<SkeletonOfferCard vertical />
<SkeletonOfferCard vertical />
<SkeletonOfferCard vertical />
<SkeletonOfferCard vertical skeleton />
<SkeletonOfferCard vertical skeleton />
<SkeletonOfferCard vertical skeleton />
</SkeletonContainer> </SkeletonContainer>
) : ( ) : (
<> <>
{arrayForMapping.map((item, index) => ( {arrayForMapping.map((item, index) => (
<SkeletonOfferCard key={index} />
<SkeletonOfferCard key={index} skeleton />
))} ))}
</> </>
)} )}

+ 1
- 7
src/components/UserReviews/UserReviews.js Näytä tiedosto

import { import {
fetchReviews, fetchReviews,
setReviews, setReviews,
fetchReviewsAsAdmin,
} from "../../store/actions/review/reviewActions"; } from "../../store/actions/review/reviewActions";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import SkeletonUserReviews from "./SkeletonUserReviews/SkeletonUserReviews"; import SkeletonUserReviews from "./SkeletonUserReviews/SkeletonUserReviews";
) )
); );



useEffect(() => { useEffect(() => {
let idProfile = routeMatch.params?.profileId; let idProfile = routeMatch.params?.profileId;
if (idProfile) { if (idProfile) {
if (props.isAdmin) {
dispatch(fetchReviewsAsAdmin(idProfile));
} else {
dispatch(fetchReviews(idProfile));
}
dispatch(fetchReviews(idProfile));
} }


// if (props.profileReviews && routeMatch.params?.profileId) { // if (props.profileReviews && routeMatch.params?.profileId) {

+ 1
- 1
src/constants/requesterStatus.js Näytä tiedosto

export default { export default {
NOONE: 0, NOONE: 0,
ME: 1, ME: 1,
INTERLUCATOR: 2
interlocutor: 2
} }

+ 4
- 4
src/hooks/useOffers/useCategoryFilter.js Näytä tiedosto



// 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

+ 1
- 1
src/hooks/useOffers/useFilters.js Näytä tiedosto

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();

+ 9
- 6
src/hooks/useOffers/useMyOffers.js Näytä tiedosto

import useSorting from "./useSorting"; import useSorting from "./useSorting";


const useMyOffers = () => { const useMyOffers = () => {
const applyFilters = () => {
paging.changePage(1);
setAppliedFilters(false);
};
const filters = useFilters(true); const filters = useFilters(true);
const sorting = useSorting(); const sorting = useSorting();
const mineOffers = useSelector(selectMineOffers); const mineOffers = useSelector(selectMineOffers);


useEffect(() => { useEffect(() => {
dispatch(fetchMineOffers()); dispatch(fetchMineOffers());
return () => {
filters.clear();
}
}, []); }, []);


const clear = () => { const clear = () => {
setAppliedFilters(false); setAppliedFilters(false);
} }


const apply = () => {
paging.changePage(1);
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];
search, search,
allOffersToShow, allOffersToShow,
totalOffers, totalOffers,
apply,
applyFilters,
clear, clear,
}; };
}; };

+ 3
- 4
src/hooks/useOffers/useOffers.js Näytä tiedosto

const applyFilters = () => { const applyFilters = () => {
setFiltersCleared(true); setFiltersCleared(true);
}; };
const clearFiltersAndApply = () => { const clearFiltersAndApply = () => {
clear(); clear();
setFiltersCleared(true); setFiltersCleared(true);
}; };
const applySorting = () => { const applySorting = () => {
paging.changePage(1); paging.changePage(1);
setFiltersCleared(true); setFiltersCleared(true);
}; };
const applySearch = () => { const applySearch = () => {
paging.changePage(1); paging.changePage(1);
setFiltersCleared(true); setFiltersCleared(true);
const clearOnlyFiltersAndApply = () => { const clearOnlyFiltersAndApply = () => {
filters.clear(); filters.clear();
paging.changePage(1); paging.changePage(1);

setFiltersCleared(true); setFiltersCleared(true);
}; };



+ 7
- 3
src/hooks/useOffers/useSubcategoryFilter.js Näytä tiedosto

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));
// } // }
}; };


const apply = () => { const apply = () => {
dispatch(setFilteredSubcategory(selectedSubcategoryLocally));
if (
Number(selectedSubcategory?._id) !==
Number(selectedSubcategoryLocally?._id)
)
dispatch(setFilteredSubcategory(selectedSubcategoryLocally));
}; };


const clear = () => { const clear = () => {

+ 0
- 19
src/hooks/useSearch.js Näytä tiedosto

// 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,
};
};

+ 6
- 1
src/initialValues/createOfferInitialValues/secondPartCreateOfferInitialValues.js Näytä tiedosto

export default (informations, offer, images) => ({ export default (informations, offer, images) => ({
images: informations?.image || offer?.images || images, images: informations?.image || offer?.images || images,
condition: informations?.condition || offer?.condition || "default",
condition:
informations?.condition ||
(typeof offer?.condition === "string" &&
offer?.condition?.charAt(0)?.toUpperCase() +
offer?.condition?.slice(1)) ||
"default",
}); });

+ 0
- 23
src/notFoundData/itemDetailsData.js Näytä tiedosto

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()
}
} }

+ 0
- 1
src/pages/HomePage/HomePage.js Näytä tiedosto

const toggleFilters = () => { const toggleFilters = () => {
setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened); setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened);
}; };

return ( return (
<HomePageContainer> <HomePageContainer>
<MainLayout <MainLayout

+ 4
- 1
src/pages/ItemDetailsPage/ItemDetailsPageMUI.js Näytä tiedosto

import UserReviews from "../../components/UserReviews/UserReviews"; import UserReviews from "../../components/UserReviews/UserReviews";
import { selectOffer } from "../../store/selectors/offersSelectors"; import { selectOffer } from "../../store/selectors/offersSelectors";
import ProfileMini from "../../components/ProfileMini/ProfileMini"; import ProfileMini from "../../components/ProfileMini/ProfileMini";
import history from "../../store/utils/history";


const ItemDetailsPage = (props) => { const ItemDetailsPage = (props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const offerId = props.match.params.offerId; const offerId = props.match.params.offerId;


useEffect(() => { useEffect(() => {
dispatch(fetchOneOffer(offerId));
const view = history?.location?.state?.view;
console.log(view)
dispatch(fetchOneOffer({ offerId, view }));
() => dispatch(clearSelectedOffer()); () => dispatch(clearSelectedOffer());
}, []); }, []);



+ 4
- 3
src/request/apiEndpoints.js Näytä tiedosto

setFingerprint: "/affiliate/fingerprint", setFingerprint: "/affiliate/fingerprint",
}, },
offers: { offers: {
getOneOffer: "offers",
getOneOffer: "offers/{offerId}",
getOffers: "offers", getOffers: "offers",
getFeaturedOffers: "offers/featured", getFeaturedOffers: "offers/featured",
addOffer: "/users/{userId}/offers", addOffer: "/users/{userId}/offers",
locations: "locations", locations: "locations",
mineOffers: "users", mineOffers: "users",
profileOffers: "users/{userId}/offers", profileOffers: "users/{userId}/offers",
profileOffersAsAdmin: "admin/users/{userId}/offers",
removeOffer: "/users/{userId}/offers/{offerId}", removeOffer: "/users/{userId}/offers/{offerId}",
removeOfferAsAdmin: "/admin/offers/{offerId}", removeOfferAsAdmin: "/admin/offers/{offerId}",
pinOffer: "admin/offers/{id}/pin", pinOffer: "admin/offers/{id}/pin",
}, },
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",
exchange: { exchange: {
getExchange: "exchanges", getExchange: "exchanges",
validateExchange: "exchanges", validateExchange: "exchanges",
acceptExchange: "users/{userId}/exchanges/{exchangeId}/accept"
acceptExchange: "users/{userId}/exchanges/{exchangeId}/accept",
}, },
reviews: { reviews: {
getUserReviews: "/users/{userId}/reviews", getUserReviews: "/users/{userId}/reviews",

+ 3
- 3
src/request/index.js Näytä tiedosto

import axios from "axios"; import axios from "axios";
import queryString from "qs";
// import queryString from "qs";


const request = axios.create({ const request = axios.create({
// baseURL: "http://192.168.88.150:3001/", // DJOLE // baseURL: "http://192.168.88.150:3001/", // DJOLE
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
// withCredentials: true, // withCredentials: true,
paramsSerializer: (params) =>
queryString.stringify(params, { arrayFormat: "comma" }),
// paramsSerializer: (params) =>
// queryString.stringify(params, { arrayFormat: "comma" }),
}); });


export const getRequest = (url, params = null, options = null) => { export const getRequest = (url, params = null, options = null) => {

+ 13
- 2
src/request/offersRequest.js Näytä tiedosto

return getRequest(apiEndpoints.offers.getOffers); return getRequest(apiEndpoints.offers.getOffers);
}; };
export const attemptFetchOneOffer = (payload) => { export const attemptFetchOneOffer = (payload) => {
const url = `${apiEndpoints.offers.getOneOffer}/${payload}`;
return getRequest(url);
return getRequest(
replaceInUrl(apiEndpoints.offers.getOneOffer, {
offerId: payload.offerId,
}),
payload.queryObject
);
}; };
export const attemptFetchMoreOffers = (page, payload) => { export const attemptFetchMoreOffers = (page, payload) => {
if (payload) if (payload)
}) + `?${queryString}` }) + `?${queryString}`
); );
}; };
export const attemptFetchProfileOffersAsAdmin = (userId, queryString = "") => {
return getRequest(
replaceInUrl(apiEndpoints.offers.profileOffersAsAdmin, {
userId: userId,
}) + `?${queryString}`
);
};
export const attemptRemoveOffer = (payload, offerId) => { export const attemptRemoveOffer = (payload, offerId) => {
return deleteRequest( return deleteRequest(
replaceInUrl(apiEndpoints.offers.removeOffer, { replaceInUrl(apiEndpoints.offers.removeOffer, {

+ 16
- 7
src/socket/socket.js Näytä tiedosto

import io from "socket.io-client"; import io from "socket.io-client";


export const socket = io("https://trampa-api-test.dilig.net/", { export const socket = io("https://trampa-api-test.dilig.net/", {
// export const socket = io("http://localhost:3001/", {
// export const socket = io(process.env.REACT_APP_BASE_API_URL, {
// export const socket = io("http://localhost:3001/", {
// export const socket = io(process.env.REACT_APP_BASE_API_URL, {
transports: ["websocket"], transports: ["websocket"],
reconnectionAttempts: 5, reconnectionAttempts: 5,
}); });
chatId, chatId,
receiverUserId, receiverUserId,
message: { message: {
userId,
user: {
_id: userId,
},
text, text,
}, },
}); });
}; };
export const acceptExchangeSocket = (chatId, userId, receiverUserId, callbackFn) => {
export const acceptExchangeSocket = (
chatId,
userId,
receiverUserId,
callbackFn
) => {
socket.emit("private_message", { socket.emit("private_message", {
chatId, chatId,
receiverUserId, receiverUserId,
message: { message: {
userId,
user: {
_id: userId
},
isAcceptRequest: true, isAcceptRequest: true,
text: ""
text: "",
}, },
}); });
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,

+ 1
- 0
src/store/middleware/accessTokensMiddleware.js Näytä tiedosto

// If refresh token is expired, log out user // If refresh token is expired, log out user
if (new Date() > new Date(refreshTokenDecoded?.exp * 1000)) { if (new Date() > new Date(refreshTokenDecoded?.exp * 1000)) {
dispatch(logoutUser()); dispatch(logoutUser());
return Promise.resolve(response)
} }
// If access token is expired, refresh access token // If access token is expired, refresh access token
if (new Date() > new Date(jwtTokenDecoded.exp * 1000)) { if (new Date() > new Date(jwtTokenDecoded.exp * 1000)) {

+ 6
- 14
src/store/reducers/chat/chatReducer.js Näytä tiedosto

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);
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) {
newSelectedChat = { ...state.selectedChat };
if (newSelectedChat.chat._id === chat.chat._id)
newSelectedChat = { ...newSelectedChat, chat: chat.chat };
} else {
newSelectedChat = { ...chat };
}
if (state.selectedChat.chat) newSelectedChat = { ...state.selectedChat };
newSelectedChat = { ...chat };
return { return {
...state, ...state,
latestChats: [...allChats], latestChats: [...allChats],

+ 14
- 19
src/store/saga/chatSaga.js Näytä tiedosto

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;
else requester = requesterStatus.INTERLUCATOR;
if (item.user._id === userId) requester = requesterStatus.ME;
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 exchange = yield select(selectExchange); const exchange = yield select(selectExchange);
const userId = yield select(selectUserId); const userId = yield select(selectUserId);
yield call(attemptSendMessage, payload.payload.chatId, messageObject); yield call(attemptSendMessage, payload.payload.chatId, messageObject);
if (chat?.offer?.offer?.userId === userId && exchange.valid === false) {
if (chat?.offer?.user._id === userId && exchange.valid === false) {
yield put(validateExchange(exchange._id)); yield put(validateExchange(exchange._id));
} }
yield call(fetchChats); yield call(fetchChats);
}); });
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({
_id: newChatId, _id: newChatId,
message: { message: {
userId,
user: {
_id: userId
},
text: payload.payload.message, text: payload.payload.message,
_created: new Date().toISOString(), _created: new Date().toISOString(),
}, },

+ 3
- 0
src/store/saga/exchangeSaga.js Näytä tiedosto

} }
function* acceptExchange({ payload }) { function* acceptExchange({ payload }) {
try { try {
console.log("accept salje i prima 2 POZVANA ACCEPT SAGA")
const userId = yield select(selectUserId); const userId = yield select(selectUserId);
yield call(attemptAcceptExchange, userId, payload.exchangeId); yield call(attemptAcceptExchange, userId, payload.exchangeId);
const data = yield call(attemptFetchExchange, payload.exchangeId); const data = yield call(attemptFetchExchange, payload.exchangeId);
yield put(setExchange(data.data)); yield put(setExchange(data.data));
if (payload.handleApiResponseSuccess)
yield call(payload.handleApiResponseSuccess);
yield put(acceptExchangeSuccess()); yield put(acceptExchangeSuccess());
} catch (e) { } catch (e) {
yield put(acceptExchangeError()); yield put(acceptExchangeError());

+ 36
- 8
src/store/saga/offersSaga.js Näytä tiedosto

attemptFetchFeaturedOffers, attemptFetchFeaturedOffers,
attemptFetchOffers, attemptFetchOffers,
attemptFetchOneOffer, attemptFetchOneOffer,
attemptFetchProfileOffersAsAdmin,
attemptPinOffer, attemptPinOffer,
attemptRemoveOffer, attemptRemoveOffer,
attemptRemoveOfferAsAdmin, attemptRemoveOfferAsAdmin,
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++) {


function* fetchOneOffer(payload) { function* fetchOneOffer(payload) {
try { try {
const data = yield call(attemptFetchOneOffer, payload.payload);
let offerId = payload.payload;
console.log("sagabb", payload.payload);
const queryObject = new URLSearchParams();
if (typeof payload.payload === "object") {
offerId = payload.payload.offerId;
queryObject.set("view", "true");
}
const data = yield call(attemptFetchOneOffer, {
offerId,
queryObject,
});
if (!data?.data) throw new Error(); if (!data?.data) throw new Error();
yield put(fetchOneOfferSuccess(data?.data)); yield put(fetchOneOfferSuccess(data?.data));
} catch (e) { } catch (e) {
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());
queryString = yield select(selectQueryString); queryString = yield select(selectQueryString);
} }
console.log(queryString.toString()); console.log(queryString.toString());
const data = yield call(
attemptFetchProfileOffers,
userId,
convertQueryStringForBackend(queryString)
);
let data;
if (payload.payload.isAdmin) {
data = yield call(
attemptFetchProfileOffersAsAdmin,
userId,
convertQueryStringForBackend(queryString)
);
} else {
data = yield call(
attemptFetchProfileOffers,
userId,
convertQueryStringForBackend(queryString)
);
}
if (payload.payload.append) { if (payload.payload.append) {
yield put(addProfileOffers(data.data.offers)); yield put(addProfileOffers(data.data.offers));
} else { } else {
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.toLowerCase());
formData.append("description", offerData.description); formData.append("description", offerData.description);
// const oldImages = []; // const oldImages = [];
for (var i = 0; i < offerData.images.length; i++) { for (var i = 0; i < offerData.images.length; i++) {

+ 1
- 1
src/store/saga/reviewSaga.js Näytä tiedosto

try { try {
console.log(payload); console.log(payload);
const data = yield call(attemptFetchReview, payload.payload); const data = yield call(attemptFetchReview, payload.payload);
yield put(setReviews([...data.data].reverse()));
yield put(setReviews([...data.data.reviews].reverse()));
yield put(fetchReviewsSuccess()); yield put(fetchReviewsSuccess());
} catch (e) { } catch (e) {
yield put(fetchReviewsError()); yield put(fetchReviewsError());

+ 5
- 3
src/util/helpers/chatHelper.js Näytä tiedosto

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,
}); });

Loading…
Peruuta
Tallenna