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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. import React, { useMemo } 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. ButtonsContainer,
  35. TooltipInnerContainer,
  36. UnpinOutlinedIcon,
  37. AcceptIconContainer,
  38. AcceptIcon,
  39. } from "./OfferCard.styled";
  40. import { ReactComponent as Message } from "../../../assets/images/svg/mail.svg";
  41. import { useHistory } from "react-router-dom";
  42. import { useDispatch, useSelector } from "react-redux";
  43. import { selectUserId } from "../../../store/selectors/loginSelectors";
  44. import useIsMobile from "../../../hooks/useIsMobile";
  45. import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";
  46. import OfferDescription from "./OfferDescription/OfferDescription";
  47. import CheckButton from "./CheckButton/CheckButton";
  48. import { formatDateLocale } from "../../../util/helpers/dateHelpers";
  49. import {
  50. toggleDeleteOfferModal,
  51. toggleEditOfferModal,
  52. } from "../../../store/actions/modal/modalActions";
  53. import { Tooltip } from "@mui/material";
  54. import { useTranslation } from "react-i18next";
  55. import { replaceInRoute } from "../../../util/helpers/routeHelpers";
  56. import {
  57. ADMIN_ITEM_DETAILS_PAGE,
  58. ITEM_DETAILS_PAGE,
  59. } from "../../../constants/pages";
  60. import exchangeStatus from "../../../constants/exchangeStatus";
  61. const OfferCard = (props) => {
  62. const dispatch = useDispatch();
  63. const history = useHistory();
  64. const userId = useSelector(selectUserId);
  65. const { isMobile } = useIsMobile();
  66. const date = formatDateLocale(new Date(props.offer?._created));
  67. const { t } = useTranslation();
  68. const pinOffer = (event) => {
  69. event.stopPropagation();
  70. dispatch(
  71. toggleDeleteOfferModal({
  72. offer: props.offer,
  73. pin: true,
  74. pinnedOffer: props.offer.pinned,
  75. deleteOffer: false,
  76. })
  77. );
  78. };
  79. const routeToItem = (itemId) => {
  80. if (!props.disabledCheckButton) {
  81. if (props.isAdmin) {
  82. history.push(
  83. replaceInRoute(ADMIN_ITEM_DETAILS_PAGE, {
  84. idProizvod: itemId,
  85. })
  86. );
  87. } else {
  88. history.push(
  89. replaceInRoute(ITEM_DETAILS_PAGE, {
  90. idProizvod: itemId,
  91. })
  92. );
  93. }
  94. }
  95. };
  96. const messageUser = (event) => {
  97. event.stopPropagation();
  98. props.messageUser(props.offer);
  99. };
  100. const makeReview = (event) => {
  101. event.stopPropagation();
  102. if (!props.disabledReviews) {
  103. props.makeReview(props.offer);
  104. }
  105. };
  106. const openEditOfferModal = (event) => {
  107. event.stopPropagation();
  108. dispatch(
  109. toggleEditOfferModal({
  110. editOffer: true,
  111. offer: props.offer,
  112. isAdmin: props.isAdmin,
  113. customUserId: props?.offer?.userId,
  114. })
  115. );
  116. };
  117. const openRemoveModal = (event) => {
  118. event.stopPropagation();
  119. dispatch(
  120. toggleDeleteOfferModal({
  121. offer: props.offer,
  122. isAdmin: props.isAdmin,
  123. })
  124. );
  125. };
  126. const acceptExchange = (event) => {
  127. event.stopPropagation();
  128. console.log("props exchange");
  129. props.acceptExchange();
  130. };
  131. const showMessageIcon = useMemo(() => {
  132. if (userId === props.offer?.userId) {
  133. return false;
  134. }
  135. return true;
  136. }, [userId, props.offer]);
  137. return (
  138. <React.Fragment>
  139. <OfferCardContainer
  140. vertical={props.vertical}
  141. sponsored={
  142. props?.pinned !== undefined
  143. ? props?.pinned?.toString()
  144. : props?.offer?.pinned?.toString()
  145. }
  146. halfwidth={props.halfwidth ? 1 : 0}
  147. onClick={() => routeToItem(props?.offer?._id)}
  148. >
  149. {/* This only shows on vertical offer card */}
  150. <OfferTitleAboveImage
  151. vertical={props.vertical}
  152. noOfButtons={
  153. props.isAdmin
  154. ? 3
  155. : props.isMyOffer
  156. ? props?.offer?.pinned
  157. ? 3
  158. : 2
  159. : props?.offer?.pinned
  160. ? 2
  161. : 1
  162. }
  163. onClick={() => routeToItem(props?.offer?._id)}
  164. >
  165. {props?.offer?.name}
  166. </OfferTitleAboveImage>
  167. {/* ^^^^^^^ */}
  168. <OfferFlexContainer vertical={props.vertical}>
  169. <OfferImageContainer vertical={props.vertical}>
  170. <OfferImage
  171. src={
  172. props?.offer?.images
  173. ? getImageUrl(
  174. props?.offer?.images[0],
  175. variants.offerCard,
  176. isMobile
  177. )
  178. : ""
  179. }
  180. vertical={props.vertical}
  181. ></OfferImage>
  182. </OfferImageContainer>
  183. <OfferInfo vertical={props.vertical}>
  184. <OfferTitle
  185. vertical={props.vertical}
  186. onClick={() => routeToItem(props?.offer?._id)}
  187. >
  188. {props?.offer?.name}
  189. </OfferTitle>
  190. <OfferAuthor vertical={props.vertical}>
  191. <OfferAuthorName vertical={props.vertical}>
  192. {props?.offer?.user?.company?.name}
  193. </OfferAuthorName>
  194. <OfferLocation vertical={props.vertical}>
  195. {props?.offer?.location?.city}
  196. </OfferLocation>
  197. </OfferAuthor>
  198. <OfferDetails>
  199. <OfferCategory vertical={props.vertical}>
  200. <DetailIcon color="black" component="span" size="16px">
  201. <CategoryIcon />
  202. </DetailIcon>
  203. <DetailText>{props?.offer?.category?.name}</DetailText>
  204. </OfferCategory>
  205. {props.dontShowViews ? (
  206. <></>
  207. ) : (
  208. <OfferViews vertical={props.vertical}>
  209. <DetailIcon color="black" component="span" size="16px">
  210. <EyeIcon />
  211. </DetailIcon>
  212. <DetailText>{props?.offer?.views?.count}</DetailText>
  213. </OfferViews>
  214. )}
  215. <OfferDate vertical={props.vertical}>
  216. <DetailIcon component="span" size="16px">
  217. <CalendarIcon />
  218. </DetailIcon>
  219. <DetailText>{date}</DetailText>
  220. </OfferDate>
  221. </OfferDetails>
  222. </OfferInfo>
  223. {!props.halfwidth ? (
  224. <React.Fragment>
  225. <Line />
  226. <OfferDescription description={props?.offer?.description} />
  227. <CheckButton
  228. disabled={props.disabledCheckButton}
  229. offerId={props?.offer?._id}
  230. sponsored={props.sponsored}
  231. />
  232. </React.Fragment>
  233. ) : (
  234. <></>
  235. )}
  236. <ButtonsContainer vertical={props.vertical}>
  237. {/* {props?.offer?.pinned && (
  238. <PinIcon vertical={props.vertical} isMyOffer={props.isMyOffer} />
  239. )} */}
  240. {props.isMyOffer ? (
  241. <>
  242. <Tooltip title={t("deleteOffer.tooltip")}>
  243. <TooltipInnerContainer>
  244. <RemoveIconContainer
  245. vertical={props.vertical}
  246. onClick={openRemoveModal}
  247. >
  248. <RemoveIcon />
  249. </RemoveIconContainer>
  250. </TooltipInnerContainer>
  251. </Tooltip>
  252. <Tooltip title={t("offer.tooltip")}>
  253. <TooltipInnerContainer>
  254. <EditIconContainer
  255. vertical={props.vertical}
  256. onClick={openEditOfferModal}
  257. >
  258. <EditIcon />
  259. </EditIconContainer>
  260. </TooltipInnerContainer>
  261. </Tooltip>
  262. </>
  263. ) : props.aboveChat ? (
  264. props.exchangeState === exchangeStatus.ACCEPTED ||
  265. props.exchangeState === exchangeStatus.REVIEWED ? (
  266. <LikeIconContainer
  267. customDisabled={props.disabledReviews}
  268. disabled={props.disabledReviews}
  269. onClick={makeReview}
  270. >
  271. <LikeIcon disabled={props.disabledReviews} />
  272. </LikeIconContainer>
  273. ) : (
  274. <AcceptIconContainer // MENJATI
  275. customDisabled={
  276. props.exchangeState === exchangeStatus.I_OFFERED
  277. }
  278. disabled={props.exchangeState === exchangeStatus.I_OFFERED}
  279. onClick={acceptExchange}
  280. >
  281. <AcceptIcon
  282. disabled={props.exchangeState === exchangeStatus.I_OFFERED}
  283. />
  284. </AcceptIconContainer>
  285. )
  286. ) : (
  287. <Tooltip title={t("messages.tooltip")}>
  288. <TooltipInnerContainer>
  289. <MessageIcon
  290. showMessageIcon={showMessageIcon}
  291. vertical={props.vertical}
  292. onClick={messageUser}
  293. >
  294. <Message />
  295. </MessageIcon>
  296. </TooltipInnerContainer>
  297. </Tooltip>
  298. )}
  299. {props.isAdmin &&
  300. (!props?.offer?.pinned ? (
  301. <Tooltip title={t("admin.pin.tooltip")}>
  302. <TooltipInnerContainer>
  303. <PinIconContainer
  304. showMessageIcon
  305. onClick={pinOffer}
  306. vertical={props.vertical}
  307. >
  308. <PinOutlinedIcon />
  309. </PinIconContainer>
  310. </TooltipInnerContainer>
  311. </Tooltip>
  312. ) : (
  313. <Tooltip title={t("admin.unpin.tooltip")}>
  314. <TooltipInnerContainer>
  315. <PinIconContainer
  316. showMessageIcon
  317. onClick={pinOffer}
  318. vertical={props.vertical}
  319. >
  320. <UnpinOutlinedIcon />
  321. </PinIconContainer>
  322. </TooltipInnerContainer>
  323. </Tooltip>
  324. ))}
  325. </ButtonsContainer>
  326. </OfferFlexContainer>
  327. </OfferCardContainer>
  328. </React.Fragment>
  329. );
  330. };
  331. OfferCard.propTypes = {
  332. children: PropTypes.node,
  333. _id: PropTypes.string,
  334. title: PropTypes.string,
  335. description: PropTypes.string,
  336. category: PropTypes.string,
  337. author: PropTypes.string,
  338. location: PropTypes.string,
  339. image: PropTypes.node,
  340. quantity: PropTypes.number,
  341. package: PropTypes.string,
  342. numberOfViews: PropTypes.number,
  343. halfwidth: PropTypes.bool,
  344. sponsored: PropTypes.bool,
  345. offer: PropTypes.any,
  346. pinned: PropTypes.bool,
  347. vertical: PropTypes.bool,
  348. isMyOffer: PropTypes.bool,
  349. aboveChat: PropTypes.bool,
  350. disabledReviews: PropTypes.bool,
  351. messageUser: PropTypes.func,
  352. makeReview: PropTypes.func,
  353. dontShowViews: PropTypes.bool,
  354. skeleton: PropTypes.bool,
  355. disabledCheckButton: PropTypes.bool,
  356. isAdmin: PropTypes.bool,
  357. exchangeState: PropTypes.any,
  358. acceptExchange: PropTypes.func,
  359. };
  360. OfferCard.defaultProps = {
  361. halfwidth: false,
  362. sponsored: false,
  363. messageUser: () => {},
  364. makeReview: () => {},
  365. };
  366. export default OfferCard;