| @@ -39,6 +39,8 @@ | |||
| "redux-persist-transform-filter": "0.0.20", | |||
| "redux-saga": "^1.1.3", | |||
| "sass": "^1.34.1", | |||
| "socket.io": "^4.5.1", | |||
| "socket.io-client": "^4.5.1", | |||
| "styled-components": "^5.3.5", | |||
| "web-vitals": "^1.1.2", | |||
| "yup": "^0.32.9" | |||
| @@ -1,4 +1,5 @@ | |||
| import React from "react"; | |||
| // import io from 'socket.io-client'; | |||
| import { Router } from "react-router-dom"; | |||
| import { Helmet } from "react-helmet-async"; | |||
| import i18next from "i18next"; | |||
| @@ -8,15 +9,85 @@ import Header from "./components/Header/Header"; | |||
| import { StyledEngineProvider } from "@mui/material"; | |||
| import GlobalStyle from "./components/Styles/globalStyles"; | |||
| // const URL = "http://192.168.88.143:3001"; | |||
| // const socket = io(URL, {autoConnect: true, transports: ['websocket']}); | |||
| const App = () => { | |||
| // console.log(io) | |||
| // const [isConnected, setIsConnected] = useState(socket.connected); | |||
| // const [lastPong, setLastPong] = useState(null); | |||
| // console.log(); | |||
| // useEffect(() => { | |||
| // socket.on("connect", (client) => { | |||
| // console.log(client); | |||
| // setIsConnected(true); | |||
| // }); | |||
| // // socket.on("connect_error", (err) => { | |||
| // // console.log(err); | |||
| // // }); | |||
| // socket.on("connection", (client) => { | |||
| // console.log(client); | |||
| // }); | |||
| // socket.on("disconnect", () => { | |||
| // setIsConnected(false); | |||
| // }); | |||
| // // 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.open; | |||
| // socket.on("pong", () => { | |||
| // setLastPong(new Date().toISOString()); | |||
| // }); | |||
| // // socket.connect(); | |||
| // return () => { | |||
| // socket.off("connect"); | |||
| // socket.off("disconnect"); | |||
| // socket.off("pong"); | |||
| // }; | |||
| // }, []); | |||
| // const handleClick = () => { | |||
| // // socket.connect(); | |||
| // // socket.emit("sokkk 2", "sock"); | |||
| // // socket.emit("sock") | |||
| // }; | |||
| // const sendPing = () => { | |||
| // socket.emit("sokkk", { | |||
| // poruka: "Za Duleta" | |||
| // }); | |||
| // }; | |||
| return ( | |||
| <Router history={history}> | |||
| <Helmet> | |||
| <title>{i18next.t("app.title")}</title> | |||
| </Helmet> | |||
| <StyledEngineProvider injectFirst> | |||
| {/* <button onClick={handleClick}>Kik</button> */} | |||
| <Header /> | |||
| <GlobalStyle /> | |||
| {/* <div> | |||
| <p>Connected: {"" + isConnected}</p> | |||
| <br /> | |||
| <p>Last pong: {lastPong || "-"}</p> | |||
| <br /> | |||
| <button onClick={sendPing}>Send ping</button> | |||
| </div> */} | |||
| <AppRoutes /> | |||
| </StyledEngineProvider> | |||
| {/* </main> */} | |||
| @@ -21,9 +21,7 @@ export const ItemDetailsCardContainer = styled(Container)` | |||
| padding: 18px; | |||
| max-width: 2000px; | |||
| position: relative; | |||
| @media (max-width: 600px) { | |||
| padding-bottom: 50px; | |||
| } | |||
| padding-bottom: 80px; | |||
| `; | |||
| export const OfferImage = styled.img` | |||
| width: 144px; | |||
| @@ -47,7 +45,7 @@ export const InfoGroup = styled(Box)` | |||
| gap: 4px; | |||
| @media (max-width: 600px) { | |||
| /* flex: 1; */ | |||
| ${props => props.last && `flex: none;`} | |||
| ${(props) => props.last && `flex: none;`} | |||
| } | |||
| `; | |||
| export const PostDate = styled(Typography)` | |||
| @@ -147,19 +145,13 @@ export const OfferDescriptionTitle = styled(Box)` | |||
| font-size: 9px; | |||
| line-height: 13px; | |||
| } | |||
| `; | |||
| export const OfferDescriptionText = styled(Box)` | |||
| font-family: "Open Sans"; | |||
| font-size: 16px; | |||
| color: ${selectedTheme.primaryDarkText}; | |||
| line-height: 22px; | |||
| max-width: calc(100% - 230px); | |||
| max-height: 120px; | |||
| overflow: hidden; | |||
| display: -webkit-box; | |||
| -webkit-line-clamp: 5; | |||
| -webkit-box-orient: vertical; | |||
| max-width: calc(100% - 30px); | |||
| @media (max-width: 600px) { | |||
| font-size: 14px; | |||
| } | |||
| @@ -211,7 +203,7 @@ export const Details = styled(Box)` | |||
| // export const OfferImage = styled.img` | |||
| // ` | |||
| export const Scroller = styled(HorizontalScroller)` | |||
| & div { | |||
| margin: 0 9px; | |||
| } | |||
| ` | |||
| & div { | |||
| margin: 0 9px; | |||
| } | |||
| `; | |||
| @@ -4,6 +4,8 @@ import { | |||
| CheckButton, | |||
| DetailIcon, | |||
| DetailText, | |||
| EditIcon, | |||
| EditIconContainer, | |||
| EyeIcon, | |||
| Line, | |||
| MessageIcon, | |||
| @@ -23,6 +25,8 @@ import { | |||
| OfferTitle, | |||
| OfferTitleAboveImage, | |||
| OfferViews, | |||
| RemoveIcon, | |||
| RemoveIconContainer, | |||
| } from "./OfferCard.styled"; | |||
| import { ReactComponent as Category } from "../../../assets/images/svg/category.svg"; | |||
| import { ReactComponent as Message } from "../../../assets/images/svg/mail.svg"; | |||
| @@ -46,16 +50,33 @@ const OfferCard = (props) => { | |||
| } | |||
| halfwidth={props.halfwidth ? 1 : 0} | |||
| > | |||
| <OfferTitleAboveImage vertical={props.vertical} onClick={() => routeToItem(props?.offer?._id)}>{props?.offer?.name}</OfferTitleAboveImage> | |||
| <OfferTitleAboveImage | |||
| vertical={props.vertical} | |||
| onClick={() => routeToItem(props?.offer?._id)} | |||
| > | |||
| {props?.offer?.name} | |||
| </OfferTitleAboveImage> | |||
| <OfferFlexContainer vertical={props.vertical}> | |||
| <OfferImageContainer vertical={props.vertical}> | |||
| <OfferImage src={props?.offer?.images[0]} vertical={props.vertical}></OfferImage> | |||
| <OfferImage | |||
| src={props?.offer?.images[0]} | |||
| vertical={props.vertical} | |||
| ></OfferImage> | |||
| </OfferImageContainer> | |||
| <OfferInfo vertical={props.vertical}> | |||
| <OfferTitle vertical={props.vertical} onClick={() => routeToItem(props?.offer?._id)}>{props?.offer?.name}</OfferTitle> | |||
| <OfferTitle | |||
| vertical={props.vertical} | |||
| onClick={() => routeToItem(props?.offer?._id)} | |||
| > | |||
| {props?.offer?.name} | |||
| </OfferTitle> | |||
| <OfferAuthor> | |||
| <OfferAuthorName vertical={props.vertical}>{props?.offer?.user?.company?.name}</OfferAuthorName> | |||
| <OfferLocation vertical={props.vertical}>{props?.offer?.location?.city}</OfferLocation> | |||
| <OfferAuthorName vertical={props.vertical}> | |||
| {props?.offer?.user?.company?.name} | |||
| </OfferAuthorName> | |||
| <OfferLocation vertical={props.vertical}> | |||
| {props?.offer?.location?.city} | |||
| </OfferLocation> | |||
| </OfferAuthor> | |||
| <OfferDetails> | |||
| <OfferCategory vertical={props.vertical}> | |||
| @@ -98,19 +119,20 @@ const OfferCard = (props) => { | |||
| <></> | |||
| )} | |||
| <MessageIcon vertical={props.vertical}> | |||
| <Message /> | |||
| </MessageIcon> | |||
| {/* {props.image} | |||
| {props.title} | |||
| {props.description} | |||
| {props.category} | |||
| {props.author} | |||
| {props.location} | |||
| {props.quantity} | |||
| {props.package} | |||
| {props.numberOfViews} */} | |||
| {props.isMyOffer ? ( | |||
| <> | |||
| <RemoveIconContainer vertical={props.vertical}> | |||
| <RemoveIcon /> | |||
| </RemoveIconContainer> | |||
| <EditIconContainer vertical={props.vertical}> | |||
| <EditIcon /> | |||
| </EditIconContainer> | |||
| </> | |||
| ) : ( | |||
| <MessageIcon vertical={props.vertical}> | |||
| <Message /> | |||
| </MessageIcon> | |||
| )} | |||
| </OfferFlexContainer> | |||
| </OfferCardContainer> | |||
| </React.Fragment> | |||
| @@ -134,6 +156,7 @@ OfferCard.propTypes = { | |||
| offer: PropTypes.any, | |||
| pinned: PropTypes.bool, | |||
| vertical: PropTypes.bool, | |||
| isMyOffer: PropTypes.bool, | |||
| }; | |||
| OfferCard.defaultProps = { | |||
| halfwidth: false, | |||
| @@ -5,6 +5,10 @@ import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton"; | |||
| import { Icon } from "../../Icon/Icon"; | |||
| import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg"; | |||
| import { ReactComponent as Remove } from "../../../assets/images/svg/trash.svg"; | |||
| import { ReactComponent as Edit } from "../../../assets/images/svg/edit.svg"; | |||
| export const OfferCardContainer = styled(Container)` | |||
| display: flex; | |||
| @@ -315,3 +319,15 @@ export const EyeIcon = styled(Eye)` | |||
| top: 1px !important; | |||
| } | |||
| `; | |||
| export const RemoveIconContainer = styled(MessageIcon)` | |||
| ` | |||
| export const RemoveIcon = styled(Remove)` | |||
| ` | |||
| export const EditIconContainer = styled(MessageIcon)` | |||
| right: 70px; | |||
| ` | |||
| export const EditIcon = styled(Edit)` | |||
| ` | |||
| @@ -256,7 +256,12 @@ const Header = () => { | |||
| }; | |||
| const handleLogoClick = () => { | |||
| history.push(HOME_PAGE); | |||
| history.push({ | |||
| pathname: HOME_PAGE, | |||
| state: { | |||
| logo: true | |||
| } | |||
| }); | |||
| } | |||
| return ( | |||
| @@ -1,21 +1,30 @@ | |||
| import React from 'react'; | |||
| import React, { useMemo } from 'react'; | |||
| import Header from "./Header/Header"; | |||
| import { useSelector } from 'react-redux'; | |||
| import { ItemDetailsContainer } from './ItemDetails.styled'; | |||
| import ItemDetailsCard from "../Cards/ItemDetailsCard/ItemDetailsCard"; | |||
| import ItemDetailsHeaderCard from "./ItemDetailsHeaderCard/ItemDetailsHeaderCard"; | |||
| import { selectOffer } from '../../store/selectors/offersSelectors'; | |||
| import { selectUserId } from '../../store/selectors/loginSelectors'; | |||
| // import { useHistory } from 'react-router-dom'; | |||
| const ItemDetails = () => { | |||
| const offer = useSelector(selectOffer); | |||
| const userId = useSelector(selectUserId); | |||
| let isMyProfile = useMemo(() => { | |||
| if (offer?.offer?.userId?.toString() === userId.toString()) { | |||
| return true; | |||
| } | |||
| return false; | |||
| }, [offer, userId]) | |||
| console.log(isMyProfile) | |||
| return ( | |||
| <ItemDetailsContainer> | |||
| <Header/> | |||
| <ItemDetailsHeaderCard offer={offer} /> | |||
| <ItemDetailsCard offer={offer}/> | |||
| <ItemDetailsHeaderCard offer={offer} isMyProfile={isMyProfile} /> | |||
| <ItemDetailsCard offer={offer} isMyOffer={isMyProfile}/> | |||
| </ItemDetailsContainer> | |||
| ) | |||
| } | |||
| @@ -13,6 +13,8 @@ import { | |||
| BottomDetails, | |||
| StatusText, | |||
| PIBIcon, | |||
| UserIcon, | |||
| UserIconContainer, | |||
| } from "./ItemDetailsHeaderCard.styled"; | |||
| import { ItemDetailsHeaderContainer } from "./ItemDetailsHeaderCard.styled"; | |||
| import { ReactComponent as Category } from "../../../assets/images/svg/category.svg"; | |||
| @@ -26,11 +28,7 @@ const ItemDetailsHeaderCard = (props) => { | |||
| console.log("header offer: ", props.offer); | |||
| const offer = props.offer; | |||
| if (!props.offer) { | |||
| return ( | |||
| <div> | |||
| Loading... | |||
| </div> | |||
| ) | |||
| return <div>Loading...</div>; | |||
| } | |||
| let percentOfSucceededExchanges; | |||
| if (offer?.companyData?.statistics?.exchanges?.succeeded === 0) { | |||
| @@ -44,24 +42,25 @@ const ItemDetailsHeaderCard = (props) => { | |||
| } | |||
| const handleGoProfile = () => { | |||
| history.push(`/profile/${offer?.offer?.userId}`); | |||
| } | |||
| }; | |||
| return ( | |||
| <ItemDetailsHeaderContainer | |||
| sponsored={offer?.offer?.pinned?.toString()} | |||
| isMyProfile={props.isMyProfile} | |||
| halfwidth={props.halfwidth ? 1 : 0} | |||
| > | |||
| <HeaderTop> | |||
| <OfferImage src={offer?.companyData?.image}/> | |||
| <OfferImage src={offer?.companyData?.image} /> | |||
| <OfferDetails> | |||
| <OfferTitle onClick={handleGoProfile}>{offer?.companyData?.company?.name}</OfferTitle> | |||
| <OfferTitle isMyProfile={props.isMyProfile} onClick={handleGoProfile}> | |||
| {offer?.companyData?.company?.name} | |||
| </OfferTitle> | |||
| <DetailContainer> | |||
| <PIBIcon | |||
| color={selectedTheme.iconStrokeColor} | |||
| component="span" | |||
| > | |||
| <PIBIcon color={selectedTheme.iconStrokeColor} component="span"> | |||
| <PIB /> | |||
| </PIBIcon> | |||
| <DetailText>PIB - {offer?.companyData?.company?.PIB}</DetailText> | |||
| <DetailText isMyProfile={props.isMyProfile}> | |||
| PIB - {offer?.companyData?.company?.PIB} | |||
| </DetailText> | |||
| </DetailContainer> | |||
| <DetailContainer shouldHideResponsive> | |||
| <DetailIcon | |||
| @@ -71,14 +70,20 @@ const ItemDetailsHeaderCard = (props) => { | |||
| > | |||
| <Category width={"22px"} /> | |||
| </DetailIcon> | |||
| <DetailText > | |||
| <DetailText isMyProfile={props.isMyProfile}> | |||
| {offer?.companyData?.company?.contacts?.location} | |||
| </DetailText> | |||
| </DetailContainer> | |||
| </OfferDetails> | |||
| <MessageIcon> | |||
| <MessageColor /> | |||
| </MessageIcon> | |||
| {props.isMyProfile ? ( | |||
| <UserIconContainer onClick={handleGoProfile}> | |||
| <UserIcon /> | |||
| </UserIconContainer> | |||
| ) : ( | |||
| <MessageIcon> | |||
| <MessageColor /> | |||
| </MessageIcon> | |||
| )} | |||
| </HeaderTop> | |||
| <HeaderDetails> | |||
| <BottomDetails> | |||
| @@ -86,7 +91,8 @@ const ItemDetailsHeaderCard = (props) => { | |||
| <b>{offer?.companyData?.statistics?.publishes?.count}</b> objava | |||
| </StatusText> | |||
| <StatusText> | |||
| <b>{offer?.companyData?.statistics?.views?.count}</b> ukupnih pregleda | |||
| <b>{offer?.companyData?.statistics?.views?.count}</b> ukupnih | |||
| pregleda | |||
| </StatusText> | |||
| <StatusText> | |||
| <b>{percentOfSucceededExchanges}</b> % uspesnih trampi | |||
| @@ -115,6 +121,7 @@ ItemDetailsHeaderCard.propTypes = { | |||
| halfwidth: PropTypes.bool, | |||
| sponsored: PropTypes.bool, | |||
| offer: PropTypes.any, | |||
| isMyProfile: PropTypes.bool, | |||
| // offer: PropTypes.shape({ | |||
| // images: PropTypes.any, | |||
| // name:PropTypes.string, | |||
| @@ -4,6 +4,8 @@ import selectedTheme from "../../../themes"; | |||
| import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton"; | |||
| import { Icon } from "../../Icon/Icon"; | |||
| import { ReactComponent as User} from "../../../assets/images/svg/user.svg"; | |||
| export const ItemDetailsHeaderContainer = styled(Box)` | |||
| display: flex; | |||
| @@ -12,11 +14,11 @@ export const ItemDetailsHeaderContainer = styled(Box)` | |||
| box-sizing: border-box; | |||
| margin: 10px 0; | |||
| background-color: ${(props) => | |||
| props.sponsored === "true" | |||
| ? selectedTheme.backgroundSponsoredColor | |||
| props.isMyProfile | |||
| ? selectedTheme.primaryPurple | |||
| : "white"}; | |||
| border-radius: 4px; | |||
| border: 1px solid ${selectedTheme.borderNormal}; | |||
| border: 1px solid ${selectedTheme.primaryPurple}; | |||
| max-width: 2000px; | |||
| position: relative; | |||
| `; | |||
| @@ -75,7 +77,7 @@ export const OfferInfo = styled(Box)` | |||
| export const OfferTitle = styled(Typography)` | |||
| margin-bottom: 12px; | |||
| font-family: "Open Sans"; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| color: ${props => props.isMyProfile ? selectedTheme.primaryYellow : selectedTheme.primaryPurple}; | |||
| font-weight: 700; | |||
| font-size: 24px; | |||
| cursor: pointer; | |||
| @@ -102,7 +104,7 @@ export const OfferLocation = styled(Box)` | |||
| `; | |||
| export const OfferPIB = styled(Box)` | |||
| font-family: "Open Sans"; | |||
| color: ${selectedTheme.primaryText}; | |||
| color: ${props => props.isMyProfile ? selectedTheme.primaryDarkTextThird : selectedTheme.primaryText}; | |||
| line-height: 16px; | |||
| font-size: 12px; | |||
| `; | |||
| @@ -111,6 +113,7 @@ export const OfferDetails = styled(Box)` | |||
| flex-direction: column; | |||
| flex-wrap: ${(props) => (!props.halfwidth ? "no-wrap" : "wrap")}; | |||
| justify-content: start; | |||
| `; | |||
| export const StatusText = styled(Grid)` | |||
| @@ -180,7 +183,7 @@ export const DetailIcon = styled(Icon)` | |||
| `; | |||
| export const DetailText = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| color: ${selectedTheme.primaryText}; | |||
| color: ${props => props.isMyProfile ? "white" : selectedTheme.primaryText}; | |||
| line-height: 16px; | |||
| font-size: 16px; | |||
| position: relative; | |||
| @@ -233,3 +236,9 @@ export const PIBIcon = styled(DetailIcon)` | |||
| } | |||
| } | |||
| `; | |||
| export const UserIconContainer = styled(MessageIcon)` | |||
| background-color: ${selectedTheme.primaryIconBackgroundColor}; | |||
| ` | |||
| export const UserIcon = styled(User)` | |||
| ` | |||
| @@ -9,30 +9,20 @@ import { | |||
| selectPinnedOffers, | |||
| selectTotalOffers, | |||
| } from "../../../store/selectors/offersSelectors"; | |||
| // import useFilters from "../../../hooks/useFilters"; | |||
| import Paging from "../../Paging/Paging"; | |||
| // import { convertQueryString } from "../../../util/helpers/queryHelpers"; | |||
| import { HOME_PAGE } from "../../../constants/pages"; | |||
| import { useHistory } from "react-router-dom"; | |||
| // import qs from "query-string"; | |||
| // import useSorting from "../../../hooks/useSorting"; | |||
| import { useQueryString } from "../../../hooks/useQueryString"; | |||
| const Offers = (props) => { | |||
| // const filters = useFilters(); | |||
| const [page, setPage] = useState(1); | |||
| // const [initialLoad, setInitialLoad] = useState(true); | |||
| const pinnedOffers = useSelector(selectPinnedOffers); | |||
| const offers = useSelector(selectOffers); | |||
| const total = useSelector(selectTotalOffers); | |||
| const history = useHistory(); | |||
| // const sorting = useSorting(); | |||
| const dispatch = useDispatch(); | |||
| const offersRef = useRef(null); | |||
| const queryStringHook = useQueryString(); | |||
| // const queryString = history.location.search.substring(1); | |||
| // const queryObject = qs.parse(queryString); | |||
| useEffect(() => { | |||
| let queryObject = queryStringHook.getQueryObject(); | |||
| if (queryObject.page && queryObject.page !== 1) { | |||
| @@ -41,8 +31,13 @@ const Offers = (props) => { | |||
| }, [history.location.search]); | |||
| useEffect(() => { | |||
| // console.log("sorting.loadedQS", sorting.loadedQS); | |||
| // console.log("queryString", queryString) | |||
| if (history?.location?.state?.logo) { | |||
| dispatch(fetchOffers({queryString: ""})); | |||
| history.location.state = undefined; | |||
| } | |||
| }, [history.location.state]) | |||
| useEffect(() => { | |||
| if (queryStringHook.loadedFromURL) { | |||
| dispatch(fetchOffers({ queryString: "?" + queryStringHook.queryString })); | |||
| history.push({ | |||
| @@ -65,7 +60,6 @@ const Offers = (props) => { | |||
| { key: "size", value: "10" }, | |||
| { key: "page", value: "1" }, | |||
| ]); | |||
| // queryStringHook.appendToQueryString("page", 1); | |||
| } | |||
| }, [queryStringHook.loadedFromURL, queryStringHook.queryString]); | |||
| @@ -1,14 +1,35 @@ | |||
| import React from 'react' | |||
| import React, { useEffect, useMemo } from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import { ProfileContainer } from './Profile.styled' | |||
| import ProfileCard from '../ProfileCard/ProfileCard' | |||
| import ProfileOffers from './ProfileOffers/ProfileOffers' | |||
| import { useDispatch, useSelector } from 'react-redux' | |||
| import { selectUserId } from '../../store/selectors/loginSelectors' | |||
| import { useRouteMatch } from 'react-router-dom' | |||
| import { fetchProfile } from '../../store/actions/profile/profileActions' | |||
| import { fetchProfileOffers } from '../../store/actions/offers/offersActions' | |||
| const Profile = () => { | |||
| const userId = useSelector(selectUserId); | |||
| const dispatch = useDispatch(); | |||
| const routeMatch = useRouteMatch(); | |||
| const idProfile = routeMatch.params.idProfile; | |||
| useEffect(() => { | |||
| if (idProfile?.length > 0) { | |||
| dispatch(fetchProfile(idProfile)); | |||
| dispatch(fetchProfileOffers(idProfile)) | |||
| } | |||
| }, [idProfile]); | |||
| const isMyProfile = useMemo(() => { | |||
| if (userId === idProfile) { | |||
| return true; | |||
| } | |||
| return false; | |||
| }, [userId, idProfile]) | |||
| return ( | |||
| <ProfileContainer> | |||
| <ProfileCard /> | |||
| <ProfileOffers /> | |||
| <ProfileCard isMyProfile={isMyProfile}/> | |||
| <ProfileOffers isMyProfile={isMyProfile}/> | |||
| </ProfileContainer> | |||
| ) | |||
| } | |||
| @@ -24,15 +24,14 @@ import { useRef } from "react"; | |||
| import { selectProfileOffers } from "../../../store/selectors/offersSelectors"; | |||
| import useScreenDimensions from "../../../hooks/useScreenDimensions"; | |||
| const ProfileOffers = () => { | |||
| const ProfileOffers = (props) => { | |||
| const [sortOption, setSortOption] = useState(sortEnum.INITIAL); | |||
| const [offersToShow, setOffersToShow] = useState([]); | |||
| const searchRef = useRef(null); | |||
| // const [toSearch, setToSearch] = useState(""); | |||
| const profileOffers = useSelector(selectProfileOffers); | |||
| const dimensions = useScreenDimensions(); | |||
| console.log(profileOffers); | |||
| const [offersToShow, setOffersToShow] = useState([]); | |||
| const { t } = useTranslation(); | |||
| useEffect(() => { | |||
| let newOffersToShow = [...offersToShow]; | |||
| if (sortOption.value === sortEnum.OLD.value) { | |||
| @@ -52,18 +51,19 @@ const ProfileOffers = () => { | |||
| } | |||
| setOffersToShow([...newOffersToShow]); | |||
| }, [sortOption]); | |||
| useEffect(() => { | |||
| if (profileOffers?.length > 0) setOffersToShow(profileOffers); | |||
| }, [profileOffers]); | |||
| const handleSearch = () => { | |||
| const valueToSearch = searchRef?.current?.value; | |||
| console.log(valueToSearch); | |||
| console.log(offersToShow); | |||
| let newOffersToShow = profileOffers.filter((item) => | |||
| item.name.toLowerCase().includes(valueToSearch.toLowerCase()) | |||
| ); | |||
| setOffersToShow([...newOffersToShow]); | |||
| }; | |||
| const handleChangeSelect = (event) => { | |||
| let chosenOption; | |||
| for (const sortOption in sortEnum) { | |||
| @@ -73,6 +73,7 @@ const ProfileOffers = () => { | |||
| } | |||
| } | |||
| }; | |||
| let listener; | |||
| const handleFocusSearch = () => { | |||
| listener = (event) => { | |||
| @@ -83,9 +84,11 @@ const ProfileOffers = () => { | |||
| }; | |||
| searchRef.current.addEventListener("keyup", listener); | |||
| }; | |||
| const handleBlurSearch = () => { | |||
| searchRef.current.removeEventListener("keyup", listener); | |||
| }; | |||
| return ( | |||
| <ProfileOffersContainer> | |||
| <HeaderSelect | |||
| @@ -112,7 +115,7 @@ const ProfileOffers = () => { | |||
| sx={{ mb: 1.4 }} | |||
| > | |||
| <OffersIcon /> | |||
| <HeaderTitle>Moje objave</HeaderTitle> | |||
| <HeaderTitle>{props.isMyProfile ? "Moje objave" : "Objave kompanije"}</HeaderTitle> | |||
| </Grid> | |||
| <SearchInput | |||
| fullWidth | |||
| @@ -133,12 +136,12 @@ const ProfileOffers = () => { | |||
| <OffersContainer> | |||
| {dimensions.width > 600 ? ( | |||
| offersToShow.map((item) => ( | |||
| <OfferCard offer={item} key={JSON.stringify(item)} pinned /> | |||
| <OfferCard isMyOffer={props.isMyProfile} offer={item} key={JSON.stringify(item)} pinned /> | |||
| )) | |||
| ) : ( | |||
| <OffersScroller hideArrows> | |||
| {offersToShow.map((item) => ( | |||
| <OfferCard vertical offer={item} key={JSON.stringify(item)} pinned />))} | |||
| <OfferCard vertical isMyOffer={props.isMyProfile} offer={item} key={JSON.stringify(item)} pinned />))} | |||
| </OffersScroller> | |||
| )} | |||
| </OffersContainer> | |||
| @@ -148,6 +151,7 @@ const ProfileOffers = () => { | |||
| ProfileOffers.propTypes = { | |||
| children: PropTypes.node, | |||
| isMyProfile: PropTypes.bool, | |||
| }; | |||
| export default ProfileOffers; | |||
| @@ -26,30 +26,11 @@ import { | |||
| import { Grid, Stack } from "@mui/material"; | |||
| import PersonOutlineIcon from "@mui/icons-material/PersonOutline"; | |||
| import { useRouteMatch } from "react-router-dom"; | |||
| import { fetchProfile } from "../../store/actions/profile/profileActions"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { useEffect } from "react"; | |||
| import { useSelector } from "react-redux"; | |||
| import { selectProfile } from "../../store/selectors/profileSelectors"; | |||
| import { selectUserId } from "../../store/selectors/loginSelectors"; | |||
| import { useState } from "react"; | |||
| import { fetchProfileOffers } from "../../store/actions/offers/offersActions"; | |||
| const ProfileCard = () => { | |||
| const [isMyProfile, setIsMyProfile] = useState(false); | |||
| const routeMatch = useRouteMatch(); | |||
| const dispatch = useDispatch(); | |||
| const ProfileCard = (props) => { | |||
| const profile = useSelector(selectProfile); | |||
| const userId = useSelector(selectUserId); | |||
| const idProfile = routeMatch.params.idProfile; | |||
| console.log(idProfile); | |||
| useEffect(() => { | |||
| if (idProfile?.length > 0) { | |||
| dispatch(fetchProfile(idProfile)); | |||
| dispatch(fetchProfileOffers(idProfile)) | |||
| if (userId === idProfile) setIsMyProfile(true); | |||
| } | |||
| }, [idProfile]); | |||
| let percentOfSucceededExchanges; | |||
| if (profile?.statistics?.exchanges?.succeeded === 0) { | |||
| @@ -73,10 +54,10 @@ const ProfileCard = () => { | |||
| sx={{ mb: 1.4 }} | |||
| > | |||
| <PersonOutlineIcon color="action" sx={{ mr: 0.9 }} /> | |||
| <HeaderTitle>Moj Profil</HeaderTitle> | |||
| <HeaderTitle>{props.isMyProfile ? "Moj profil" : "Profil kompanije"}</HeaderTitle> | |||
| </Grid> | |||
| <ProfileCardWrapper variant="outlined" isMyProfile={isMyProfile}> | |||
| {isMyProfile ? (<EditButton> | |||
| <ProfileCardWrapper variant="outlined" isMyProfile={props.isMyProfile}> | |||
| {props.isMyProfile ? (<EditButton> | |||
| <EditIcon /> | |||
| </EditButton>) : ( | |||
| <MessageButton> | |||
| @@ -109,7 +90,7 @@ const ProfileCard = () => { | |||
| alignItems="start" | |||
| sx={{ ml: 2 }} | |||
| > | |||
| <ProfileName isMyProfile={isMyProfile} variant="h5"> | |||
| <ProfileName isMyProfile={props.isMyProfile} variant="h5"> | |||
| {profile?.company?.name} | |||
| </ProfileName> | |||
| <ProfilePIBContainer | |||
| @@ -119,7 +100,7 @@ const ProfileCard = () => { | |||
| alignItems="center" | |||
| > | |||
| <PocketIcon /> | |||
| <ProfilePIB isMyProfile={isMyProfile} variant="subtitle2"> | |||
| <ProfilePIB isMyProfile={props.isMyProfile} variant="subtitle2"> | |||
| PIB: {profile?.company?.PIB} | |||
| </ProfilePIB> | |||
| </ProfilePIBContainer> | |||
| @@ -133,20 +114,20 @@ const ProfileCard = () => { | |||
| alignItems={{ xs: "start", sm: "center" }} | |||
| > | |||
| <Stack direction="row"> | |||
| <LocationIcon isMyProfile={isMyProfile} /> | |||
| <ContactItem isMyProfile={isMyProfile} variant="subtitle2"> | |||
| <LocationIcon isMyProfile={props.isMyProfile} /> | |||
| <ContactItem isMyProfile={props.isMyProfile} variant="subtitle2"> | |||
| {profile?.company?.contacts?.location} | |||
| </ContactItem> | |||
| </Stack> | |||
| <Stack direction="row"> | |||
| <MailIcon isMyProfile={isMyProfile} /> | |||
| <ContactItem isMyProfile={isMyProfile} variant="subtitle2"> | |||
| <MailIcon isMyProfile={props.isMyProfile} /> | |||
| <ContactItem isMyProfile={props.isMyProfile} variant="subtitle2"> | |||
| {profile?.email} | |||
| </ContactItem> | |||
| </Stack> | |||
| <Stack direction="row"> | |||
| <GlobeIcon isMyProfile={isMyProfile} /> | |||
| <ContactItem isMyProfile={isMyProfile} variant="subtitle2"> | |||
| <GlobeIcon isMyProfile={props.isMyProfile} /> | |||
| <ContactItem isMyProfile={props.isMyProfile} variant="subtitle2"> | |||
| {profile?.company?.contacts?.web} | |||
| </ContactItem> | |||
| </Stack> | |||
| @@ -197,6 +178,7 @@ const ProfileCard = () => { | |||
| ProfileCard.propTypes = { | |||
| children: PropTypes.node, | |||
| isMyProfile: PropTypes.bool, | |||
| }; | |||
| export default ProfileCard; | |||
| @@ -38,6 +38,8 @@ export const EditButton = styled(Box)` | |||
| export const MessageButton = styled(EditButton)` | |||
| background: ${selectedTheme.primaryPurple}; | |||
| width: 40px; | |||
| height: 40px; | |||
| `; | |||
| export const ProfileCardWrapper = styled(Card)` | |||
| @@ -210,7 +212,8 @@ export const MessageIcon = styled(Mail)` | |||
| width: 19.5px; | |||
| height: 19.5px; | |||
| position: relative; | |||
| right: 0.7px; | |||
| left: 2.5px; | |||
| top: 3.5px; | |||
| & path { | |||
| stroke: ${selectedTheme.primaryYellow}; | |||
| } | |||