| import PropTypes from "prop-types"; | import PropTypes from "prop-types"; | ||||
| import { | import { | ||||
| HeaderPopoverContainer, | HeaderPopoverContainer, | ||||
| NameOfProduct, | |||||
| PopoverButton, | PopoverButton, | ||||
| PopoverButtonsContainer, | PopoverButtonsContainer, | ||||
| PopoverList, | PopoverList, | ||||
| PopoverListItemTextContainer, | PopoverListItemTextContainer, | ||||
| PopoverNoItemsText, | PopoverNoItemsText, | ||||
| PopoverTitle, | PopoverTitle, | ||||
| SecondaryText, | |||||
| SecondaryTextContainer, | |||||
| } from "./HeaderPopover.styled"; | } from "./HeaderPopover.styled"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| onClick: item.onClick, | onClick: item.onClick, | ||||
| }} | }} | ||||
| primary={item.title} | primary={item.title} | ||||
| secondary={item.text} | |||||
| secondary={ | |||||
| <SecondaryTextContainer> | |||||
| <SecondaryText>{item.text}</SecondaryText> | |||||
| <NameOfProduct>{item?.bigText}</NameOfProduct> | |||||
| </SecondaryTextContainer> | |||||
| } | |||||
| ></PopoverListItemTextContainer> | ></PopoverListItemTextContainer> | ||||
| </PopoverListItem> | </PopoverListItem> | ||||
| )) | )) | ||||
| buttonOnClick: PropTypes.func, | buttonOnClick: PropTypes.func, | ||||
| secondButtonOnClick: PropTypes.func, | secondButtonOnClick: PropTypes.func, | ||||
| hideButtons: PropTypes.bool, | hideButtons: PropTypes.bool, | ||||
| bigText: PropTypes.string, | |||||
| }; | }; | ||||
| export default HeaderPopover; | export default HeaderPopover; |
| font-size: 13px; | font-size: 13px; | ||||
| font-family: "DM Sans"; | font-family: "DM Sans"; | ||||
| `; | `; | ||||
| export const NameOfProduct = styled(Typography)` | |||||
| font-size: 12px; | |||||
| font-weight: 700; | |||||
| font-family: "DM Sans"; | |||||
| letter-spacing: 0.02em; | |||||
| color: ${selectedTheme.primaryDarkText}; | |||||
| `; | |||||
| export const SecondaryTextContainer = styled(Box)` | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| gap: 4px; | |||||
| `; | |||||
| export const SecondaryText = styled(Typography)` | |||||
| font-family: "DM Sans"; | |||||
| font-size: 9px; | |||||
| letter-spacing: 0.01em; | |||||
| color: ${selectedTheme.primaryDarkText}; | |||||
| `; |
| const [lastChats, setLastChats] = useState([]); | const [lastChats, setLastChats] = useState([]); | ||||
| const convertMessages = (messages) => { | const convertMessages = (messages) => { | ||||
| console.log(messages) | |||||
| return messages | return messages | ||||
| .map((item) => ({ | .map((item) => ({ | ||||
| src: item.interlocutorData.image, | src: item.interlocutorData.image, | ||||
| title: item.interlocutorData.name, | title: item.interlocutorData.name, | ||||
| onClick: () => goToMessage(item?.chat?._id), | onClick: () => goToMessage(item?.chat?._id), | ||||
| text: item?.chat?.messages[item?.chat?.messages?.length - 1]?.text, | |||||
| text: "Proizvod: ", | |||||
| bigText: item.offerData.name | |||||
| })) | })) | ||||
| .slice(0, 2); | .slice(0, 2); | ||||
| }; | }; |
| import Autosuggest from "react-autosuggest"; | import Autosuggest from "react-autosuggest"; | ||||
| import { AutoSuggestTextFieldContainer } from "./AutoSuggestTextField.styled"; | import { AutoSuggestTextFieldContainer } from "./AutoSuggestTextField.styled"; | ||||
| const languages = [ | |||||
| { | |||||
| name: "C", | |||||
| year: 1972, | |||||
| }, | |||||
| { | |||||
| name: "C#", | |||||
| year: 2000, | |||||
| }, | |||||
| { | |||||
| name: "C++", | |||||
| year: 1983, | |||||
| }, | |||||
| { | |||||
| name: "Clojure", | |||||
| year: 2007, | |||||
| }, | |||||
| { | |||||
| name: "Elm", | |||||
| year: 2012, | |||||
| }, | |||||
| { | |||||
| name: "Go", | |||||
| year: 2009, | |||||
| }, | |||||
| { | |||||
| name: "Haskell", | |||||
| year: 1990, | |||||
| }, | |||||
| { | |||||
| name: "Java", | |||||
| year: 1995, | |||||
| }, | |||||
| { | |||||
| name: "Javascript", | |||||
| year: 1995, | |||||
| }, | |||||
| { | |||||
| name: "Perl", | |||||
| year: 1987, | |||||
| }, | |||||
| { | |||||
| name: "PHP", | |||||
| year: 1995, | |||||
| }, | |||||
| { | |||||
| name: "Python", | |||||
| year: 1991, | |||||
| }, | |||||
| { | |||||
| name: "Ruby", | |||||
| year: 1995, | |||||
| }, | |||||
| { | |||||
| name: "Scala", | |||||
| year: 2003, | |||||
| }, | |||||
| ]; | |||||
| const escapeRegexCharacters = (str) => | const escapeRegexCharacters = (str) => | ||||
| str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); | str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); | ||||
| const getSuggestions = (value) => { | |||||
| const escapedValue = escapeRegexCharacters(value.trim()); | |||||
| if (escapedValue === "") { | |||||
| return []; | |||||
| } | |||||
| const regex = new RegExp("^" + escapedValue, "i"); | |||||
| const suggestions = languages.filter((language) => regex.test(language.name)); | |||||
| if (suggestions.length === 0) { | |||||
| return [{ isAddNew: true }]; | |||||
| } | |||||
| return suggestions; | |||||
| }; | |||||
| const AutoSuggestTextField = () => { | |||||
| const [value, setValue] = useState(""); | |||||
| const AutoSuggestTextField = (props) => { | |||||
| const [suggestions, setSuggestions] = useState([]); | const [suggestions, setSuggestions] = useState([]); | ||||
| const data = [...props.data]; | |||||
| const onChange = (event, { newValue }) => { | |||||
| setValue(newValue); | |||||
| const getSuggestions = (value) => { | |||||
| const escapedValue = escapeRegexCharacters(value.trim()); | |||||
| if (escapedValue === "") { | |||||
| return []; | |||||
| } | |||||
| const regex = new RegExp("^" + escapedValue, "i"); | |||||
| const suggestions = data.filter((dataItem) => regex.test(dataItem.name)); | |||||
| if (suggestions.length === 0) { | |||||
| return [{ isAddNew: true }]; | |||||
| } | |||||
| return suggestions; | |||||
| }; | }; | ||||
| const getSuggestionValue = (suggestion) => { | const getSuggestionValue = (suggestion) => { | ||||
| if (suggestion.isAddNew) { | |||||
| return value; | |||||
| } | |||||
| return suggestion.name; | return suggestion.name; | ||||
| }; | }; | ||||
| setSuggestions([]); | setSuggestions([]); | ||||
| }; | }; | ||||
| const onSuggestionSelected = (event, { suggestion }) => { | |||||
| if (suggestion.isAddNew) { | |||||
| console.log("Add new:", value); | |||||
| } | |||||
| }; | |||||
| const renderSuggestion = (suggestion) => { | const renderSuggestion = (suggestion) => { | ||||
| if (suggestion.isAddNew) { | |||||
| return ( | |||||
| <span> | |||||
| [+] Add new: <strong>{value}</strong> | |||||
| </span> | |||||
| ); | |||||
| } | |||||
| return suggestion.name; | return suggestion.name; | ||||
| }; | }; | ||||
| const inputProps = { | const inputProps = { | ||||
| placeholder: "Type 'c'", | |||||
| value, | |||||
| onChange: onChange, | |||||
| placeholder: props.placeholder, | |||||
| value: props.value, | |||||
| onChange: props.onChange, | |||||
| }; | }; | ||||
| return ( | return ( | ||||
| onSuggestionsClearRequested={onSuggestionsClearRequested} | onSuggestionsClearRequested={onSuggestionsClearRequested} | ||||
| getSuggestionValue={getSuggestionValue} | getSuggestionValue={getSuggestionValue} | ||||
| renderSuggestion={renderSuggestion} | renderSuggestion={renderSuggestion} | ||||
| onSuggestionSelected={onSuggestionSelected} | |||||
| inputProps={inputProps} | inputProps={inputProps} | ||||
| /> | /> | ||||
| </AutoSuggestTextFieldContainer> | </AutoSuggestTextFieldContainer> | ||||
| AutoSuggestTextField.propTypes = { | AutoSuggestTextField.propTypes = { | ||||
| children: PropTypes.node, | children: PropTypes.node, | ||||
| placeholder: PropTypes.string, | |||||
| value: PropTypes.string, | |||||
| onChange: PropTypes.func, | |||||
| data: PropTypes.array, | |||||
| }; | }; | ||||
| export default AutoSuggestTextField; | export default AutoSuggestTextField; |
| font-size: 16px; | font-size: 16px; | ||||
| padding-bottom: 6px; | padding-bottom: 6px; | ||||
| } | } | ||||
| & input:hover { | |||||
| /* & input:hover { | |||||
| border: 1px solid rgba(0, 0, 0, 0.87); | border: 1px solid rgba(0, 0, 0, 0.87); | ||||
| } | |||||
| } */ | |||||
| & input:focus-visible { | & input:focus-visible { | ||||
| border: 2px solid ${selectedTheme.primaryPurple}; | border: 2px solid ${selectedTheme.primaryPurple}; | ||||
| } | } | ||||
| & input::placeholder { | |||||
| color: rgba(0,0,0, 0.38); | |||||
| } | |||||
| & div { | |||||
| z-index: 3000; | |||||
| background-color: ${selectedTheme.primaryBackgroundColor}; | |||||
| } | |||||
| & div ul { | |||||
| border: 1px solid black; | |||||
| border-radius: 4px; | |||||
| padding: 10px; | |||||
| } | |||||
| & div ul li { | & div ul li { | ||||
| background-color: white; | |||||
| padding-left: 16px; | |||||
| cursor: pointer; | |||||
| height: 40px; | |||||
| padding-top: 10px; | |||||
| font-family: "DM Sans"; | |||||
| border-radius: 4px; | |||||
| } | |||||
| & div ul li:hover { | |||||
| background-color: ${selectedTheme.primaryPurple}; | |||||
| color: ${selectedTheme.primaryBackgroundColor}; | |||||
| } | } | ||||
| } | } | ||||
| `; | `; |
| italicPlaceholder: false, | italicPlaceholder: false, | ||||
| showAnimation: false, | showAnimation: false, | ||||
| height: "48px", | height: "48px", | ||||
| // font: "DM Sans" | |||||
| font: "DM Sans" | |||||
| }; | }; |
| authScopeSetHelper, | authScopeSetHelper, | ||||
| authScopeStringGetHelper, | authScopeStringGetHelper, | ||||
| } from '../util/helpers/authScopeHelpers'; | } from '../util/helpers/authScopeHelpers'; | ||||
| import selectedTheme from '../themes'; | |||||
| const useToggleColorMode = () => { | const useToggleColorMode = () => { | ||||
| const currentColorMode = authScopeStringGetHelper('colorMode') || 'light'; | const currentColorMode = authScopeStringGetHelper('colorMode') || 'light'; | ||||
| () => | () => | ||||
| createTheme({ | createTheme({ | ||||
| palette: { | palette: { | ||||
| mode, | |||||
| primary: { | |||||
| main: selectedTheme.primaryPurple | |||||
| } | |||||
| }, | }, | ||||
| }), | }), | ||||
| [mode] | [mode] |
| welcome: "Dobro došli na trampu, želimo vam uspešno trampovanje!", | welcome: "Dobro došli na trampu, želimo vam uspešno trampovanje!", | ||||
| imageError: "Slika je obavezna!", | imageError: "Slika je obavezna!", | ||||
| serverError: "Greška sa serverom!", | serverError: "Greška sa serverom!", | ||||
| phoneNumberNoOfCharacters: "Broj telefona mora imati izmedju 6 i 15 karaktera!", | |||||
| locationError: "Odaberite ispravnu lokaciju!", | |||||
| websiteError: "Unesite ispravnu adresu svog website!" | |||||
| }, | }, | ||||
| forgotPassword: { | forgotPassword: { | ||||
| title: "Povrati lozinku", | title: "Povrati lozinku", |
| import { PrimaryButton } from "../../../../components/Buttons/PrimaryButton/PrimaryButton"; | import { PrimaryButton } from "../../../../components/Buttons/PrimaryButton/PrimaryButton"; | ||||
| import selectedTheme from "../../../../themes"; | import selectedTheme from "../../../../themes"; | ||||
| import AutoSuggestTextField from "../../../../components/TextFields/AutoSuggestTextField/AutoSuggestTextField"; | import AutoSuggestTextField from "../../../../components/TextFields/AutoSuggestTextField/AutoSuggestTextField"; | ||||
| import { useSelector } from "react-redux"; | |||||
| import { selectLocations } from "../../../../store/selectors/locationsSelectors"; | |||||
| import { ErrorMessage } from "../FirstPart/FirstPartOfRegistration.styled"; | |||||
| const ThirdPartOfRegistration = (props) => { | const ThirdPartOfRegistration = (props) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const locations = useSelector(selectLocations); | |||||
| useEffect(() => { | useEffect(() => { | ||||
| if (props.informations?.phoneNumber) { | if (props.informations?.phoneNumber) { | ||||
| formik.setFieldValue("phoneNumber", props.informations?.phoneNumber) | |||||
| formik.setFieldValue("phoneNumber", props.informations?.phoneNumber); | |||||
| } | } | ||||
| if (props.informations?.location) { | if (props.informations?.location) { | ||||
| formik.setFieldValue("location", props.informations?.location) | |||||
| formik.setFieldValue("location", props.informations?.location); | |||||
| } | } | ||||
| if (props.informations?.website) { | if (props.informations?.website) { | ||||
| formik.setFieldValue("website", props.informations?.website) | |||||
| formik.setFieldValue("website", props.informations?.website); | |||||
| } | } | ||||
| }, [props.informations]) | |||||
| }, [props.informations]); | |||||
| const handleSubmit = () => { | const handleSubmit = () => { | ||||
| if (formik.values.website?.length !== 0 && !formik.values.website.match( | |||||
| /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm | |||||
| )) { | |||||
| if ( | |||||
| formik.values.website?.length !== 0 && | |||||
| !formik.values.website.match( | |||||
| /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm | |||||
| ) | |||||
| ) { | |||||
| formik.setFieldError("website"); | formik.setFieldError("website"); | ||||
| } else { | } else { | ||||
| props.handleSubmit(formik.values); | props.handleSubmit(formik.values); | ||||
| } | } | ||||
| } | |||||
| }; | |||||
| const formik = useFormik({ | const formik = useFormik({ | ||||
| initialValues: { | initialValues: { | ||||
| }, | }, | ||||
| validationSchema: Yup.object().shape({ | validationSchema: Yup.object().shape({ | ||||
| phoneNumber: Yup.number(), | phoneNumber: Yup.number(), | ||||
| location: Yup.string(), | |||||
| website: Yup.string() | |||||
| location: Yup.string().oneOf( | |||||
| locations.map((item) => item.city), | |||||
| "Greska!!!" | |||||
| ), | |||||
| website: Yup.string(), | |||||
| }), | }), | ||||
| onSubmit: handleSubmit, | onSubmit: handleSubmit, | ||||
| validateOnBlur: true, | validateOnBlur: true, | ||||
| type="number" | type="number" | ||||
| value={formik.values.phoneNumber} | value={formik.values.phoneNumber} | ||||
| onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
| error={ | |||||
| (formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber)) | |||||
| } | |||||
| error={formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber)} | |||||
| helperText={formik.touched.phoneNumber && formik.errors.phoneNumber} | helperText={formik.touched.phoneNumber && formik.errors.phoneNumber} | ||||
| autoFocus | autoFocus | ||||
| fullWidth | fullWidth | ||||
| /> | /> | ||||
| <TextField | |||||
| {/* <TextField | |||||
| name="location" | name="location" | ||||
| placeholder={t("common.labelLocation")} | placeholder={t("common.labelLocation")} | ||||
| margin="normal" | margin="normal" | ||||
| error={formik.touched.location && Boolean(formik.errors.location)} | error={formik.touched.location && Boolean(formik.errors.location)} | ||||
| helperText={formik.touched.location && formik.errors.location} | helperText={formik.touched.location && formik.errors.location} | ||||
| fullWidth | fullWidth | ||||
| /> */} | |||||
| <AutoSuggestTextField | |||||
| placeholder={t("common.labelLocation")} | |||||
| data={locations.map((item) => ({ name: item.city }))} | |||||
| value={formik.values.location} | |||||
| onChange={(event, { newValue }) => | |||||
| formik.setFieldValue("location", newValue) | |||||
| } | |||||
| /> | /> | ||||
| <TextField | <TextField | ||||
| fullWidth | fullWidth | ||||
| /> | /> | ||||
| <AutoSuggestTextField /> | |||||
| <ErrorMessage>{formik.errors.phoneNumber}</ErrorMessage> | |||||
| <PrimaryButton | <PrimaryButton | ||||
| type="submit" | type="submit" |