浏览代码

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

bugfix/1919
Djordje Mitrovic 3 年前
父节点
当前提交
264564519c
共有 100 个文件被更改,包括 25623 次插入555 次删除
  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. 10
    3
      src/components/Cards/CreateOfferCard/CreateOffer.js
  10. 2
    2
      src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.js
  11. 14
    1
      src/components/Cards/FilterCard/Choser/CompanyChoser/CompanyChoser.js
  12. 14
    3
      src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.js
  13. 16
    7
      src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.js
  14. 1
    1
      src/components/Cards/FilterCard/FilterCard.js
  15. 3
    2
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/CheckboxDropdownList/CheckboxDropdownList.js
  16. 0
    1
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js
  17. 1
    0
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown.js
  18. 4
    1
      src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js
  19. 3
    2
      src/components/Cards/ItemDetailsCard/ImagesCarousel/ImagesCarousel.js
  20. 22
    24
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.js
  21. 19
    21
      src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js
  22. 19
    0
      src/components/Cards/LittleOfferCard/LittleOfferCard.styled.js
  23. 5
    1
      src/components/Cards/MessageCard/MessageCard.styled.js
  24. 18
    12
      src/components/Cards/MiniChatCard/MiniChatCard.js
  25. 17
    9
      src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.js
  26. 1
    1
      src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.styled.js
  27. 2
    2
      src/components/Cards/OfferCard/DeleteOffer/DeleteOfferLabeledCard/DeleteOfferLabeledCard.js
  28. 5
    1
      src/components/Cards/OfferCard/DeleteOffer/DeleteOfferLabeledCard/DeleteOfferLabeledCard.styled.js
  29. 8
    4
      src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.js
  30. 7
    1
      src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.styled.js
  31. 8
    5
      src/components/Cards/OfferCard/OfferCard.js
  32. 6
    2
      src/components/Cards/ProfileCard/ProfileControl/ProfileControl.js
  33. 6
    6
      src/components/Cards/RequestExchangeCard/RequestExchangeCard.js
  34. 2
    0
      src/components/Cards/RequestExchangeCard/RequestExchangeCard.styled.js
  35. 28
    12
      src/components/Cards/RequestExchangeCard/RequestExchangeMessage/RequestExchangeMessage.js
  36. 14
    14
      src/components/Cards/UserReviewsCard/UserReviewsCard.js
  37. 3
    0
      src/components/Cards/UserReviewsCard/UserReviewsSingleCard/RemoveButton/RemoveButton.js
  38. 15
    9
      src/components/Cards/UserReviewsCard/UserReviewsSingleCard/RemoveButton/RemoveButton.styled.js
  39. 3
    1
      src/components/Cards/UserReviewsCard/UserReviewsSingleCard/ReviewQuote/ReviewQuote.styled.js
  40. 2
    0
      src/components/Cards/UserReviewsCard/UserReviewsSingleCard/UserReviewsSingleCard.js
  41. 3
    2
      src/components/ChatColumn/ChatColumn.js
  42. 4
    8
      src/components/CreateReview/CreateReview.js
  43. 15
    7
      src/components/CreateReview/CreateReview.styled.js
  44. 2
    1
      src/components/CreateReview/FirstStep/FirstStepCreateReview.js
  45. 5
    3
      src/components/CreateReview/FirstStep/FirstStepCreateReview.styled.js
  46. 13
    13
      src/components/CreateReview/SecondStep/SecondStepCreateReview.js
  47. 13
    1
      src/components/CreateReview/SecondStep/SecondStepCreateReview.styled.js
  48. 6
    0
      src/components/CreateReview/ThirdStep/ThirdStepCreateReview.js
  49. 42
    42
      src/components/DirectChat/DirectChat.js
  50. 14
    10
      src/components/DirectChat/DirectChatContent/DirectChatContent.js
  51. 1
    1
      src/components/DirectChat/DirectChatContent/DirectChatContent.styled.js
  52. 19
    12
      src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.js
  53. 7
    0
      src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.styled.js
  54. 28
    11
      src/components/DirectChat/DirectChatHeader/DirectChatHeader.js
  55. 16
    12
      src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js
  56. 11
    7
      src/components/DirectChat/MiniChatColumn/MiniChatColumn.js
  57. 7
    1
      src/components/Header/Drawer/Buttons/MyProfileButton/MyProfileButton.js
  58. 1
    1
      src/components/Header/Header.js
  59. 2
    0
      src/components/Header/SearchInput/SearchInput.js
  60. 12
    6
      src/components/ItemDetails/ItemDetails.js
  61. 36
    11
      src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js
  62. 1
    1
      src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/Category/CategoryDetail.js
  63. 1
    1
      src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/PIB/PIBDetail.js
  64. 5
    5
      src/components/ItemDetails/ItemDetailsHeaderCard/StatisticDetails/StatisticDetails.js
  65. 8
    5
      src/components/MarketPlace/Header/Header.js
  66. 3
    0
      src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.js
  67. 10
    2
      src/components/MarketPlace/Offers/Offers.js
  68. 6
    2
      src/components/MarketPlace/Offers/OffersList/OffersList.js
  69. 1
    1
      src/components/Modals/EditCategory/EditCategory.js
  70. 23
    9
      src/components/Popovers/MyMessages/MyMessages.js
  71. 7
    2
      src/components/Popovers/MyPosts/MyPosts.js
  72. 11
    4
      src/components/Profile/ProfileOffers/ProfileOffers.js
  73. 17
    13
      src/components/UserReviews/ReviewsSorting/ReviewsSorting.js
  74. 70
    52
      src/components/UserReviews/UserReviews.js
  75. 5
    2
      src/components/UserReviews/UserReviews.styled.js
  76. 1
    0
      src/constants/chatConstants.js
  77. 1
    1
      src/constants/requesterStatus.js
  78. 4
    4
      src/hooks/useOffers/useCategoryFilter.js
  79. 1
    1
      src/hooks/useOffers/useFilters.js
  80. 9
    6
      src/hooks/useOffers/useMyOffers.js
  81. 3
    4
      src/hooks/useOffers/useOffers.js
  82. 9
    1
      src/hooks/useOffers/useSearch.js
  83. 7
    3
      src/hooks/useOffers/useSubcategoryFilter.js
  84. 0
    19
      src/hooks/useSearch.js
  85. 2
    0
      src/i18n/resources/rs.js
  86. 6
    1
      src/initialValues/createOfferInitialValues/secondPartCreateOfferInitialValues.js
  87. 1
    1
      src/layouts/ProfileLayout/ProfileLayout.js
  88. 2
    2
      src/layouts/ProfileLayout/ProfileLayout.styled.js
  89. 0
    23
      src/notFoundData/itemDetailsData.js
  90. 1
    1
      src/pages/AdminHomePage/AdminItemDetailsPage/AdminItemDetailsPage.js
  91. 5
    5
      src/pages/AdminHomePage/AdminLocationsPage/AdminLocationsPage.styled.js
  92. 0
    1
      src/pages/HomePage/HomePage.js
  93. 4
    1
      src/pages/ItemDetailsPage/ItemDetailsPageMUI.js
  94. 4
    3
      src/request/apiEndpoints.js
  95. 3
    3
      src/request/index.js
  96. 13
    2
      src/request/offersRequest.js
  97. 16
    7
      src/socket/socket.js
  98. 1
    0
      src/store/middleware/accessTokensMiddleware.js
  99. 6
    14
      src/store/reducers/chat/chatReducer.js
  100. 0
    0
      src/store/saga/chatSaga.js

+ 24800
- 42
package-lock.json
文件差异内容过多而无法显示
查看文件


+ 0
- 1
src/App.js 查看文件

@@ -22,7 +22,6 @@ const App = () => {
useEffect(() => {
socketInit(userId);
}, [userId]);

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

+ 1
- 0
src/components/Admin/Sidebar/MarketplaceButton/MarketplaceButton.js 查看文件

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

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

+ 1
- 0
src/components/Admin/Sidebar/SidebarNavigation/SidebarNavigation.js 查看文件

@@ -11,6 +11,7 @@ import { useTranslation } from "react-i18next";
import { isInRoute, routeMatches } from "../../../../util/helpers/routeHelpers";
import { ADMIN_HOME_PAGE, ADMIN_USERS_PAGE } from "../../../../constants/pages";
import { ADMIN_NAVIGATION } from "../../../../constants/adminNavigation";
import history from "../../../../store/utils/history";

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

+ 4
- 4
src/components/Buttons/ArrowButton/ArrowButton.styled.js 查看文件

@@ -1,5 +1,5 @@
import { ReactComponent as DownArrow } from "../../../assets/images/svg/arrow-down.svg";
import styled from "styled-components";
import styled, { css } from "styled-components";
import selectedTheme from "../../../themes";
import { IconButton } from "../IconButton/IconButton";

@@ -11,9 +11,9 @@ export const ArrowIcon = styled(DownArrow)`
`}
width: 18px;
height: 18px;
/* position: relative;
position: relative;
top: 1px;
left: 1px; */
left: 1px;
& path {
${(props) =>
props.disabled &&
@@ -46,7 +46,7 @@ export const ArrowContainer = styled(IconButton)`
}
${(props) =>
props.disabled &&
`
css`
border 1px solid ${selectedTheme.colors.iconStrokeDisabledColor} !important;
&:hover {
background-color: inherit;

+ 1
- 1
src/components/Buttons/IconButton/IconButton.js 查看文件

@@ -18,7 +18,7 @@ export const IconButton = (props) => {
onClick={props.onClick}
sx={props.style}
iconcolor={props.iconColor}
{...props}
// {...props}
>
{props.children}
</IconButtonStyled>

+ 13
- 7
src/components/Cards/ChatCard/ChatCard.js 查看文件

@@ -12,42 +12,48 @@ import MobileOfferDetails from "./MobileOfferDetails/MobileOfferDetails";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";
import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile";
import { useSelector } from "react-redux";
import { selectUserId } from "../../../store/selectors/loginSelectors";

// Chat card is shown only on mobile phones (route /messages)
const ChatCard = (props) => {
const { isMobile } = useIsMobile();
const userId = useSelector(selectUserId);

const chat = useMemo(() => {
return props.chat;
}, [props.chat]);

const routeToItem = () => {
props.navigateToChat(chat?.chat?._id);
props.navigateToChat(chat?._id);
};
const interlocutor = useMemo(() => {
return userId === chat?.participants[0]._id ? 1 : 0;
}, [userId, chat]);

return (
<ChatCardContainer onClick={routeToItem}>
<UserImgWrapper>
<UserImage
src={getImageUrl(
chat?.interlocutorData?.image,
chat?.participants[interlocutor].image,
variants.chatCard,
isMobile
)}
/>
</UserImgWrapper>
<ChatInfo isBlocked={props.chat.interlocutorData?._blocked}>
<ChatInfo isBlocked={props.chat.participants[interlocutor]?._blocked}>
<ProfileNameContainer>
<UserName>{chat?.interlocutorData?.name}</UserName>
{(props.chat.interlocutorData?._blocked ||
props.chat.interlocutorData?._deleted) && (
<UserName>{chat?.participants[interlocutor]?.company?.name}</UserName>
{(props.chat?.participants[interlocutor]?._blocked ||
props.chat?.participants[interlocutor]?._deleted) && (
<BlockedProfile
redText
chatCard
shortText
aboveTitle
hideIcon
deleted={props.chat.interlocutorData?._deleted}
deleted={props.chat?.participants[interlocutor]?._deleted}
/>
)}
</ProfileNameContainer>

+ 1
- 1
src/components/Cards/ChatCard/MobileOfferDetails/MobileOfferDetails.js 查看文件

@@ -12,7 +12,7 @@ const MobileOfferDetails = (props) => {
return (
<OfferCardContainerMobile>
<OfferTextMobile>{t("messages.cardProduct")}</OfferTextMobile>
<OfferTitleMobile>{props.chat?.offerData?.name}</OfferTitleMobile>
<OfferTitleMobile>{props.chat?.offer?.name}</OfferTitleMobile>
</OfferCardContainerMobile>
);
};

+ 10
- 3
src/components/Cards/CreateOfferCard/CreateOffer.js 查看文件

@@ -35,7 +35,10 @@ import {
ITEM_DETAILS_PAGE,
PROFILE_PAGE,
} from "../../../constants/pages";
import { dynamicRouteMatches, replaceInRoute } from "../../../util/helpers/routeHelpers";
import {
dynamicRouteMatches,
replaceInRoute,
} from "../../../util/helpers/routeHelpers";
import { selectIsLoadingByActionType } from "../../../store/selectors/loadingSelectors";
import {
OFFER_ADD_SCOPE,
@@ -64,8 +67,12 @@ const CreateOffer = ({ editOffer, offer, isAdmin, customUserId }) => {
if (editOffer) {
if (routeMatches(BASE_PAGE) || routeMatches(HOME_PAGE))
dispatch(fetchOffers({ queryString }));
if (dynamicRouteMatches(PROFILE_PAGE) || dynamicRouteMatches(ADMIN_SINGLE_USER_PAGE))
if (isAdmin) dispatch(fetchProfileOffers(customUserId));
if (
dynamicRouteMatches(PROFILE_PAGE) ||
dynamicRouteMatches(ADMIN_SINGLE_USER_PAGE)
)
if (isAdmin)
dispatch(fetchProfileOffers({ idProfile: customUserId, isAdmin }));
else dispatch(fetchProfileOffers(userId));

if (

+ 2
- 2
src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.js 查看文件

@@ -23,7 +23,6 @@ const CategoryChoser = forwardRef((props, ref) => {
filters.subcategory.setSelectedSubcategory({});
props.offers.applyFilters();
};
console.log(props);
useImperativeHandle(ref, () => ({
closeSection: () => {
setIsOpened(false);
@@ -33,7 +32,8 @@ const CategoryChoser = forwardRef((props, ref) => {

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

+ 14
- 1
src/components/Cards/FilterCard/Choser/CompanyChoser/CompanyChoser.js 查看文件

@@ -11,6 +11,7 @@ import FilterSubDropdown from "../../FilterDropdown/Checkbox/FilterSubDropdown/F

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

@@ -26,6 +27,18 @@ const CompanyChoser = forwardRef((props, ref) => {
}
}, [filters.companies.selectedCompaniesLocally]);

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

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

return (
<FilterSubDropdown
searchPlaceholder={t("filters.company.placeholder")}
@@ -35,7 +48,7 @@ const CompanyChoser = forwardRef((props, ref) => {
handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)}
icon={<CompanyIcon />}
title={t("filters.company.title")}
setItemsSelected={filters.companies.setSelectedCompanies}
setItemsSelected={handleSetItemsSelected}
companies
offers={props.offers}
/>

+ 14
- 3
src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.js 查看文件

@@ -12,11 +12,10 @@ import { useTranslation } from "react-i18next";

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

console.log(props);

const allLocations = useMemo(
() => filters.locations.allLocations || [],
[filters.locations]
@@ -33,6 +32,18 @@ const LocationChoser = forwardRef((props, ref) => {
setIsOpened(true);
}
}, [filters.locations.selectedLocationsLocally]);

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

const handleSetItemsSelected = (items) => {
filters.locations.setSelectedLocations(items);
setAppliedFilters(true);
};
return (
<FilterCheckboxDropdown
searchPlaceholder={t("filters.location.placeholder")}
@@ -42,7 +53,7 @@ const LocationChoser = forwardRef((props, ref) => {
handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)}
icon={<LocationIcon />}
title={t("filters.location.title")}
setItemsSelected={filters.locations.setSelectedLocations}
setItemsSelected={handleSetItemsSelected}
offers={props.offers}
/>
);

+ 16
- 7
src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.js 查看文件

@@ -32,11 +32,18 @@ const SubcategoryChoser = forwardRef((props, ref) => {
},
}));

const handleSelectSubcategory = (subcategory) => {
filters.subcategory.setSelectedSubcategory(subcategory, !props.myOffers);
// if (props.myOffers) props.offers?.applyFilters();
};

useEffect(() => {
if (props?.queryStringHook?.isInitiallyLoaded || props.isMyOffers) {
if (props?.queryStringHook?.isInitiallyLoaded || props.myOffers) {
if (
!filters.category.selectedCategoryLocally ||
filters.category.selectedCategoryLocally?._id === 0
(filters.category.selectedCategoryLocally &&
!("_id" in filters.category.selectedCategoryLocally)) ||
filters.category.selectedCategoryLocally?._id === 0 ||
!filters.category.selectedCategoryLocally
) {
setIsOpened(false);
setIsDisabled(true);
@@ -46,12 +53,14 @@ const SubcategoryChoser = forwardRef((props, ref) => {
}
} else {
if (
!filters.subcategory.selectedSubcategoryLocally ||
(filters.subcategory.selectedSubcategoryLocally &&
!("_id" in filters.subcategory.selectedSubcategoryLocally)) ||
filters.subcategory.selectedSubcategoryLocally?._id === 0
) {
setIsOpened(false);
if (
!filters.category.selectedCategoryLocally ||
(filters.category.selectedCategoryLocally &&
!("_id" in filters.category.selectedCategoryLocally)) ||
filters.category.selectedCategoryLocally?._id === 0
) {
setIsDisabled(true);
@@ -74,7 +83,7 @@ const SubcategoryChoser = forwardRef((props, ref) => {
: t("filters.subcategories.title")
}
searchPlaceholder={t("filters.subcategories.placeholder")}
setSelected={filters.subcategory.setSelectedSubcategory}
setSelected={handleSelectSubcategory}
selected={filters.subcategory.selectedSubcategoryLocally}
open={isOpened}
disabled={isDisabled}
@@ -91,7 +100,7 @@ SubcategoryChoser.propTypes = {
filters: PropTypes.any,
categoryOpened: PropTypes.bool,
queryStringHook: PropTypes.any,
isMyOffers: PropTypes.bool,
myOffers: PropTypes.bool,
offers: PropTypes.any,
};


+ 1
- 1
src/components/Cards/FilterCard/FilterCard.js 查看文件

@@ -50,7 +50,7 @@ const FilterCard = (props) => {
queryStringHook={offers.queryStringHook}
ref={subcategoryRef}
categoryOpened={categoryRef.current?.isOpened}
isMyOffers={props.myOffers}
myOffers={props.myOffers}
offers={offers}
/>


+ 3
- 2
src/components/Cards/FilterCard/FilterDropdown/Checkbox/CheckboxDropdownList/CheckboxDropdownList.js 查看文件

@@ -16,8 +16,9 @@ const CheckboxDropdownList = (props) => {
const data = props.data;
const [isOpened, setIsOpened] = useState(false);
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 = () => {
setIsOpened((prevState) => !prevState);

+ 0
- 1
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js 查看文件

@@ -9,7 +9,6 @@ const FilterCheckboxDropdown = (props) => {
const [isOpened, setIsOpened] = useState(false);
const [toSearch, setToSearch] = useState("");
const { data } = props;
console.log(props);

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

+ 1
- 0
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown.js 查看文件

@@ -48,6 +48,7 @@ const FilterSubDropdown = (props) => {
filters={props.filters}
icon={props.icon}
data={data}
offers={props?.offers}
searchPlaceholder={props.searchPlaceholder}
open={props?.open !== undefined ? props.open : isOpened}
handleOpen={handleOpen}

+ 4
- 1
src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js 查看文件

@@ -111,7 +111,10 @@ const FilterRadioDropdown = (props) => {
label={props.firstOption.label}
// number={item.numberOfProducts}
fullWidth
checked={!props.selected || props.selected._id === 0}
checked={
(props?.selected && !("_id" in props?.selected)) ||
props?.selected?._id === 0 || !props?.selected
}
onChange={props.setSelected}
/>
</DropdownItem>

+ 3
- 2
src/components/Cards/ItemDetailsCard/ImagesCarousel/ImagesCarousel.js 查看文件

@@ -37,7 +37,7 @@ const ImagesCarousel = (props) => {
<CloseButtonIcon />
</CloseButton>
<Scroller isCarousel>
{props?.offer?.offer?.images.map((image) => {
{props?.images.map((image) => {
if (!image) return;
return (
<OfferImage
@@ -48,7 +48,7 @@ const ImagesCarousel = (props) => {
})}
</Scroller>
<Offer>
{t("carousel.offer")} <OfferSpan>{props.offer.offer.name}</OfferSpan>
{t("carousel.offer")} <OfferSpan>{props.offer.name}</OfferSpan>
</Offer>
</ImagesCarouselContainer>
</>
@@ -59,6 +59,7 @@ ImagesCarousel.propTypes = {
offer: PropTypes.any,
onModalClose: PropTypes.any,
createOffer: PropTypes.bool,
images: PropTypes.array
};

export default ImagesCarousel;

+ 22
- 24
src/components/Cards/ItemDetailsCard/ItemDetailsCard.js 查看文件

@@ -50,11 +50,12 @@ const ItemDetailsCard = (props) => {
const offer = useMemo(() => {
if (props.offer) {
if (
props.offer.offer._id === routeMatch.params?.offerId ||
props.createOffer
props.offer._id === routeMatch.params?.offerId &&
!props?.createOffer
) {
return props.offer;
}
if (props.createOffer) return props.offer.offer;
}
return itemDetailsData;
}, [props.offer, props.createOffer, routeMatch.params]);
@@ -66,21 +67,21 @@ const ItemDetailsCard = (props) => {
}, []);

useEffect(() => {
if (offer?.offer?._id) {
increaseOfferCounter(offer?.offer?._id);
if (offer?._id) {
increaseOfferCounter(offer?._id);
}
}, [offer]);

const date = formatDateLocale(new Date(offer?.offer?._created));
const date = formatDateLocale(new Date(offer?._created));

const startExchange = () => {
startChat(chats, offer?.offer, userId);
startChat(chats, offer, userId);
};

const showDeleteOfferModalHandler = () => {
dispatch(
toggleDeleteOfferModal({
offer: offer.offer,
offer: offer,
isAdmin: props.isAdmin,
})
);
@@ -90,23 +91,24 @@ const ItemDetailsCard = (props) => {
dispatch(
toggleEditOfferModal({
editOffer: true,
offer: offer?.offer,
offer: offer,
isAdmin: props.isAdmin,
customUserId: offer?.offer?.userId,
customUserId: offer?.user?._id,
})
);
};
const showPinOfferModalHandler = () => {
dispatch(
toggleDeleteOfferModal({
offer: offer?.offer,
offer: offer,
pin: true,
pinnedOffer: offer?.offer?.pinned,
pinnedOffer: offer?.pinned,
deleteOffer: false,
})
);
};

console.log(props)
return (
<>
<ItemDetailsCardContainer
@@ -120,21 +122,15 @@ const ItemDetailsCard = (props) => {
<Info>
<Information
icon={<CategoryIcon />}
value={offer?.offer?.category?.name}
value={offer?.category?.name}
/>
<Information
icon={<SubcategoryIcon />}
value={offer?.offer?.subcategory}
/>
<Information
icon={<QuantityIcon />}
value={offer?.offer?.condition}
value={offer?.subcategory}
/>
<Information icon={<QuantityIcon />} value={offer?.condition} />
{!props.hideViews && (
<Information
icon={<EyeIcon />}
value={offer?.offer?.views?.count}
/>
<Information icon={<EyeIcon />} value={offer?.views?.count} />
)}
</Info>
<PostDate previewCard={props.previewCard}>{date}</PostDate>
@@ -153,9 +149,11 @@ const ItemDetailsCard = (props) => {
<DateButtonsContainer>
{props.isMyOffer && (
<ButtonsContainer>
<PinIconContainer onClick={showPinOfferModalHandler}>
{offer?.offer?.pinned ? <UnpinIcon /> : <PinIcon />}
</PinIconContainer>
{props?.isAdmin && (
<PinIconContainer onClick={showPinOfferModalHandler}>
{offer?.pinned ? <UnpinIcon /> : <PinIcon />}
</PinIconContainer>
)}
<EditIconContainer onClick={showEditOfferModalHandler}>
<EditIcon />
</EditIconContainer>

+ 19
- 21
src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js 查看文件

@@ -28,8 +28,8 @@ const OfferDetails = (props) => {
const [imagesCarouselModal, setImagesCarouselModal] = useState(false);

useEffect(() => {
if (props?.offer?.offer?.images) {
props.offer.offer.images.map((file) => {
if (props?.offer?.images) {
props.offer.images.map((file) => {
if (file) {
if (typeof file !== "string") {
var reader = new FileReader();
@@ -49,11 +49,15 @@ const OfferDetails = (props) => {
}
});
}
}, [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 = () => {
setImagesCarouselModal(false);
};
console.log(props);
return (
<>
<Details
@@ -64,13 +68,9 @@ const OfferDetails = (props) => {
>
{!isMobile && props.singleOffer && (
<ScrollerVertical>
{props?.offer?.offer?.images.map((item, index) => (
{images.map((item, index) => (
<OfferImage
src={
props.createOffer
? images[index]
: getImageUrl(item, variants.offerCard, isMobile)
}
src={images[index]}
alt={t("offer.imageAlt")}
key={item}
previewCard={props.previewCard}
@@ -85,20 +85,14 @@ const OfferDetails = (props) => {
singleOffer={props.singleOffer}
previewCard={props.previewCard}
>
<OfferTitle singleOffer={props.singleOffer}>
{offer?.offer?.name}
</OfferTitle>
<OfferTitle singleOffer={props.singleOffer}>{offer?.name}</OfferTitle>
{isMobile && (
<ScrollerHorizontal>
{props?.offer?.offer?.images.map((item, index) => {
{images.map((item, index) => {
if (!item) return;
return (
<OfferImage
src={
props.createOffer
? images[index]
: getImageUrl(item, variants.offerCard, isMobile)
}
src={images[index]}
key={item}
previewCard={props.previewCard}
onClick={() =>
@@ -117,7 +111,7 @@ const OfferDetails = (props) => {
{t("itemDetailsCard.description")}
</OfferDescriptionTitle>
<OfferDescriptionText showBarterButton={props.showExchangeButton}>
{offer?.offer?.description}
{offer?.description}
</OfferDescriptionText>
<DesciprtionPostDate previewCard={props.previewCard}>
{date}
@@ -126,7 +120,11 @@ const OfferDetails = (props) => {
</OfferInfoContainer>
</Details>
{imagesCarouselModal && (
<ImagesCarousel offer={props.offer} onModalClose={onModalClose} />
<ImagesCarousel
offer={props.offer}
images={images}
onModalClose={onModalClose}
/>
)}
</>
);

+ 19
- 0
src/components/Cards/LittleOfferCard/LittleOfferCard.styled.js 查看文件

@@ -17,6 +17,9 @@ export const LittleOfferCardContainer = styled(Box)`
display: flex;
flex-direction: row;
position: relative;
@media (max-width: 600px) {
width: 211px;
}
`
export const OfferImage = styled.img`
width: 54px;
@@ -28,6 +31,7 @@ export const OfferImage = styled.img`
`
export const OfferDetails = styled(Box)`
display: flex;
text-align: left;
flex-direction: column;
margin-top: 25px;
margin-left: 9px;
@@ -50,6 +54,9 @@ export const OfferCategoryIcon = styled(Category)`
position: relative;
top: 1.5px;
right: 2px;
& path {
stroke-width: 1;
}
`
export const OfferSwapsIconContainer = styled(Icon)`
width: 40px;
@@ -63,10 +70,22 @@ export const OfferSwapsIconContainer = styled(Icon)`
width: 40px;
height: 40px;
}
@media (max-width: 600px) {
width: 32px;
height: 32px;
top: -15px;
right: -15px;
}
`
export const OfferSwapsIcon = styled(Swaps)`
width: 18px;
height: 18px;
position: relative;
top: 10px;
@media (max-width: 600px) {
width: 14px;
height: 14px;
top: 2px;
left: -4px;
}
`

+ 5
- 1
src/components/Cards/MessageCard/MessageCard.styled.js 查看文件

@@ -14,7 +14,9 @@ export const ProfileImage = styled.img`
overflow: hidden;
border-radius: 100%;
@media (max-width: 600px) {
display: none;
width: 18px;
height: 18px;
min-width: 18px;
}
`;
export const MessageContent = styled(Box)`
@@ -29,6 +31,8 @@ export const MessageContent = styled(Box)`
min-width: 110px;
@media (max-width: 600px) {
width: 100%;
margin: 0;
${props => props.ismymessage ? "margin-right: 9px;" : "margin-left: 9px;"}
}
`;
export const MessageText = styled(Typography)`

+ 18
- 12
src/components/Cards/MiniChatCard/MiniChatCard.js 查看文件

@@ -16,40 +16,46 @@ import history from "../../../store/utils/history";
import { replaceInRoute } from "../../../util/helpers/routeHelpers";
import { DIRECT_CHAT_PAGE } from "../../../constants/pages";
import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile";
import { useMemo } from "react";
import { useSelector } from "react-redux";
import { selectUserId } from "../../../store/selectors/loginSelectors";

const MiniChatCard = (props) => {
const { t } = useTranslation();
const { isMobile } = useIsMobile();
const userId = useSelector(selectUserId);
const changeChat = () => {
history.push(
replaceInRoute(DIRECT_CHAT_PAGE, {
chatId: props?.chat?.chat?._id,
chatId: props?.chat?._id,
})
);
};
const interlocutorData = useMemo(() => {
if (props?.chat?.participants) {
let interlocutor = props?.chat?.participants[0]._id === userId ? 1 : 0;
return props?.chat?.participants[interlocutor];
}
return {};
}, [props?.chat]);
return (
<MiniChatCardContainer selected={props.selected} onClick={changeChat}>
<ProfileImage
src={getImageUrl(
props?.chat?.interlocutorData?.image,
variants.chatCard,
isMobile
)}
src={getImageUrl(interlocutorData?.image, variants.chatCard, isMobile)}
/>
<ProfileDetails isBlocked={props.chat.interlocutorData?._blocked}>
<ProfileDetails isBlocked={interlocutorData?._blocked}>
<ProfileNameContainer>
<ProfileName selected={props.selected}>
{props?.chat?.interlocutorData?.name}
{interlocutorData?.company?.name}
</ProfileName>
{(props.chat.interlocutorData?._blocked ||
props.chat.interlocutorData?._deleted) && (
{(interlocutorData?._blocked || interlocutorData?._deleted) && (
<BlockedProfile
redText
chatCard
shortText
aboveTitle
hideIcon
deleted={props.chat.interlocutorData?._deleted}
deleted={interlocutorData?._deleted}
/>
)}
</ProfileNameContainer>
@@ -57,7 +63,7 @@ const MiniChatCard = (props) => {
{t("messages.cardProduct")}
</ProfileProduct>
<ProfileProductName selected={props.selected}>
{props?.chat?.offerData?.name}
{props?.chat?.offer?.name}
</ProfileProductName>
</ProfileDetails>
</MiniChatCardContainer>

+ 17
- 9
src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.js 查看文件

@@ -26,12 +26,12 @@ import { useHistory } from "react-router-dom";
import useIsMobile from "../../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter";
import { selectQueryString } from "../../../../store/selectors/queryStringSelectors";
import OfferDescription from "./OfferDescription/OfferDescription";
import CancelButton from "./CancelButton/CancelButton";
import SaveButton from "./SaveButton/SaveButton";
import { closeModal } from "../../../../store/actions/modal/modalActions";
import {
dynamicRouteMatches,
replaceInRoute,
routeMatches,
} from "../../../../util/helpers/routeHelpers";
import {
@@ -42,13 +42,14 @@ import {
ITEM_DETAILS_PAGE,
PROFILE_PAGE,
} from "../../../../constants/pages";
import { OfferDescriptionContainer } from "./DeleteOfferLabeledCard/DeleteOfferLabeledCard.styled";

const DeleteOffer = (props) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const queryString = useSelector(selectQueryString);
const history = useHistory();
const userId = props.offer.userId;
const userId = props.offer.user._id;
const { isMobile } = useIsMobile();
const offerId = props.offer._id;
const closeDeleteModalHandler = () => {
@@ -60,15 +61,22 @@ const DeleteOffer = (props) => {
dynamicRouteMatches(PROFILE_PAGE) ||
dynamicRouteMatches(ADMIN_SINGLE_USER_PAGE)
)
dispatch(fetchProfileOffers(userId));
dispatch(fetchProfileOffers({ idProfile: userId, isAdmin: true }));
if (routeMatches(HOME_PAGE) || routeMatches(BASE_PAGE))
dispatch(fetchOffers({ queryString }));
if (
dynamicRouteMatches(ITEM_DETAILS_PAGE) ||
dynamicRouteMatches(ADMIN_ITEM_DETAILS_PAGE)
) {
if (dynamicRouteMatches(ITEM_DETAILS_PAGE)) {
history.push(
replaceInRoute(PROFILE_PAGE, {
profileId: userId,
})
);
}
if (dynamicRouteMatches(ADMIN_ITEM_DETAILS_PAGE)) {
if (props.pin) dispatch(fetchOneOffer(props.offer?._id));
else history.goBack();
else
history.push(
replaceInRoute(ADMIN_SINGLE_USER_PAGE, { profileId: userId })
);
}
};

@@ -110,7 +118,7 @@ const DeleteOffer = (props) => {
)}
/>
</OfferImageContainer>
<OfferDescription
<OfferDescriptionContainer
offerName={props.offer.name}
categoryName={props.offer.category.name}
/>

+ 1
- 1
src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.styled.js 查看文件

@@ -53,7 +53,7 @@ export const OfferImageContainer = styled(Box)`
border-radius: 2px;

@media screen and (max-width: 600px) {
margin-right: 13px;
/* margin-right: 13px; */
}
`;


+ 2
- 2
src/components/Cards/OfferCard/DeleteOffer/DeleteOfferLabeledCard/DeleteOfferLabeledCard.js 查看文件

@@ -1,6 +1,7 @@
import React from "react";
import PropTypes from "prop-types";
import {
OfferDescriptionContainer,
OfferImage,
OfferImageContainer,
OfferInfo,
@@ -11,7 +12,6 @@ import {
getImageUrl,
variants,
} from "../../../../../util/helpers/imageUrlGetter";
import OfferDescription from "../OfferDescription/OfferDescription";
import useIsMobile from "../../../../../hooks/useIsMobile";

const DeleteOfferLabeledCard = (props) => {
@@ -27,7 +27,7 @@ const DeleteOfferLabeledCard = (props) => {
)}
/>
</OfferImageContainer>
<OfferDescription
<OfferDescriptionContainer
offerName={props.offer.name}
categoryName={props.offer.category.name}
/>

+ 5
- 1
src/components/Cards/OfferCard/DeleteOffer/DeleteOfferLabeledCard/DeleteOfferLabeledCard.styled.js 查看文件

@@ -3,6 +3,7 @@ import styled from "styled-components";
import selectedTheme from "../../../../../themes";
import { ReactComponent as Remove } from "../../../../../assets/images/svg/trash-gold.svg";
import { IconButton } from "../../../../Buttons/IconButton/IconButton";
import OfferDescription from "../OfferDescription/OfferDescription";
export const OfferInfo = styled(Box)`
width: 211px;
height: 90px;
@@ -23,7 +24,7 @@ export const OfferImageContainer = styled(Box)`
border-radius: 2px;

@media screen and (max-width: 600px) {
margin-right: 13px;
/* margin-right: 13px; */
}
`;

@@ -56,3 +57,6 @@ export const RemoveIconContainer = styled(RemoveIconBorder)`
export const RemoveIcon = styled(Remove)`
cursor: default;
`;
export const OfferDescriptionContainer = styled(OfferDescription)`
margin-left: 0;
`

+ 8
- 4
src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.js 查看文件

@@ -3,6 +3,7 @@ import PropTypes from "prop-types";
import {
CategoryIcon,
CategoryIconContainer,
OfferCategoryContainer,
OfferDescriptionCategory,
OfferDescriptionContainer,
OfferDescriptionTitle,
@@ -11,9 +12,9 @@ import selectedTheme from "../../../../../themes";

const OfferDescription = (props) => {
return (
<OfferDescriptionContainer>
<OfferDescriptionContainer className={props?.className}>
<OfferDescriptionTitle>{props.offerName}</OfferDescriptionTitle>
<OfferDescriptionCategory>
<OfferCategoryContainer>
<CategoryIconContainer
color={selectedTheme.colors.iconStrokeDisabledColor}
component="span"
@@ -21,8 +22,10 @@ const OfferDescription = (props) => {
>
<CategoryIcon />
</CategoryIconContainer>
{props.categoryName}
</OfferDescriptionCategory>
<OfferDescriptionCategory>
{props.categoryName}
</OfferDescriptionCategory>
</OfferCategoryContainer>
</OfferDescriptionContainer>
);
};
@@ -30,6 +33,7 @@ const OfferDescription = (props) => {
OfferDescription.propTypes = {
offerName: PropTypes.string,
categoryName: PropTypes.string,
className: PropTypes.string,
};

export default OfferDescription;

+ 7
- 1
src/components/Cards/OfferCard/DeleteOffer/OfferDescription/OfferDescription.styled.js 查看文件

@@ -35,15 +35,21 @@ export const OfferDescriptionCategory = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryDarkText};
`;
export const OfferCategoryContainer = styled(Box)`
display: flex;
flex-direction: row;
white-space: nowrap;
`

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

+ 8
- 5
src/components/Cards/OfferCard/OfferCard.js 查看文件

@@ -87,11 +87,14 @@ const OfferCard = (props) => {
})
);
} else {
history.push(
replaceInRoute(ITEM_DETAILS_PAGE, {
history.push({
pathname: replaceInRoute(ITEM_DETAILS_PAGE, {
offerId: itemId,
})
);
}),
state: {
view: true,
},
});
}
}
};
@@ -112,7 +115,7 @@ const OfferCard = (props) => {
editOffer: true,
offer: props.offer,
isAdmin: props.isAdmin,
customUserId: props?.offer?.userId,
customUserId: props?.offer?.user._id,
})
);
};

+ 6
- 2
src/components/Cards/ProfileCard/ProfileControl/ProfileControl.js 查看文件

@@ -54,7 +54,10 @@ const ProfileControl = (props) => {
);
};
const handleEditProfile = () => {
if (!props.profile?._blocked) {
console.log("edit")
console.log(props)
if (!props.profile?._blocked || props?.isAdmin) {
console.log("edit2")
dispatch(
toggleEditProfileModal({
userId: props.profile._id,
@@ -67,9 +70,10 @@ const ProfileControl = (props) => {
);
}
};
console.log(props)
return (
<ButtonsContainer>
{props.profile?._blocked && !props.isMobile && <BlockedProfile />}
{props.profile?._blocked && !props.isMobile && !props?.isAdmin && <BlockedProfile />}
{props.isAdmin && (
<>
{props.profile?._blocked ? (

+ 6
- 6
src/components/Cards/RequestExchangeCard/RequestExchangeCard.js 查看文件

@@ -26,15 +26,15 @@ const RequestExchangeCard = (props) => {
const requester = useSelector(selectRequester);
const exchange = useSelector(selectExchange);
const amIBuyer = useMemo(
() => exchange?.buyer?.userId === userId,
() => exchange?.buyer?.user?._id === userId,
[exchange, userId]
);
const haveIAccepted = useMemo(
() => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted),
[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]
);
const message = useMemo(() => {
@@ -52,18 +52,18 @@ const RequestExchangeCard = (props) => {
</MessageText>
);
}
} else if (requester === requesterStatus.INTERLUCATOR) {
} else if (requester === requesterStatus.interlocutor) {
return (
<RequestExchangeMessage
haveIAccepted={haveIAccepted}
chatId={props.chatId}
userId={userId}
interlucatorUserId={interlucatorUserId}
interlocutorUserId={interlocutorUserId}
/>
);
}
return "";
}, [requester, t, haveIAccepted, interlucatorUserId, userId, exchange]);
}, [requester, t, haveIAccepted, interlocutorUserId, userId, exchange]);
return (
<RequestExchangeCardContainer ismymessage={props.isMyMessage}>
<InfoIcon />

+ 2
- 0
src/components/Cards/RequestExchangeCard/RequestExchangeCard.styled.js 查看文件

@@ -20,6 +20,8 @@ export const MessageContent = styled(Box)`
min-width: 110px;
@media (max-width: 600px) {
width: 100%;
margin: 0;
${props => props.ismymessage ? "margin-right: 9px;" : "margin-left: 9px;"}
}
`;
export const MessageText = styled(Typography)`

+ 28
- 12
src/components/Cards/RequestExchangeCard/RequestExchangeMessage/RequestExchangeMessage.js 查看文件

@@ -9,8 +9,14 @@ import {
import { useTranslation } from "react-i18next";
import { acceptExchangeSocket } from "../../../../socket/socket";
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 { convertLocalDateToUTCDate } from "../../../../util/helpers/dateHelpers";
import requesterStatus from "../../../../constants/requesterStatus";
@@ -21,22 +27,21 @@ const RequestExchangeMessage = (props) => {
const exchange = useSelector(selectExchange);
const requester = useSelector(selectRequester);

const handleAcceptExchange = () => {
const handleAcceptExchangeSuccess = () => {
console.log("accept salje i prima 3 POZVANA RESPONSE FUNKCIJA");
acceptExchangeSocket(
props.chatId,
props.userId,
props.interlucatorUserId,
props.interlocutorUserId,
() => {
dispatch(
acceptExchange({
exchangeId: exchange._id,
})
);
console.log("accept salje i prima 4 SOCKET FUNKCIJA");
dispatch(
addNewMessage({
_id: props.chatId,
message: {
userId: props.userId,
user: {
_id: props.userId,
},
text: "",
isAcceptRequest: true,
_created: convertLocalDateToUTCDate(new Date()),
@@ -49,6 +54,15 @@ const RequestExchangeMessage = (props) => {
}
);
};
const handleAcceptExchange = () => {
console.log("accept salje i prima 1 POZVANA FUNKCIJA");
dispatch(
acceptExchange({
exchangeId: exchange._id,
handleApiResponseSuccess: handleAcceptExchangeSuccess,
})
);
};
return (
<RequestExchangeMessageContainer>
<RequestExchangeMessageText>
@@ -65,7 +79,9 @@ const RequestExchangeMessage = (props) => {
onClick={handleAcceptExchange}
disabled={props.haveIAccepted}
>
{props.haveIAccepted ? t("messages.acceptedRequest") : t("messages.acceptRequest")}
{props.haveIAccepted
? t("messages.acceptedRequest")
: t("messages.acceptRequest")}
</RequestExchangeMessageButton>
</RequestExchangeMessageButtonsContainer>
</RequestExchangeMessageContainer>
@@ -76,7 +92,7 @@ RequestExchangeMessage.propTypes = {
children: PropTypes.node,
chatId: PropTypes.string,
userId: PropTypes.string,
interlucatorUserId: PropTypes.string,
interlocutorUserId: PropTypes.string,
haveIAccepted: PropTypes.any,
};


+ 14
- 14
src/components/Cards/UserReviewsCard/UserReviewsCard.js 查看文件

@@ -13,6 +13,12 @@ const UserReviewsCard = (props) => {
...props.review,
};
}
let userWhoGaveReview =
props?.review?.exchange?.buyer?.user?._id === props?.review?.user?._id
? "buyer"
: "seller";
let userWhoRevievedReview =
userWhoGaveReview === "buyer" ? "seller" : "buyer";
let isSuccessfulSwap = reviewEnum.YES.mainText.toUpperCase();
if (
props.review.succeeded === reviewEnum.NO.backendText ||
@@ -32,24 +38,16 @@ const UserReviewsCard = (props) => {
isGoodCommunication = reviewEnum.NO.mainText.toUpperCase();
return {
_id: props.review._id,
name:
props.review?.reviewAdditionalData?.userWhoGave?.company?.name ||
props.review?.offer?.name,
image:
props.review?.reviewAdditionalData?.userWhoGave?.image ||
props.review?.offer?.image,
userId: props.review.userId,
name: props?.review?.exchange[userWhoGaveReview]?.user?.company?.name,
image: props?.review?.exchange[userWhoGaveReview]?.user?.image,
userId: props.review.user?._id,
isGoodCommunication,
isSuccessfulSwap,
quote: props?.review?.message,
offerName:
props?.review?.reviewAdditionalData?.offerData?.name ||
props?.review?.userWhoGaveReview?.name,
offerImage:
props?.review?.reviewAdditionalData?.offerData?.firstImage ||
props?.review?.userWhoGaveReview?.image,
offerName: props?.review?.exchange?.offer?.name,
offerImage: props?.review?.exchange?.offer?.images[0],
userWhoReceived:
props?.review?.reviewAdditionalData?.userWhoReceived?.company?.name,
props?.review?.exchange[userWhoRevievedReview]?.user?.company?.name,
_deleted: props?.review?._deleted,
};
}, [props.review]);
@@ -67,6 +65,7 @@ const UserReviewsCard = (props) => {
handleRemove={handleRemove}
hasGivenReview={props.hasGivenReview}
rightReviews={props.rightReviews}
isProfileReviews={props?.isProfileReviews}
isAdmin={props.isAdmin}
/>
);
@@ -84,6 +83,7 @@ UserReviewsCard.propTypes = {
hasGivenReview: PropTypes.bool,
rightReviews: PropTypes.bool,
isAdmin: PropTypes.bool,
userId: PropTypes.string,
};
UserReviewsCard.defaultProps = {
isProfileReviews: false,

+ 3
- 0
src/components/Cards/UserReviewsCard/UserReviewsSingleCard/RemoveButton/RemoveButton.js 查看文件

@@ -3,11 +3,13 @@ import PropTypes from "prop-types";
import { RemoveButtonContainer, RemoveIcon } from "./RemoveButton.styled";

const RemoveButton = (props) => {
console.log(props)
return (
<RemoveButtonContainer
isRemoved={props.isRemoved}
onClick={props.onClick}
hasGivenReview={props.hasGivenReview}
isProfileReviews={props?.isProfileReviews}
>
<RemoveIcon isRemoved={props.isRemoved} />
</RemoveButtonContainer>
@@ -19,6 +21,7 @@ RemoveButton.propTypes = {
onClick: PropTypes.func,
hasGivenReview: PropTypes.bool,
isRemoved: PropTypes.bool,
isProfileReviews: PropTypes.any
};

export default RemoveButton;

+ 15
- 9
src/components/Cards/UserReviewsCard/UserReviewsSingleCard/RemoveButton/RemoveButton.styled.js 查看文件

@@ -6,18 +6,24 @@ import { IconButton } from "../../../../Buttons/IconButton/IconButton";

export const RemoveButtonContainer = styled(IconButton)`
position: absolute;
top: ${(props) => (props.hasGivenReview ? "79px" : "16px")};
top: ${(props) =>
props.hasGivenReview && props.isProfileReviews ? "79px" : "16px"};
right: 16px;
background-color: ${props => props.isRemoved ? "transparent" : selectedTheme.colors.primaryIconBackgroundColor};
background-color: ${(props) =>
props.isRemoved
? "transparent"
: selectedTheme.colors.primaryIconBackgroundColor};
border-radius: 100%;
width: 32px;
height: 32px;
${props => props.isRemoved && css`
& button:hover {
background-color: transparent;
cursor: auto;
}
`}
${(props) =>
props.isRemoved &&
css`
& button:hover {
background-color: transparent;
cursor: auto;
}
`}
& button {
width: 32px;
height: 32px;
@@ -25,6 +31,6 @@ export const RemoveButtonContainer = styled(IconButton)`
`;
export const RemoveIcon = styled(Remove)`
& path {
stroke: ${props => props.isRemoved && selectedTheme.colors.blockedColor};
stroke: ${(props) => props.isRemoved && selectedTheme.colors.blockedColor};
}
`;

+ 3
- 1
src/components/Cards/UserReviewsCard/UserReviewsSingleCard/ReviewQuote/ReviewQuote.styled.js 查看文件

@@ -19,7 +19,9 @@ export const ReviewQuoteContainer = styled(Box)`
export const ThumbContainer = styled(Grid)`
max-width: 20px;
`;
export const ReviewQuoteTextContainer = styled(Grid)``;
export const ReviewQuoteTextContainer = styled(Box)`
flex: 1;
`;
export const ReviewQuoteText = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
font-size: 16px;

+ 2
- 0
src/components/Cards/UserReviewsCard/UserReviewsSingleCard/UserReviewsSingleCard.js 查看文件

@@ -41,6 +41,7 @@ const UserReviewsSingleCard = (props) => {
<RemoveButton
review={props.review}
onClick={handleRemove}
isProfileReviews={props?.isProfileReviews}
hasGivenReview={props.hasGivenReview}
isRemoved={props.review?._deleted}
/>
@@ -63,6 +64,7 @@ UserReviewsSingleCard.propTypes = {
isAdmin: PropTypes.bool,
className: PropTypes.string,
lastReview: PropTypes.bool,
isProfileReviews: PropTypes.any,
};
UserReviewsSingleCard.defaultProps = {
lastReview: false,

+ 3
- 2
src/components/ChatColumn/ChatColumn.js 查看文件

@@ -24,7 +24,7 @@ import {
fetchChats,
} from "../../store/actions/chat/chatActions";
import useSorting from "../../hooks/useOffers/useSorting";
import { addMesageListener, removeMessageListener } from "../../socket/socket";
import { addMessageListener, removeMessageListener } from "../../socket/socket";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants";
import SkeletonChatColumn from "./SkeletonChatColumn/SkeletonChatColumn";
@@ -60,7 +60,8 @@ export const ChatColumn = (props) => {
history.goBack();
return;
}
addMesageListener(({ succeed, data }) => {
addMessageListener(({ succeed, data }) => {

if (succeed) {
dispatch(
addNewMessage({

+ 4
- 8
src/components/CreateReview/CreateReview.js 查看文件

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

+ 15
- 7
src/components/CreateReview/CreateReview.styled.js 查看文件

@@ -38,17 +38,17 @@ export const CreateReviewContainer = styled(Box)`
max-width: 100vw;
left: 0;
top: 0;
padding: 0 30px;
padding: 0 18px;
}
`;
export const NextButton = styled(PrimaryButton)`
@media (max-width: 600px) {
height: 42px;
position: absolute;
bottom: 15px;
width: calc(100% - 48px);
bottom: 9px;
width: calc(100vw - 36px);
left: 0;
margin-left: 24px;
margin-left: 9px;
}
`;
export const CloseButton = styled(IconButton)`
@@ -56,8 +56,8 @@ export const CloseButton = styled(IconButton)`
top: 36px;
right: 36px;
@media (max-width: 600px) {
top: 24px;
right: 24px;
top: 32px;
right: 22px;
}
`;
export const CloseIcon = styled(Close)`
@@ -76,7 +76,7 @@ export const BackIcon = styled(Box)`
left: 36px;

@media (max-width: 600px) {
top: 24px;
top: 40px;
left: 24px;
width: 18px;
height: 18px;
@@ -101,3 +101,11 @@ export const CreateReviewTitle = styled(Typography)`
margin-bottom: 24px;
}
`;
export const CreateReviewFlexContainer = styled(Box)`
@media (max-width: 600px) {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
`

+ 2
- 1
src/components/CreateReview/FirstStep/FirstStepCreateReview.js 查看文件

@@ -22,6 +22,7 @@ import NextButton from "./NextButton/NextButton";
const FirstStepCreateReview = (props) => {
const offer = props.offer;
const interlocutor = props.interlocutor;
console.log(props);
const { t } = useTranslation();
const handleSubmit = (values) => {
props.goToNextStep(values);
@@ -54,7 +55,7 @@ const FirstStepCreateReview = (props) => {
)}
/>
</ProfileImageContainer>
<ProfileName>{interlocutor.name}</ProfileName>
<ProfileName>{interlocutor.company.name}</ProfileName>
<LittleOfferCard
image={offer?.images[0]}
name={offer?.name}

+ 5
- 3
src/components/CreateReview/FirstStep/FirstStepCreateReview.styled.js 查看文件

@@ -9,7 +9,9 @@ export const FirstStepCreateReviewContainer = styled(Box)`
text-align: center;
padding: 36px;
@media (max-width: 600px) {
padding: 18px;
padding: 0;
padding-top: 36px;
flex: 1;
}
`;
export const CreateReviewTitle = styled(Typography)`
@@ -71,9 +73,9 @@ export const SelectField = styled(Select)`
text-align: left;
${props => props.exchange && `background-color: ${selectedTheme.colors.backgroundSponsoredColor};`}
@media (max-width: 600px) {
height: 33px;
height: 40px;
font-size: 14px;
margin-bottom: 12px;
margin-bottom: 18px;
}
`;
export const SelectOption = styled(Option)`

+ 13
- 13
src/components/CreateReview/SecondStep/SecondStepCreateReview.js 查看文件

@@ -27,20 +27,20 @@ const SecondStepCreateReview = (props) => {
: t("reviews.modalTitle")}
</CreateReviewTitle>
<ReviewCard
givingReview
profileReviews={[
{
name: mineProfile?.company?.name,
image: mineProfile?.image,
offerName: props?.offer?.name,
offerImage: props?.offer?.images[0],
isGoodCommunication: props.review?.correctCommunication,
isSuccessfulSwap: props.review?.exchangeSucceed,
quote: props.review.comment,
},
]}
givingReview={{
name: mineProfile?.company?.name,
image: mineProfile?.image,
offerName: props?.offer?.name,
offerImage: props?.offer?.images[0],
isGoodCommunication: props.review?.correctCommunication,
isSuccessfulSwap: props.review?.exchangeSucceed,
quote: props.review.comment,
}}
/>
<NextButton
removingReview={props.removingReview}
onClick={goToNextStep}
/>
<NextButton removingReview={props.removingReview} onClick={goToNextStep} />
</SecondStepCreateReviewContainer>
);
};

+ 13
- 1
src/components/CreateReview/SecondStep/SecondStepCreateReview.styled.js 查看文件

@@ -6,7 +6,8 @@ import UserReviews from "../../UserReviews/UserReviews";
export const SecondStepCreateReviewContainer = styled(Box)`
padding: 36px;
@media (max-width: 600px) {
padding: 18px;
padding: 0;
padding-top: 36px;
}
`;
export const ReviewCard = styled(UserReviews)`
@@ -21,4 +22,15 @@ export const ReviewCard = styled(UserReviews)`
margin: 0;
}
}
& * {
overflow:hidden;
}
@media (max-width: 600px) {
position: relative;
top: -24px;
& > div {
position: static;
margin-top: 0px;
}
}
`;

+ 6
- 0
src/components/CreateReview/ThirdStep/ThirdStepCreateReview.js 查看文件

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

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

+ 42
- 42
src/components/DirectChat/DirectChat.js 查看文件

@@ -24,7 +24,7 @@ import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants";
import { selectUserId } from "../../store/selectors/loginSelectors";
import {
acceptExchangeSocket,
addMesageListener,
addMessageListener,
removeMessageListener,
} from "../../socket/socket";
import { makeErrorToastMessage } from "../../store/utils/makeToastMessage";
@@ -35,11 +35,13 @@ import {
} from "../../store/selectors/exchangeSelector";
import {
acceptExchange,
fetchExchange,
setRequester,
} from "../../store/actions/exchange/exchangeActions";
import { convertLocalDateToUTCDate } from "../../util/helpers/dateHelpers";
import requesterStatus from "../../constants/requesterStatus";
import exchangeStatus from "../../constants/exchangeStatus";
import { NEW_CHAT } from "../../constants/chatConstants";

const DirectChat = () => {
const chat = useSelector(selectSelectedChat);
@@ -59,9 +61,9 @@ const DirectChat = () => {

const offerObject = useMemo(() => {
if (location?.state?.offerId) {
return offer?.offer;
return offer;
}
return chat?.offer?.offer;
return chat?.offer;
}, [chat, location.state, offer]);

const chatObject = useMemo(() => {
@@ -72,7 +74,7 @@ const DirectChat = () => {
}, [chat, location.state]);

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

@@ -81,14 +83,14 @@ const DirectChat = () => {
let haveIAccepted = amIBuyer
? exchange.buyer?.accepted
: exchange.seller?.accepted;
let haveInterlucatorAccepted = amIBuyer
let haveinterlocutorAccepted = amIBuyer
? exchange.seller?.accepted
: exchange.buyer?.accepted;
let haveIReviewed = amIBuyer
? exchange.buyer.givenReview
: exchange.seller.givenReview;
if (haveIAccepted) {
if (haveInterlucatorAccepted) {
if (haveinterlocutorAccepted) {
if (haveIReviewed) {
return exchangeStatus.REVIEWED;
} else {
@@ -98,7 +100,7 @@ const DirectChat = () => {
return exchangeStatus.I_OFFERED;
}
} else {
if (haveInterlucatorAccepted) {
if (haveinterlocutorAccepted) {
return exchangeStatus.I_AM_OFFERED;
} else {
return exchangeStatus.INITIAL;
@@ -110,21 +112,13 @@ const DirectChat = () => {

const interlocutorObject = useMemo(() => {
if (location?.state?.offerId) {
return {
image: offer?.companyData?.image,
name: offer?.companyData?.company?.name,
location: offer?.companyData?.company?.contacts?.location,
userId: offer?.offer?.userId,
telephone: offer?.companyData?.company?.contacts?.telephone,
};
return offer?.user;
}
return {
...chat?.interlocutor,
userId:
chat?.chat?.participants[0] === userId
? chat?.chat?.participants[1]
: chat?.chat?.participants[0],
};
if (chat?.participants) {
let interlocutor = userId === chat?.participants[0]._id ? 1 : 0;
return chat?.participants[interlocutor];
}
return {};
}, [chat, location.state, offer]);

// Fetch chat after it is created
@@ -137,11 +131,11 @@ const DirectChat = () => {

// Listener to socket.IO chat
useEffect(() => {
addMesageListener(({ succeed, data }) => {
addMessageListener(({ succeed, data }) => {
if (succeed) {
if (
[...allChats].find((item) => {
return item.chat._id === data.chatId;
return item._id === data.chatId;
})
) {
dispatch(
@@ -150,11 +144,11 @@ const DirectChat = () => {
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 {
dispatch(fetchChats());
@@ -166,33 +160,30 @@ const DirectChat = () => {
}
});
return () => removeMessageListener();
}, [allChats, routeMatch]);

}, [allChats, routeMatch, requester]);

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

+ 14
- 10
src/components/DirectChat/DirectChatContent/DirectChatContent.js 查看文件

@@ -23,18 +23,18 @@ const DirectChatContent = (props) => {
const myProfileImage = useSelector(selectMineProfilePicture);
const messagesRef = useRef(null);
const requester = useSelector(selectRequester);
const interlucatorProfileImage = props?.interlucator?.image;
const interlocutorProfileImage = props?.interlocutor?.image;
const isLoadingChatContent = useSelector(
selectIsLoadingByActionType(CHAT_SCOPE)
);
const messages = props?.chat?.chat?.messages;
const messages = props?.chat?.messages;
useEffect(() => {
messagesRef.current?.scrollTo({
top: messagesRef.current.scrollHeight,
behaviour: "smooth",
});
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
}, [props?.chat?.chat?.messages, messagesRef, isLoadingChatContent]);
}, [props?.chat?.messages, messagesRef, isLoadingChatContent]);

const handleRefresh = () => {
props.refreshChat();
@@ -46,16 +46,20 @@ const DirectChatContent = (props) => {
) : (
<DirectChatContentContainer>
<DirectChatContentHeader
interlucator={props?.interlucator}
interlocutor={props?.interlocutor}
exchangeState={props.exchangeState}
/>
<MessagesList ref={messagesRef} exchangeState={props?.exchangeState}>
{messages?.map((item) => {
const isMyMessage = userId === item.userId;
const isMyMessage = userId === item.user?._id;
const image = isMyMessage
? myProfileImage
: interlucatorProfileImage;
if (requester === requesterStatus.INTERLUCATOR && isMyMessage && item?.isAcceptRequest)
: interlocutorProfileImage;
if (
requester === requesterStatus.interlocutor &&
isMyMessage &&
item?.isAcceptRequest
)
return;
return (
<MessageContainer key={item?._id || item?._created}>
@@ -63,7 +67,7 @@ const DirectChatContent = (props) => {
<RequestExchangeCard
isMyMessage={isMyMessage}
message={item}
chatId={props?.chat?.chat?._id}
chatId={props?.chat?._id}
/>
) : (
<MessageCard
@@ -79,7 +83,7 @@ const DirectChatContent = (props) => {
<DirectChatNewMessage
chat={props?.chat}
refreshChat={handleRefresh}
interlucator={props.interlucator}
interlocutor={props.interlocutor}
/>
</DirectChatContentContainer>
)}
@@ -90,7 +94,7 @@ const DirectChatContent = (props) => {
DirectChatContent.propTypes = {
children: PropTypes.node,
chat: PropTypes.any,
interlucator: PropTypes.any,
interlocutor: PropTypes.any,
refreshChat: PropTypes.func,
exchangeState: PropTypes.any,
};

+ 1
- 1
src/components/DirectChat/DirectChatContent/DirectChatContent.styled.js 查看文件

@@ -27,7 +27,7 @@ export const MessagesList = styled(Box)`
/* justify-content: flex-end; */
/* align-items: flex-end; */
@media (max-width: 600px) {
padding: 18px 0;
padding: 18px 18px;
}
&::-webkit-scrollbar {
width: 5px;

+ 19
- 12
src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.js 查看文件

@@ -32,9 +32,8 @@ const DirectChatContentHeader = (props) => {
const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null);
const { isMobile } = useIsMobile();
const mineProfileBlocked = useSelector(selectAmIBlocked);

const togglePhonePopover = (event) => {
if (props.interlucator?.telephone) {
if (props.interlocutor?.company?.contacts?.telephone) {
setShowPhonePopover((prevState) => !prevState);
setPhonePopoverAnchorEl((prevState) => {
if (prevState) return null;
@@ -43,10 +42,10 @@ const DirectChatContentHeader = (props) => {
}
};
const routeToUser = () => {
if (!props?.interlucator?._blocked)
if (!props?.interlocutor?._blocked)
history.push(
replaceInRoute(PROFILE_PAGE, {
profileId: props?.interlucator?.userId,
profileId: props?.interlocutor?._id,
})
);
};
@@ -57,19 +56,19 @@ const DirectChatContentHeader = (props) => {
<ProfileImage
onClick={routeToUser}
src={getImageUrl(
props?.interlucator?.image,
props?.interlocutor?.image,
variants.chatHeader,
isMobile
)}
/>
<ProfileDetails>
<ProfileName onClick={routeToUser}>
{props?.interlucator?.name}
{props?.interlocutor?.company?.name}
</ProfileName>
<ProfileLocation>
<ProfileLocationIcon />
<ProfileLocationText>
{props?.interlucator?.location}
{props?.interlocutor?.company?.contacts?.location}
</ProfileLocationText>
</ProfileLocation>
</ProfileDetails>
@@ -78,8 +77,8 @@ const DirectChatContentHeader = (props) => {
<PhoneIconContainer
disabled={
mineProfileBlocked ||
props?.interlucator?._blocked ||
!props.interlucator?.telephone
props?.interlocutor?._blocked ||
!props.interlocutor?.company?.contacts?.telephone
}
onClick={togglePhonePopover}
>
@@ -91,7 +90,11 @@ const DirectChatContentHeader = (props) => {
open={showPhonePopover}
anchorRight
onClose={togglePhonePopover}
content={<PhonePopover phoneNumber={props.interlucator?.telephone} />}
content={
<PhonePopover
phoneNumber={props.interlocutor?.company?.contacts?.telephone}
/>
}
/>
</DirectChatContentHeaderContainer>
{(props.exchangeState === exchangeStatus.I_OFFERED ||
@@ -100,7 +103,11 @@ const DirectChatContentHeader = (props) => {
<DirectChatHeaderStatusContainer>
<DirectChatHeaderStatusText>
{props.exchangeState === exchangeStatus.I_OFFERED
? t("messages.requestSentLong")
? isMobile
? t("messages.requestSentShort")
: t("messages.requestSentLong")
: isMobile
? t("messages.requestSuccessfulShort")
: t("messages.requestSuccessfulLong")}
</DirectChatHeaderStatusText>
</DirectChatHeaderStatusContainer>
@@ -111,7 +118,7 @@ const DirectChatContentHeader = (props) => {

DirectChatContentHeader.propTypes = {
children: PropTypes.node,
interlucator: PropTypes.any,
interlocutor: PropTypes.any,
exchangeState: PropTypes.bool,
};


+ 7
- 0
src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.styled.js 查看文件

@@ -96,6 +96,10 @@ export const DirectChatHeaderStatusContainer = styled(Box)`
height: 39px;
width: 100%;
padding: 9px 36px;
@media (max-width: 600px) {
height: 36px;
padding: 8px 18px;
}
`;
export const DirectChatHeaderStatusText = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
@@ -103,4 +107,7 @@ export const DirectChatHeaderStatusText = styled(Typography)`
font-size: 16px;
line-height: 21px;
color: white;
@media (max-width: 600px) {
font-size: 14px;
}
`;

+ 28
- 11
src/components/DirectChat/DirectChatHeader/DirectChatHeader.js 查看文件

@@ -5,10 +5,14 @@ import OfferCard from "../../Cards/OfferCard/OfferCard";
import { useSelector } from "react-redux";
import { selectExchange } from "../../../store/selectors/exchangeSelector";
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 { selectUserId } from "../../../store/selectors/loginSelectors";
import { toggleCreateReviewModal } from "../../../store/actions/modal/modalActions";
import { setOneChat } from "../../../store/actions/chat/chatActions";

const DirectChatHeader = (props) => {
const exchange = useSelector(selectExchange);
@@ -17,17 +21,32 @@ const DirectChatHeader = (props) => {
const chat = useSelector(selectSelectedChat);

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

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

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

const isDisabledCheckButton = useMemo(() => {
if (props?.interlocutor?._blocked) return true;
if (chat?.offer?._deleted) return true;
return false;
}, [exchange, userId]);
}, [props.interlocutor, chat]);

const showReviewModal = () => {
dispatch(
@@ -40,7 +59,7 @@ const DirectChatHeader = (props) => {
};

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

const acceptExchange = () => {
@@ -51,14 +70,12 @@ const DirectChatHeader = (props) => {
<OfferCard
offer={props.offer}
aboveChat
disabledReviews={props.interlocutor?._blocked || isDisabledReviews}
disabledReviews={isDisabledReviews}
makeReview={showReviewModal}
acceptExchange={acceptExchange}
exchangeState={props?.exchangeState}
dontShowViews
disabledCheckButton={
props.interlocutor?._blocked || props?.offer?._deleted
}
disabledCheckButton={isDisabledCheckButton}
/>
</DirectChatHeaderContainer>
);

+ 16
- 12
src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js 查看文件

@@ -34,21 +34,24 @@ const DirectChatNewMessage = (props) => {
const userId = useSelector(selectUserId);
const handleSend = useCallback(
(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(
addNewMessage({
_id: chatId,
message: {
userId,
user: {
_id: userId,
},
text: typedValue,
_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));
}
}
@@ -57,7 +60,7 @@ const DirectChatNewMessage = (props) => {
}
setTypedValue("");
},
[typedValue, props.chat?.chat?._id, userId, props.interlucator.userId]
[typedValue, props.chat?._id, userId, props.interlocutor]
);
const handleMessageSendSuccess = (newChatId) => {
history.replace(`${newChatId}`);
@@ -82,21 +85,22 @@ const DirectChatNewMessage = (props) => {
startNewChat({
offerId,
message: typedValue,
interlucatorUserId: props.interlucator.userId,
interlocutorUserId: props.interlocutor._id,
handleMessageSendSuccess,
})
);
};
console.log(props)
if (mineProfileBlocked) {
return <NotAllowedChat mineProfileBlocked />;
}
if (props?.chat?.interlocutor?._deleted) {
if (props?.interlocutor?._deleted) {
return <NotAllowedChat deleted />;
}
if (props?.chat?.offer?.offer?._deleted) {
if (props?.chat?.offer?._deleted) {
return <NotAllowedChat />;
}
if (props?.chat?.interlocutor?._blocked) {
if (props?.interlocutor?._blocked) {
return <NotAllowedChat blocked />;
}
return (
@@ -127,7 +131,7 @@ DirectChatNewMessage.propTypes = {
children: PropTypes.node,
chatId: PropTypes.any,
refreshChat: PropTypes.func,
interlucator: PropTypes.any,
interlocutor: PropTypes.any,
chat: PropTypes.any,
};


+ 11
- 7
src/components/DirectChat/MiniChatColumn/MiniChatColumn.js 查看文件

@@ -36,12 +36,16 @@ const MiniChatColumn = () => {
const newChat = useMemo(() => {
if (location.state?.offerId) {
return {
interlocutorData: {
image: offer?.companyData?.image,
name: offer?.companyData?.company?.name,
},
offerData: {
name: offer?.offer?.name,
participants: [
{
image: offer?.user?.image,
company: {
name: offer?.user?.company?.name,
},
},
],
offer: {
name: offer?.name,
},
};
}
@@ -72,7 +76,7 @@ const MiniChatColumn = () => {
<MiniChatCard
key={Date.now() * Math.random()}
chat={item}
selected={item?.chat?._id === selectedChat?.chat?._id}
selected={item?._id === selectedChat?._id}
/>
);
})}

+ 7
- 1
src/components/Header/Drawer/Buttons/MyProfileButton/MyProfileButton.js 查看文件

@@ -8,6 +8,8 @@ import { useSelector } from "react-redux";
import { selectProfileName } from "../../../../../store/selectors/profileSelectors";
import { selectUserId } from "../../../../../store/selectors/loginSelectors";
import history from "../../../../../store/utils/history";
import { PROFILE_PAGE } from "../../../../../constants/pages";
import { replaceInRoute } from "../../../../../util/helpers/routeHelpers";

const MyProfileButton = (props) => {
const name = useSelector(selectProfileName);
@@ -15,7 +17,11 @@ const MyProfileButton = (props) => {
const { t } = useTranslation();
const handleClick = () => {
props.toggleDrawer();
history.push(`/profile/${userId}`);
history.push(
replaceInRoute(PROFILE_PAGE, {
profileId: userId,
})
);
};
return (
<DrawerButton onClick={handleClick}>

+ 1
- 1
src/components/Header/Header.js 查看文件

@@ -112,7 +112,7 @@ const Header = () => {
logo: true,
},
});
searchRef.current.value = "";
if (searchRef?.current) searchRef.current.value = "";
}
};


+ 2
- 0
src/components/Header/SearchInput/SearchInput.js 查看文件

@@ -16,9 +16,11 @@ const SearchInput = forwardRef((props, ref) => {
const { t } = useTranslation();
const handleSearch = () => {
if (routeMatches(HOME_PAGE) || routeMatches(BASE_PAGE)) {
console.log("uslo unutra")
debounceHelper(() => props.handleSearch(ref.current.value), 500);
}
};
console.log(routeMatches(HOME_PAGE))
const handleManualSearch = () => {
debounceHelper(() => {}, 500);
props.handleSearch(ref.current.value);

+ 12
- 6
src/components/ItemDetails/ItemDetails.js 查看文件

@@ -25,10 +25,7 @@ const ItemDetails = (props) => {
selectIsLoadingByActionType(ONE_OFFER_SCOPE)
);
let isMyProfile = useMemo(() => {
if (
offer?.offer?.userId?.toString() === userId?.toString() ||
props.isAdmin
)
if (offer?.user?._id?.toString() === userId?.toString() || props.isAdmin)
return true;
return false;
}, [offer, userId, props.isAdmin]);
@@ -41,7 +38,11 @@ const ItemDetails = (props) => {
) : (
<>
{!props.singleOffer && (
<ItemDetailsHeaderCard offer={offer} isMyProfile={isMyProfile} />
<ItemDetailsHeaderCard
offer={offer}
isMyProfile={isMyProfile}
isAdmin={props?.isAdmin}
/>
)}
{props.singleOffer && (
<OfferIconContainer>
@@ -49,7 +50,12 @@ const ItemDetails = (props) => {
<OfferIconText>{t("offer.product")}</OfferIconText>
</OfferIconContainer>
)}
<ItemDetailsCard offer={offer} isMyOffer={isMyProfile} isAdmin={props.isAdmin} singleOffer />
<ItemDetailsCard
offer={offer}
isMyOffer={isMyProfile}
isAdmin={props.isAdmin}
singleOffer
/>
</>
)}
</ItemDetailsContainer>

+ 36
- 11
src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js 查看文件

@@ -25,6 +25,13 @@ import { useMemo } from "react";
import itemDetailsData from "../../../notFoundData/itemDetailsData";
import { Tooltip } from "@mui/material";
import { useTranslation } from "react-i18next";
import { replaceInRoute } from "../../../util/helpers/routeHelpers";
import {
ADMIN_SINGLE_USER_PAGE,
DIRECT_CHAT_PAGE,
PROFILE_PAGE,
} from "../../../constants/pages";
import { NEW_CHAT } from "../../../constants/chatConstants";

const ItemDetailsHeaderCard = (props) => {
const history = useHistory();
@@ -33,7 +40,7 @@ const ItemDetailsHeaderCard = (props) => {
const { t } = useTranslation();
const offer = useMemo(() => {
if (props.offer) {
if (props.offer.offer._id === routeMatch.params.offerId) {
if (props.offer._id === routeMatch.params.offerId) {
return props.offer;
}
}
@@ -43,18 +50,35 @@ const ItemDetailsHeaderCard = (props) => {
const { isMobile } = useIsMobile();

const handleGoProfile = () => {
history.push(`/profile/${offer?.offer?.userId}`);
if (props?.isAdmin) {
history.push(
replaceInRoute(ADMIN_SINGLE_USER_PAGE, {
profileId: props?.offer?.user?._id,
})
);
} else {
history.push(
replaceInRoute(PROFILE_PAGE, {
profileId: props?.offer?.user?._id,
})
);
}
};
const messageUser = (offer) => {
const chatItem = chats.find(
(item) => item.chat.offerId === offer?.offer?._id
);
const chatItem = chats.find((item) => item.offer._id === offer?._id);
if (chatItem !== undefined) {
history.push(`/messages/${chatItem.chat._id}`);
history.push(DIRECT_CHAT_PAGE, {
chatId: chatItem._id,
});
} else {
if (offer?.offer?.userId !== userId) {
history.push(`/messages/newMessage`, {
offerId: offer?.offer?._id,
if (offer?.user?._id !== userId) {
history.push({
pathname: replaceInRoute(DIRECT_CHAT_PAGE, {
chatId: NEW_CHAT,
}),
state: {
offerId: offer?._id,
},
});
}
}
@@ -67,14 +91,14 @@ const ItemDetailsHeaderCard = (props) => {
<HeaderTop>
<OfferImage
src={getImageUrl(
offer?.companyData?.image ? offer.companyData.image : "",
offer?.user?.image ? offer.user.image : "",
variants.profileImage,
isMobile
)}
/>
<OfferDetails>
<OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}>
{offer?.companyData?.company?.name}
{offer?.user?.company?.name}
</OfferTitle>
<PIBDetail offer={offer} isMyProfile={props.isMyProfile} />
<CategoryDetail offer={offer} isMyProfile={props.isMyProfile} />
@@ -115,6 +139,7 @@ ItemDetailsHeaderCard.propTypes = {
offer: PropTypes.any,
isMyProfile: PropTypes.bool,
singleOffer: PropTypes.bool,
isAdmin: PropTypes.bool,
};
ItemDetailsHeaderCard.defaultProps = {
halfwidth: false,

+ 1
- 1
src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/Category/CategoryDetail.js 查看文件

@@ -16,7 +16,7 @@ const CategoryDetail = (props) => {
<LocationIcon />
</DetailIcon>
<DetailText ismyprofile={props.isMyProfile}>
{offer.offer?.location?.city}
{offer?.location?.city}
</DetailText>
</DetailContainer>
);

+ 1
- 1
src/components/ItemDetails/ItemDetailsHeaderCard/OfferDetail/PIB/PIBDetail.js 查看文件

@@ -15,7 +15,7 @@ const PIBDetail = (props) => {
<PIB />
</PIBIcon>
<DetailText isMyProfile={props.isMyProfile}>
{`${t("itemDetailsCard.PIB")}${offer?.companyData?.company?.PIB}`}
{`${t("itemDetailsCard.PIB")}${offer?.user?.company?.PIB}`}
</DetailText>
</DetailContainer>
);

+ 5
- 5
src/components/ItemDetails/ItemDetailsHeaderCard/StatisticDetails/StatisticDetails.js 查看文件

@@ -12,13 +12,13 @@ const StatisticDetails = (props) => {
const { t } = useTranslation();
const offer = props.offer;
const percentOfSucceededExchanges = useMemo(() => {
if (offer?.companyData?.statistics?.exchanges?.succeeded === 0) {
if (offer?.user?.statistics?.exchanges?.succeeded === 0) {
return 0 + "%";
} else {
return (
Math.ceil(
(offer?.companyData?.statistics?.exchanges?.total /
offer?.companyData?.statistics?.exchanges?.succeeded) *
(offer?.user?.statistics?.exchanges?.total /
offer?.user?.statistics?.exchanges?.succeeded) *
100
) + "%"
);
@@ -30,13 +30,13 @@ const StatisticDetails = (props) => {
<BottomDetails>
<StatusText>
<StatusValue>
{offer?.companyData?.statistics?.publishes?.count}
{offer?.user?.statistics?.publishes?.count}
</StatusValue>
{t("itemDetailsCard.offers")}
</StatusText>
<StatusText>
<StatusValue>
{offer?.companyData?.statistics?.views?.count}
{offer?.user?.statistics?.views?.count}
</StatusValue>
{t("itemDetailsCard.totalViews")}
</StatusText>

+ 8
- 5
src/components/MarketPlace/Header/Header.js 查看文件

@@ -91,6 +91,7 @@ const Header = (props) => {
headerTitle={headerTitle}
headerIcon={headerIcon}
offers={props?.offers}
myOffers={props?.myOffers}
hideBackButton={props?.hideBackButton}
/>
{/* ^^^^^^ */}
@@ -103,11 +104,13 @@ const Header = (props) => {
/>

{/* Select option to choose sorting */}
<HeaderSelect
myOffers={props?.myOffers}
sorting={sorting}
hideSorting={props?.hideSorting}
/>
{!props?.hideSorting && (
<HeaderSelect
myOffers={props?.myOffers}
sorting={sorting}
hideSorting={props?.hideSorting}
/>
)}
{/* ^^^^^^ */}
</HeaderOptions>
</HeaderContainer>

+ 3
- 0
src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.js 查看文件

@@ -31,15 +31,18 @@ const TooltipHeader = (props) => {
const handleClickCategory = () => {
props?.offers?.filters?.locations.clear();
props?.offers?.filters?.subcategory.clear();
props?.offers?.filters?.companies?.clear();
props?.offers?.applyFilters();
};
const handleClickSubcategory = () => {
props?.offers?.filters?.locations.clear();
props?.offers?.filters?.companies?.clear();
props?.offers?.applyFilters();
};
const goBack = () => {
history.goBack();
};
console.log(props)
return (
<Tooltip title={headerString.text}>
<TooltipInnerContainer>

+ 10
- 2
src/components/MarketPlace/Offers/Offers.js 查看文件

@@ -9,11 +9,18 @@ import OffersNotFound from "./OffersNotFound/OffersNotFound";
const Offers = (props) => {
const offers = props?.offers;
const arrayForMapping = Array.apply(null, Array(4)).map(() => {});
console.log("rerender");

return (
<>
<OffersFilterButton />
<OffersFilterButton
offers={props?.offers}
isAdmin={props?.isAdmin}
myOffers={props?.myOffers}
toggleFilters={props?.toggleFilters}
/>
<OffersSearchField />
<OffersNotFound />
{!props?.skeleton && <OffersNotFound />}
<OffersList
loading={props?.skeleton}
offers={offers}
@@ -21,6 +28,7 @@ const Offers = (props) => {
isGrid={props?.isGrid}
isUsers={props?.isUsers}
users={props?.users}
myOffers={props?.myOffers}
/>
{props?.skeleton &&
arrayForMapping.map((item, index) => (

+ 6
- 2
src/components/MarketPlace/Offers/OffersList/OffersList.js 查看文件

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

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

+ 1
- 1
src/components/Modals/EditCategory/EditCategory.js 查看文件

@@ -56,7 +56,7 @@ const EditCategory = (props) => {
};

const handleApiResponseSuccess = () => {
if (clickedOnNext) {
if (clickedOnNext && props?.showSecondButton) {
formik.resetForm();
inputRef.current.focus();
} else closeModalHandler();

+ 23
- 9
src/components/Popovers/MyMessages/MyMessages.js 查看文件

@@ -9,6 +9,8 @@ import HeaderPopover from "../HeaderPopover/HeaderPopover";
import PropTypes from "prop-types";
import { makeErrorToastMessage } from "../../../store/utils/makeToastMessage";
import { EyeIcon } from "./MyMessages.styled";
import { DIRECT_CHAT_PAGE } from "../../../constants/pages";
import { replaceInRoute } from "../../../util/helpers/routeHelpers";

export const MyMessages = (props) => {
const { t } = useTranslation();
@@ -20,13 +22,16 @@ export const MyMessages = (props) => {

const convertMessages = (messages) => {
return messages
.map((item) => ({
src: item.interlocutorData.image,
title: item.interlocutorData.name,
onClick: () => goToMessage(item?.chat?._id),
text: "Proizvod: ",
bigText: item.offerData.name,
}))
.map((item) => {
let interlocutor = userId === item.participants[0]._id ? 1 : 0;
return {
src: item.participants[interlocutor]?.image,
title: item.participants[interlocutor]?.company?.name,
onClick: () => goToMessage(item?._id),
text: "Proizvod: ",
bigText: item.offer.name,
};
})
.slice(0, 2);
};

@@ -42,7 +47,12 @@ export const MyMessages = (props) => {
}, [chats]);
const goToMessages = () => {
if (lastChats.length !== 0) {
history.push(`/messages/${chats[0].chat?._id}`);
console.log(chats);
history.push({
pathname: replaceInRoute(DIRECT_CHAT_PAGE, {
chatId: chats[0]._id,
}),
});
props.closePopover();
} else {
makeErrorToastMessage(t("messages.noMessagesToast"));
@@ -50,7 +60,11 @@ export const MyMessages = (props) => {
}
};
const goToMessage = (chatId) => {
history.push(`/messages/${chatId}`);
history.push(
replaceInRoute(DIRECT_CHAT_PAGE, {
chatId,
})
);
props.closePopover();
};
return (

+ 7
- 2
src/components/Popovers/MyPosts/MyPosts.js 查看文件

@@ -8,8 +8,9 @@ import { selectMineHeaderOffers } from "../../../store/selectors/offersSelectors
import { fetchMineHeaderOffers } from "../../../store/actions/offers/offersActions";
import { selectProfileName } from "../../../store/selectors/profileSelectors";
import { useHistory } from "react-router-dom";
import { MY_OFFERS_PAGE } from "../../../constants/pages";
import { ITEM_DETAILS_PAGE, MY_OFFERS_PAGE } from "../../../constants/pages";
import { useMemo } from "react";
import { replaceInRoute } from "../../../util/helpers/routeHelpers";

export const MyPosts = (props) => {
const { t } = useTranslation();
@@ -59,7 +60,11 @@ export const MyPosts = (props) => {
}, [arrayOfMineOffers, mineOffers]);

const goToOffer = (id) => {
history.push(`/proizvodi/${id}`);
history.push(
replaceInRoute(ITEM_DETAILS_PAGE, {
offerId: id,
})
);
props.closePopover();
};
const goToMySwaps = () => {

+ 11
- 4
src/components/Profile/ProfileOffers/ProfileOffers.js 查看文件

@@ -54,6 +54,12 @@ const ProfileOffers = (props) => {
const dispatch = useDispatch();
const searchRef = useRef(null);

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

useEffect(() => {
dispatch(
fetchProfileOffers({
@@ -62,6 +68,7 @@ const ProfileOffers = (props) => {
sortOption: sortOption,
append: isMobile && append,
page: paging.currentPage,
isAdmin: props?.isAdmin,
})
);
setAppend(true);
@@ -107,14 +114,14 @@ const ProfileOffers = (props) => {
<ProfileOffersHeaderSkeleton />
{isMobile ? (
<SkeletonContainer>
<SkeletonOfferCard vertical />
<SkeletonOfferCard vertical />
<SkeletonOfferCard vertical />
<SkeletonOfferCard vertical skeleton />
<SkeletonOfferCard vertical skeleton />
<SkeletonOfferCard vertical skeleton />
</SkeletonContainer>
) : (
<>
{arrayForMapping.map((item, index) => (
<SkeletonOfferCard key={index} />
<SkeletonOfferCard key={index} skeleton />
))}
</>
)}

+ 17
- 13
src/components/UserReviews/ReviewsSorting/ReviewsSorting.js 查看文件

@@ -19,13 +19,11 @@ const ReviewsSorting = forwardRef((props, ref) => {
const [value, setValue] = useState();
const changeValue = (event) => {
if (props.isAdmin) {
// if(event.target.value.value === 1) {
// dispatch(setReviews(reviews.givenReviews));
// } else {
// dispatch(setReviews(reviews.receivedReviews));
// }


// if(event.target.value.value === 1) {
// dispatch(setReviews(reviews.givenReviews));
// } else {
// dispatch(setReviews(reviews.receivedReviews));
// }
} else {
dispatch(
setReviews(
@@ -42,19 +40,25 @@ const ReviewsSorting = forwardRef((props, ref) => {
const sortEnum = useMemo(() => {
if (props.isAdmin) return sortAdminEnum;
return reviewSortEnum;
});
}, [props.isAdmin]);

const initialSortOption = useMemo(() => {
if (props.isAdmin) return sortAdminEnum.GIVEN;
return reviewSortEnum.INITIAL;
}, [props.isAdmin]);

useImperativeHandle(ref, () => ({
sortValue: value,
hasGivenReview: value?.value === sortAdminEnum.GIVEN.value
}))
hasGivenReview: value?.value === sortAdminEnum.GIVEN.value,
}));
return (
<HeaderSelect
value={value || sortEnum.INITIAL}
value={value || initialSortOption}
IconComponent={DownArrowIcon}
onChange={changeValue}
>
<SelectOption style={{ display: "none" }} value={sortEnum.INITIAL}>
{sortEnum.INITIAL.mainText}
<SelectOption style={{ display: "none" }} value={initialSortOption}>
{initialSortOption.mainText}
</SelectOption>
{Object.keys(sortEnum).map((property) => {
if (sortEnum[property].value === 0) return;

+ 70
- 52
src/components/UserReviews/UserReviews.js 查看文件

@@ -17,21 +17,19 @@ import { useDispatch, useSelector } from "react-redux";
import { selectOffer } from "../../store/selectors/offersSelectors";
import { selectSelectedReviews } from "../../store/selectors/reviewSelector";
import { useRouteMatch } from "react-router-dom";
import {
fetchReviews,
setReviews,
fetchReviewsAsAdmin,
} from "../../store/actions/review/reviewActions";
import { fetchReviews } from "../../store/actions/review/reviewActions";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import SkeletonUserReviews from "./SkeletonUserReviews/SkeletonUserReviews";
import { ONE_OFFER_SCOPE } from "../../store/actions/offers/offersActionConstants";
import {
REVIEW_GET_SCOPE,
REVIEW_GET_AS_ADMIN_SCOPE,
} from "../../store/actions/review/reviewActionConstants";
import { REVIEW_GET_SCOPE } from "../../store/actions/review/reviewActionConstants";
import ReviewsSorting from "./ReviewsSorting/ReviewsSorting";
import { sortReviews } from "../../util/helpers/reviewsHelper";
// import { selectUserId } from "../../store/selectors/loginSelectors";
import { dynamicRouteMatches } from "../../util/helpers/routeHelpers";
import {
ADMIN_SINGLE_USER_PAGE,
DIRECT_CHAT_PAGE,
PROFILE_PAGE,
} from "../../constants/pages";
import { selectUserId } from "../../store/selectors/loginSelectors";

const UserReviews = (props) => {
const [isGiven, setIsGiven] = useState(true);
@@ -42,58 +40,73 @@ const UserReviews = (props) => {
const dispatch = useDispatch();
const listRef = useRef(null);
const sortRef = useRef(null);
// const userId = useSelector(selectUserId);
const mineUserId = useSelector(selectUserId);

const isLoadingReview = useSelector(
selectIsLoadingByActionType(
props.isAdmin
? REVIEW_GET_AS_ADMIN_SCOPE
: props.isProfileReviews
? REVIEW_GET_SCOPE
: ONE_OFFER_SCOPE
props.givingReview ? ONE_OFFER_SCOPE : REVIEW_GET_SCOPE
)
);

const userId = useMemo(() => {
if (
dynamicRouteMatches(PROFILE_PAGE) ||
dynamicRouteMatches(ADMIN_SINGLE_USER_PAGE)
) {
return routeMatch.params.profileId;
}
if (dynamicRouteMatches(DIRECT_CHAT_PAGE)) {
return mineUserId;
}
return offer?.user?._id;
}, [offer, routeMatch.params]);

useEffect(() => {
let idProfile = routeMatch.params?.profileId;
if (idProfile) {
if (props.isAdmin) {
dispatch(fetchReviewsAsAdmin(idProfile));
} else {
dispatch(fetchReviews(idProfile));
}
if (!props?.givingReview && userId) {
dispatch(fetchReviews(userId));
}
}, [props.givingReview, userId]);

// if (props.profileReviews && routeMatch.params?.profileId) {
// let idProfile = routeMatch.params?.profileId;
// dispatch(fetchReviews(idProfile));
// }
}, [props.profileReviews, routeMatch]);
console.log(props);
const lastThreeReviews = useMemo(() => {
if (props.isAdmin) {
if (isGiven) {
return reviews.givenReviews;
} else {
return reviews.receivedReviews;
}
if (props.givingReview) return [props.givingReview];
if (props.isProfileReviews && Array.isArray(reviews) && !props.isAdmin) {
return reviews.filter((singleReview) => {
let userWhoRecievedReview =
singleReview?.exchange?.buyer?.user?._id === singleReview?.user?._id
? "seller"
: "buyer";
return (
singleReview?.exchange[userWhoRecievedReview]?.user?._id === userId
);
});
}
if (props.isProfileReviews) {
return reviews;
}
if (props.givingReview) {
return [...props.profileReviews];
}
if (offer?.companyData?.lastThreeReviews) {
// Making array of reviews in same order(sorting) so when comparing
// them, I can make valid condition
if (
JSON.stringify(sortReviews(reviews)) !==
JSON.stringify(sortReviews(offer?.companyData?.lastThreeReviews))
) {
dispatch(setReviews([...offer?.companyData.lastThreeReviews]));
}
return [...offer?.companyData?.lastThreeReviews];
if (Array.isArray(reviews)) {
return reviews.reduce((result, singleReview) => {
let userWhoGaveReview =
singleReview?.exchange?.buyer?.user?._id === singleReview?.user?._id
? "buyer"
: "seller";
let userWhoRevievedReview =
userWhoGaveReview === "buyer" ? "seller" : "buyer";
if (props.isAdmin) {
if (isGiven) {
if (
userId === singleReview?.exchange[userWhoGaveReview]?.user?._id
) {
result.push(singleReview);
}
} else {
if (
userId ===
singleReview?.exchange[userWhoRevievedReview]?.user?._id
) {
result.push(singleReview);
}
}
}
return result;
}, []);
}
return [];
}, [props.profileReviews, offer, props.isProfileReviews, reviews, isGiven]);
@@ -110,7 +123,10 @@ const UserReviews = (props) => {
};

return (
<UserReviewsContainer className={props.className}>
<UserReviewsContainer
className={props.className}
givingReview={props.givingReview}
>
{!props.givingReview &&
(isLoadingReview || isLoadingReview === undefined) ? (
<SkeletonUserReviews />
@@ -149,6 +165,8 @@ const UserReviews = (props) => {
showRemoveIcon={props.isAdmin}
review={review}
key={index}
isProfileReviews={props?.isProfileReviews}
userId={userId}
isAdmin={props.isAdmin}
hasGivenReview={isGiven}
givingReview={props.givingReview}

+ 5
- 2
src/components/UserReviews/UserReviews.styled.js 查看文件

@@ -5,7 +5,9 @@ import ThumbDownIcon from "@mui/icons-material/ThumbDown";
import selectedTheme from "../../themes";
import { ReactComponent as DownArrow } from "../../assets/images/svg/up-arrow.svg";

export const UserReviewsContainer = styled(Box)``;
export const UserReviewsContainer = styled(Box)`
${(props) => props.givingReview && `overflow: hidden;`}
`;

export const ReviewsBox = styled(Box)`
width: 100%;
@@ -34,7 +36,8 @@ export const ReviewsBox = styled(Box)`
: "350px"};
padding: 0;
width: 100%;
margin: 0 ${(props) => (props.isAdmin ? "18px" : "0")};
margin: 0
${(props) => (props.isAdmin && props.isProfileReviews ? "18px" : "0")};
margin-top: 60px;
}
`;

+ 1
- 0
src/constants/chatConstants.js 查看文件

@@ -0,0 +1 @@
export const NEW_CHAT = "newChat"

+ 1
- 1
src/constants/requesterStatus.js 查看文件

@@ -1,5 +1,5 @@
export default {
NOONE: 0,
ME: 1,
INTERLUCATOR: 2
interlocutor: 2
}

+ 4
- 4
src/hooks/useOffers/useCategoryFilter.js 查看文件

@@ -21,11 +21,11 @@ const useCategoryFilter = () => {

// Set selected category locally in state
// If second argument is true, then selected category is also updated in redux
const setSelectedCategory = (category, immediateApply = false) => {
const setSelectedCategory = (category) => {
setSelectedCategoryLocally(category);
if (immediateApply) {
dispatch(setFilteredCategory(category));
}
// if (immediateApply) {
// dispatch(setFilteredCategory(category));
// }
};

// Find category object by providing its name

+ 1
- 1
src/hooks/useOffers/useFilters.js 查看文件

@@ -4,7 +4,7 @@ import useCompaniesFilter from "./useCompanyFilter";
import useLocationsFilter from "./useLocationsFilter";
import useSubcategoryFilter from "./useSubcategoryFilter";

const useFilters = (clearAll = false, applyFilters) => {
const useFilters = (clearAll = false, applyFilters = () => {}) => {
const category = useCategoryFilter();
const subcategory = useSubcategoryFilter(applyFilters);
const locations = useLocationsFilter();

+ 9
- 6
src/hooks/useOffers/useMyOffers.js 查看文件

@@ -9,6 +9,10 @@ import useSearch from "./useSearch";
import useSorting from "./useSorting";

const useMyOffers = () => {
const applyFilters = () => {
paging.changePage(1);
setAppliedFilters(false);
};
const filters = useFilters(true);
const sorting = useSorting();
const mineOffers = useSelector(selectMineOffers);
@@ -20,6 +24,10 @@ const useMyOffers = () => {

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

const clear = () => {
@@ -27,11 +35,6 @@ const useMyOffers = () => {
setAppliedFilters(false);
}

const apply = () => {
paging.changePage(1);
setAppliedFilters(false);
};

// Filter, search and sort all mine offers
const allOffersToShow = useMemo(() => {
let mineOffersFiltered = [...mineOffers];
@@ -100,7 +103,7 @@ const useMyOffers = () => {
search,
allOffersToShow,
totalOffers,
apply,
applyFilters,
clear,
};
};

+ 3
- 4
src/hooks/useOffers/useOffers.js 查看文件

@@ -140,17 +140,17 @@ const useOffers = () => {
const applyFilters = () => {
setFiltersCleared(true);
};
const clearFiltersAndApply = () => {
clear();
setFiltersCleared(true);
};
const applySorting = () => {
paging.changePage(1);
setFiltersCleared(true);
};
const applySearch = () => {
paging.changePage(1);
setFiltersCleared(true);
@@ -172,7 +172,6 @@ const useOffers = () => {
const clearOnlyFiltersAndApply = () => {
filters.clear();
paging.changePage(1);

setFiltersCleared(true);
};


+ 9
- 1
src/hooks/useOffers/useSearch.js 查看文件

@@ -16,6 +16,7 @@ import { routeMatches } from "../../util/helpers/routeHelpers";
const useSearch = (applyAllFilters) => {
const [searchStringLocally, setSearchStringLocally] = useState("");
const [isInitallyLoaded, setIsInitiallyLoaded] = useState(false);
const [appliedSearch, setAppliedSearch] = useState(false);
const dispatch = useDispatch();
const searchString = useSelector(selectSearchString);
const history = useHistory();
@@ -47,6 +48,13 @@ const useSearch = (applyAllFilters) => {
}
}, [history.location.pathname]);

useEffect(() => {
if (appliedSearch) {
applyAllFilters();
setAppliedSearch(false);
}
}, [appliedSearch]);

// On every local change of search string, global state of search string should be also updated
useEffect(() => {
if (isInitallyLoaded && applyAllFilters) {
@@ -62,7 +70,7 @@ const useSearch = (applyAllFilters) => {
const searchOffersImmediately = (searchValue) => {
setIsInitiallyLoaded(true);
searchOffers(searchValue);
applyAllFilters();
setAppliedSearch(true);
};

const setSearchStringManually = (searchValue) => {

+ 7
- 3
src/hooks/useOffers/useSubcategoryFilter.js 查看文件

@@ -3,7 +3,7 @@ import { useDispatch, useSelector } from "react-redux";
import { setFilteredSubcategory } from "../../store/actions/filters/filtersActions";
import { selectSelectedSubcategory } from "../../store/selectors/filtersSelectors";

const useSubcategoryFilter = (applyFilters) => {
const useSubcategoryFilter = (applyFilters = () => {}) => {
const selectedSubcategory = useSelector(selectSelectedSubcategory);
const dispatch = useDispatch();
const initialOption = {
@@ -31,12 +31,16 @@ const useSubcategoryFilter = (applyFilters) => {
const setSelectedSubcategory = (subcategory) => {
setSelectedSubcategoryLocally(subcategory);
// if (immediateApply) {
dispatch(setFilteredSubcategory(subcategory));
dispatch(setFilteredSubcategory(subcategory));
// }
};

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

const clear = () => {

+ 0
- 19
src/hooks/useSearch.js 查看文件

@@ -1,19 +0,0 @@
// import useQueryString from "./useOffers/useQueryString";

export const useSearch = () => {
// const queryStringHook = useQueryString();
const searchOffers = () => {
// if (searchString?.length !== 0) {
// queryStringHook.appendToQueryString("oname", searchString);
// } else {
// const newQueryString = new URLSearchParams(queryStringHook.queryString);
// if (newQueryString.has("oname")) {
// queryStringHook.deleteFromQueryString("oname");
// }
// }
};

return {
searchOffers,
};
};

+ 2
- 0
src/i18n/resources/rs.js 查看文件

@@ -263,7 +263,9 @@ export default {
acceptedRequest: "Prihvaćeno",
declineRequest: "Odbij",
requestSuccessfulLong: "Uspešno ste ostvarili trampu sa ovom kompanijom.",
requestSuccessfulShort: "Uspešno ste otvarili trampu.",
requestSentLong: "Ponudili ste trampu kompaniji. Čeka se odgovor...",
requestSentShort: "Ponudili ste trampu kompaniji.",
},
editProfile: {
website: "Web Sajt",

+ 6
- 1
src/initialValues/createOfferInitialValues/secondPartCreateOfferInitialValues.js 查看文件

@@ -1,4 +1,9 @@
export default (informations, offer, 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",
});

+ 1
- 1
src/layouts/ProfileLayout/ProfileLayout.js 查看文件

@@ -17,7 +17,7 @@ const ProfileLayout = (props) => {
{props.children}
<ContentRightCardContainer container spacing={2}>
<Content sm={12} md={8} lg={8} xl={9} item>{props.content}</Content>
<RightCard sm={0} md={4} lg={4} xl={3} item singleOffer={props.singleOffer} profile={props.profile}>
<RightCard sm={12} md={4} lg={4} xl={3} item singleOffer={props.singleOffer} profile={props.profile}>
{props.rightCard}
</RightCard>
</ContentRightCardContainer>

+ 2
- 2
src/layouts/ProfileLayout/ProfileLayout.styled.js 查看文件

@@ -12,7 +12,7 @@ export const ProfileLayoutContainer = styled(Container)`
/* flex: 1; */
height: 100%;
@media (max-width: 1350px) {
padding-right: ${props => props.isAdmin ? "36px" : "0"};
padding-right: ${(props) => (props.isAdmin ? "36px" : "0")};
}
@media (max-width: 600px) {
padding-left: 0;
@@ -31,7 +31,6 @@ export const RightCard = styled(Grid)`
padding-left: 0;
${(props) => props.profile && `min-width: 350px;`}

@media screen and (min-width: 600px) {
margin-top: 34px;
margin-left: ${(props) => (props.profile ? "0" : "36px")};
@@ -44,6 +43,7 @@ export const RightCard = styled(Grid)`
margin-left: 0;
}
@media (max-width: 600px) {
width: 100%;
min-width: 0;
}
`;

+ 0
- 23
src/notFoundData/itemDetailsData.js 查看文件

@@ -2,28 +2,6 @@ import i18next from "i18next";
import defaultImage from "../constants/defaultImage";

export default {
companyData: {
company: {
PIB: i18next.t("notFoundData.PIB"),
name: i18next.t("notFoundData.companyName")
},
image: defaultImage,
lastThreeReviews: [],
statistics: {
exchanges: {
failed: 0,
succeeded: 0,
total: 0,
},
publishes: {
count: 0,
},
views: {
count: 0,
}
}
},
offer: {
category: {
name: i18next.t("notFoundData.categoryName")
},
@@ -43,5 +21,4 @@ export default {
count: 0
},
_created: new Date().toString()
}
}

+ 1
- 1
src/pages/AdminHomePage/AdminItemDetailsPage/AdminItemDetailsPage.js 查看文件

@@ -42,7 +42,7 @@ const AdminItemDetailsPage = (props) => {
content={<ItemDetails singleOffer isAdmin />}
rightCard={
<>
<ProfileMini /> <UserReviews rightReviews />
<ProfileMini /> <UserReviews isAdmin rightReviews />
</>
}
/>

+ 5
- 5
src/pages/AdminHomePage/AdminLocationsPage/AdminLocationsPage.styled.js 查看文件

@@ -15,19 +15,19 @@ export const AdminLocationsPageContainer = styled(Box)`
padding: 18px;
min-height: (100vh - 72px);
padding-bottom: 100px;
top: 65px;
top: 38px;
}
`;
export const AdminLocationsHeader = styled(Header)`
top: 0;
@media (max-width: 600px) {
top: -5px;
top: 0px;
margin-top: 0px;
& > div {
margin-top: -10px;
margin-top: 0px;
}
& > div > div > div:nth-child(1) {
top: 15px;
& > div > div > div {
top: 25px;
left: 0;
}
}

+ 0
- 1
src/pages/HomePage/HomePage.js 查看文件

@@ -17,7 +17,6 @@ const HomePage = () => {
const toggleFilters = () => {
setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened);
};

return (
<HomePageContainer>
<MainLayout

+ 4
- 1
src/pages/ItemDetailsPage/ItemDetailsPageMUI.js 查看文件

@@ -11,6 +11,7 @@ import {
import UserReviews from "../../components/UserReviews/UserReviews";
import { selectOffer } from "../../store/selectors/offersSelectors";
import ProfileMini from "../../components/ProfileMini/ProfileMini";
import history from "../../store/utils/history";

const ItemDetailsPage = (props) => {
const dispatch = useDispatch();
@@ -19,7 +20,9 @@ const ItemDetailsPage = (props) => {
const offerId = props.match.params.offerId;

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


+ 4
- 3
src/request/apiEndpoints.js 查看文件

@@ -166,7 +166,7 @@ export default {
setFingerprint: "/affiliate/fingerprint",
},
offers: {
getOneOffer: "offers",
getOneOffer: "offers/{offerId}",
getOffers: "offers",
getFeaturedOffers: "offers/featured",
addOffer: "/users/{userId}/offers",
@@ -176,13 +176,14 @@ export default {
locations: "locations",
mineOffers: "users",
profileOffers: "users/{userId}/offers",
profileOffersAsAdmin: "admin/users/{userId}/offers",
removeOffer: "/users/{userId}/offers/{offerId}",
removeOfferAsAdmin: "/admin/offers/{offerId}",
pinOffer: "admin/offers/{id}/pin",
},
chat: {
getChat: "chats",
getUserChats: "users/{userId}/chat",
getUserChats: "users/{userId}/chats",
getOneChat: "users/{userId}/chats/{chatId}",
createChat: "users/{userId}/offers/{offerId}/chat",
sendMessage: "chats",
@@ -190,7 +191,7 @@ export default {
exchange: {
getExchange: "exchanges",
validateExchange: "exchanges",
acceptExchange: "users/{userId}/exchanges/{exchangeId}/accept"
acceptExchange: "users/{userId}/exchanges/{exchangeId}/accept",
},
reviews: {
getUserReviews: "/users/{userId}/reviews",

+ 3
- 3
src/request/index.js 查看文件

@@ -1,5 +1,5 @@
import axios from "axios";
import queryString from "qs";
// import queryString from "qs";

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

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

+ 13
- 2
src/request/offersRequest.js 查看文件

@@ -18,8 +18,12 @@ export const attemptFetchFeaturedOffers = (payload) => {
return getRequest(apiEndpoints.offers.getOffers);
};
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) => {
if (payload)
@@ -42,6 +46,13 @@ export const attemptFetchProfileOffers = (userId, queryString = "") => {
}) + `?${queryString}`
);
};
export const attemptFetchProfileOffersAsAdmin = (userId, queryString = "") => {
return getRequest(
replaceInUrl(apiEndpoints.offers.profileOffersAsAdmin, {
userId: userId,
}) + `?${queryString}`
);
};
export const attemptRemoveOffer = (payload, offerId) => {
return deleteRequest(
replaceInUrl(apiEndpoints.offers.removeOffer, {

+ 16
- 7
src/socket/socket.js 查看文件

@@ -1,8 +1,8 @@
import io from "socket.io-client";

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"],
reconnectionAttempts: 5,
});
@@ -20,25 +20,34 @@ export const sendMessage = (chatId, userId, text, receiverUserId) => {
chatId,
receiverUserId,
message: {
userId,
user: {
_id: userId,
},
text,
},
});
};
export const acceptExchangeSocket = (chatId, userId, receiverUserId, callbackFn) => {
export const acceptExchangeSocket = (
chatId,
userId,
receiverUserId,
callbackFn
) => {
socket.emit("private_message", {
chatId,
receiverUserId,
message: {
userId,
user: {
_id: userId
},
isAcceptRequest: true,
text: ""
text: "",
},
});
callbackFn();
};

export const addMesageListener = (listener) => {
export const addMessageListener = (listener) => {
socket.on("private_message", (data) =>
listener({
succeed: true,

+ 1
- 0
src/store/middleware/accessTokensMiddleware.js 查看文件

@@ -40,6 +40,7 @@ export default ({ dispatch }) =>
// If refresh token is expired, log out user
if (new Date() > new Date(refreshTokenDecoded?.exp * 1000)) {
dispatch(logoutUser());
return Promise.resolve(response)
}
// If access token is expired, refresh access token
if (new Date() > new Date(jwtTokenDecoded.exp * 1000)) {

+ 6
- 14
src/store/reducers/chat/chatReducer.js 查看文件

@@ -33,7 +33,7 @@ function setChats(state, action) {
function setChatsTotal(state, action) {
return {
...state,
total: action.payload
total: action.payload,
};
}
function setOneChat(state, action) {
@@ -47,26 +47,18 @@ function clearChats() {
}
function addNewMessage(state, { payload }) {
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) {
chat = {
...chat,
chat: {
...chat.chat,
messages: [...chat.chat.messages, payload.message],
},
messages: [...chat.messages, payload.message],
};
allChats = allChats.filter((item) => item.chat._id !== chat.chat._id);
allChats = allChats.filter((item) => item._id !== chat._id);
allChats = [chat, ...allChats];
}
let newSelectedChat = {};
if (state.selectedChat.chat) {
newSelectedChat = { ...state.selectedChat };
if (newSelectedChat.chat._id === chat.chat._id)
newSelectedChat = { ...newSelectedChat, chat: chat.chat };
} else {
newSelectedChat = { ...chat };
}
if (state.selectedChat.chat) newSelectedChat = { ...state.selectedChat };
newSelectedChat = { ...chat };
return {
...state,
latestChats: [...allChats],

+ 0
- 0
src/store/saga/chatSaga.js 查看文件


部分文件因为文件数量过多而无法显示

正在加载...
取消
保存