Browse Source

Merge branch 'feature/609' of http://git.dilig.net/selenaaasi/trampa-frontend

feature/618
Djordje Mitrovic 3 years ago
parent
commit
2d6c229cc0
33 changed files with 531 additions and 286 deletions
  1. 5
    120
      src/App.js
  2. 3
    1
      src/components/Cards/ChatCard/ChatCard.js
  3. 11
    1
      src/components/Cards/ChatCard/LittleOfferDetails/LittleOfferDetails.js
  4. 3
    3
      src/components/Cards/CreateOfferCard/CreateOffer.js
  5. 15
    6
      src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js
  6. 39
    23
      src/components/Cards/LittleOfferCard/LittleOfferCard.js
  7. 7
    1
      src/components/Cards/MessageCard/MessageCard.js
  8. 11
    1
      src/components/Cards/MiniChatCard/MiniChatCard.js
  9. 11
    1
      src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.js
  10. 12
    1
      src/components/Cards/OfferCard/OfferCard.js
  11. 5
    1
      src/components/Cards/UserReviewsCard/UserReviewsCard.js
  12. 12
    1
      src/components/ChatColumn/ChatColumn.js
  13. 22
    2
      src/components/DirectChat/DirectChat.js
  14. 6
    4
      src/components/DirectChat/DirectChatContent/DirectChatContent.js
  15. 15
    6
      src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.js
  16. 50
    12
      src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js
  17. 1
    1
      src/components/Header/Header.js
  18. 32
    14
      src/components/ImagePicker/ImagePicker.js
  19. 11
    1
      src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js
  20. 1
    0
      src/components/MarketPlace/Offers/OffersNotFound.styled.js
  21. 5
    2
      src/components/Popovers/HeaderPopover/HeaderPopover.js
  22. 11
    1
      src/components/ProfileCard/ProfileMainInfo/ProfileMainInfo.js
  23. 5
    1
      src/pages/RegisterPages/Register/Register.js
  24. 1
    0
      src/request/index.js
  25. 31
    0
      src/socket/socket.js
  26. 1
    0
      src/store/actions/chat/chatActionConstants.js
  27. 5
    1
      src/store/actions/chat/chatActions.js
  28. 3
    1
      src/store/middleware/accessTokensMiddleware.js
  29. 51
    22
      src/store/reducers/chat/chatReducer.js
  30. 45
    5
      src/store/saga/offersSaga.js
  31. 45
    29
      src/store/saga/profileSaga.js
  32. 14
    24
      src/store/saga/registerSaga.js
  33. 42
    0
      src/util/helpers/imageUrlGetter.js

+ 5
- 120
src/App.js View File

/*eslint-disable*/ /*eslint-disable*/
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import io from "socket.io-client";
import { Router } from "react-router-dom"; import { Router } from "react-router-dom";
import { Helmet } from "react-helmet-async"; import { Helmet } from "react-helmet-async";
import i18next from "i18next"; import i18next from "i18next";
import GlobalStyle from "./components/Styles/globalStyles"; import GlobalStyle from "./components/Styles/globalStyles";
import { ToastContainer } from "react-toastify"; import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import { socketInit } from "./socket/socket";
import { useSelector } from "react-redux";
import { selectUserId } from "./store/selectors/loginSelectors";


const URL = "https://trampa-api-test.dilig.net";
const socket2 = io("https://trampa-api-test.dilig.net", { autoConnect: true, reconnectionAttempts: 5 });
const socket = io("https://trampa-api-test.dilig.net", {
autoConnect: true,
transports: ["websocket"],
reconnectionAttempts: 5,
});
const socket4 = io("https://trampa-api-test.dilig.net", { autoConnect: true, reconnectionAttempts: 5 });
const socket3 = io("https://trampa-api-test.dilig.net", {
autoConnect: true,
transports: ["websocket"],
reconnectionAttempts: 5,
});
const App = () => { const App = () => {
console.log(socket);
console.log(socket2);
const userId = useSelector(selectUserId);


const [isConnected, setIsConnected] = useState(socket.connected);
const [lastPong, setLastPong] = useState(null);
console.log();
useEffect(() => {
socket.auth = {
// userId: "62de57c6dff6f986e43d14ec",
userId: "62ff762554ec55060e3a456b",
sessionID: localStorage.getItem("sessionID"),
};
socket.on("connect", (client) => {
console.log("client: ", client);
setIsConnected(true);
});
socket2.on("connect", (client) => {
console.log("client: ", client);
setIsConnected(true);
});
socket3.on("connect", (client) => {
console.log("client: ", client);
setIsConnected(true);
});
socket4.on("connect", (client) => {
console.log("client: ", client);
setIsConnected(true);
});
socket.on("session", ({ sessionID, userID }) => {
localStorage.setItem("sessionID", sessionID);
localStorage.setItem("userID", userID);
console.log("sessionID: ", sessionID);
console.log("userID: ", userID);
});
// socket.on("connect_error", (err) => {
// console.log(err);
// });
socketInit(userId);


socket.on("connection", (client) => {
console.log(client);
});

socket.on("disconnect", () => {
setIsConnected(false);
});

// socket.on("user disconnected", (userID) => {
// console.log(userID);
// });

// // socket.on('emit', (client) => {
// // console.log(client);
// // })
// socket.on("sokkk", (clg) => {
// console.log(clg);
// });
// // socket.onAny((event, ...args) => {
// // console.log(event, args);
// // });
// socket.on("povratna", (data) => {
// console.log(data);
// });
// socket.on("private_message", (data) => {
// console.log(data);
// });

// // socket.open;

// socket.on("pong", () => {
// setLastPong(new Date().toISOString());
// });

// // socket.connect();

return () => {
socket.off("connect");
socket.off("disconnect");
socket.off("pong");
socket.off("reconnection_attempt")
};
}, []);
const handleClick = () => {
// socket.connect();
// socket.emit("sokkk 2", "sock");
// socket.emit("sock")
};
const sendPing = () => {
socket.emit("private_message", {
text: "Probica",
// toUserId: "62de5844dff6f986e43d14f6",
toUserId: "62de57c6dff6f986e43d14ec",
chatId: "62eb8424632e1112ef467750",
});
};
const disconnect = () => {
// socket.disconnect();
socket.disconnect();
};
return ( return (
<Router history={history}> <Router history={history}>
<Helmet> <Helmet>
<Header /> <Header />
<GlobalStyle /> <GlobalStyle />
<ToastContainer /> <ToastContainer />
{/* <div style={{ position: "relative", top: "100px", left: "400px" }}>
<p>Connected: {"" + isConnected}</p>
<br />
<p>Last pong: {lastPong || "-"}</p>
<br />
<button onClick={sendPing}>Send ping</button>
<br />
<button onClick={disconnect}>Disconnect</button>
</div> */}
<AppRoutes /> <AppRoutes />
</StyledEngineProvider> </StyledEngineProvider>
</Router> </Router>

+ 3
- 1
src/components/Cards/ChatCard/ChatCard.js View File

import OfferLocation from "./OfferLocation/OfferLocation"; import OfferLocation from "./OfferLocation/OfferLocation";
import ChatCommands from "./ChatCommands/ChatCommands"; import ChatCommands from "./ChatCommands/ChatCommands";
import useIsMobile from "../../../hooks/useIsMobile"; import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const ChatCard = (props) => { const ChatCard = (props) => {
const history = useHistory(); const history = useHistory();
> >
<Col> <Col>
<UserImgWrapper> <UserImgWrapper>
<UserImage src={chat?.interlocutorData?.image} />
{/* <UserImage src={chat?.interlocutorData?.image} /> */}
<UserImage src={getImageUrl(chat?.interlocutorData?.image, variants.chatCard, isMobile)} />
</UserImgWrapper> </UserImgWrapper>


<ChatInfo> <ChatInfo>

+ 11
- 1
src/components/Cards/ChatCard/LittleOfferDetails/LittleOfferDetails.js View File

} from "./LittleOfferDetails.styled"; } from "./LittleOfferDetails.styled";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Col } from "../ChatCard.styled"; import { Col } from "../ChatCard.styled";
import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter";
import useIsMobile from "../../../../hooks/useIsMobile";


const LittleOfferDetails = (props) => { const LittleOfferDetails = (props) => {
const chat = props.chat; const chat = props.chat;
const { t } = useTranslation(); const { t } = useTranslation();
const { isMobile } = useIsMobile();
return ( return (
<Col mobileDisappear> <Col mobileDisappear>
<ChatOffer> <ChatOffer>
<OfferImgWrapper> <OfferImgWrapper>
<OfferImage src={chat?.offerData?.firstImage} />
{/* <OfferImage src={chat?.offerData?.firstImage} /> */}
<OfferImage
src={getImageUrl(
chat?.offerData?.firstImage,
variants.offerCard,
isMobile
)}
/>
</OfferImgWrapper> </OfferImgWrapper>
<OfferCardContainer> <OfferCardContainer>
<OfferText>{t("messages.cardProduct")}</OfferText> <OfferText>{t("messages.cardProduct")}</OfferText>

+ 3
- 3
src/components/Cards/CreateOfferCard/CreateOffer.js View File

.filter((img) => img !== undefined) .filter((img) => img !== undefined)
.map((img) => .map((img) =>
img img
.replace("data:image/jpg;base64,", "")
.replace("data:image/jpeg;base64,", "")
.replace("data:image/png;base64,", "")
// .replace("data:image/jpg;base64,", "")
// .replace("data:image/jpeg;base64,", "")
// .replace("data:image/png;base64,", "")
); );


const offerData = { const offerData = {

+ 15
- 6
src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js View File

import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useScreenDimensions from "../../../../hooks/useScreenDimensions"; import useScreenDimensions from "../../../../hooks/useScreenDimensions";
import { formatDateLocale } from "../../../../util/helpers/dateHelpers"; import { formatDateLocale } from "../../../../util/helpers/dateHelpers";
import useIsMobile from "../../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter";


const OfferDetails = (props) => { const OfferDetails = (props) => {
const offer = props.offer; const offer = props.offer;
const { t } = useTranslation(); const { t } = useTranslation();
const dimension = useScreenDimensions(); const dimension = useScreenDimensions();
const { isMobile } = useIsMobile();
const date = formatDateLocale(new Date(offer?.offer?._created)); const date = formatDateLocale(new Date(offer?.offer?._created));
return ( return (
<Details <Details
> >
{dimension.width < 600 || !props.singleOffer ? ( {dimension.width < 600 || !props.singleOffer ? (
<ScrollerHorizontal> <ScrollerHorizontal>
{offer?.offer?.images?.map((item) => {
return <OfferImage src={item} key={item} />;
})}
{offer?.offer?.images?.map((item) => (
<OfferImage
src={getImageUrl(item, variants.offerCard, isMobile)}
key={item}
/>
))}
</ScrollerHorizontal> </ScrollerHorizontal>
) : ( ) : (
<ScrollerVertical> <ScrollerVertical>
{offer?.offer?.images?.map((item) => {
return <OfferImage src={item} key={item} />;
})}
{offer?.offer?.images?.map((item) => (
<OfferImage
src={getImageUrl(item, variants.offerCard, isMobile)}
key={item}
/>
))}
</ScrollerVertical> </ScrollerVertical>
)} )}
<OfferInfoContainer singleOffer={props.singleOffer}> <OfferInfoContainer singleOffer={props.singleOffer}>

+ 39
- 23
src/components/Cards/LittleOfferCard/LittleOfferCard.js View File

import React from 'react'
import PropTypes from 'prop-types'
import { LittleOfferCardContainer, OfferCategory, OfferCategoryIcon, OfferDetails, OfferImage, OfferName, OfferSwapsIcon, OfferSwapsIconContainer } from './LittleOfferCard.styled'
import React from "react";
import PropTypes from "prop-types";
import {
LittleOfferCardContainer,
OfferCategory,
OfferCategoryIcon,
OfferDetails,
OfferImage,
OfferName,
OfferSwapsIcon,
OfferSwapsIconContainer,
} from "./LittleOfferCard.styled";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const LittleOfferCard = (props) => { const LittleOfferCard = (props) => {
return (
<LittleOfferCardContainer>
<OfferImage src={props.image} />
<OfferDetails>
<OfferName>{props.name}</OfferName>
<OfferCategory>
<OfferCategoryIcon />
{props.categoryName}</OfferCategory>
</OfferDetails>
<OfferSwapsIconContainer>
<OfferSwapsIcon />
</OfferSwapsIconContainer>
</LittleOfferCardContainer>
)
}
const { isMobile } = useIsMobile();
return (
<LittleOfferCardContainer>
{/* <OfferImage src={props.image} /> */}
<OfferImage
src={getImageUrl(props.image, variants.reviewCard, isMobile)}
/>
<OfferDetails>
<OfferName>{props.name}</OfferName>
<OfferCategory>
<OfferCategoryIcon />
{props.categoryName}
</OfferCategory>
</OfferDetails>
<OfferSwapsIconContainer>
<OfferSwapsIcon />
</OfferSwapsIconContainer>
</LittleOfferCardContainer>
);
};


LittleOfferCard.propTypes = { LittleOfferCard.propTypes = {
image: PropTypes.string,
name: PropTypes.string,
categoryName: PropTypes.string,
}
image: PropTypes.string,
name: PropTypes.string,
categoryName: PropTypes.string,
};


export default LittleOfferCard
export default LittleOfferCard;

+ 7
- 1
src/components/Cards/MessageCard/MessageCard.js View File

ProfileImage, ProfileImage,
} from "./MessageCard.styled"; } from "./MessageCard.styled";
import { formatDateTime } from "../../../util/helpers/dateHelpers"; import { formatDateTime } from "../../../util/helpers/dateHelpers";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const MessageCard = (props) => { const MessageCard = (props) => {
const message = props.message; const message = props.message;
const { isMobile } = useIsMobile();


const dateString = formatDateTime(new Date(message._created)); const dateString = formatDateTime(new Date(message._created));
return ( return (
<MessageCardContainer isMyMessage={props.isMyMessage}> <MessageCardContainer isMyMessage={props.isMyMessage}>
<ProfileImage src={props.image} />
{/* <ProfileImage src={props.image} /> */}
<ProfileImage
src={getImageUrl(props.image, variants.chatMessage, isMobile)}
/>
<MessageContent isMyMessage={props.isMyMessage}> <MessageContent isMyMessage={props.isMyMessage}>
<MessageText isMyMessage={props.isMyMessage}> <MessageText isMyMessage={props.isMyMessage}>
{props.message.text} {props.message.text}

+ 11
- 1
src/components/Cards/MiniChatCard/MiniChatCard.js View File

} from "./MiniChatCard.styled"; } from "./MiniChatCard.styled";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const MiniChatCard = (props) => { const MiniChatCard = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const history = useHistory(); const history = useHistory();
const { isMobile } = useIsMobile();
const changeChat = () => { const changeChat = () => {
history.push(`/messages/${props?.chat?.chat?._id}`); history.push(`/messages/${props?.chat?.chat?._id}`);
}; };
return ( return (
<MiniChatCardContainer selected={props.selected} onClick={changeChat}> <MiniChatCardContainer selected={props.selected} onClick={changeChat}>
<ProfileImage src={props?.chat?.interlocutorData?.image} />
{/* <ProfileImage src={props?.chat?.interlocutorData?.image} /> */}
<ProfileImage
src={getImageUrl(
props?.chat?.interlocutorData?.image,
variants.chatCard,
isMobile
)}
/>
<ProfileDetails> <ProfileDetails>
<ProfileName selected={props.selected}> <ProfileName selected={props.selected}>
{props?.chat?.interlocutorData?.name} {props?.chat?.interlocutorData?.name}

+ 11
- 1
src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.js View File

} from "../../../../store/actions/offers/offersActions"; } from "../../../../store/actions/offers/offersActions";
import { useTranslation, Trans } from "react-i18next"; import { useTranslation, Trans } from "react-i18next";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import useIsMobile from "../../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter";


const DeleteOffer = (props) => { const DeleteOffer = (props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const history = useHistory(); const history = useHistory();
const userId = props.offer.userId; const userId = props.offer.userId;
const { isMobile } = useIsMobile();
const offerId = props.offer._id; const offerId = props.offer._id;
const closeDeleteModalHandler = () => { const closeDeleteModalHandler = () => {
props.closeModalHandler(); props.closeModalHandler();
<DeleteOfferContainer> <DeleteOfferContainer>
<OfferInfo> <OfferInfo>
<OfferImageContainer> <OfferImageContainer>
<OfferImage src={props.offer.images[0]} />
{/* <OfferImage src={props.offer.images[0]} /> */}
<OfferImage
src={getImageUrl(
props.offer.images[0],
variants.deleteChat,
isMobile
)}
/>
</OfferImageContainer> </OfferImageContainer>
<OfferDescription> <OfferDescription>
<OfferDescriptionTitle>{props.offer.name}</OfferDescriptionTitle> <OfferDescriptionTitle>{props.offer.name}</OfferDescriptionTitle>

+ 12
- 1
src/components/Cards/OfferCard/OfferCard.js View File

import CreateOffer from "../CreateOfferCard/CreateOffer"; import CreateOffer from "../CreateOfferCard/CreateOffer";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { selectUserId } from "../../../store/selectors/loginSelectors"; import { selectUserId } from "../../../store/selectors/loginSelectors";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const OfferCard = (props) => { const OfferCard = (props) => {
const [deleteOfferModal, setDeleteOfferModal] = useState(false); const [deleteOfferModal, setDeleteOfferModal] = useState(false);
const [editOfferModal, setEditOfferModal] = useState(false); const [editOfferModal, setEditOfferModal] = useState(false);
const history = useHistory(); const history = useHistory();
const userId = useSelector(selectUserId); const userId = useSelector(selectUserId);
const { isMobile } = useIsMobile();


const routeToItem = (itemId) => { const routeToItem = (itemId) => {
history.push(`/proizvodi/${itemId}`); history.push(`/proizvodi/${itemId}`);
<OfferFlexContainer vertical={props.vertical}> <OfferFlexContainer vertical={props.vertical}>
<OfferImageContainer vertical={props.vertical}> <OfferImageContainer vertical={props.vertical}>
<OfferImage <OfferImage
src={props?.offer?.images ? props?.offer?.images[0] : ""}
src={
props?.offer?.images
? getImageUrl(
props?.offer?.images[0],
variants.offerCard,
isMobile
)
: ""
}
vertical={props.vertical} vertical={props.vertical}
></OfferImage> ></OfferImage>
</OfferImageContainer> </OfferImageContainer>

+ 5
- 1
src/components/Cards/UserReviewsCard/UserReviewsCard.js View File

import { ListItem } from "@mui/material"; import { ListItem } from "@mui/material";
import selectedTheme from "../../../themes"; import selectedTheme from "../../../themes";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const UserReviewsCard = (props) => { const UserReviewsCard = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const {isMobile} = useIsMobile()


const review = useMemo(() => { const review = useMemo(() => {
if (props.givingReview) { if (props.givingReview) {
<ReviewContainer key={review?.image}> <ReviewContainer key={review?.image}>
<ListItem alignItems="flex-start" sx={{ alignItems: "center", mt: 2 }}> <ListItem alignItems="flex-start" sx={{ alignItems: "center", mt: 2 }}>
<ProfileImageContainer> <ProfileImageContainer>
<ProfileImage alt={review?.name} src={review?.image} />
{/* <ProfileImage alt={review?.name} src={review?.image} /> */}
<ProfileImage src={getImageUrl(review?.image, variants.reviewCard, isMobile)} />
</ProfileImageContainer> </ProfileImageContainer>
<ProfileName sx={{ color: selectedTheme.primaryPurple }}> <ProfileName sx={{ color: selectedTheme.primaryPurple }}>
<b>{review?.name}</b> <b>{review?.name}</b>

+ 12
- 1
src/components/ChatColumn/ChatColumn.js View File

import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { selectLatestChats } from "../../store/selectors/chatSelectors"; import { selectLatestChats } from "../../store/selectors/chatSelectors";
import { fetchChats } from "../../store/actions/chat/chatActions";
import { addNewMessage, fetchChats } from "../../store/actions/chat/chatActions";
import useSorting from "../../hooks/useOffers/useSorting"; import useSorting from "../../hooks/useOffers/useSorting";
import { addMesageListener, removeMessageListener } from "../../socket/socket";


export const DownArrow = (props) => { export const DownArrow = (props) => {
<IconStyled {...props}> <IconStyled {...props}>
dispatch(fetchChats()); dispatch(fetchChats());
}, []); }, []);


useEffect(() => {
addMesageListener((data) => {
dispatch(addNewMessage({
_id: data.chatId,
message: data.message
}))
});
return () => removeMessageListener();
}, [])

useEffect(() => { useEffect(() => {
setSortOption(sorting.selectedSortOption); setSortOption(sorting.selectedSortOption);
}, [sorting.selectedSortOption]); }, [sorting.selectedSortOption]);

+ 22
- 2
src/components/DirectChat/DirectChat.js View File

import DirectChatHeader from "./DirectChatHeader/DirectChatHeader"; import DirectChatHeader from "./DirectChatHeader/DirectChatHeader";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useLocation, useRouteMatch } from "react-router-dom"; import { useLocation, useRouteMatch } from "react-router-dom";
import { fetchOneChat, setOneChat } from "../../store/actions/chat/chatActions";
import { addNewMessage, fetchOneChat, setOneChat } from "../../store/actions/chat/chatActions";
import { selectSelectedChat } from "../../store/selectors/chatSelectors"; import { selectSelectedChat } from "../../store/selectors/chatSelectors";
import DirectChatContent from "./DirectChatContent/DirectChatContent"; import DirectChatContent from "./DirectChatContent/DirectChatContent";
import { selectOffer } from "../../store/selectors/offersSelectors"; import { selectOffer } from "../../store/selectors/offersSelectors";
import SkeletonDirectChat from "./SkeletonDirectChat/SkeletonDirectChat"; import SkeletonDirectChat from "./SkeletonDirectChat/SkeletonDirectChat";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants"; import { CHAT_SCOPE } from "../../store/actions/chat/chatActionConstants";
import { selectUserId } from "../../store/selectors/loginSelectors";
import { addMesageListener, removeMessageListener } from "../../socket/socket";


const DirectChat = () => { const DirectChat = () => {
const chat = useSelector(selectSelectedChat); const chat = useSelector(selectSelectedChat);
const routeMatch = useRouteMatch(); const routeMatch = useRouteMatch();
const location = useLocation(); const location = useLocation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const userId = useSelector(selectUserId);
const isLoadingDirectChat = useSelector( const isLoadingDirectChat = useSelector(
selectIsLoadingByActionType(CHAT_SCOPE) selectIsLoadingByActionType(CHAT_SCOPE)
); );
}, [chat, location.state]); }, [chat, location.state]);


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


useEffect(() => { useEffect(() => {
} }
}, [routeMatch.params.idChat, location.state?.offerId]); }, [routeMatch.params.idChat, location.state?.offerId]);


useEffect(() => {
addMesageListener((data) => {
dispatch(addNewMessage({
_id: data.chatId,
message: data.message
}))
});
return () => removeMessageListener();
}, [])

const refreshChat = () => { const refreshChat = () => {
if (routeMatch.params.idChat === "newMessage") { if (routeMatch.params.idChat === "newMessage") {
dispatch(fetchOneOffer(location.state.offerId)); dispatch(fetchOneOffer(location.state.offerId));

+ 6
- 4
src/components/DirectChat/DirectChatContent/DirectChatContent.js View File

props.refreshChat(); props.refreshChat();
}; };
useEffect(() => { useEffect(() => {
const offsetBottom =
messagesRef.current?.offsetTop + messagesRef.current?.offsetHeight;
messagesRef.current?.scrollTo({ top: offsetBottom, behaviour: "smooth" });
console.dir(messagesRef.current)
// const offsetBottom =
// messagesRef.current?.offsetTop + messagesRef.current?.offsetHeight;
messagesRef.current?.scrollTo({ top: messagesRef.current.scrollHeight, behaviour: "smooth" });
}, [messages]); }, [messages]);
return ( return (
<> <>
? myProfileImage ? myProfileImage
: interlucatorProfileImage; : interlucatorProfileImage;
return ( return (
<MessageContainer key={item?._id}>
<MessageContainer key={item?._id || item?._created}>
<MessageCard <MessageCard
message={item} message={item}
image={image} image={image}
<DirectChatNewMessage <DirectChatNewMessage
chatId={props?.chat?._id} chatId={props?.chat?._id}
refreshChat={handleRefresh} refreshChat={handleRefresh}
interlucator={props.interlucator}
/> />
</DirectChatContentContainer> </DirectChatContentContainer>
)} )}

+ 15
- 6
src/components/DirectChat/DirectChatContent/DirectChatContentHeader/DirectChatContentHeader.js View File

} from "./DirectChatContentHeader.styled"; } from "./DirectChatContentHeader.styled";
import PopoverComponent from "../../../Popovers/PopoverComponent"; import PopoverComponent from "../../../Popovers/PopoverComponent";
import PhonePopover from "../../../Popovers/PhonePopover/PhonePopover"; import PhonePopover from "../../../Popovers/PhonePopover/PhonePopover";
import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter";
import useIsMobile from "../../../../hooks/useIsMobile";


const DirectChatContentHeader = (props) => { const DirectChatContentHeader = (props) => {
const [showPhonePopover, setShowPhonePopover] = useState(false); const [showPhonePopover, setShowPhonePopover] = useState(false);
const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null); const [phonePopoverAnchorEl, setPhonePopoverAnchorEl] = useState(null);
const { isMobile } = useIsMobile();


const togglePhonePopover = (event) => { const togglePhonePopover = (event) => {
console.log(event);
setShowPhonePopover(true);
setPhonePopoverAnchorEl(event.currentTarget);
}
console.log(event);
setShowPhonePopover(true);
setPhonePopoverAnchorEl(event.currentTarget);
};


return ( return (
<DirectChatContentHeaderContainer> <DirectChatContentHeaderContainer>
<DirectChatContentHeaderFlexContainer> <DirectChatContentHeaderFlexContainer>
<ProfileImage src={props?.interlucator?.image} />
{/* <ProfileImage src={props?.interlucator?.image} /> */}
<ProfileImage
src={getImageUrl(
props?.interlucator?.image,
variants.chatHeader,
isMobile
)}
/>
<ProfileDetails> <ProfileDetails>
<ProfileName>{props?.interlucator?.name}</ProfileName> <ProfileName>{props?.interlucator?.name}</ProfileName>
<ProfileLocation> <ProfileLocation>

+ 50
- 12
src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js View File

import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import selectedTheme from "../../../themes"; import selectedTheme from "../../../themes";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
// import {
// fetchChats,
// startNewChat,
// } from "../../../store/actions/chat/chatActions";
// import { useHistory, useLocation } from "react-router-dom";
import { sendMessage } from "../../../socket/socket";
import { useSelector } from "react-redux";
import { selectUserId } from "../../../store/selectors/loginSelectors";
import { import {
addNewMessage,
fetchChats, fetchChats,
sendMessage,
startNewChat, startNewChat,
} from "../../../store/actions/chat/chatActions"; } from "../../../store/actions/chat/chatActions";
import { useHistory, useLocation } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
// import { selectUserId } from "../../../store/selectors/loginSelectors";


const DirectChatNewMessage = (props) => { const DirectChatNewMessage = (props) => {
const [typedValue, setTypedValue] = useState(""); const [typedValue, setTypedValue] = useState("");
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);
console.log(props);
const dispatch = useDispatch(); const dispatch = useDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const location = useLocation(); const location = useLocation();
const history = useHistory(); const history = useHistory();
const handleApiResponseSuccess = () => {
props.refreshChat();
};
// const handleApiResponseSuccess = () => {
// props.refreshChat();
// };
const userId = useSelector(selectUserId);
const handleSend = useCallback(() => { const handleSend = useCallback(() => {
if (location.state?.offerId) {
initiateNewChat(typedValue);
} else {
// if (location.state?.offerId) {
// initiateNewChat(typedValue);
// } else {
// dispatch(
// sendMessage({
// message: typedValue,
// chatId: props.chatId,
// handleApiResponseSuccess,
// })
// );
// }
console.log(props.chatId, typedValue, props.interlucator.userId);
if (props.chatId) {
sendMessage(props.chatId, userId, typedValue, props.interlucator.userId);
dispatch( dispatch(
sendMessage({
message: typedValue,
chatId: props.chatId,
handleApiResponseSuccess,
addNewMessage({
_id: props.chatId,
message: {
userId,
text: typedValue,
_created: new Date().toISOString(),
},
}) })
); );
} else {
initiateNewChat(typedValue);
} }
// socket.emit("private_message", {
// chatId: props.chatId,
// receiverUserId: props.interlucator.userId,
// message: typedValue
// // message: {
// // userId: userId,
// // text: typedValue,
// // receiverUserId: props.interlucator.userId
// // }
// })
setTypedValue(""); setTypedValue("");
}, [typedValue]);
}, [typedValue, props.chatId, userId, props.interlucator.userId]);
const handleMessageSendSuccess = (newChatId) => { const handleMessageSendSuccess = (newChatId) => {
history.replace(`${newChatId}`); history.replace(`${newChatId}`);
dispatch(fetchChats()); dispatch(fetchChats());
children: PropTypes.node, children: PropTypes.node,
chatId: PropTypes.any, chatId: PropTypes.any,
refreshChat: PropTypes.func, refreshChat: PropTypes.func,
interlucator: PropTypes.any,
}; };


export default DirectChatNewMessage; export default DirectChatNewMessage;

+ 1
- 1
src/components/Header/Header.js View File

color: selectedTheme.primaryPurple, color: selectedTheme.primaryPurple,
}} }}
> >
<Badge badgeContent={3} color="primary">
<Badge color="primary">
<MailIcon /> <MailIcon />
</Badge> </Badge>
</IconButton> </IconButton>

+ 32
- 14
src/components/ImagePicker/ImagePicker.js View File

import { IconButton } from "../Buttons/IconButton/IconButton"; import { IconButton } from "../Buttons/IconButton/IconButton";
import { ReactComponent as EditIcon } from "../../assets/images/svg/edit.svg"; import { ReactComponent as EditIcon } from "../../assets/images/svg/edit.svg";
import { ReactComponent as TrashIcon } from "../../assets/images/svg/trash.svg"; import { ReactComponent as TrashIcon } from "../../assets/images/svg/trash.svg";
import { getImageUrl, variants } from "../../util/helpers/imageUrlGetter";


const ImagePicker = (props) => { const ImagePicker = (props) => {
const fileInputRef = useRef(null); const fileInputRef = useRef(null);
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);


useEffect(() => { useEffect(() => {
if (props.image)
setImage(props.image);
}, [props.image]);

let listener = useCallback((event) => {
if (imageRef.current) {
if (imageRef.current.contains(event.target)) {
setIsEditing(true);
if (props.image) {
if (typeof props.image === 'string') {
setImage(getImageUrl(props.image, variants.offerCard))
} else { } else {
setIsEditing(false);
handleImage(props.image);
} }
} }
}, [imageRef.current])
}, [props.image]);

let listener = useCallback(
(event) => {
if (imageRef.current) {
if (imageRef.current.contains(event.target)) {
setIsEditing(true);
} else {
setIsEditing(false);
}
}
},
[imageRef.current]
);
useEffect(() => { useEffect(() => {
window.addEventListener("click", listener); window.addEventListener("click", listener);
return () => window.removeEventListener("click", listener); return () => window.removeEventListener("click", listener);
fileInputRef.current.value = ""; fileInputRef.current.value = "";
fileInputRef.current.click(); fileInputRef.current.click();
}; };
const handleImage = (event) => {
const handleImage = (file) => {
let reader = new FileReader(); let reader = new FileReader();
reader.readAsDataURL(event.target.files[0]);
reader.readAsDataURL(file);
// reader.readAsBinaryString(file);
reader.onload = () => { reader.onload = () => {
if (props.setImage) props.setImage(reader.result);
if (props.setImage) props.setImage(file);
console.log(reader.result);
setImage(reader.result); setImage(reader.result);
}; };
reader.onerror = (error) => { reader.onerror = (error) => {
className={props.className} className={props.className}
onClick={!image ? handleChange : () => {}} onClick={!image ? handleChange : () => {}}
hasImage={props.image} hasImage={props.image}
component="form"
> >
<AddFile type="file" ref={fileInputRef} onInput={handleImage} accept=".jpg, .jpeg, .png" />
<AddFile
type="file"
ref={fileInputRef}
onInput={(event) => handleImage(event.target.files[0])}
accept=".jpg, .jpeg, .png"
formEncType="multipart/form-data"
/>
{image ? ( {image ? (
<React.Fragment> <React.Fragment>
<ImageUploaded src={image} draggable={false} ref={imageRef} /> <ImageUploaded src={image} draggable={false} ref={imageRef} />

+ 11
- 1
src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js View File

import StatisticDetails from "./StatisticDetails/StatisticDetails"; import StatisticDetails from "./StatisticDetails/StatisticDetails";
import PIBDetail from "./OfferDetail/PIB/PIBDetail"; import PIBDetail from "./OfferDetail/PIB/PIBDetail";
import CategoryDetail from "./OfferDetail/Category/CategoryDetail"; import CategoryDetail from "./OfferDetail/Category/CategoryDetail";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const ItemDetailsHeaderCard = (props) => { const ItemDetailsHeaderCard = (props) => {
const history = useHistory(); const history = useHistory();
const chats = useSelector(selectLatestChats); const chats = useSelector(selectLatestChats);
const offer = props.offer; const offer = props.offer;
const userId = useSelector(selectUserId); const userId = useSelector(selectUserId);
const { isMobile } = useIsMobile();


const handleGoProfile = () => { const handleGoProfile = () => {
history.push(`/profile/${offer?.offer?.userId}`); history.push(`/profile/${offer?.offer?.userId}`);
halfwidth={props.halfwidth ? 1 : 0} halfwidth={props.halfwidth ? 1 : 0}
> >
<HeaderTop> <HeaderTop>
<OfferImage src={offer?.companyData?.image} />
{/* <OfferImage src={offer?.companyData?.image} /> */}
<OfferImage
src={getImageUrl(
offer?.companyData?.image,
variants.profileImage,
isMobile
)}
/>
<OfferDetails> <OfferDetails>
<OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}> <OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}>
{offer?.companyData?.company?.name} {offer?.companyData?.company?.name}

+ 1
- 0
src/components/MarketPlace/Offers/OffersNotFound.styled.js View File

align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 70vh; height: 70vh;
text-align: center;
`; `;


export const OffersNotFoundHeading = styled(Typography)` export const OffersNotFoundHeading = styled(Typography)`

+ 5
- 2
src/components/Popovers/HeaderPopover/HeaderPopover.js View File

SecondaryTextContainer, SecondaryTextContainer,
} from "./HeaderPopover.styled"; } from "./HeaderPopover.styled";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";


const HeaderPopover = (props) => { const HeaderPopover = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const {isMobile} = useIsMobile();
return ( return (
<HeaderPopoverContainer> <HeaderPopoverContainer>
<PopoverTitle p={2}>{props.title}</PopoverTitle> <PopoverTitle p={2}>{props.title}</PopoverTitle>
{props.isProfile ? ( {props.isProfile ? (
<PopoverListItemProfileAvatar <PopoverListItemProfileAvatar
alt={item.alt} alt={item.alt}
src={item.src}
src={getImageUrl(item.src, variants.profileCard, isMobile)}
onClick={item?.onClick} onClick={item?.onClick}
/> />
) : ( ) : (
<PopoverListItemAvatar <PopoverListItemAvatar
alt={item.alt} alt={item.alt}
src={item.src}
src={getImageUrl(item.src, variants.profileCard, isMobile)}
onClick={item?.onClick} onClick={item?.onClick}
/> />
)} )}

+ 11
- 1
src/components/ProfileCard/ProfileMainInfo/ProfileMainInfo.js View File

ProfilePIB, ProfilePIB,
} from "./ProfileMainInfo.styled"; } from "./ProfileMainInfo.styled";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";
import useIsMobile from "../../../hooks/useIsMobile";


const ProfileMainInfo = (props) => { const ProfileMainInfo = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { isMobile } = useIsMobile();
return ( return (
<ProfileMainInfoContainer> <ProfileMainInfoContainer>
<AvatarImageContainer> <AvatarImageContainer>
<AvatarImage
{/* <AvatarImage
alt={props.profile?.company?.name} alt={props.profile?.company?.name}
src={props.profile?.image} src={props.profile?.image}
/> */}
<AvatarImage
src={getImageUrl(
props.profile?.image,
variants.profileImage,
isMobile
)}
/> />
</AvatarImageContainer> </AvatarImageContainer>
<ProfileMainInfoGrid> <ProfileMainInfoGrid>

+ 5
- 1
src/pages/RegisterPages/Register/Register.js View File

import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { import {
RegisterPageContainer, RegisterPageContainer,
} }
}; };


useEffect(() => {
console.log("informations", informations)
}, [informations])



const registerUser = (values) => { const registerUser = (values) => {
dispatch( dispatch(

+ 1
- 0
src/request/index.js View File

// baseURL: "http://192.168.88.175:3005/", // baseURL: "http://192.168.88.175:3005/",
// baseURL: "http://192.168.88.143:3001/", // DULE // baseURL: "http://192.168.88.143:3001/", // DULE
baseURL: "https://trampa-api-test.dilig.net/", baseURL: "https://trampa-api-test.dilig.net/",
// baseURL: "http://localhost:3001/",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },

+ 31
- 0
src/socket/socket.js View File

import io from "socket.io-client";

export const socket = io("https://trampa-api-test.dilig.net/", {
autoConnect: true,
transports: ["websocket"],
reconnectionAttempts: 5,
});

export const socketInit = (userId) => {
socket.auth = {
userId,
};
};

export const sendMessage = (chatId, userId, text, receiverUserId) => {
socket.emit("private_message", {
chatId,
receiverUserId,
message: {
userId,
text,
},
});
};

export const addMesageListener = (listener) => {
return socket.on("private_message", listener);
};
export const removeMessageListener = () => {
return socket.off("private_message");
};

+ 1
- 0
src/store/actions/chat/chatActionConstants.js View File

export const CHAT_SET = createSetType("CHAT_SET"); export const CHAT_SET = createSetType("CHAT_SET");
export const CHAT_ONE_SET = createSetType("CHAT_ONE_SET"); export const CHAT_ONE_SET = createSetType("CHAT_ONE_SET");
export const CHAT_CLEAR = createSetType("CHAT_CLEAR"); export const CHAT_CLEAR = createSetType("CHAT_CLEAR");
export const CHAT_ADD_MESSAGE = createSetType("CHAT_ADD_MESSAGE");
// export const ADD_ONE_CHAT = "CHAT_ONE_ADD"; // export const ADD_ONE_CHAT = "CHAT_ONE_ADD";

+ 5
- 1
src/store/actions/chat/chatActions.js View File

import { CHAT_CLEAR, CHAT_FETCH, CHAT_FETCH_ERROR, CHAT_FETCH_SUCCESS, CHAT_HEADER_FETCH, CHAT_HEADER_FETCH_ERROR, CHAT_HEADER_FETCH_SUCCESS, CHAT_NEW_FETCH, CHAT_NEW_FETCH_ERROR, CHAT_NEW_FETCH_SUCCESS, CHAT_ONE_FETCH, CHAT_ONE_FETCH_ERROR, CHAT_ONE_FETCH_SUCCESS, CHAT_ONE_SET, CHAT_SEND_ERROR, CHAT_SEND_FETCH, CHAT_SEND_SUCCESS, CHAT_SET } from "./chatActionConstants";
import { CHAT_ADD_MESSAGE, CHAT_CLEAR, CHAT_FETCH, CHAT_FETCH_ERROR, CHAT_FETCH_SUCCESS, CHAT_HEADER_FETCH, CHAT_HEADER_FETCH_ERROR, CHAT_HEADER_FETCH_SUCCESS, CHAT_NEW_FETCH, CHAT_NEW_FETCH_ERROR, CHAT_NEW_FETCH_SUCCESS, CHAT_ONE_FETCH, CHAT_ONE_FETCH_ERROR, CHAT_ONE_FETCH_SUCCESS, CHAT_ONE_SET, CHAT_SEND_ERROR, CHAT_SEND_FETCH, CHAT_SEND_SUCCESS, CHAT_SET } from "./chatActionConstants";


export const fetchChats = (payload) => ({ export const fetchChats = (payload) => ({
type: CHAT_FETCH, type: CHAT_FETCH,
}) })
export const startNewChatError = () => ({ export const startNewChatError = () => ({
type: CHAT_NEW_FETCH_ERROR type: CHAT_NEW_FETCH_ERROR
})
export const addNewMessage = (payload) => ({
type: CHAT_ADD_MESSAGE,
payload
}) })

+ 3
- 1
src/store/middleware/accessTokensMiddleware.js View File

// const baseURL = "http://192.168.88.143:3001/"; // DULE // const baseURL = "http://192.168.88.143:3001/"; // DULE
// const baseURL = "http://192.168.88.175:3005/"; // const baseURL = "http://192.168.88.175:3005/";
const baseURL = "https://trampa-api-test.dilig.net/"; const baseURL = "https://trampa-api-test.dilig.net/";
// const baseURL = "http://localhost:3001/";


//Interceptor unique name //Interceptor unique name
export const accessTokensMiddlewareInterceptorName = "ACCESS_TOKEN_INTERCEPTOR"; export const accessTokensMiddlewareInterceptorName = "ACCESS_TOKEN_INTERCEPTOR";
const axiosResponse = await axios.post(`${baseURL}auth/refresh`, { const axiosResponse = await axios.post(`${baseURL}auth/refresh`, {
token: refresh, token: refresh,
}); });
const newToken = axiosResponse.data.token;
const newToken = axiosResponse.data;

response.headers.Authorization = `Bearer ${newToken}`; response.headers.Authorization = `Bearer ${newToken}`;
dispatch(refreshUserToken(newToken)); dispatch(refreshUserToken(newToken));
} }

+ 51
- 22
src/store/reducers/chat/chatReducer.js View File

import { CHAT_CLEAR, CHAT_ONE_SET, CHAT_SET } from "../../actions/chat/chatActionConstants"
import createReducer from "../../utils/createReducer"
import {
CHAT_ADD_MESSAGE,
CHAT_CLEAR,
CHAT_ONE_SET,
CHAT_SET,
} from "../../actions/chat/chatActionConstants";
import createReducer from "../../utils/createReducer";


const initialState = { const initialState = {
latestChats: [],
selectedChat: {}
}
latestChats: [],
selectedChat: {},
};


export default createReducer( export default createReducer(
{
[CHAT_SET]: setChats,
[CHAT_ONE_SET]: setOneChat,
[CHAT_CLEAR]: clearChats
},
initialState
)
{
[CHAT_SET]: setChats,
[CHAT_ONE_SET]: setOneChat,
[CHAT_CLEAR]: clearChats,
[CHAT_ADD_MESSAGE]: addNewMessage,
},
initialState
);


function setChats(state, action) { function setChats(state, action) {
return {
...state,
latestChats: [...action.payload]
}
return {
...state,
latestChats: [...action.payload],
};
} }
function setOneChat(state, action) { function setOneChat(state, action) {
return {
...state,
selectedChat: action.payload
}
return {
...state,
selectedChat: action.payload,
};
} }
function clearChats() { function clearChats() {
return initialState;
}
return initialState;
}
function addNewMessage(state, { payload }) {
let allChats = [...state.latestChats];
let chat = allChats.find((item) => item.chat._id === payload._id);
console.log(chat);
chat = {
...chat,
chat: {
...chat.chat,
messages: [...chat.chat.messages, payload.message],
},
};
allChats = allChats.filter((item) => item.chat._id !== chat.chat._id);
allChats = [chat, ...allChats];
let newSelectedChat = { ...state.selectedChat };
console.log(chat);
console.log(newSelectedChat);
if (newSelectedChat.chat._id === chat.chat._id) newSelectedChat = { ...newSelectedChat, chat: chat.chat };
return {
...state,
latestChats: [...allChats],
selectedChat: { ...newSelectedChat },
};
}

+ 45
- 5
src/store/saga/offersSaga.js View File

"?" + newQueryString.toString() "?" + newQueryString.toString()
); );
yield put(setTotalOffers(data.data.total)); yield put(setTotalOffers(data.data.total));
yield put(setOffers(data.data.offers.filter(offer => !offer.pinned)));
yield put(setPinnedOffers(data.data.offers.filter(offer => offer.pinned)));
yield put(setOffers(data.data.offers.filter((offer) => !offer.pinned)));
yield put(
setPinnedOffers(data.data.offers.filter((offer) => offer.pinned))
);
yield put(fetchOffersSuccess()); yield put(fetchOffersSuccess());
} catch (e) { } catch (e) {
yield put(fetchOffersError()); yield put(fetchOffersError());


function* createOffer(payload) { function* createOffer(payload) {
try { try {
yield call(attemptAddOffer, payload.payload.values.offerData);
console.log(payload.payload.values.offerData);
const offerData = payload.payload.values.offerData;
const formData = new FormData();
formData.append("category[name]", offerData.category.name);
formData.append("condition", offerData.condition);
formData.append("description", offerData.description);
// formData.append("file", JSON.stringify(offerData.images))
for (var i = 0; i < offerData.images.length; i++) {
formData.append("file", offerData.images[i]);
}
formData.append("location[city]", offerData.location.city);
formData.append("name", offerData.name);
formData.append("subcategory", offerData.subcategory);
yield call(attemptAddOffer, formData);
yield put(addOfferSuccess()); yield put(addOfferSuccess());
if (payload.payload.handleApiResponseSuccess) { if (payload.payload.handleApiResponseSuccess) {
yield call(payload.payload.handleApiResponseSuccess); yield call(payload.payload.handleApiResponseSuccess);


function* editOffer(payload) { function* editOffer(payload) {
try { try {
console.log(payload);
const offerId = payload.payload.offerId; const offerId = payload.payload.offerId;
const editedData = payload.payload.offerData;
yield call(attemptEditOffer, offerId, editedData);
// const editedData = payload.payload.offerData;
const offerData = payload.payload.offerData;
const formData = new FormData();
formData.append("category[name]", offerData.category.name);
formData.append("condition", offerData.condition);
formData.append("description", offerData.description);
// const oldImages = [];
for (var i = 0; i < offerData.images.length; i++) {
if (offerData.images[i] !== null) {
if (typeof offerData.images[i] === "string") {
formData.append("images[]", offerData.images[i]);
} else {
formData.append("file", offerData.images[i]);
}
}
}
// if (oldImages.length > 0) {
// formData.append("images", JSON.stringify(oldImages));
// }
// if (oldImages.length === offerData.images.length) {
// formData.append("file", "");
// }
formData.append("location[city]", offerData.location.city);
formData.append("name", offerData.name);
formData.append("subcategory", offerData.subcategory);
yield call(attemptEditOffer, offerId, formData);
yield put(editOfferSuccess()); yield put(editOfferSuccess());
if (payload.payload.handleApiResponseSuccess) { if (payload.payload.handleApiResponseSuccess) {
yield call(payload.payload.handleApiResponseSuccess); yield call(payload.payload.handleApiResponseSuccess);

+ 45
- 29
src/store/saga/profileSaga.js View File



function* changeMineProfile(payload) { function* changeMineProfile(payload) {
try { try {
let image;
if (payload.payload.firmLogo.includes("data:image")) {
image = payload.payload.firmLogo
.replace("data:image/jpeg;base64,", "")
.replace("data:image/jpg;base64,", "")
.replace("data:image/png;base64,", "");
} else if (payload.payload.firmLogo === "") {
image = "";
}
// console.log(payload);
// let image;
// if (payload.payload.firmLogo) {
// image = payload.payload.firmLogo;
// } else if (payload.payload.firmLogo === "") {
// image = "";
// }

// const reqData = {
// company: {
// name: payload.payload.firmName,
// PIB: payload.payload.firmPIB,
// contacts: {
// telephone: payload.payload.firmPhone.toString(),
// location: payload.payload.firmLocation ?? "",
// web: payload.payload.firmWebsite,
// },
// },
// image: image,
// };


const reqData = {
company: {
name: payload.payload.firmName,
PIB: payload.payload.firmPIB,
contacts: {
telephone: payload.payload.firmPhone.toString(),
location: payload.payload.firmLocation ?? "",
web: payload.payload.firmWebsite,
},
},
image: image,
};
// if (payload.payload.firmLogo?.includes("https")) delete reqData.image;
// if (reqData.company.contacts.telephone.length === 0)
// delete reqData.company.contacts.telephone;
// if (reqData.company.contacts.location.length === 0)
// delete reqData.company.contacts.location;
// if (reqData.company.contacts.web.length === 0)
// delete reqData.company.contacts.web;


if (payload.payload.firmLogo.includes("https")) delete reqData.image;
if (reqData.company.contacts.telephone.length === 0)
delete reqData.company.contacts.telephone;
if (reqData.company.contacts.location.length === 0)
delete reqData.company.contacts.location;
if (reqData.company.contacts.web.length === 0)
delete reqData.company.contacts.web;
const requestBody = new FormData();
if (typeof payload.payload.firmLogo !== "string")
requestBody.append("file", payload.payload.firmLogo);
requestBody.append("company[name]", payload.payload.firmName);
requestBody.append("company[PIB]", payload.payload.firmPIB);
if (payload.payload.firmPhone.toString().length !== 0)
requestBody.append(
"company[contacts][telephone]",
payload.payload.firmPhone
);
if (payload.payload.firmLocation.toString().length !== 0)
requestBody.append(
"company[contacts][location]",
payload.payload.firmLocation
);
if (payload.payload.firmWebsite.toString().length !== 0)
requestBody.append("company[contacts][web]", payload.payload.firmWebsite);


const userId = yield select(selectUserId); const userId = yield select(selectUserId);
const data = yield call(attemptEditProfile, userId, reqData);
const data = yield call(attemptEditProfile, userId, requestBody);
yield put(editMineProfileSuccess()); yield put(editMineProfileSuccess());
if (payload.payload.handleApiResponseSuccess) { if (payload.payload.handleApiResponseSuccess) {
yield call(payload.payload.handleApiResponseSuccess); yield call(payload.payload.handleApiResponseSuccess);

+ 14
- 24
src/store/saga/registerSaga.js View File



function* fetchRegisterUser({ payload }) { function* fetchRegisterUser({ payload }) {
try { try {
let requestData = {
email: payload.values.mail.toString(),
password: payload.values.password.toString(),
image: payload.values.image
.replace("data:image/jpeg;base64,", "")
.replace("data:image/jpg;base64,", "")
.replace("data:image/png;base64,", ""),
company: {
name: payload.values.nameOfFirm.toString(),
PIB: payload.values.PIB.toString(),
contacts: {
telephone: payload.values.phoneNumber.toString(),
location: payload.values.location.toString(),
web: payload.values.website.toString(),
},
},
};
if (payload.values.phoneNumber?.length === 0)
delete requestData.company.contacts.telephone;
if (payload.values.location?.length === 0)
delete requestData.company.contacts.location;
if (payload.values.website?.length === 0)
delete requestData.company.contacts.web;
yield call(attemptRegister, requestData);
const requestBody = new FormData();
console.log("requeest body image", payload.values.image);
requestBody.append("email", payload.values.mail);
requestBody.append("password", payload.values.password);
requestBody.append("file", payload.values.image);
requestBody.append("company[name]", payload.values.nameOfFirm);
requestBody.append("company[PIB]", payload.values.PIB);
if (payload.values.phoneNumber.toString().length !== 0)
requestBody.append("company[contacts][telephone]", payload.values.phoneNumber);
if (payload.values.location.toString().length !== 0)
requestBody.append("company[contacts][location]", payload.values.location);
if (payload.values.website.toString().length !== 0)
requestBody.append("company[contacts][web]", payload.values.website);
yield call(attemptRegister, requestBody);


const { data } = yield call(attemptLogin, { const { data } = yield call(attemptLogin, {
email: payload.values.mail, email: payload.values.mail,

+ 42
- 0
src/util/helpers/imageUrlGetter.js View File

const CLOUDFLARE = "CLOUDFLARE";
// const IMAGE_KIT = "IMAGEKIT";

const IMAGE_PLATFORM = CLOUDFLARE;

export const variants = {
offerCard: "offerCard",
offerDetails: "offerDetails",
profileImage: "profileImage",
reviewCard: "reviewCard",
chatHeader: "chatHeader",
chatMessage: "chatMessage",
chatCard: "chatCard",
deleteChat: "chatHeader",
profileCard: "profileCard"
}

const cloudFlareVariants = {
offerCard: "primary",
offerCardMobile: "primaryMobile",
offerDetails: "primary",
offerDetailsMobile: "primary",
profileImage: "primary",
profileImageMobile: "profileImage",
reviewCard: "review",
reviewCardMobile: "review",
chatHeader: "chatHeader",
chatHeaderMobile: "chatHeader",
chatMessage: "chatHeader",
chatMessageMobile: "chatHeader",
chatCard: "chatCard",
chatCardMobile: "chatCard",
profileCard: "profileCard"

}
export const getImageUrl = (imageUrl, variant, isMobile) => {
let imageVariant = "";
if (IMAGE_PLATFORM === CLOUDFLARE) {
imageVariant = isMobile ? cloudFlareVariants[variant + "Mobile"] : cloudFlareVariants[variant];
}
return imageUrl + imageVariant;
}

Loading…
Cancel
Save