Explorar el Código

Merged without create-offer

feature/code-cleanup-joca
Djordje Mitrovic hace 3 años
padre
commit
da81195da6
Se han modificado 45 ficheros con 1320 adiciones y 173 borrados
  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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

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

+ 10
- 1
src/store/reducers/offers/offersReducer.js Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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 Ver fichero

@@ -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"
}

Cargando…
Cancelar
Guardar