Bläddra i källkod

Merged without create-offer

feature/code-cleanup-joca
Djordje Mitrovic 3 år sedan
förälder
incheckning
da81195da6
45 ändrade filer med 1320 tillägg och 173 borttagningar
  1. 5
    2
      src/AppRoutes.js
  2. 44
    0
      src/AppRoutes.js.orig
  3. 4
    0
      src/assets/images/svg/pocket.svg
  4. 5
    6
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.js
  5. 63
    16
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.styled.js
  6. 69
    60
      src/components/Cards/OfferCard/OfferCard.js
  7. 78
    7
      src/components/Cards/OfferCard/OfferCard.styled.js
  8. 19
    7
      src/components/Header/Header.js
  9. 3
    1
      src/components/Header/Header.styled.js
  10. 13
    8
      src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js
  11. 73
    26
      src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.styled.js
  12. 2
    1
      src/components/Popovers/MyPosts/MyPosts.js
  13. 8
    4
      src/components/Popovers/MyProfile/MyProfile.js
  14. 20
    0
      src/components/Profile/Profile.js
  15. 6
    0
      src/components/Profile/Profile.styled.js
  16. 153
    0
      src/components/Profile/ProfileOffers/ProfileOffers.js
  17. 105
    0
      src/components/Profile/ProfileOffers/ProfileOffers.styled.js
  18. 202
    0
      src/components/ProfileCard/ProfileCard.js
  19. 222
    0
      src/components/ProfileCard/ProfileCard.styled.js
  20. 16
    5
      src/components/Scroller/HorizontalScroller.js
  21. 2
    2
      src/components/UserReviewsCard/UserReviewsCard.js
  22. 1
    0
      src/components/UserReviewsCard/UserReviewsCard.styled.js
  23. 1
    0
      src/constants/pages.js
  24. 1
    2
      src/hooks/useQueryString.js
  25. 2
    2
      src/layouts/ItemDetailsLayout/ItemDetailsLayout.js
  26. 8
    0
      src/layouts/ItemDetailsLayout/ItemDetailsLayout.styled.js
  27. 3
    0
      src/layouts/ProfileLayout/ProfileLayout.styled.js
  28. 43
    2
      src/pages/HomePage/HomePageMUI.js
  29. 30
    0
      src/pages/ProfilePage/ProfilePage.js
  30. 15
    0
      src/pages/ProfilePage/ProfilePage.styled.js
  31. 2
    2
      src/request/index.js
  32. 1
    1
      src/request/offersRequest.js
  33. 6
    0
      src/store/actions/offers/offersActionConstants.js
  34. 10
    0
      src/store/actions/offers/offersActions.js
  35. 5
    1
      src/store/actions/profile/profileActionConstants.js
  36. 8
    1
      src/store/actions/profile/profileActions.js
  37. 3
    1
      src/store/middleware/accessTokensMiddleware.js
  38. 1
    1
      src/store/reducers/filters/filtersReducer.js
  39. 10
    1
      src/store/reducers/offers/offersReducer.js
  40. 9
    1
      src/store/reducers/profile/profileReducer.js
  41. 15
    5
      src/store/saga/offersSaga.js
  42. 18
    4
      src/store/saga/profileSaga.js
  43. 4
    0
      src/store/selectors/offersSelectors.js
  44. 7
    3
      src/store/selectors/profileSelectors.js
  45. 5
    1
      src/themes/primaryTheme/primaryThemeColors.js

+ 5
- 2
src/AppRoutes.js Visa fil

@@ -4,7 +4,6 @@ import { Redirect, Route, Switch } from 'react-router-dom';
import {
LOGIN_PAGE,
HOME_PAGE,
FORGOT_PASSWORD_PAGE,
NOT_FOUND_PAGE,
ERROR_PAGE,
BASE_PAGE,
@@ -13,7 +12,9 @@ import {
REGISTER_SUCCESSFUL_PAGE,
RESET_PASSWORD_PAGE,
CREATE_OFFER_PAGE,
ITEM_DETAILS_PAGE
ITEM_DETAILS_PAGE,
FORGOT_PASSWORD_PAGE,
PROFILE_PAGE
} from './constants/pages';
import LoginPage from './pages/LoginPage/LoginPage';
import HomePage from './pages/HomePage/HomePageMUI';
@@ -27,6 +28,7 @@ import RegisterSuccessful from './pages/RegisterPages/RegisterSuccessful.js/Regi
import ResetPasswordPage from './pages/ResetPasswordPage/ResetPasswordPage';
import CreateOffer from './pages/CreateOffer/CreateOffer';
import ItemDetailsPage from './pages/ItemDetailsPage/ItemDetailsPageMUI';
import ProfilePage from './pages/ProfilePage/ProfilePage';


const AppRoutes = () => {
@@ -43,6 +45,7 @@ const AppRoutes = () => {
<Route path={RESET_PASSWORD_PAGE} component={ResetPasswordPage}/>
<Route path={CREATE_OFFER_PAGE} component={CreateOffer}/>
<Route path={ITEM_DETAILS_PAGE} component={ItemDetailsPage} />
<Route path={PROFILE_PAGE} component={ProfilePage} />
<Route path={HOME_PAGE} component={HomePage} />
{/*
<PrivateRoute

+ 44
- 0
src/AppRoutes.js.orig Visa fil

@@ -0,0 +1,44 @@
import React from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';

import {
LOGIN_PAGE,
HOME_PAGE,
NOT_FOUND_PAGE,
ERROR_PAGE,
BASE_PAGE,
} from './constants/pages';
<<<<<<< HEAD

// import LoginPage from './pages/LoginPage/LoginPage';
import LoginPage from './pages/LoginPage/LoginPageMUI';
// import HomePage from './pages/HomePage/HomePage';
import ProfilePage from './pages/ProfilePage/ProfilePage';
=======
import LoginPage from './pages/LoginPage/LoginPage';
import HomePage from './pages/HomePage/HomePageMUI';
>>>>>>> filter-offer-card
import NotFoundPage from './pages/ErrorPages/NotFoundPage';
import ErrorPage from './pages/ErrorPages/ErrorPage';
import PrivateRoute from './components/Router/PrivateRoute';


const AppRoutes = () => {
return (
<Switch>
<Route exact path={BASE_PAGE} component={LoginPage} />
<Route exact path={LOGIN_PAGE} component={LoginPage} />
<Route path={NOT_FOUND_PAGE} component={NotFoundPage} />
<Route path={ERROR_PAGE} component={ErrorPage} />
<PrivateRoute
exact
path={HOME_PAGE}
component={ProfilePage}
/>
<Redirect from="*" to={NOT_FOUND_PAGE} />
</Switch>
)};


export default AppRoutes;

+ 4
- 0
src/assets/images/svg/pocket.svg Visa fil

@@ -0,0 +1,4 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.66659 2.75H18.3333C18.8195 2.75 19.2858 2.94315 19.6296 3.28697C19.9734 3.63079 20.1666 4.0971 20.1666 4.58333V10.0833C20.1666 12.5145 19.2008 14.8461 17.4817 16.5651C15.7626 18.2842 13.4311 19.25 10.9999 19.25C9.79613 19.25 8.60414 19.0129 7.49199 18.5522C6.37984 18.0916 5.36931 17.4163 4.51811 16.5651C2.79902 14.8461 1.83325 12.5145 1.83325 10.0833V4.58333C1.83325 4.0971 2.02641 3.63079 2.37022 3.28697C2.71404 2.94315 3.18035 2.75 3.66659 2.75V2.75Z" stroke="#9E9E9E" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.33325 9.1665L10.9999 12.8332L14.6666 9.1665" stroke="#9E9E9E" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

+ 5
- 6
src/components/Cards/ItemDetailsCard/ItemDetailsCard.js Visa fil

@@ -15,14 +15,13 @@ import {
Details,
OfferDetails,
OfferImage,
Scroller,
} from "./ItemDetailsCard.styled";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as Subcategory } from "../../../assets/images/svg/subcategory.svg";
import { ReactComponent as Quantity } from "../../../assets/images/svg/quantity.svg";
import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg";
import selectedTheme from "../../../themes";
import HorizontalScroller from "../../Scroller/HorizontalScroller";
// import {ReactComponent as DummyImage1 } from "../../../assets/images/svg/dummyImages/offer-1.svg"


const ItemDetailsCard = (props) => {
@@ -60,7 +59,7 @@ const ItemDetailsCard = (props) => {
<InfoText>{offer?.offer?.condition}</InfoText>
</InfoGroup>
<InfoGroup>
<InfoIcon color={"black"} component="span" size="12px">
<InfoIcon color={"black"} component="span" size="12px" last>
<Eye width={"18px"} height={"20px"} />
</InfoIcon>
<InfoText>{offer?.offer?.views?.viewers?.length}</InfoText>
@@ -69,12 +68,12 @@ const ItemDetailsCard = (props) => {
<PostDate>Objavljeno: {dayCreated}.{monthCreated}.{yearCreated}</PostDate>
</OfferInfo>
<Details>
<OfferTitle>{props.offer.name}</OfferTitle>
<HorizontalScroller>
<OfferTitle>{offer?.offer?.name}</OfferTitle>
<Scroller>
{offer?.offer?.images?.map(item => (
<OfferImage src={item} key={item} />
))}
</HorizontalScroller>
</Scroller>
<OfferDetails>
<OfferDescriptionTitle>Opis:</OfferDescriptionTitle>
<OfferDescriptionText>{offer?.offer?.description}</OfferDescriptionText>

+ 63
- 16
src/components/Cards/ItemDetailsCard/ItemDetailsCard.styled.js Visa fil

@@ -4,6 +4,7 @@ import selectedTheme from "../../../themes";
//import { IconButton } from "../../Buttons/IconButton/IconButton";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import { Icon } from "../../Icon/Icon";
import HorizontalScroller from "../../Scroller/HorizontalScroller";

export const ItemDetailsCardContainer = styled(Container)`
display: flex;
@@ -13,11 +14,16 @@ export const ItemDetailsCardContainer = styled(Container)`
margin: 10px 0;
border: 1px solid ${selectedTheme.borderNormal};
background-color: ${(props) =>
props.sponsored === 'true' ? selectedTheme.backgroundSponsoredColor : "white"};
props.sponsored === "true"
? selectedTheme.backgroundSponsoredColor
: "white"};
border-radius: 4px;
padding: 18px;
max-width: 2000px;
position: relative;
@media (max-width: 600px) {
padding-bottom: 50px;
}
`;
export const OfferImage = styled.img`
width: 144px;
@@ -29,30 +35,49 @@ export const OfferInfo = styled(Box)`
flex: 2;
flex-direction: row;
justify-content: space-between;
margin:18px 0;
margin: 18px 0;
@media (max-width: 600px) {
margin: 0;
}
`;
export const InfoGroup = styled(Box)`
display: flex;
flex-direction: row;
align-items:center;
gap:4px;
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
@media (max-width: 600px) {
/* flex: 1; */
${props => props.last && `flex: none;`}
}
`;
export const PostDate = styled(Typography)`
font-family: "Open Sans";
font-size: 12px;
color: ${selectedTheme.primaryText};
font-family: "Open Sans";
font-size: 12px;
color: ${selectedTheme.primaryText};
@media (max-width: 600px) {
display: none;
}
`;
export const Info = styled(Box)`
display:flex;
gap:18px;
display: flex;
gap: 18px;
@media (max-width: 600px) {
flex: 1;
gap: 0;
justify-content: space-between;
margin-bottom: 15px;
}
`;
export const InfoIcon = styled(Box)`
display:flex;
align-items:center;
display: flex;
align-items: center;
`;
export const InfoText = styled(Typography)`
font-family: "Open Sans";
text-transform: capitalize;
@media (max-width: 600px) {
font-size: 12px;
}
`;
export const OfferTitle = styled(Typography)`
font-family: "Open Sans";
@@ -61,6 +86,9 @@ export const OfferTitle = styled(Typography)`
font-weight: 700;
font-size: 24px;
padding: 0 72px;
@media (max-width: 600px) {
padding: 0;
}
`;
export const OfferAuthor = styled(Box)`
display: flex;
@@ -85,6 +113,9 @@ export const OfferDetails = styled(Box)`
flex-wrap: ${(props) => (!props.halfwidth ? "no-wrap" : "wrap")};
justify-content: space-between;
padding: 0 72px;
@media (max-width: 600px) {
padding: 0;
}
`;
export const OfferCategory = styled(Box)`
font-family: "Open Sans";
@@ -112,6 +143,11 @@ export const OfferDescriptionTitle = styled(Box)`
font-size: 12px;
color: ${selectedTheme.primaryDarkText};
line-height: 16px;
@media (max-width: 600px) {
font-size: 9px;
line-height: 13px;
}

`;
export const OfferDescriptionText = styled(Box)`
font-family: "Open Sans";
@@ -124,6 +160,9 @@ export const OfferDescriptionText = styled(Box)`
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
@media (max-width: 600px) {
font-size: 14px;
}
`;
export const OfferDescription = styled(Box)`
flex: 3;
@@ -160,11 +199,19 @@ export const CheckButton = styled(PrimaryButton)`
background-color: ${selectedTheme.primaryPurple} !important;
color: white !important;
}
@media (max-width: 600px) {
height: 44px;
}
`;
export const Details = styled(Box)`
display:flex;
flex-direction:column;
gap:12px;
display: flex;
flex-direction: column;
gap: 12px;
`;
// export const OfferImage = styled.img`
// `
export const Scroller = styled(HorizontalScroller)`
& div {
margin: 0 9px;
}
`

+ 69
- 60
src/components/Cards/OfferCard/OfferCard.js Visa fil

@@ -33,69 +33,76 @@ const OfferCard = (props) => {
const history = useHistory();

const routeToItem = (itemId) => {
history.push(`/proizvodi/${itemId}`)
}
history.push(`/proizvodi/${itemId}`);
};
return (
<React.Fragment>
<OfferCardContainer
sponsored={props.offer.pinned.toString()}
halfwidth={props.halfwidth ? 1 : 0}
>
<OfferTitleAboveImage>{props.offer.name}</OfferTitleAboveImage>
<OfferFlexContainer>
<OfferImageContainer>
<OfferImage src={props.offer.images[0]}></OfferImage>
</OfferImageContainer>
<OfferInfo>
<OfferTitle>{props.offer.name}</OfferTitle>
<OfferAuthor>
<OfferAuthorName>{props.offer.description}</OfferAuthorName>
<OfferLocation>{props.offer.location.city}</OfferLocation>
</OfferAuthor>
<OfferDetails>
<OfferCategory>
<DetailIcon color="black" component="span" size="16px">
<Category width={"14px"} />
</DetailIcon>
<DetailText>{props.offer.category.name}</DetailText>
</OfferCategory>
<OfferViews>
<DetailIcon color="black" component="span" size="16px">
<EyeIcon />
</DetailIcon>
<DetailText>{props.offer.views.viewers.length}</DetailText>
</OfferViews>
</OfferDetails>
</OfferInfo>
{!props.halfwidth ? (
<React.Fragment>
<Line />
<OfferDescription>
<OfferDescriptionTitle>Opis:</OfferDescriptionTitle>
<OfferDescriptionText>
{props.offer.description}
</OfferDescriptionText>
</OfferDescription>
<OfferCardContainer
vertical={props.vertical}
sponsored={
props.pinned !== undefined
? props.pinned.toString()
: props?.offer?.pinned.toString()
}
halfwidth={props.halfwidth ? 1 : 0}
>
<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>
</OfferImageContainer>
<OfferInfo vertical={props.vertical}>
<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>
</OfferAuthor>
<OfferDetails>
<OfferCategory vertical={props.vertical}>
<DetailIcon color="black" component="span" size="16px">
<Category width={"14px"} />
</DetailIcon>
<DetailText>{props?.offer?.category.name}</DetailText>
</OfferCategory>
<OfferViews vertical={props.vertical}>
<DetailIcon color="black" component="span" size="16px">
<EyeIcon />
</DetailIcon>
<DetailText>{props?.offer?.views?.viewers?.length}</DetailText>
</OfferViews>
</OfferDetails>
</OfferInfo>
{!props.halfwidth ? (
<React.Fragment>
<Line />
<OfferDescription>
<OfferDescriptionTitle>Opis:</OfferDescriptionTitle>
<OfferDescriptionText>
{props?.offer?.description}
</OfferDescriptionText>
</OfferDescription>

<CheckButton
variant={props.sponsored ? "contained" : "outlined"}
buttoncolor={selectedTheme.primaryPurple}
textcolor={props.sponsored ? "white" : selectedTheme.primaryPurple}
style={{fontWeight: "600"}}
onClick = {() => routeToItem(props.offer._id)}
>
Pogledaj proizvod
</CheckButton>
</React.Fragment>
) : (
<></>
)}
<CheckButton
variant={props.sponsored ? "contained" : "outlined"}
buttoncolor={selectedTheme.primaryPurple}
textcolor={
props.sponsored ? "white" : selectedTheme.primaryPurple
}
style={{ fontWeight: "600" }}
onClick={() => routeToItem(props?.offer?._id)}
>
Pogledaj proizvod
</CheckButton>
</React.Fragment>
) : (
<></>
)}

<MessageIcon>
<Message />
</MessageIcon>
<MessageIcon vertical={props.vertical}>
<Message />
</MessageIcon>

{/* {props.image}
{/* {props.image}
{props.title}
{props.description}
{props.category}
@@ -104,8 +111,8 @@ const OfferCard = (props) => {
{props.quantity}
{props.package}
{props.numberOfViews} */}
</OfferFlexContainer>
</OfferCardContainer>
</OfferFlexContainer>
</OfferCardContainer>
</React.Fragment>
);
};
@@ -125,6 +132,8 @@ OfferCard.propTypes = {
halfwidth: PropTypes.bool,
sponsored: PropTypes.bool,
offer: PropTypes.any,
pinned: PropTypes.bool,
vertical: PropTypes.bool,
};
OfferCard.defaultProps = {
halfwidth: false,

+ 78
- 7
src/components/Cards/OfferCard/OfferCard.styled.js Visa fil

@@ -28,6 +28,13 @@ export const OfferCardContainer = styled(Container)`
height: 184px;
padding: 18px;
padding-top: 12px;
${(props) =>
props.vertical &&
`
height: 330px;
width: 180px;
margin: 0 18px;
`}
}
`;
export const OfferFlexContainer = styled(Container)`
@@ -36,6 +43,13 @@ export const OfferFlexContainer = styled(Container)`
margin: 0;
padding: 0;
max-height: 184px;
@media (max-width: 600px) {
${(props) =>
props.vertical &&
`
flex-direction: column;
`}
}
`;
export const OfferImage = styled.img`
max-width: 144px;
@@ -43,10 +57,14 @@ export const OfferImage = styled.img`
width: 144px;
height: 144px;
@media (max-width: 600px) {
max-width: 108px;
${(props) =>
!props.vertical &&
`
max-width: 108px;
max-height: 108px;
width: 108px;
height: 108px;
`}
}
`;
export const OfferInfo = styled(Box)`
@@ -55,6 +73,12 @@ export const OfferInfo = styled(Box)`
flex-direction: column;
justify-content: space-between;
margin-left: 18px;
${(props) =>
props.vertical &&
`
margin-left: 0;
margin-top: 5px;
`}
`;
export const OfferTitle = styled(Typography)`
font-family: "Open Sans";
@@ -62,9 +86,21 @@ export const OfferTitle = styled(Typography)`
color: ${selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
cursor: pointer;
@media (max-width: 550px) {
font-size: 18px;
display: none;
${(props) =>
props.vertical &&
`
display: flex;
flex: none;
position: relative;
line-height: 22px;
margin-top: 5px;
font-size: 18px;

`}
}
`;
export const OfferAuthor = styled(Box)`
@@ -79,8 +115,14 @@ export const OfferAuthorName = styled(Typography)`
color: ${selectedTheme.primaryText};
@media (max-width: 600px) {
font-size: 14px;
position: relative;
left: -1px;
${(props) =>
props.vertical &&
`
line-height: 19px;
font-size: 14px;
position: absolute;
bottom: 80px;
`}
}
`;
export const OfferLocation = styled(Typography)`
@@ -88,6 +130,14 @@ export const OfferLocation = styled(Typography)`
color: ${selectedTheme.primaryDarkText};
line-height: 16px;
font-size: 12px;
${(props) =>
props.vertical &&
`
font-size: 12px;
margin-top: 5px;
position: absolute;
bottom: 61px;
`}
`;
export const OfferDetails = styled(Box)`
display: flex;
@@ -106,6 +156,12 @@ export const OfferCategory = styled(Box)`
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
${(props) =>
props.vertical &&
`
position: absolute;
bottom: 15px;
`}
`;
export const OfferPackage = styled(Box)`
font-family: "Open Sans";
@@ -118,6 +174,11 @@ export const OfferViews = styled(Box)`
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
${(props) =>
props.vertical &&
`
display: none;
`}
`;
export const OfferDescriptionTitle = styled(Box)`
font-family: "Open Sans";
@@ -203,6 +264,11 @@ export const MessageIcon = styled(IconButton)`
top: 16px;
right: 16px;
padding: 0;
${(props) =>
props.vertical &&
`
display: none;
`}
& button svg {
width: 16px;
height: 16px;
@@ -218,10 +284,14 @@ export const OfferImageContainer = styled(Box)`
width: 144px;
height: 144px;
@media (max-width: 600px) {
min-width: 108px;
min-height: 108px;
width: 108px;
height: 108px;
${(props) =>
!props.vertical ?
`
min-width: 108px;
min-height: 108px;
width: 108px;
height: 108px;
` : `margin-top: 4px;`}
border-radius: 4px;
overflow: hidden;
box-shadow: 4px 4px 9px rgba(0, 0, 0, 0.12);
@@ -232,6 +302,7 @@ export const OfferTitleAboveImage = styled(OfferTitle)`
padding-top: 5px;
padding-left: 1px;
display: block;
${(props) => props.vertical && `display: none;`}
@media (min-width: 551px) {
display: none;
}

+ 19
- 7
src/components/Header/Header.js Visa fil

@@ -47,17 +47,18 @@ import { useDispatch, useSelector } from "react-redux";
import { selectUserId } from "../../store/selectors/loginSelectors";
import { useSearch } from "../../hooks/useSearch";
import { selectProfileName } from "../../store/selectors/profileSelectors";
import { fetchProfile } from "../../store/actions/profile/profileActions";
import { useHistory, useRouteMatch } from "react-router-dom";
import { LOGIN_PAGE, REGISTER_PAGE } from "../../constants/pages";
import { HOME_PAGE, LOGIN_PAGE, REGISTER_PAGE } from "../../constants/pages";
import useFilters from "../../hooks/useFilters";
import FilterCard from "../Cards/FilterCard/FilterCard";
import { useQueryString } from "../../hooks/useQueryString";
import { convertQueryStringFrontend } from "../../util/helpers/queryHelpers";
import { fetchMineProfile } from "../../store/actions/profile/profileActions";

const Header = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const [openFilters, setOpenFilters] = useState(false);
const [showSearchBar, setShowSearchBar] = useState(true);
const [numberOfFilters, setNumberOfFilters] = useState(0);
const { t } = useTranslation();
const theme = useTheme();
@@ -73,10 +74,8 @@ const Header = () => {
const searchMobileRef = useRef(null);
const queryStringHook = useQueryString();
useEffect(() => {
if (user?.length > 1) {
dispatch(fetchProfile(user));
}
}, [user]);
dispatch(fetchMineProfile());
}, []);
useEffect(() => {
setUserPopoverOpen(false);
setUserAnchorEl(null);
@@ -85,6 +84,13 @@ const Header = () => {
setUserAnchorEl(null);
};
}, []);
useEffect(() => {
if (history.location.pathname !== "/home") {
setShowSearchBar(false);
} else {
setShowSearchBar(true);
}
}, [history.location.pathname])
useEffect(() => {
setNumberOfFilters(filters.calculateFiltersChosen());
}, [
@@ -121,6 +127,7 @@ const Header = () => {
if (
location.pathname === "/login" ||
location.pathname === "/register" ||
location.pathname === "/register/success" ||
location.pathname === "/forgot-password" ||
location.pathname === "/reset-password" ||
location.pathname === "/"
@@ -248,6 +255,10 @@ const Header = () => {
setOpenFilters((prevState) => !prevState);
};

const handleLogoClick = () => {
history.push(HOME_PAGE);
}

return (
<HeaderContainer style={{ display: shouldShow ? "block" : "none" }}>
<AppBar
@@ -258,7 +269,7 @@ const Header = () => {
>
<Toolbar>
<ToolsContainer>
<LogoContainer>
<LogoContainer onClick={() => handleLogoClick()}>
<LogoHorizontal />
</LogoContainer>
{matches && (
@@ -422,6 +433,7 @@ const Header = () => {
</AppBar>
<SearchInputMobile
fullWidth
shouldShow={showSearchBar}
ref={searchMobileRef}
InputProps={{
endAdornment: (

+ 3
- 1
src/components/Header/Header.styled.js Visa fil

@@ -61,6 +61,7 @@ export const LogoContainer = styled(Box)`
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
`;
export const ToolsButtonsContainer = styled(Box)`
display: flex;
@@ -176,8 +177,9 @@ export const SearchInputMobile = styled(SearchInput)`
width: 80%;
top: 70px;
height: 46px;
left: -50px;
left: -5px;
font-family: "Open Sans";
${props => !props.shouldShow && `display: none;`}
& div {
background-color: white;
height: 40px;

+ 13
- 8
src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js Visa fil

@@ -12,14 +12,17 @@ import {
HeaderDetails,
BottomDetails,
StatusText,
PIBIcon,
} from "./ItemDetailsHeaderCard.styled";
import { ItemDetailsHeaderContainer } from "./ItemDetailsHeaderCard.styled";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as PIB } from "../../../assets/images/svg/pib.svg";
import { ReactComponent as MessageColor } from "../../../assets/images/svg/mailColor.svg";
import selectedTheme from "../../../themes";
import { useHistory } from "react-router-dom";

const ItemDetailsHeaderCard = (props) => {
const history = useHistory();
console.log("header offer: ", props.offer);
const offer = props.offer;
if (!props.offer) {
@@ -39,26 +42,28 @@ const ItemDetailsHeaderCard = (props) => {
100
);
}
const handleGoProfile = () => {
history.push(`/profile/${offer?.offer?.userId}`);
}
return (
<ItemDetailsHeaderContainer
sponsored={props.sponsored.toString()}
sponsored={offer?.offer?.pinned?.toString()}
halfwidth={props.halfwidth ? 1 : 0}
>
<HeaderTop>
<OfferImage src={offer?.companyData?.image}/>
<OfferDetails>
<OfferTitle>{offer?.companyData?.company?.name}</OfferTitle>
<OfferTitle onClick={handleGoProfile}>{offer?.companyData?.company?.name}</OfferTitle>
<DetailContainer>
<DetailIcon
<PIBIcon
color={selectedTheme.iconStrokeColor}
component="span"
size="22px"
>
<PIB width={"22px"} />
</DetailIcon>
<PIB />
</PIBIcon>
<DetailText>PIB - {offer?.companyData?.company?.PIB}</DetailText>
</DetailContainer>
<DetailContainer>
<DetailContainer shouldHideResponsive>
<DetailIcon
color={selectedTheme.iconStrokeColor}
component="span"
@@ -66,7 +71,7 @@ const ItemDetailsHeaderCard = (props) => {
>
<Category width={"22px"} />
</DetailIcon>
<DetailText>
<DetailText >
{offer?.companyData?.company?.contacts?.location}
</DetailText>
</DetailContainer>

+ 73
- 26
src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.styled.js Visa fil

@@ -12,44 +12,58 @@ export const ItemDetailsHeaderContainer = styled(Box)`
box-sizing: border-box;
margin: 10px 0;
background-color: ${(props) =>
props.sponsored === 'true' ? selectedTheme.backgroundSponsoredColor : "white"};
props.sponsored === "true"
? selectedTheme.backgroundSponsoredColor
: "white"};
border-radius: 4px;
border: 1px solid ${selectedTheme.borderNormal};
max-width: 2000px;
position: relative;
`;
export const DetailContainer = styled(Box)`
display: flex;
flex-direction: row;
align-items: center;
gap:7px;
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
display: flex;
flex-direction: row;
align-items: center;
gap: 7px;
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
line-height: 16px;
margin-bottom: 7px;
font-size: 12px;
@media (max-width: 600px) {
${(props) => props.shouldHideResponsive && `display: none;`}
}
`;
export const HeaderTop = styled(Box)`
display:flex;
flex-direction: row;
padding:18px;
gap:18px;
display: flex;
flex-direction: row;
padding: 18px;
gap: 18px;
`;
export const HeaderDetails = styled(Box)`
background-color: ${selectedTheme.primaryIconBackgroundColor};
`;
background-color: ${selectedTheme.primaryIconBackgroundColor};
`;
export const BottomDetails = styled(Box)`
max-width:fit-content;
max-width: fit-content;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 12px;
grid-row-gap: 12px;
grid-row-gap: 12px;
padding: 18px;
@media (max-width: 600px) {
display: flex;
flex-direction: column;
}
`;
export const OfferImage = styled.img`
border-radius: 50%;
width: 144px;
height: 144px;
border-radius: 50%;
width: 144px;
height: 144px;
@media (max-width: 600px) {
width: 90px;
height: 90px;
}
`;
export const OfferInfo = styled(Box)`
display: flex;
@@ -59,11 +73,15 @@ export const OfferInfo = styled(Box)`
margin-left: 18px;
`;
export const OfferTitle = styled(Typography)`
margin-bottom:12px;
margin-bottom: 12px;
font-family: "Open Sans";
color: ${selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
cursor: pointer;
@media (max-width: 600px) {
font-size: 18px;
}
`;
export const OfferAuthor = styled(Box)`
display: flex;
@@ -96,9 +114,12 @@ export const OfferDetails = styled(Box)`
`;

export const StatusText = styled(Grid)`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
@media (max-width: 600px) {
font-size: 12px;
}
`;
export const OfferCategory = styled(Box)`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
@@ -150,8 +171,8 @@ export const Line = styled(Box)`
margin: auto 0;
`;
export const DetailIcon = styled(Icon)`
display:flex;
align-items:center;
display: flex;
align-items: center;
& svg {
width: 22px;
position: relative;
@@ -163,6 +184,9 @@ export const DetailText = styled(Typography)`
line-height: 16px;
font-size: 16px;
position: relative;
@media (max-width: 600px) {
font-size: 14px;
}
`;
export const CheckButton = styled(PrimaryButton)`
width: 180px;
@@ -185,4 +209,27 @@ export const MessageIcon = styled(IconButton)`
border-radius: 100%;
padding-top: 2px;
text-align: center;
@media (max-width: 600px) {
width: 32px;
height: 32px;
& button svg {
width: 16px;
height: 16px;
position: relative;
top: -4px;
left: -2px;
}
}
`;
export const PIBIcon = styled(DetailIcon)`
position: relative;
top: 1px;
& span svg {
width: 22px;
height: 22px;
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
}
`;

+ 2
- 1
src/components/Popovers/MyPosts/MyPosts.js Visa fil

@@ -31,6 +31,7 @@ export const MyPosts = () => {
useEffect(() => {
dispatch(fetchMineOffers());
}, []);
console.log("mineOffers: ", mineOffers)
useEffect(() => {
if (mineOffers?.length > 0) {
if (mineOffers.length > 1) {
@@ -63,7 +64,7 @@ export const MyPosts = () => {
setArrayOfMineOffers([])
}
}
});
}, [mineOffers]);
return (
<HeaderPopover
title={t("header.myOffers")}

+ 8
- 4
src/components/Popovers/MyProfile/MyProfile.js Visa fil

@@ -3,9 +3,9 @@ import { LogoutIcon, ProfileImgPIB } from "./MyProfile.styled";
import HeaderPopover from "../HeaderPopover/HeaderPopover";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { selectProfile } from "../../../store/selectors/profileSelectors";
import { selectMineProfile } from "../../../store/selectors/profileSelectors";
import { selectUserId } from "../../../store/selectors/loginSelectors";
import { fetchProfile } from "../../../store/actions/profile/profileActions";
import { fetchMineProfile } from "../../../store/actions/profile/profileActions";
import selectedTheme from "../../../themes";
import { EyeIcon } from "../HeaderPopover/HeaderPopover.styled";
import { logoutUser } from "../../../store/actions/login/loginActions";
@@ -14,14 +14,14 @@ import { LOGIN_PAGE } from "../../../constants/pages";

export const MyProfile = () => {
const { t } = useTranslation();
const profile = useSelector(selectProfile);
const profile = useSelector(selectMineProfile);
const userId = useSelector(selectUserId);
const dispatch = useDispatch();
const history = useHistory();
const [profileAsArray, setProfileAsArray] = useState([]);
useEffect(() => {
if (userId?.length > 1) {
dispatch(fetchProfile(userId));
dispatch(fetchMineProfile());
}
}, [userId]);
useEffect(() => {
@@ -47,6 +47,9 @@ export const MyProfile = () => {
const handleLogout = () => {
dispatch(logoutUser(handleLogoutSuccess));
};
const seeMyProfile = () => {
history.push(`/profile/${userId}`);
}
return (
<HeaderPopover
title={t("header.myProfile")}
@@ -54,6 +57,7 @@ export const MyProfile = () => {
buttonText={t("header.checkProfile")}
buttonIcon={<EyeIcon color={selectedTheme.iconYellowColor} />}
isProfile
buttonOnClick={() => seeMyProfile()}
secondButtonIcon={<LogoutIcon color={selectedTheme.iconYellowColor} />}
secondButtonText={"Odjavite se"}
secondButtonOnClick={handleLogout}

+ 20
- 0
src/components/Profile/Profile.js Visa fil

@@ -0,0 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
import { ProfileContainer } from './Profile.styled'
import ProfileCard from '../ProfileCard/ProfileCard'
import ProfileOffers from './ProfileOffers/ProfileOffers'

const Profile = () => {
return (
<ProfileContainer>
<ProfileCard />
<ProfileOffers />
</ProfileContainer>
)
}

Profile.propTypes = {
children: PropTypes.node,
}

export default Profile

+ 6
- 0
src/components/Profile/Profile.styled.js Visa fil

@@ -0,0 +1,6 @@
import { Box } from "@mui/material";
import styled from "styled-components";

export const ProfileContainer = styled(Box)`

`

+ 153
- 0
src/components/Profile/ProfileOffers/ProfileOffers.js Visa fil

@@ -0,0 +1,153 @@
import React from "react";
import PropTypes from "prop-types";
import {
DownArrow,
HeaderSelect,
HeaderTitle,
IconContainer,
OffersContainer,
OffersIcon,
OffersScroller,
ProfileOffersContainer,
SearchIcon,
SearchInput,
SelectOption,
} from "./ProfileOffers.styled";
import { Grid } from "@mui/material";
import { useState } from "react";
import { sortEnum } from "../../../enums/sortEnum";
import { useEffect } from "react";
import { useSelector } from "react-redux";
import OfferCard from "../../Cards/OfferCard/OfferCard";
import { useTranslation } from "react-i18next";
import { useRef } from "react";
import { selectProfileOffers } from "../../../store/selectors/offersSelectors";
import useScreenDimensions from "../../../hooks/useScreenDimensions";

const ProfileOffers = () => {
const [sortOption, setSortOption] = useState(sortEnum.INITIAL);
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) {
newOffersToShow.sort(
(a, b) => new Date(a._created) - new Date(b._created)
);
}
if (sortOption.value === sortEnum.NEW.value) {
newOffersToShow.sort(
(a, b) => new Date(b._created) - new Date(a._created)
);
}
if (sortOption.value === sortEnum.POPULAR.value) {
newOffersToShow.sort(
(a, b) => a.views.viewers.length - b.views.viewers.length
);
}
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) {
if (sortEnum[sortOption].value === event.target.value) {
chosenOption = sortEnum[sortOption];
setSortOption(chosenOption);
}
}
};
let listener;
const handleFocusSearch = () => {
listener = (event) => {
if (event.keyCode === 13) {
event.preventDefault();
handleSearch();
}
};
searchRef.current.addEventListener("keyup", listener);
};
const handleBlurSearch = () => {
searchRef.current.removeEventListener("keyup", listener);
};
return (
<ProfileOffersContainer>
<HeaderSelect
value={sortOption?.value ? sortOption.value : sortEnum.INITIAL.value}
IconComponent={DownArrow}
onChange={handleChangeSelect}
>
{Object.keys(sortEnum).map((property) => {
return (
<SelectOption
value={sortEnum[property].value}
key={sortEnum[property].value}
>
{sortEnum[property].mainText}
</SelectOption>
);
})}
</HeaderSelect>
<Grid
container
direction="row"
justifyContent="start"
alignItems="center"
sx={{ mb: 1.4 }}
>
<OffersIcon />
<HeaderTitle>Moje objave</HeaderTitle>
</Grid>
<SearchInput
fullWidth
ref={searchRef}
onFocus={handleFocusSearch}
onBlur={handleBlurSearch}
// ref={searchRef}
placeholder={t("header.searchOffers")}
italicPlaceholder
InputProps={{
endAdornment: (
<IconContainer onClick={handleSearch}>
<SearchIcon />
</IconContainer>
),
}}
/>
<OffersContainer>
{dimensions.width > 600 ? (
offersToShow.map((item) => (
<OfferCard offer={item} key={JSON.stringify(item)} pinned />
))
) : (
<OffersScroller hideArrows>
{offersToShow.map((item) => (
<OfferCard vertical offer={item} key={JSON.stringify(item)} pinned />))}
</OffersScroller>
)}
</OffersContainer>
</ProfileOffersContainer>
);
};

ProfileOffers.propTypes = {
children: PropTypes.node,
};

export default ProfileOffers;

+ 105
- 0
src/components/Profile/ProfileOffers/ProfileOffers.styled.js Visa fil

@@ -0,0 +1,105 @@
import { Box, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";
import {ReactComponent as Search} from "../../../assets/images/svg/magnifying-glass.svg"
import {ReactComponent as Refresh} from "../../../assets/images/svg/refresh.svg"
import { TextField } from "../../TextFields/TextField/TextField";
import { Icon } from "../../Icon/Icon";
import Select from "../../Select/Select";
import Option from "../../Select/Option/Option";
import { ReactComponent as Down } from "../../../assets/images/svg/down-arrow.svg";
import HorizontalScroller from "../../Scroller/HorizontalScroller";

export const ProfileOffersContainer = styled(Box)`
width: 100%;
box-sizing: border-box;
padding: 0 50px;
margin-top: 34px;
position: relative;
@media (max-width: 600px) {
padding: 0;
}
`;
export const HeaderTitle = styled(Typography)`
font-size: 16px;
font-family: "Open Sans";
color: ${selectedTheme.primaryDarkTextThird};
position: relative;
margin-left: 10px;
@media (max-width: 600px) {
font-size: 12px;
}
`;
export const OffersIcon = styled(Refresh)`
width: 18px;
height: 18px;
& path {
stroke: ${selectedTheme.primaryDarkTextThird};
}
@media (max-width: 600px) {
width: 12px;
height: 12px;
}
`
export const SearchInput = styled(TextField)`
position: relative;
top: 15px;
& div fieldset {
border-color: ${selectedTheme.primaryPurple} !important;
}
@media (max-width: 600px) {
top: 5px;
height: 46px;
& div {
background-color: white;
}
}
`
export const SearchIcon = styled(Search)`
width: 18px;
height: 18px;
`
export const IconContainer = styled(Icon)`
cursor: pointer;
position: relative;
top: 4px;
`
export const HeaderSelect = styled(Select)`
width: 210px;
height: 35px;
font-family: "Open Sans";
margin-top: 3px;
font-weight: 400;
position: absolute;
top: -8px;
right: 50px;
& div:first-child {
padding-left: 8px;
}

@media (max-width: 650px) {
width: 144px;
height: 30px;
font-size: 14px;
right: 1px;
}
`;
export const SelectOption = styled(Option)`
@media (max-width: 600px) {
height: 20px !important;
min-height: 35px;
margin: 2px;
}
`;
export const DownArrow = styled(Down)`
`
export const OffersContainer = styled(Box)`
margin-top: 30px;
`
export const OffersScroller = styled(HorizontalScroller)`
height: 330px;
margin-left: 0;
& div {
margin-left: 0;
}
`

+ 202
- 0
src/components/ProfileCard/ProfileCard.js Visa fil

@@ -0,0 +1,202 @@
import React from "react";
import PropTypes from "prop-types";
import {
EditButton,
ProfileCardWrapper,
ProfileName,
ProfilePIB,
ProfileMainInfo,
ProfileContact,
ContactItem,
ProfileStats,
StatsItem,
ProfileCardContainer,
AvatarImage,
HeaderTitle,
PocketIcon,
LocationIcon,
MailIcon,
GlobeIcon,
ProfilePIBContainer,
EditIcon,
MessageIcon,
MessageButton,
} from "./ProfileCard.styled";

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 { 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 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) {
percentOfSucceededExchanges = 0;
} else {
percentOfSucceededExchanges = Math.ceil(
(profile?.statistics?.exchanges?.total /
profile?.statistics?.exchanges?.succeeded) *
100
);
}
console.log(profile);
return (
<>
<ProfileCardContainer>
<Grid
container
direction="row"
justifyContent="start"
alignItems="center"
sx={{ mb: 1.4 }}
>
<PersonOutlineIcon color="action" sx={{ mr: 0.9 }} />
<HeaderTitle>Moj Profil</HeaderTitle>
</Grid>
<ProfileCardWrapper variant="outlined" isMyProfile={isMyProfile}>
{isMyProfile ? (<EditButton>
<EditIcon />
</EditButton>) : (
<MessageButton>
<MessageIcon />
</MessageButton>
)}
<Grid
container
direction="column"
justifyContent="center"
alignItems="start"
>
{/* Profile Main Info */}
<ProfileMainInfo
container
direction="row"
justifyContent="start"
alignItems="start"
>
<Grid
direction="column"
justifyContent="start"
alignItems="center"
>
<AvatarImage alt="Player.rs" src={profile?.image} />
</Grid>
<Grid
direction="column"
justifyContent="center"
alignItems="start"
sx={{ ml: 2 }}
>
<ProfileName isMyProfile={isMyProfile} variant="h5">
{profile?.company?.name}
</ProfileName>
<ProfilePIBContainer
container
direction="row"
justifyContent="center"
alignItems="center"
>
<PocketIcon />
<ProfilePIB isMyProfile={isMyProfile} variant="subtitle2">
PIB: {profile?.company?.PIB}
</ProfilePIB>
</ProfilePIBContainer>
</Grid>
</ProfileMainInfo>
{/* Profile Contact */}
<ProfileContact
container
direction={{ xs: "column", sm: "row" }}
justifyContent={{ xs: "center", sm: "start" }}
alignItems={{ xs: "start", sm: "center" }}
>
<Stack direction="row">
<LocationIcon isMyProfile={isMyProfile} />
<ContactItem isMyProfile={isMyProfile} variant="subtitle2">
{profile?.company?.contacts?.location}
</ContactItem>
</Stack>
<Stack direction="row">
<MailIcon isMyProfile={isMyProfile} />
<ContactItem isMyProfile={isMyProfile} variant="subtitle2">
{profile?.email}
</ContactItem>
</Stack>
<Stack direction="row">
<GlobeIcon isMyProfile={isMyProfile} />
<ContactItem isMyProfile={isMyProfile} variant="subtitle2">
{profile?.company?.contacts?.web}
</ContactItem>
</Stack>
</ProfileContact>
{/* Profile Stats */}
<ProfileStats
container
direction="row"
justifyContent="start"
alignItems="center"
>
<Grid
container
direction="column"
justifyContent="center"
alignItems="start"
sx={{ width: "fit-content" }}
>
<StatsItem variant="subtitle2">
<b>{profile?.statistics?.publishes?.count}</b> objava
</StatsItem>

<StatsItem variant="subtitle2">
<b>{percentOfSucceededExchanges}%</b> uspešna komunikacija
</StatsItem>
</Grid>
<Grid
container
direction="column"
justifyContent="center"
alignItems="start"
sx={{ width: "fit-content" }}
>
<StatsItem variant="subtitle2">
<b>{profile?.statistics?.views?.count}</b> ukupnih pregleda
</StatsItem>
<StatsItem variant="subtitle2">
<b>{percentOfSucceededExchanges}%</b> korektna saradnja
</StatsItem>
</Grid>
</ProfileStats>
</Grid>
</ProfileCardWrapper>
</ProfileCardContainer>
</>
);
};

ProfileCard.propTypes = {
children: PropTypes.node,
};

export default ProfileCard;

+ 222
- 0
src/components/ProfileCard/ProfileCard.styled.js Visa fil

@@ -0,0 +1,222 @@
import styled from "styled-components";
import { Card, Typography, Grid, Box } from "@mui/material";
import selectedTheme from "../../themes";
import { ReactComponent as Edit } from "../../assets/images/svg/edit.svg";
import { ReactComponent as Pocket } from "../../assets/images/svg/pocket.svg";
import { ReactComponent as Globe } from "../../assets/images/svg/globe.svg";
import { ReactComponent as Mail } from "../../assets/images/svg/mail.svg";
import { ReactComponent as Location } from "../../assets/images/svg/location.svg";
// import { PRIMARY_PURPLE_COLOR, PRIMARY_YELLOW_COLOR } from '../../constants/stylesConstants';

export const ProfileCardContainer = styled(Box)`
width: 100%;
box-sizing: border-box;
padding: 0 50px;
margin-top: 34px;
@media (max-width: 600px) {
padding: 0;
}
`;
export const EditIcon = styled(Edit)`
width: 18px;
height: 18px;
& path {
stroke: ${selectedTheme.primaryPurple};
}
`;
export const EditButton = styled(Box)`
position: absolute;
right: 1rem;
top: 1rem;
color: ${selectedTheme.primaryPurple};
font-weight: 900;
background: #f4f4f4;
border-radius: 360px;
padding: 0.45rem 0.45rem 0.27rem 0.57rem;
cursor: pointer;
`;

export const MessageButton = styled(EditButton)`
background: ${selectedTheme.primaryPurple};
`;

export const ProfileCardWrapper = styled(Card)`
border: 1px solid ${selectedTheme.primaryPurple};
background: ${(props) =>
props.isMyProfile ? selectedTheme.primaryPurple : "white"};
width: 100%;
min-width: fit-content;
padding: 1rem;
position: relative;
`;

export const ProfileName = styled(Typography)`
color: ${(props) =>
props.isMyProfile
? selectedTheme.primaryYellow
: selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
font-family: "Open Sans";
margin-bottom: 5px;
@media (max-width: 600px) {
font-size: 18px;
}
`;

export const ProfilePIB = styled(Typography)`
color: ${(props) =>
props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
margin-top: 0.18rem;
font-family: "Open Sans";
font-size: 16px;
padding-top: 1px;
@media (max-width: 600px) {
font-size: 14px;
}
`;
export const ProfilePIBContainer = styled(Grid)`
position: relative;
left: 5px;
`;

export const ProfileMainInfo = styled(Grid)``;

export const ProfileContact = styled(Grid)`
padding-top: 2rem;
padding-bottom: 2rem;
@media (max-width: 600px) {
padding-bottom: 1rem;
}
`;

export const ContactItem = styled(Typography)`
margin-right: 2rem;
margin-left: 0.4rem;
color: ${(props) =>
props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
display: unset;
font-family: "Open Sans";
letter-spacing: 0.02em;
font-size: 16px;
position: relative;
bottom: 1px;
@media (max-width: 600px) {
font-size: 14px;
bottom: 4px;
}
`;

export const StatsItem = styled(Typography)`
margin-right: 2rem;
display: unset;
margin-left: 1rem;
font-family: "Open Sans";
font-size: 16px;
margin-bottom: 2px;
@media (max-width: 600px) {
font-size: 12px;
}
`;

export const ProfileStats = styled(Grid)`
background: ${selectedTheme.primaryDarkTextSecond};
width: calc(100% + 2rem);
padding-top: 1.3rem;
padding-bottom: 1.3rem;
margin-bottom: -1rem;
margin-left: -1rem;
border-radius: 0 0 4px 4px;
`;
export const AvatarImage = styled.img`
min-height: 144px;
min-width: 144px;
width: 144px;
height: 144px;
border-radius: 100%;
@media (max-width: 600px) {
min-height: 90px;
min-width: 90px;
width: 90px;
height: 90px;
}
`;
export const HeaderTitle = styled(Typography)`
font-size: 16px;
font-family: "Open Sans";
color: ${selectedTheme.primaryDarkTextThird};
position: relative;
@media (max-width: 600px) {
font-size: 12px;
}
`;
export const PocketIcon = styled(Pocket)`
width: 22px;
height: 22px;
position: relative;
left: -5px;
top: 2px;
& path {
stroke: #b4b4b4;
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const MailIcon = styled(Mail)`
height: 24px;
width: 24px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const GlobeIcon = styled(Globe)`
height: 22px;
width: 22px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const LocationIcon = styled(Location)`
height: 22px;
width: 22px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const MessageIcon = styled(Mail)`
width: 19.5px;
height: 19.5px;
position: relative;
right: 0.7px;
& path {
stroke: ${selectedTheme.primaryYellow};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
right: 0.5px;
}
`;

+ 16
- 5
src/components/Scroller/HorizontalScroller.js Visa fil

@@ -54,9 +54,14 @@ const HorizontalScroller = (props) => {
scrollRef.current.scrollBy({ left: -50, behaviour: "smooth" });
};
return (
<HorizontalScrollerContainer style={props.containerStyle}>
<ArrowButton onClick={handleLeft} disabled={isDisabledLeftButton} side={"left"}>
</ArrowButton>
<HorizontalScrollerContainer style={props.containerStyle} className={props.className}>
{!props.hideArrows && (
<ArrowButton
onClick={handleLeft}
disabled={isDisabledLeftButton}
side={"left"}
></ArrowButton>
)}
<ListContainer
innerRef={scrollRef}
style={props.listStyle}
@@ -64,8 +69,13 @@ const HorizontalScroller = (props) => {
>
{props.children}
</ListContainer>
<ArrowButton onClick={handleRight} disabled={isDisabledRightButton} side={"right"}>
</ArrowButton>
{!props.hideArrows && (
<ArrowButton
onClick={handleRight}
disabled={isDisabledRightButton}
side={"right"}
></ArrowButton>
)}
</HorizontalScrollerContainer>
);
};
@@ -75,6 +85,7 @@ HorizontalScroller.propTypes = {
className: PropTypes.string,
containerStyle: PropTypes.any,
listStyle: PropTypes.any,
hideArrows: PropTypes.bool,
};

export default HorizontalScroller;

+ 2
- 2
src/components/UserReviewsCard/UserReviewsCard.js Visa fil

@@ -34,7 +34,7 @@ const UserReviewsCard = (props) => {
<Typography>{props.heading}</Typography>
</Grid>
<ReviewList>
{dataMockupdata.map((review) => (
{offer?.companyData?.lastThreeReviews?.map((review) => (
<>
<ListItem
alignItems="flex-start"
@@ -69,7 +69,7 @@ const UserReviewsCard = (props) => {
variant="body2"
color="text.primary"
>
&quot;{review.quote}&quot;
&quot;{review?.quote}&quot;
</Typography>
</Grid>
</Grid>

+ 1
- 0
src/components/UserReviewsCard/UserReviewsCard.styled.js Visa fil

@@ -13,6 +13,7 @@ export const ReviewList = styled(List)`
padding: 2rem;
border-radius: 4px 0 0 4px;
height: 100%;
width: 100%;
overflow-y: auto;
&::-webkit-scrollbar {
width: 5px;

+ 1
- 0
src/constants/pages.js Visa fil

@@ -10,3 +10,4 @@ export const REGISTER_SUCCESSFUL_PAGE = "/register/success";
export const RESET_PASSWORD_PAGE = "/reset-password/:token";
export const CREATE_OFFER_PAGE = "/create-offer";
export const ITEM_DETAILS_PAGE = "/proizvodi/:idProizvod";
export const PROFILE_PAGE = "/profile/:idProfile"

+ 1
- 2
src/hooks/useQueryString.js Visa fil

@@ -3,7 +3,6 @@ import { useEffect, useState } from "react";
// import _ from "lodash"
import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import { HOME_PAGE } from "../constants/pages";
import { setQueryString as setQueryStringSaga } from "../store/actions/queryString/queryStringActions";
import { selectQueryString } from "../store/selectors/queryStringSelectors";
// import useFilters from "./useFilters";
@@ -53,7 +52,7 @@ export const useQueryString = () => {
useEffect(() => {
if (!initial) {
history.push({
pathname: HOME_PAGE,
pathname: history.location.pathname,
search: "?" + globalQueryString,
});
}

+ 2
- 2
src/layouts/ItemDetailsLayout/ItemDetailsLayout.js Visa fil

@@ -8,10 +8,10 @@ const ItemDetailsLayout = (props) => {
<ItemDetailsLayoutContainer>
{props.children}
<Grid container maxHeight="xl" spacing={2}>
<Content item xs={10} lg={9} xl={9.6} md={8} >
<Content item xs={12} lg={9} xl={9.6} md={8} >
{props.content}
</Content>
<RightCard item xs={2} lg={3} xl={2.4} md={4} >
<RightCard item xs={0} lg={3} xl={2.4} md={4} >
{props.rightCard}
</RightCard>

+ 8
- 0
src/layouts/ItemDetailsLayout/ItemDetailsLayout.styled.js Visa fil

@@ -10,11 +10,19 @@ export const ItemDetailsLayoutContainer = styled(Container)`
display: flex;
flex: 1;
height: 100%;
@media (max-width: 1024px) {
padding-right: 54px;
}
@media (max-width: 600px) {
padding-left: 18px;
padding-right: 18px;
}
`

export const RightCard = styled(Grid)`
margin-top: 30px;
border-top-right-radius: 4px;
width: 100%;
`
export const Content = styled(Grid)`
`

+ 3
- 0
src/layouts/ProfileLayout/ProfileLayout.styled.js Visa fil

@@ -11,6 +11,9 @@ export const ProfileLayoutContainer = styled(Container)`
flex: 1;
height: 100%;
margin-top: 80px;
@media (max-width: 600px) {
margin-top: 40px;
}
`

export const LeftCard = styled(Grid)`

+ 43
- 2
src/pages/HomePage/HomePageMUI.js Visa fil

@@ -21,6 +21,47 @@ const HomePage = () => {
<MainLayout leftCard={<FilterCard />} content={<MarketPlace />} />
</HomePageContainer>
);
};

}
export default HomePage;

// import React from 'react';
// import { Box } from '@mui/material';
// import Navbar from '../../components/MUI/NavbarComponent';
// import Modals from '../../components/MUI/Examples/ModalsExample';
// import DataGrid from '../../components/MUI/Examples/DataGridExample';
// import PagingSortingFiltering from '../../components/MUI/Examples/PagingSortingFilteringExample';
// import PagingSortingFilteringServerSide from '../../components/MUI/Examples/PagingSortingFilteringExampleServerSide';
// import RandomDataProvider from '../../context/RandomDataContext';
// import { GridStyled } from './HomePage.styled';
// import OfferCard from '../../components/Cards/OfferCard/OfferCard';

// const HomePage = () => {
// return (
// <>
// <Navbar />
// <OfferCard />
// <Box sx={{ mt: 4, mx: 4 }}>

// <GridStyled container spacing={2} justifyContent="center">
// <GridStyled item xs={12} md={3}>
// <Modals />

// </GridStyled>
// <GridStyled item xs={12} md={6}>
// <DataGrid />
// </GridStyled>
// <GridStyled item xs={12} md={9}>
// <PagingSortingFiltering />
// </GridStyled>
// <GridStyled item xs={12} md={9}>
// {/* Move to higher components? */}
// <RandomDataProvider>
// <PagingSortingFilteringServerSide />
// </RandomDataProvider>
// </GridStyled>
// </GridStyled>
// </Box>
// </>
// );
// };


+ 30
- 0
src/pages/ProfilePage/ProfilePage.js Visa fil

@@ -0,0 +1,30 @@
import React from "react";
// import Navbar from "../../components/MUI/NavbarComponent";
import UserReviewsCard from "../../components/UserReviewsCard/UserReviewsCard";
// import { ProfilePageWrapper } from "./ProfilePage.styled";
import ItemDetailsLayout from "../../layouts/ItemDetailsLayout/ItemDetailsLayout";
import { ProfilePageContainer } from "./ProfilePage.styled";
import Profile from "../../components/Profile/Profile";
// import FilterCard from "../../components/Cards/FilterCard/FilterCard";

const ProfilePage = () => {
return (
<ProfilePageContainer>
{/* <Navbar /> */}
{/* <ProfilePageWrapper
container
direction="row"
justifyContent="center"
alignItems="start"
sx={{ pt: 3 }}
>
{/* <FilterCard />
<ProfileCard />
<UserReviewsCard heading="Moje ocene" />
</ProfilePageWrapper> */}
<ItemDetailsLayout content={<Profile/>} rightCard={<UserReviewsCard/>} />
</ProfilePageContainer>
);
};

export default ProfilePage;

+ 15
- 0
src/pages/ProfilePage/ProfilePage.styled.js Visa fil

@@ -0,0 +1,15 @@
import styled from 'styled-components';
import { Grid, Box } from '@mui/material';

export const ProfilePageWrapper = styled(Grid)`
background: #F4F4F4;
min-height: 100vh;
max-height: fit-content;
padding-bottom: 2rem;
`;
export const ProfilePageContainer = styled(Box)`
margin-top: 80px;
@media (max-width: 600px) {
margin-top: 40px;
}
`

+ 2
- 2
src/request/index.js Visa fil

@@ -2,8 +2,8 @@ import axios from "axios";
import queryString from "qs";

const request = axios.create({
baseURL: "http://192.168.88.150:3001/",
// baseURL: "http://192.168.88.176:3001/",
// baseURL: "http://192.168.88.150:3001/",
baseURL: "http://192.168.88.175:3005/",
headers: {
"Content-Type": "application/json",
},

+ 1
- 1
src/request/offersRequest.js Visa fil

@@ -17,6 +17,6 @@ export const attemptFetchMoreOffers = (page, payload) => {
export const attemptAddOffer = (payload) => {
return postRequest(apiEndpoints.offers.addOffer, payload)
}
export const attemptFetchMineOffers = (payload) => {
export const attemptFetchProfileOffers = (payload) => {
return getRequest(`${apiEndpoints.offers.mineOffers}/${payload}/offers`)
}

+ 6
- 0
src/store/actions/offers/offersActionConstants.js Visa fil

@@ -13,6 +13,11 @@ export const OFFERS_SUCCESS = createSuccessType(OFFERS_SCOPE);
export const OFFERS_ERROR = createErrorType(OFFERS_SCOPE);
export const OFFERS_CLEAR = createClearType(OFFERS_SCOPE);

const OFFERS_PROFILE_SCOPE = "OFFERS_PROFILE_SCOPE";
export const OFFERS_PROFILE_FETCH = createFetchType(OFFERS_PROFILE_SCOPE);



export const ONE_OFFER_FETCH = createFetchType(ONE_OFFER_SCOPE);
export const ONE_OFFER_SUCCESS = createSuccessType(ONE_OFFER_FETCH);
export const ONE_OFFER_ERROR = createErrorType(ONE_OFFER_SCOPE);
@@ -28,3 +33,4 @@ export const OFFERS_NO_MORE = "OFFERS_NO_MORE";
export const OFFERS_SET_TOTAL = "OFFERS_SET_TOTAL";
export const OFFERS_MINE_SET = "OFFERS_MY_ADD";
export const OFFER_ADD = "OFFER_ADD";
export const OFFERS_PROFILE_SET = "OFFERS_PROFILE_SET";

+ 10
- 0
src/store/actions/offers/offersActions.js Visa fil

@@ -9,6 +9,8 @@ import {
OFFERS_NO_MORE,
OFFERS_PINNED_ADD,
OFFERS_PINNED_SET,
OFFERS_PROFILE_FETCH,
OFFERS_PROFILE_SET,
OFFERS_SET,
OFFERS_SET_TOTAL,
OFFERS_SUCCESS,
@@ -94,3 +96,11 @@ export const setMineOffers = (payload) => ({
type: OFFERS_MINE_SET,
payload,
});
export const fetchProfileOffers = (payload) => ({
type: OFFERS_PROFILE_FETCH,
payload,
})
export const setProfileOffers = (payload) => ({
type: OFFERS_PROFILE_SET,
payload,
})

+ 5
- 1
src/store/actions/profile/profileActionConstants.js Visa fil

@@ -5,4 +5,8 @@ export const PROFILE_FETCH = createFetchType(PROFILE_SCOPE);
export const PROFILE_SUCCESS = createSuccessType(PROFILE_SCOPE);
export const PROFILE_ERROR = createErrorType(PROFILE_SCOPE);

export const PROFILE_SET = "PROFILE_SET";
const PROFILE_MINE_SCOPE = "PROFILE_MINE_SCOPE";
export const PROFILE_MINE_FETCH = createFetchType(PROFILE_MINE_SCOPE);

export const PROFILE_SET = "PROFILE_SET";
export const PROFILE_MINE_SET = "PROFILE_MINE_SET";

+ 8
- 1
src/store/actions/profile/profileActions.js Visa fil

@@ -1,4 +1,4 @@
import { PROFILE_ERROR, PROFILE_FETCH, PROFILE_SET, PROFILE_SUCCESS } from "./profileActionConstants";
import { PROFILE_ERROR, PROFILE_FETCH, PROFILE_MINE_FETCH, PROFILE_MINE_SET, PROFILE_SET, PROFILE_SUCCESS } from "./profileActionConstants";

export const fetchProfile = (payload) => ({
type: PROFILE_FETCH,
@@ -16,4 +16,11 @@ export const fetchErrorProfile = (payload) => ({
export const setProfile = (payload) => ({
type: PROFILE_SET,
payload,
})
export const setMineProfile = (payload) => ({
type: PROFILE_MINE_SET,
payload,
})
export const fetchMineProfile = () => ({
type: PROFILE_MINE_FETCH,
})

+ 3
- 1
src/store/middleware/accessTokensMiddleware.js Visa fil

@@ -13,7 +13,7 @@ import { logoutUser, refreshUserToken } from "../actions/login/loginActions";
// import { setUserAccessToken } from "../actions/user/userActions";

//Change URL with .env
const baseURL = "http://192.168.88.150:3001/";
const baseURL = "http://192.168.88.175:3005/";
// const baseURL = "http://192.168.88.175:3005/";

//Interceptor unique name
@@ -26,6 +26,7 @@ export default ({ dispatch }) =>
const jwtToken = authScopeStringGetHelper(JWT_TOKEN);
const refresh = authScopeStringGetHelper(JWT_REFRESH_TOKEN);
if (!jwtToken || !refresh) return Promise.resolve(response);
console.log('ispod je');
const jwtTokenDecoded = jwt.decode(jwtToken);
const refreshTokenDecoded = jwt.decode(refresh);
if (!response.headers?.Authorization) {
@@ -38,6 +39,7 @@ export default ({ dispatch }) =>
}
// If access token is expired, refresh access token
if (new Date() > new Date(jwtTokenDecoded.exp * 1000)) {
console.log('untura je')
const axiosResponse = await axios.post(`${baseURL}auth/refresh`, {
token: refresh,
});

+ 1
- 1
src/store/reducers/filters/filtersReducer.js Visa fil

@@ -90,4 +90,4 @@ function setIsAppliedStatus(state, {payload}) {
isApplied: payload,
}
}
}
}

+ 10
- 1
src/store/reducers/offers/offersReducer.js Visa fil

@@ -13,6 +13,7 @@ import {
ONE_OFFER_ERROR,
ONE_OFFER_SUCCESS,
OFFERS_SET_TOTAL,
OFFERS_PROFILE_SET,
} from "../../actions/offers/offersActionConstants";
import createReducer from "../../utils/createReducer";

@@ -20,6 +21,7 @@ const initialState = {
offers: [],
pinnedOffers: [],
mineOffers: [],
profileOffers: [],
total: 0,
error: "",
newOffer: "",
@@ -42,7 +44,8 @@ export default createReducer(
[OFFERS_PINNED_ADD]: addPinnedOffers,
[OFFERS_PINNED_SET]: setPinnedOffers,
[OFFERS_SET_TOTAL]: setTotalOffers,
[OFFERS_MINE_SET]: setMineOffers
[OFFERS_MINE_SET]: setMineOffers,
[OFFERS_PROFILE_SET]: setProfileOffers,
},
initialState
);
@@ -127,3 +130,9 @@ function setMineOffers(state, action) {
mineOffers: action.payload
}
}
function setProfileOffers(state, action) {
return {
...state,
profileOffers: action.payload
}
}

+ 9
- 1
src/store/reducers/profile/profileReducer.js Visa fil

@@ -1,13 +1,15 @@
import { PROFILE_SET } from "../../actions/profile/profileActionConstants";
import { PROFILE_MINE_SET, PROFILE_SET } from "../../actions/profile/profileActionConstants";
import createReducer from "../../utils/createReducer";

const initialState = {
profile: {},
mineProfile: {},
};

export default createReducer(
{
[PROFILE_SET]: setProfile,
[PROFILE_MINE_SET]: setMineProfile,
},
initialState
);
@@ -18,3 +20,9 @@ function setProfile(state, action) {
profile: action.payload,
};
}
function setMineProfile(state, action) {
return {
...state,
mineProfile: action.payload
}
}

+ 15
- 5
src/store/saga/offersSaga.js Visa fil

@@ -1,9 +1,9 @@
import { attemptAddOffer, attemptFetchOffers, attemptFetchOneOffer } from "../../request/offersRequest";
import { OFFERS_FETCH, OFFER_ADD, ONE_OFFER_FETCH } from "../actions/offers/offersActionConstants";
import { setOffers, setOffer } from "../actions/offers/offersActions";
import { OFFERS_FETCH, OFFERS_PROFILE_FETCH, OFFER_ADD, ONE_OFFER_FETCH } from "../actions/offers/offersActionConstants";
import { setOffers, setOffer, setProfileOffers } from "../actions/offers/offersActions";
import { all, takeLatest, call, put, select } from "@redux-saga/core/effects";
import {
attemptFetchMineOffers,
attemptFetchProfileOffers,
attemptFetchMoreOffers,
} from "../../request/offersRequest";
import { convertQueryStringBackend } from "../../util/helpers/queryHelpers";
@@ -86,7 +86,6 @@ function* fetchMoreOffers(payload) {
}
}


function* createOffer(payload) {
try {
const data = yield call(attemptAddOffer, payload);
@@ -112,13 +111,23 @@ function* fetchOneOffer(payload) {
function* fetchMineOffers() {
try {
const userId = yield select(selectUserId);
const data = yield call(attemptFetchMineOffers, userId);
const data = yield call(attemptFetchProfileOffers, userId);
yield put(setMineOffers(data.data));
} catch (e) {
console.log(e);
}
}

function* fetchProfileOffers(payload) {
try {
const userId = payload.payload;
const data = yield call(attemptFetchProfileOffers, userId)
yield put (setProfileOffers(data.data));
} catch (e) {
console.log(e);
}
}

export default function* offersSaga() {
yield all(
[
@@ -127,5 +136,6 @@ export default function* offersSaga() {
takeLatest(ONE_OFFER_FETCH, fetchOneOffer),
takeLatest(OFFERS_FETCH_MORE, fetchMoreOffers),
takeLatest(OFFERS_MINE_FETCH, fetchMineOffers),
takeLatest(OFFERS_PROFILE_FETCH, fetchProfileOffers)
]);
}

+ 18
- 4
src/store/saga/profileSaga.js Visa fil

@@ -1,7 +1,8 @@
import { all, call, put, takeLatest } from "@redux-saga/core/effects";
import { all, call, put, takeLatest, select } from "@redux-saga/core/effects";
import { attemptFetchProfile } from "../../request/profileRequest";
import { PROFILE_FETCH } from "../actions/profile/profileActionConstants";
import { setProfile } from "../actions/profile/profileActions";
import { PROFILE_FETCH, PROFILE_MINE_FETCH } from "../actions/profile/profileActionConstants";
import { setMineProfile, setProfile } from "../actions/profile/profileActions";
import { selectUserId } from "../selectors/loginSelectors";

function* fetchProfile(payload) {
try {
@@ -15,8 +16,21 @@ function* fetchProfile(payload) {
}
}

function* fetchMineProfile() {
try {
const userId = yield select(selectUserId);
const data = yield call(attemptFetchProfile, userId);
console.log(data);
if (data) yield put(setMineProfile(data.data));
}
catch (e) {
console.log(e);
}
}

export default function* profileSaga() {
yield all([
takeLatest(PROFILE_FETCH, fetchProfile)
takeLatest(PROFILE_FETCH, fetchProfile),
takeLatest(PROFILE_MINE_FETCH, fetchMineProfile)
])
}

+ 4
- 0
src/store/selectors/offersSelectors.js Visa fil

@@ -32,3 +32,7 @@ export const selectMineOffers = createSelector(
offersSelector,
(state) => state.mineOffers
)
export const selectProfileOffers = createSelector(
offersSelector,
(state) => state.profileOffers
)

+ 7
- 3
src/store/selectors/profileSelectors.js Visa fil

@@ -1,12 +1,16 @@
import { createSelector } from "reselect";

const profileSelector = (state) => state.profile.profile;
const profileSelector = (state) => state.profile

export const selectProfileName = createSelector(
profileSelector,
(state) => state?.company?.name
(state) => state?.mineProfile?.company?.name
)
export const selectProfile = createSelector(
profileSelector,
(state) => state
(state) => state.profile
)
export const selectMineProfile = createSelector(
profileSelector,
(state) => state?.mineProfile
)

+ 5
- 1
src/themes/primaryTheme/primaryThemeColors.js Visa fil

@@ -9,14 +9,18 @@ export const primaryThemeColors = {
primaryDarkGrayText: "#DCDCDC",
primaryIconBackgroundColor: "#E4E4E4",
borderNormal: "#D4D4D4",
primaryDarkTextSecond: "#E4E4E4",
borderSponsoredColor: "#E5D0FF",
backgroundSponsoredColor: "#F5EDFF",
offerBackgroundColor: "#F5F5F5",
selectOptionTextColor: "#1D1D1D",
primaryDarkText: "#505050",
primaryDarkTextThird: "#4D4D4D",
iconStrokeColor: "#8C8C8C",
// iconStrokeDisabledColor: "#818181"
iconStrokeDisabledColor: '#C4C4C4',
imagePickerBackground: "#E4E4E4",
iconYellowColor: "#FEB005"
iconYellowColor: "#FEB005",
iconMineProfileColor: "#9E9E9E",
iconProfileColor: "#C4C4C4"
}

Laddar…
Avbryt
Spara