| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import BackdropComponent from "../../../MUI/BackdropComponent"; | |||||
| import { | |||||
| CloseButton, | |||||
| ImagesCarouselContainer, | |||||
| ImagesCarouselHeader, | |||||
| Offer, | |||||
| OfferImage, | |||||
| OfferSpan, | |||||
| Scroller, | |||||
| } from "./ImagesCarousel.styled"; | |||||
| import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter"; | |||||
| import useIsMobile from "../../../../hooks/useIsMobile"; | |||||
| import { ReactComponent as CloseButtonIcon } from "../../../../assets/images/svg/close-modal.svg"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| const ImagesCarousel = (props) => { | |||||
| const { isMobile } = useIsMobile(); | |||||
| const { t } = useTranslation(); | |||||
| const closeCreateOfferModal = () => { | |||||
| props.onModalClose(); | |||||
| }; | |||||
| return ( | |||||
| <> | |||||
| <BackdropComponent | |||||
| isLoading | |||||
| handleClose={closeCreateOfferModal} | |||||
| position="fixed" | |||||
| /> | |||||
| <ImagesCarouselContainer> | |||||
| <ImagesCarouselHeader> | |||||
| {t("carousel.imagesReview")} | |||||
| </ImagesCarouselHeader> | |||||
| <CloseButton onClick={closeCreateOfferModal}> | |||||
| <CloseButtonIcon /> | |||||
| </CloseButton> | |||||
| <Scroller> | |||||
| {props?.offer?.offer?.images.map((image) => { | |||||
| if (!image) return; | |||||
| return ( | |||||
| <OfferImage | |||||
| src={getImageUrl(image, variants.carousel, isMobile)} | |||||
| key={image} | |||||
| /> | |||||
| ); | |||||
| })} | |||||
| </Scroller> | |||||
| <Offer> | |||||
| {t("carousel.offer")} <OfferSpan>{props.offer.offer.name}</OfferSpan> | |||||
| </Offer> | |||||
| </ImagesCarouselContainer> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| ImagesCarousel.propTypes = { | |||||
| offer: PropTypes.any, | |||||
| onModalClose: PropTypes.any, | |||||
| createOffer: PropTypes.bool, | |||||
| }; | |||||
| export default ImagesCarousel; |
| import styled from "styled-components"; | |||||
| import { Box } from "@mui/system"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import HorizontalScroller from "../../../Scroller/HorizontalScroller"; | |||||
| export const ImagesCarouselContainer = styled(Box)` | |||||
| width: 756px; | |||||
| height: 774px; | |||||
| position: fixed; | |||||
| top: calc(50% - 387px); | |||||
| left: calc(50% - 378px); | |||||
| z-index: 150; | |||||
| background-color: #fff; | |||||
| padding: 0 18px 18px 18px; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: center; | |||||
| border-radius: 4px; | |||||
| @media (max-width: 600px) { | |||||
| width: 350px; | |||||
| height: 383px; | |||||
| overflow: hidden; | |||||
| top: calc(50% - 191.5px); | |||||
| left: calc(50% - 175px); | |||||
| padding-bottom: 36px; | |||||
| } | |||||
| `; | |||||
| export const ImagesCarouselHeader = styled(Box)` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| font-size: 24px; | |||||
| font-weight: 700; | |||||
| color: ${selectedTheme.colors.primaryPurple}; | |||||
| margin-top: 36px; | |||||
| @media (max-width: 600px) { | |||||
| font-size: 18px; | |||||
| } | |||||
| `; | |||||
| export const Scroller = styled(HorizontalScroller)` | |||||
| max-width: 100%; | |||||
| max-height: 576px; | |||||
| margin-top: 36px; | |||||
| margin-bottom: 38px; | |||||
| @media (max-width: 600px) { | |||||
| margin-bottom: 18px; | |||||
| } | |||||
| `; | |||||
| export const OfferImage = styled.img` | |||||
| min-width: 576px; | |||||
| min-height: 576px; | |||||
| margin-right: 23px; | |||||
| margin-left: 10px; | |||||
| border-radius: 4px; | |||||
| object-fit: cover; | |||||
| @media (max-width: 600px) { | |||||
| min-width: 216px; | |||||
| min-height: 216px; | |||||
| margin-right: 18px; | |||||
| margin-left: 0; | |||||
| } | |||||
| `; | |||||
| export const Offer = styled.p` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| font-size: 12px; | |||||
| @media (max-width: 600px) { | |||||
| font-size: 9px; | |||||
| } | |||||
| `; | |||||
| export const OfferSpan = styled.span` | |||||
| font-size: 16px; | |||||
| font-weight: 700; | |||||
| @media (max-width: 600px) { | |||||
| font-size: 12px; | |||||
| } | |||||
| `; | |||||
| export const CloseButton = styled(Box)` | |||||
| position: absolute; | |||||
| top: 42px; | |||||
| right: 42px; | |||||
| cursor: pointer; | |||||
| @media (max-width: 600px) { | |||||
| top: 38px; | |||||
| right: 21px; | |||||
| svg { | |||||
| width: 18px; | |||||
| } | |||||
| } | |||||
| `; |
| import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter"; | import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter"; | ||||
| import { useEffect } from "react"; | import { useEffect } from "react"; | ||||
| import { useState } from "react"; | import { useState } from "react"; | ||||
| import ImagesCarousel from "../ImagesCarousel/ImagesCarousel"; | |||||
| const OfferDetails = (props) => { | const OfferDetails = (props) => { | ||||
| const offer = props.offer; | const offer = props.offer; | ||||
| const dimension = useScreenDimensions(); | const dimension = useScreenDimensions(); | ||||
| const { isMobile } = useIsMobile(); | const { isMobile } = useIsMobile(); | ||||
| const [images, setImages] = useState([]); | const [images, setImages] = useState([]); | ||||
| const [imagesCarouselModal, setImagesCarouselModal] = useState(false); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (props?.offer?.offer?.images) { | if (props?.offer?.offer?.images) { | ||||
| } | } | ||||
| }, [props?.offer?.offer?.images]); | }, [props?.offer?.offer?.images]); | ||||
| const date = formatDateLocale(new Date(offer?.offer?._created)); | const date = formatDateLocale(new Date(offer?.offer?._created)); | ||||
| const onModalClose = () => { | |||||
| setImagesCarouselModal(false); | |||||
| }; | |||||
| return ( | return ( | ||||
| <Details | |||||
| hasScrollBar={!props.showPublishButton} | |||||
| exchange={props.showExchangeButton} | |||||
| singleOffer={props.singleOffer} | |||||
| previewCard={props.previewCard} | |||||
| > | |||||
| {dimension.width <= 600 || !props.singleOffer ? ( | |||||
| <ScrollerHorizontal> | |||||
| {props?.offer?.offer?.images.map((item, index) => { | |||||
| if (!item) return; | |||||
| return ( | |||||
| <> | |||||
| <Details | |||||
| hasScrollBar={!props.showPublishButton} | |||||
| exchange={props.showExchangeButton} | |||||
| singleOffer={props.singleOffer} | |||||
| previewCard={props.previewCard} | |||||
| > | |||||
| {dimension.width <= 600 || !props.singleOffer ? ( | |||||
| <ScrollerHorizontal> | |||||
| {props?.offer?.offer?.images.map((item, index) => { | |||||
| if (!item) return; | |||||
| return ( | |||||
| <OfferImage | |||||
| src={ | |||||
| props.createOffer | |||||
| ? images[index] | |||||
| : getImageUrl(item, variants.offerCard, isMobile) | |||||
| } | |||||
| key={item} | |||||
| previewCard={props.previewCard} | |||||
| onClick={() => | |||||
| !props.previewCard && setImagesCarouselModal(true) | |||||
| } | |||||
| /> | |||||
| ); | |||||
| })} | |||||
| </ScrollerHorizontal> | |||||
| ) : ( | |||||
| <ScrollerVertical> | |||||
| {props?.offer?.offer?.images.map((item, index) => ( | |||||
| <OfferImage | <OfferImage | ||||
| src={ | src={ | ||||
| props.createOffer | props.createOffer | ||||
| : getImageUrl(item, variants.offerCard, isMobile) | : getImageUrl(item, variants.offerCard, isMobile) | ||||
| } | } | ||||
| key={item} | key={item} | ||||
| previewCard={props.previewCard} | |||||
| onClick={() => | |||||
| !props.previewCard && setImagesCarouselModal(true) | |||||
| } | |||||
| /> | /> | ||||
| ); | |||||
| })} | |||||
| </ScrollerHorizontal> | |||||
| ) : ( | |||||
| <ScrollerVertical> | |||||
| {props?.offer?.offer?.images.map((item, index) => ( | |||||
| <OfferImage | |||||
| src={ | |||||
| props.createOffer | |||||
| ? images[index] | |||||
| : getImageUrl(item, variants.offerCard, isMobile) | |||||
| } | |||||
| key={item} | |||||
| /> | |||||
| ))} | |||||
| </ScrollerVertical> | |||||
| )} | |||||
| <OfferInfoContainer | |||||
| singleOffer={props.singleOffer} | |||||
| previewCard={props.previewCard} | |||||
| > | |||||
| <OfferTitle singleOffer={props.singleOffer}> | |||||
| {offer?.offer?.name} | |||||
| </OfferTitle> | |||||
| <OfferLittleDetails | |||||
| ))} | |||||
| </ScrollerVertical> | |||||
| )} | |||||
| <OfferInfoContainer | |||||
| singleOffer={props.singleOffer} | singleOffer={props.singleOffer} | ||||
| previewCard={props.previewCard} | previewCard={props.previewCard} | ||||
| > | > | ||||
| <OfferDescriptionTitle> | |||||
| {t("itemDetailsCard.description")} | |||||
| </OfferDescriptionTitle> | |||||
| <OfferDescriptionText showBarterButton={props.showExchangeButton}> | |||||
| {offer?.offer?.description} | |||||
| </OfferDescriptionText> | |||||
| <DesciprtionPostDate previewCard={props.previewCard}> | |||||
| {date} | |||||
| </DesciprtionPostDate> | |||||
| </OfferLittleDetails> | |||||
| </OfferInfoContainer> | |||||
| </Details> | |||||
| <OfferTitle singleOffer={props.singleOffer}> | |||||
| {offer?.offer?.name} | |||||
| </OfferTitle> | |||||
| <OfferLittleDetails | |||||
| singleOffer={props.singleOffer} | |||||
| previewCard={props.previewCard} | |||||
| > | |||||
| <OfferDescriptionTitle> | |||||
| {t("itemDetailsCard.description")} | |||||
| </OfferDescriptionTitle> | |||||
| <OfferDescriptionText showBarterButton={props.showExchangeButton}> | |||||
| {offer?.offer?.description} | |||||
| </OfferDescriptionText> | |||||
| <DesciprtionPostDate previewCard={props.previewCard}> | |||||
| {date} | |||||
| </DesciprtionPostDate> | |||||
| </OfferLittleDetails> | |||||
| </OfferInfoContainer> | |||||
| </Details> | |||||
| {imagesCarouselModal && ( | |||||
| <ImagesCarousel offer={props.offer} onModalClose={onModalClose} /> | |||||
| )} | |||||
| </> | |||||
| ); | ); | ||||
| }; | }; | ||||
| height: 144px; | height: 144px; | ||||
| margin-right: 20px; | margin-right: 20px; | ||||
| object-fit: cover; | object-fit: cover; | ||||
| ${(props) => !props.previewCard && `cursor: pointer;`} | |||||
| @media screen and (max-width: 600px) { | @media screen and (max-width: 600px) { | ||||
| min-width: 144px; | min-width: 144px; |
| const dispatch = useDispatch(); | const dispatch = useDispatch(); | ||||
| const { isMobile } = useIsMobile(); | const { isMobile } = useIsMobile(); | ||||
| const userId = useSelector(selectUserId); | const userId = useSelector(selectUserId); | ||||
| const locations = useSelector((state) => state.locations.locations); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| setShowDetails(!isMobile); | setShowDetails(!isMobile); | ||||
| () => editProfileInitialValues(props?.profile), | () => editProfileInitialValues(props?.profile), | ||||
| [props?.profile] | [props?.profile] | ||||
| ); | ); | ||||
| const validationSchema = useMemo(() => { | |||||
| return editProfileValidation(locations); | |||||
| }, []); | |||||
| const formik = useFormik({ | const formik = useFormik({ | ||||
| initialValues, | initialValues, | ||||
| validationSchema: editProfileValidation, | |||||
| validationSchema: validationSchema, | |||||
| onSubmit: handleSubmit, | onSubmit: handleSubmit, | ||||
| validateOnBlur: true, | validateOnBlur: true, | ||||
| enableReinitialize: true, | enableReinitialize: true, |
| product: "Proizvod", | product: "Proizvod", | ||||
| descriptionLabel: "Opis:", | descriptionLabel: "Opis:", | ||||
| checkButtonLabel: "Pogledaj proizvod", | checkButtonLabel: "Pogledaj proizvod", | ||||
| offers: "Objave" | |||||
| offers: "Objave", | |||||
| }, | }, | ||||
| apiErrors: { | apiErrors: { | ||||
| somethingWentWrong: "Greška sa serverom!", | somethingWentWrong: "Greška sa serverom!", | ||||
| labelLocationRequired: "Lokacija je obavezna!", | labelLocationRequired: "Lokacija je obavezna!", | ||||
| labelPhoneValid: "Unesite validan broj telefona", | labelPhoneValid: "Unesite validan broj telefona", | ||||
| labelPhoneRequired: "Broj telefona je obavezan!", | labelPhoneRequired: "Broj telefona je obavezan!", | ||||
| labelLocationValid: "Unesite validnu lokaciju!", | |||||
| }, | }, | ||||
| deleteOffer: { | deleteOffer: { | ||||
| areYouSure: "Da li ste sigurni da želite da <br /> obrišete proizvod?", | areYouSure: "Da li ste sigurni da želite da <br /> obrišete proizvod?", | ||||
| description: "Opis", | description: "Opis", | ||||
| email: "Mejl kompanije", | email: "Mejl kompanije", | ||||
| }, | }, | ||||
| carousel: { | |||||
| imagesReview: "Pregled fotografija", | |||||
| offer: "Proizvod:", | |||||
| }, | |||||
| }; | }; |
| deleteChat: "chatHeader", | deleteChat: "chatHeader", | ||||
| profileCard: "profileCard", | profileCard: "profileCard", | ||||
| createReviewCard: "createReviewCard", | createReviewCard: "createReviewCard", | ||||
| carousel: "carousel", | |||||
| }; | }; | ||||
| const cloudFlareVariants = { | const cloudFlareVariants = { | ||||
| chatCardMobile: "chatCard", | chatCardMobile: "chatCard", | ||||
| profileCard: "profileCard", | profileCard: "profileCard", | ||||
| createReviewCard: "primaryMobile", | createReviewCard: "primaryMobile", | ||||
| carousel: "carousel", | |||||
| carouselMobile: "carouselMobile", | |||||
| }; | }; | ||||
| export const getImageUrl = (imageUrl, variant, isMobile = false) => { | export const getImageUrl = (imageUrl, variant, isMobile = false) => { | ||||
| let imageVariant = ""; | let imageVariant = ""; |
| import * as Yup from "yup"; | import * as Yup from "yup"; | ||||
| import i18n from "../i18n"; | import i18n from "../i18n"; | ||||
| export default Yup.object().shape({ | |||||
| firmName: Yup.string().required(i18n.t("editProfile.labelNameRequired")), | |||||
| firmPIB: Yup.string() | |||||
| .required(i18n.t("editProfile.labelPIBRequired")) | |||||
| .min(9, i18n.t("register.PIBnoOfCharacters")) | |||||
| .max(9, i18n.t("register.PIBnoOfCharacters")), | |||||
| firmLocation: Yup.string(), | |||||
| firmWebsite: Yup.string(), | |||||
| firmApplink: Yup.string(), | |||||
| firmPhone: Yup.string() | |||||
| .min(6, i18n.t("editProfile.labelPhoneValid")) | |||||
| .max(14, i18n.t("editProfile.labelPhoneValid")), | |||||
| }); | |||||
| export default (locations) => | |||||
| Yup.object().shape({ | |||||
| firmName: Yup.string().required(i18n.t("editProfile.labelNameRequired")), | |||||
| firmPIB: Yup.string() | |||||
| .required(i18n.t("editProfile.labelPIBRequired")) | |||||
| .min(9, i18n.t("register.PIBnoOfCharacters")) | |||||
| .max(9, i18n.t("register.PIBnoOfCharacters")), | |||||
| firmLocation: Yup.string().oneOf( | |||||
| locations.map((l) => l.city), | |||||
| i18n.t("editProfile.labelLocationValid") | |||||
| ), | |||||
| firmWebsite: Yup.string(), | |||||
| firmApplink: Yup.string(), | |||||
| firmPhone: Yup.string() | |||||
| .min(6, i18n.t("editProfile.labelPhoneValid")) | |||||
| .max(14, i18n.t("editProfile.labelPhoneValid")), | |||||
| }); |