You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

OfferCard.js 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. import React, { useMemo, useState } from "react";
  2. import PropTypes from "prop-types";
  3. import {
  4. DetailIcon,
  5. DetailText,
  6. EditIcon,
  7. EditIconContainer,
  8. EyeIcon,
  9. Line,
  10. MessageIcon,
  11. OfferAuthor,
  12. OfferAuthorName,
  13. OfferCardContainer,
  14. OfferCategory,
  15. OfferDetails,
  16. OfferFlexContainer,
  17. OfferImage,
  18. OfferImageContainer,
  19. OfferInfo,
  20. OfferLocation,
  21. OfferTitle,
  22. OfferTitleAboveImage,
  23. OfferViews,
  24. OfferDate,
  25. PinIcon,
  26. RemoveIcon,
  27. RemoveIconContainer,
  28. LikeIcon,
  29. LikeIconContainer,
  30. CategoryIcon,
  31. CalendarIcon,
  32. PinIconContainer,
  33. PinOutlinedIcon,
  34. } from "./OfferCard.styled";
  35. import DeleteOffer from "./DeleteOffer/DeleteOffer";
  36. import { ReactComponent as Message } from "../../../assets/images/svg/mail.svg";
  37. import { useHistory } from "react-router-dom";
  38. import CreateOffer from "../CreateOfferCard/CreateOffer";
  39. import { useSelector } from "react-redux";
  40. import { selectUserId } from "../../../store/selectors/loginSelectors";
  41. import useIsMobile from "../../../hooks/useIsMobile";
  42. import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";
  43. import OfferDescription from "./OfferDescription/OfferDescription";
  44. import CheckButton from "./CheckButton/CheckButton";
  45. import { formatDateLocale } from "../../../util/helpers/dateHelpers";
  46. const OfferCard = (props) => {
  47. const [deleteOfferModal, setDeleteOfferModal] = useState(false);
  48. const [editOfferModal, setEditOfferModal] = useState(false);
  49. const history = useHistory();
  50. const userId = useSelector(selectUserId);
  51. const { isMobile } = useIsMobile();
  52. const date = formatDateLocale(new Date(props.offer?._created));
  53. const pinOffer = (event) => {
  54. event.stopPropagation();
  55. };
  56. const routeToItem = (itemId) => {
  57. if (!props.disabledCheckButton) {
  58. history.push(`/proizvodi/${itemId}`);
  59. }
  60. };
  61. const messageUser = (event) => {
  62. event.stopPropagation();
  63. props.messageUser(props.offer);
  64. };
  65. const makeReview = (event) => {
  66. event.stopPropagation();
  67. if (!props.disabledReviews) {
  68. props.makeReview(props.offer);
  69. }
  70. };
  71. const openEditOfferModal = (event) => {
  72. event.stopPropagation();
  73. setEditOfferModal(true);
  74. };
  75. const openRemoveModal = (event) => {
  76. event.stopPropagation();
  77. setDeleteOfferModal(true);
  78. };
  79. const closeModalHandler = () => {
  80. setDeleteOfferModal(false);
  81. };
  82. const closeCreateOfferModal = () => {
  83. setEditOfferModal(false);
  84. };
  85. const showMessageIcon = useMemo(() => {
  86. if (userId === props.offer?.userId) {
  87. return false;
  88. }
  89. return true;
  90. }, [userId, props.offer]);
  91. if (deleteOfferModal || editOfferModal) {
  92. document.body.style.overflow = "hidden";
  93. } else {
  94. document.body.style.overflow = "auto";
  95. }
  96. return (
  97. <React.Fragment>
  98. <OfferCardContainer
  99. vertical={props.vertical}
  100. sponsored={
  101. props?.pinned !== undefined
  102. ? props?.pinned?.toString()
  103. : props?.offer?.pinned?.toString()
  104. }
  105. halfwidth={props.halfwidth ? 1 : 0}
  106. onClick={() => routeToItem(props?.offer?._id)}
  107. >
  108. {/* This only shows on vertical offer card */}
  109. <OfferTitleAboveImage
  110. vertical={props.vertical}
  111. onClick={() => routeToItem(props?.offer?._id)}
  112. >
  113. {props?.offer?.name}
  114. </OfferTitleAboveImage>
  115. {/* ^^^^^^^ */}
  116. <OfferFlexContainer vertical={props.vertical}>
  117. <OfferImageContainer vertical={props.vertical}>
  118. <OfferImage
  119. src={
  120. props?.offer?.images
  121. ? getImageUrl(
  122. props?.offer?.images[0],
  123. variants.offerCard,
  124. isMobile
  125. )
  126. : ""
  127. }
  128. vertical={props.vertical}
  129. ></OfferImage>
  130. </OfferImageContainer>
  131. <OfferInfo vertical={props.vertical}>
  132. <OfferTitle
  133. vertical={props.vertical}
  134. onClick={() => routeToItem(props?.offer?._id)}
  135. >
  136. {props?.offer?.name}
  137. </OfferTitle>
  138. <OfferAuthor>
  139. <OfferAuthorName vertical={props.vertical}>
  140. {props?.offer?.user?.company?.name}
  141. </OfferAuthorName>
  142. <OfferLocation vertical={props.vertical}>
  143. {props?.offer?.location?.city}
  144. </OfferLocation>
  145. </OfferAuthor>
  146. <OfferDetails>
  147. <OfferCategory vertical={props.vertical}>
  148. <DetailIcon color="black" component="span" size="16px">
  149. <CategoryIcon />
  150. </DetailIcon>
  151. <DetailText>{props?.offer?.category?.name}</DetailText>
  152. </OfferCategory>
  153. {props.dontShowViews ? (
  154. <></>
  155. ) : (
  156. <OfferViews vertical={props.vertical}>
  157. <DetailIcon color="black" component="span" size="16px">
  158. <EyeIcon />
  159. </DetailIcon>
  160. <DetailText>{props?.offer?.views?.count}</DetailText>
  161. </OfferViews>
  162. )}
  163. <OfferDate vertical={props.vertical}>
  164. <DetailIcon component="span" size="16px">
  165. <CalendarIcon />
  166. </DetailIcon>
  167. <DetailText>{date}</DetailText>
  168. </OfferDate>
  169. </OfferDetails>
  170. </OfferInfo>
  171. {!props.halfwidth ? (
  172. <React.Fragment>
  173. <Line />
  174. <OfferDescription description={props?.offer?.description} />
  175. <CheckButton
  176. disabled={props.disabledCheckButton}
  177. offerId={props?.offer?._id}
  178. sponsored={props.sponsored}
  179. />
  180. </React.Fragment>
  181. ) : (
  182. <></>
  183. )}
  184. {props.isMyOffer ? (
  185. <>
  186. <RemoveIconContainer
  187. vertical={props.vertical}
  188. onClick={openRemoveModal}
  189. >
  190. <RemoveIcon />
  191. </RemoveIconContainer>
  192. <EditIconContainer
  193. vertical={props.vertical}
  194. onClick={openEditOfferModal}
  195. >
  196. <EditIcon />
  197. </EditIconContainer>
  198. </>
  199. ) : props.aboveChat ? (
  200. <LikeIconContainer
  201. disabled={props.disabledReviews}
  202. onClick={makeReview}
  203. >
  204. <LikeIcon disabled={props.disabledReviews} />
  205. </LikeIconContainer>
  206. ) : (
  207. <MessageIcon
  208. showMessageIcon={showMessageIcon}
  209. vertical={props.vertical}
  210. onClick={messageUser}
  211. >
  212. <Message />
  213. </MessageIcon>
  214. )}
  215. {props.isAdmin && !props.pinned && (
  216. <PinIconContainer showMessageIcon onClick={pinOffer}>
  217. <PinOutlinedIcon />
  218. </PinIconContainer>
  219. )}
  220. {props?.offer?.pinned && <PinIcon isMyOffer={props.isMyOffer} />}
  221. </OfferFlexContainer>
  222. </OfferCardContainer>
  223. {deleteOfferModal && (
  224. <DeleteOffer
  225. offer={props.offer}
  226. closeModalHandler={closeModalHandler}
  227. />
  228. )}
  229. {editOfferModal && (
  230. <CreateOffer
  231. editOffer
  232. closeCreateOfferModal={closeCreateOfferModal}
  233. offer={props.offer}
  234. />
  235. )}
  236. </React.Fragment>
  237. );
  238. };
  239. OfferCard.propTypes = {
  240. children: PropTypes.node,
  241. _id: PropTypes.string,
  242. title: PropTypes.string,
  243. description: PropTypes.string,
  244. category: PropTypes.string,
  245. author: PropTypes.string,
  246. location: PropTypes.string,
  247. image: PropTypes.node,
  248. quantity: PropTypes.number,
  249. package: PropTypes.string,
  250. numberOfViews: PropTypes.number,
  251. halfwidth: PropTypes.bool,
  252. sponsored: PropTypes.bool,
  253. offer: PropTypes.any,
  254. pinned: PropTypes.bool,
  255. vertical: PropTypes.bool,
  256. isMyOffer: PropTypes.bool,
  257. aboveChat: PropTypes.bool,
  258. disabledReviews: PropTypes.bool,
  259. messageUser: PropTypes.func,
  260. makeReview: PropTypes.func,
  261. dontShowViews: PropTypes.bool,
  262. skeleton: PropTypes.bool,
  263. disabledCheckButton: PropTypes.bool,
  264. isAdmin: PropTypes.bool,
  265. };
  266. OfferCard.defaultProps = {
  267. halfwidth: false,
  268. sponsored: false,
  269. messageUser: () => {},
  270. makeReview: () => {},
  271. };
  272. export default OfferCard;