\r\n
{t(\"common:reset-password\")} \r\n
\r\n
{t(\"common:reset-password-info-a\")} {t(\"common:reset-password-info-b\")}
\r\n
\r\n {\r\n emailElement = r;\r\n }}\r\n onChange={emailChange} \r\n onKeyPress={submitEditing}\r\n placeholder=\"E-mail\"\r\n />\r\n {emailError && {t(\"common:emailError\")} }\r\n \r\n
\r\n
{t(\"common:exit\")} \r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(ResetPassword));\r\n","import React, {useState, useEffect} from 'react';\r\nimport {\r\n FormControl,\r\n FormHelperText,\r\n Input, \r\n InputAdornment,\r\n IconButton \r\n} from '@material-ui/core';\r\nimport { Visibility, VisibilityOff } from '@material-ui/icons';\r\nimport GreenSubminButton from '../buttons/greenSubmitButton';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport Utils from '../../Utils';\r\n\r\nlet passwordElement;\r\nlet newPasswordElement;\r\nlet repeatPasswordElement;\r\n\r\nconst ChangePassword = ({ feathersStore })=> {\r\n\r\n const [loading, setLoading] = useState(false);\r\n const [password, setPassword] = useState(\"\");\r\n const [showPassword, setShowPassword] = useState(false);\r\n const [passwordError, setPasswordError] = useState(false);\r\n const [newPassword, setNewPassword] = useState(\"\");\r\n const [showNewPassword, setShowNewPassword] = useState(false);\r\n const [newPasswordError, setNewPasswordError] = useState(false);\r\n const [repeatPassword, setRepeatPassword] = useState(\"\");\r\n const [repeatPasswordError, setRepeatPasswordError] = useState(false);\r\n const [showRepeatPassword, setShowRepeatPassword] = useState(false); \r\n const [secondTime1, setSecondTime1] = useState(false);\r\n const [secondTime2, setSecondTime2] = useState(false);\r\n\r\n useEffect(() => {\r\n passwordElement.focus();\r\n }, []);\r\n\r\n const passwordChange = event => { \r\n setPassword(event.target.value);\r\n secondTime1 && passwordValidation(event.target.value); \r\n };\r\n\r\n const newPasswordChange = event => { \r\n setNewPassword(event.target.value);\r\n secondTime2 && newPasswordValidation(event.target.value); \r\n };\r\n\r\n const repeatPasswordChange = event => { \r\n setRepeatPassword(event.target.value); \r\n };\r\n\r\n const passwordValidation = val => {\r\n if (!Utils.validatePassword(val) ) {\r\n setPasswordError(true);\r\n }else{\r\n setPasswordError(false);\r\n }\r\n } \r\n\r\n const newPasswordValidation = val => {\r\n if (!Utils.validatePassword(val) ) {\r\n setNewPasswordError(true);\r\n }else{\r\n setNewPasswordError(false);\r\n }\r\n } \r\n\r\n const handleClickShowPassword = () => {\r\n setShowPassword(!showPassword);\r\n };\r\n\r\n const handleClickShowNewPassword = () => {\r\n setShowNewPassword(!showNewPassword);\r\n };\r\n\r\n const handleClickShowRepeatPassword = () => {\r\n setShowRepeatPassword(!showRepeatPassword);\r\n };\r\n\r\n const enterPasswordPressed = (ev) => { \r\n if (ev.key === 'Enter') {\r\n newPasswordElement.focus();\r\n }\r\n }\r\n\r\n const enterNewPasswordPressed = (ev) => { \r\n if (ev.key === 'Enter') {\r\n repeatPasswordElement.focus();\r\n }\r\n }\r\n\r\n const enterRepeatPasswordPressed = (ev) => { \r\n if (ev.key === 'Enter') {\r\n \r\n }\r\n }\r\n \r\n const newPasswordFocus = () => { \r\n setSecondTime1(true);\r\n passwordValidation(password); \r\n };\r\n\r\n const repeatPasswordFocus = () => { \r\n setSecondTime2(true);\r\n newPasswordValidation(newPassword);\r\n };\r\n\r\n const handleMouseDownPassword = (event) => {\r\n event.preventDefault();\r\n };\r\n\r\n const onClick = async () => {\r\n setLoading(true);\r\n if (newPassword === repeatPassword){\r\n try{\r\n await feathersStore.changePassword(newPassword);\r\n setLoading(false);\r\n alert('Επιτυχής αλλαγή password');\r\n }catch (error){\r\n setLoading(false);\r\n alert(`Ανεπιτυχής αλλαγή password, ${error.message}`)\r\n resetFields(); \r\n }\r\n }else{\r\n // setRepeatPasswordError(true);\r\n setLoading(false);\r\n resetFields(); \r\n alert(\"Το επαναληπτικό password δεν ταιριάζει\");\r\n \r\n }\r\n }\r\n\r\n const resetFields = () => {\r\n setPassword(\"\");\r\n setNewPassword(\"\");\r\n setRepeatPassword(\"\");\r\n setSecondTime1(false);\r\n setSecondTime2(false);\r\n setPasswordError(false);\r\n setNewPasswordError(false);\r\n setRepeatPasswordError(false);\r\n setShowPassword(false);\r\n setShowNewPassword(false);\r\n setShowRepeatPassword(false);\r\n }\r\n\r\n return(\r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(ChangePassword));","import React, {useState, useEffect} from 'react';\r\nimport Camera from '../buttons/camera';\r\nimport Lock from '@material-ui/icons/Lock'\r\nimport CloseIcon from '@material-ui/icons/Close';\r\nimport ExpandMore from '@material-ui/icons/ExpandMore';\r\nimport 'react-slidedown/lib/slidedown.css'\r\nimport ChangePassword from '../screenComponents/changePassword'\r\nimport GreenSubmitButton from '../buttons/greenSubmitButton';\r\nimport { \r\n FormControl,\r\n FormHelperText,\r\n Input \r\n } from '@material-ui/core';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport Utils from '../../Utils';\r\nimport { CSSTransition } from 'react-transition-group';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nlet firstNameElement;\r\nlet lastNameElement;\r\nlet phoneElement;\r\n\r\nconst ProfileSettings = ({feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation(['common', 'account']);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n const [email, setEmail] = useState(feathersStore.user.email); \r\n const [firstName, setFirstName] = useState(feathersStore.user.firstname); \r\n const [lastName, setLastName] = useState(feathersStore.user.lastname); \r\n const [phone, setPhone] = useState(feathersStore.user.phone); \r\n const [firstNameError, setFirstNameError] = useState(false); \r\n const [lastNameError, setLastNameError] = useState(false); \r\n const [phoneError, setPhoneError] = useState(false); \r\n const [loading, setLoading] = useState(false); \r\n const [activeDropdown, setActiveDropdown] = useState(false);\r\n \r\n const firstNameChange = event => { \r\n setFirstName(event.target.value);\r\n firstNameValidation(event.target.value); \r\n };\r\n\r\n const lastNameChange = event => { \r\n setLastName(event.target.value);\r\n lastNameValidation(event.target.value); \r\n };\r\n\r\n const phoneChange = event => { \r\n setPhone(event.target.value);\r\n phoneValidation(event.target.value); \r\n };\r\n\r\n const firstNameValidation = val => {\r\n if (!Utils.validateName(val) ) {\r\n setFirstNameError(true);\r\n }else{\r\n setFirstNameError(false);\r\n }\r\n }\r\n\r\n const lastNameValidation = val => {\r\n if (!Utils.validateName(val) ) {\r\n setLastNameError(true);\r\n }else{\r\n setLastNameError(false);\r\n }\r\n }\r\n\r\n const phoneValidation = val => {\r\n if (!Utils.validatePhone(val) ) {\r\n setPhoneError(true);\r\n }else{\r\n setPhoneError(false);\r\n }\r\n } \r\n\r\n const enterFirstNamePressed = (ev) => { \r\n if (ev.key === 'Enter') {\r\n lastNameElement.focus();\r\n }\r\n }\r\n\r\n const enterLastNamePressed = (ev) => {\r\n if (ev.key === 'Enter') {\r\n phoneElement.focus();\r\n }\r\n }\r\n\r\n const enterPhonePressed = (ev) => {\r\n if (ev.key === 'Enter') {\r\n firstNameElement.focus();\r\n }\r\n }\r\n\r\n const submitEditing = async(ev) => {\r\n if (ev.key === 'Enter') {\r\n updateUser();\r\n }\r\n }\r\n\r\n const updateUser = () => {\r\n setLoading(true);\r\n feathersStore.patchUser(feathersStore.user._id, firstName, lastName, phone)\r\n .then(user => {\r\n feathersStore.setUser(user);\r\n setLoading(false);\r\n alert(t(\"account:update-alert\"));\r\n })\r\n .catch(error => {\r\n setLoading(false);\r\n alert(`${t(\"account:update-alert\")}: ${error.message}`)\r\n });\r\n };\r\n\r\n const toggleChangePassword = () => {\r\n setActiveDropdown(!activeDropdown)\r\n }\r\n\r\n return(\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n
toggleChangePassword()}>{t(\"account:psw\")} \r\n \r\n {activeDropdown ? \r\n
toggleChangePassword()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n :\r\n
toggleChangePassword()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n }\r\n
\r\n
\r\n \r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(ProfileSettings));","import React, {useState, useEffect} from 'react';\r\n//import Modal from 'react-awesome-modal';\r\nimport {\r\n FormControl,\r\n FormHelperText,\r\n Input,\r\n TextareaAutosize,\r\n Modal\r\n} from '@material-ui/core';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport CloseButton from '../../buttons/closeButton'\r\nimport GreenSubmitButton from '../../buttons/greenSubmitButton';\r\nimport { easings } from 'react-animation'\r\nimport RoundedButton from '../../buttons/roundedButton'\r\nimport HomeIcon from '@material-ui/icons/Home';\r\nimport ApartmentIcon from '@material-ui/icons/Apartment';\r\nimport BusinessCenterIcon from '@material-ui/icons/BusinessCenter';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport Utils from '../../../Utils'; \r\nimport \"./AddOrEditAddressModal.css\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nlet streetElement;\r\nlet streetNumberElement;\r\nlet cityElement;\r\nlet postcodeElement;\r\nlet apartmentElement;\r\nlet addressCommentElement;\r\n\r\nfunction getModalStyle() {\r\n const top = 50;\r\n const left = 50 ;\r\n\r\n return {\r\n top: `${top}%`,\r\n left: `${left}%`,\r\n transform: `translate(-${top}%, -${left}%)`,\r\n };\r\n}\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n paper: {\r\n position: 'absolute',\r\n \r\n backgroundColor: theme.palette.background.paper,\r\n // border: '2px solid #000',\r\n boxShadow: theme.shadows[5],\r\n // padding: theme.spacing(2, 4, 3),\r\n },\r\n}));\r\n\r\nconst AddOrEditaddressModal = ({visible, close, itemToEdit, feathersStore})=> { \r\n\r\n const { t, i18n } = useTranslation(['common','account']);\r\n\r\n const classes = useStyles();\r\n const [modalStyle] = React.useState(getModalStyle);\r\n \r\n const [otherSelected, setOther] = useState(false);\r\n const [homeSelected, setHome] = useState(false);\r\n const [workSelected, setWork] = useState(false);\r\n const [header, setHeader] = useState(\"\");\r\n const [title, setTitle] = useState(\"Οικία\");\r\n const [streetNumber, setStreetNumber] = useState(\"\");\r\n const [street, setStreet] = useState(\"\");\r\n const [apartment, setApartment] = useState(\"\"); \r\n const [addressComment, setAddressComment] = useState(\"\"); \r\n const [postcode, setPostcode] = useState(\"\"); \r\n const [city, setCity] = useState(\"\"); \r\n const [active, setActive] = useState(false); \r\n const [streetError, setStreetError] = useState(false);\r\n const [streetNumberError, setStreetNumberError] = useState(false); \r\n const [cityError, setCityError] = useState(false);\r\n const [loading, setLoading] = useState(false); \r\n\r\n \r\n useEffect(() => {\r\n i18n.changeLanguage(feathersStore.language); \r\n setHeader(t(\"account:add-new-address\"));\r\n if(Object.keys(itemToEdit).length !== 0 && itemToEdit.constructor === Object){\r\n setHeader(t(\"account:modal-header-update\"));\r\n setTitle(itemToEdit.title);\r\n switch(itemToEdit.title){\r\n case \"Οικία\" : setHome(true);\r\n break;\r\n case \"Έργασία\" : setWork(true);\r\n break;\r\n case \"Άλλη Τοποθεσία\" : setOther(true);\r\n break;\r\n }\r\n setStreet(itemToEdit.street);\r\n setStreetNumber(itemToEdit.streetNumber);\r\n setCity(itemToEdit.city);\r\n setPostcode(itemToEdit.postcode);\r\n setApartment(itemToEdit.apartment);\r\n setAddressComment(itemToEdit.addressComment);\r\n setActive(itemToEdit.active);\r\n } \r\n }, [feathersStore.language])\r\n\r\n const PressOther = ()=> {\r\n setOther(true);\r\n setHome(false);\r\n setWork(false);\r\n setTitle('Άλλη Τοποθεσία')\r\n }\r\n\r\n const PressHome = ()=> {\r\n setOther(false);\r\n setHome(true);\r\n setWork(false);\r\n setTitle('Οικία')\r\n }\r\n\r\n const PressWork = ()=> {\r\n setOther(false);\r\n setHome(false);\r\n setWork(true);\r\n setTitle('Έργασία');\r\n }\r\n\r\n const onChangeText = key => (event) => {\r\n \r\n switch(key){\r\n case \"street\" : {setStreet(event.target.value); streetValidation(event.target.value);}\r\n break;\r\n case \"streetNumber\" : {setStreetNumber(event.target.value); streetNumberValidation(event.target.value);}\r\n break;\r\n case \"city\" : {setCity(event.target.value); cityValidation(event.target.value);}\r\n break;\r\n case \"postcode\" : setPostcode(event.target.value); \r\n break;\r\n case \"apartment\" : setApartment(event.target.value);\r\n break;\r\n case \"addressComment\" : setAddressComment(event.target.value);\r\n break;\r\n }\r\n };\r\n\r\n const enterPressed = key => (ev) => { \r\n if (ev.key === 'Enter') {\r\n switch(key){\r\n case \"street\" : streetNumberElement.focus();\r\n break;\r\n case \"streetNumber\" : cityElement.focus();\r\n break;\r\n case \"city\" : postcodeElement.focus();\r\n break;\r\n case \"postcode\" : apartmentElement.focus();\r\n break;\r\n case \"apartment\" : addressCommentElement.focus();\r\n break;\r\n case \"addressComment\" : streetElement.focus();\r\n break;\r\n }\r\n \r\n }\r\n }\r\n\r\n const streetValidation = val => {\r\n if (!Utils.validateNonEmpty(val) ) {\r\n setStreetError(true);\r\n }else{\r\n setStreetError(false);\r\n }\r\n }\r\n\r\n const streetNumberValidation = val => {\r\n if (!Utils.validateNonEmpty(val) ) { \r\n setStreetNumberError(true);\r\n }else{\r\n setStreetNumberError(false);\r\n }\r\n }\r\n\r\n const cityValidation = val => {\r\n if (!Utils.validateNonEmpty(val) ) {\r\n setCityError(true);\r\n }else{\r\n setCityError(false);\r\n }\r\n }\r\n\r\n const saveAddress = async () => {\r\n setLoading(true); \r\n let clonedAddresses=[...feathersStore.user?.addresses]; \r\n const data = { title, city, street, streetNumber, postcode, apartment, addressComment, active}; \r\n if(Object.keys(itemToEdit).length !== 0 && itemToEdit.constructor === Object){\r\n const index = clonedAddresses.indexOf(itemToEdit);\r\n clonedAddresses.splice(index, 1, data);\r\n }else {\r\n clonedAddresses.push(data); \r\n } \r\n try{\r\n const user = await feathersStore.patchAddresses( feathersStore.user._id, [...clonedAddresses]);\r\n feathersStore.setUser(user);\r\n setLoading(false); \r\n alert(t(\"common:update-success\"));\r\n }catch (error){\r\n setLoading(false); \r\n alert(t(\"common:update-error\") + `: ${error.message}`)\r\n }\r\n };\r\n\r\n return(\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
{header} \r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n
{t(\"account:helper-text\")} \r\n
\r\n {\r\n streetElement = r;\r\n }}\r\n onChange={onChangeText(\"street\")} \r\n onKeyPress={enterPressed(\"street\")} \r\n placeholder={t(\"common:street\") + \"*\"}\r\n />\r\n {streetError && {t(\"common:street-error\")} }\r\n \r\n
\r\n {\r\n streetNumberElement = r;\r\n }}\r\n onChange={onChangeText(\"streetNumber\")} \r\n onKeyPress={enterPressed(\"streetNumber\")} \r\n placeholder={t(\"common:streetNumber\") + \"*\"}\r\n />\r\n {streetNumberError && {t(\"common:streetNumber-error\")} }\r\n \r\n
\r\n {\r\n cityElement = r;\r\n }}\r\n onChange={onChangeText(\"city\")} \r\n onKeyPress={enterPressed(\"city\")} \r\n placeholder={t(\"common:city\") + \"*\"}\r\n />\r\n {cityError && {t(\"common:city-error\")} }\r\n \r\n
\r\n {\r\n postcodeElement = r;\r\n }}\r\n onChange={onChangeText(\"postcode\")} \r\n onKeyPress={enterPressed(\"postcode\")} \r\n placeholder={t(\"common:postcode\") + \"*\"}\r\n /> \r\n \r\n
\r\n {\r\n apartmentElement = r;\r\n }}\r\n onChange={onChangeText(\"apartment\")} \r\n onKeyPress={enterPressed(\"apartment\")} \r\n placeholder={t(\"common:apartment\")}\r\n /> \r\n \r\n
\r\n {\r\n addressCommentElement = r;\r\n }}\r\n onChange={onChangeText(\"addressComment\")} \r\n onKeyPress={enterPressed(\"addressComment\")} \r\n placeholder={t(\"account:address-comments\")}\r\n /> \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(AddOrEditaddressModal));","import React from 'react'\r\nimport Person from '@material-ui/icons/Person';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst SignInButton = ({onClickSignIn})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n return(\r\n
\r\n \r\n {t('common:sign-in')} \r\n \r\n )\r\n}\r\n\r\nexport default SignInButton;","import React, {useEffect} from 'react'\r\n//import BagIcon from '@material-ui/icons/LocalMall'\r\nimport ShoppingCartOutlinedIcon from '@material-ui/icons/ShoppingCartOutlined';\r\nimport { Link } from 'react-router-dom';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport \"./CartButton.css\"\r\n\r\n\r\nconst CartButton = ({ feathersStore }) => {\r\n\r\n useEffect(() => {\r\n const cart = localStorage.getItem('fire_cart');\r\n cart && feathersStore\r\n .setCartLength(JSON.parse(localStorage.getItem('fire_cart')).length);\r\n }, []);\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n \r\n {feathersStore.cartLength} \r\n \r\n \r\n >\r\n )\r\n}\r\n\r\n\r\nexport default inject('feathersStore')(observer(CartButton));","import React, { useEffect } from 'react'\r\nimport PersonIcon from '@material-ui/icons/Person';\r\nimport {Link} from 'react-router-dom'\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst AccountButton = (feathersStore)=> {\r\n\r\n const { t, i18n } = useTranslation('account');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n }, [feathersStore.language]);\r\n\r\n return(\r\n
\r\n
\r\n \r\n {t(\"account:myAccount\")} \r\n \r\n \r\n )\r\n}\r\n\r\nexport default AccountButton;","import React, { useState, useEffect } from 'react';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport {Link} from 'react-router-dom';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';\r\nimport Menu from '@material-ui/core/Menu';\r\nimport TreeView from '@material-ui/lab/TreeView';\r\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\r\nimport ChevronRightIcon from '@material-ui/icons/ChevronRight';\r\nimport TreeItem from '@material-ui/lab/TreeItem';\r\nimport { useHistory } from 'react-router-dom';\r\nimport '../screenComponents/categoriesBar/CategoriesNavBar.css'\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n root: {\r\n maxHeight: 350,\r\n flexGrow: 1,\r\n maxWidth: 450, \r\n marginRight: theme.spacing(2)\r\n },\r\n button: {\r\n margin: theme.spacing(1),\r\n marginLeft: theme.spacing(0),\r\n // marginRight: theme.spacing(0),\r\n width: theme.spacing(8),\r\n // backgroundColor: Colors.primary,\r\n color: \"#fff\"\r\n },\r\n menuItem: {\r\n fontSize: theme.spacing(2),\r\n }\r\n}));\r\n\r\nconst CategoriesMenu = ({node, feathersStore})=> {\r\n\r\n const classes = useStyles(); \r\n const history = useHistory();\r\n\r\n const [anchorEl, setAnchorEl] = useState(null); \r\n \r\n const handleClick = (event) => {\r\n setAnchorEl(event.currentTarget);\r\n };\r\n\r\n const handleClose = () => {\r\n setAnchorEl(null);\r\n };\r\n\r\n const handlePress = item => () => { \r\n const payload = { \r\n categoryId: item.id, \r\n title: item.name, \r\n searchText: \"\"\r\n }; \r\n feathersStore.setSearchCategory(payload); \r\n history.push({\r\n pathname: `/Home/${item.name}` \r\n });\r\n handleClose();\r\n }\r\n\r\n const renderTree = (nodes) => (\r\n
}\r\n expandIcon={
} \r\n >\r\n {Array.isArray(nodes.childrens) ? nodes.childrens.map((node) => renderTree(node)) : null}\r\n \r\n );\r\n \r\n return(\r\n <>\r\n
\r\n \r\n
\r\n
\r\n {node.name}\r\n \r\n {node.childrens.length > 0 && 0 ? handleClick : null}>\r\n \r\n }\r\n \r\n
\r\n >\r\n )\r\n}\r\nexport default inject('feathersStore')(observer(CategoriesMenu));\r\n","import React, { useState } from 'react';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport './CategoriesNavBar.css';\r\nimport { CircularProgress } from '@material-ui/core';\r\nimport { setPageStateUpdate } from '@material-ui/data-grid';\r\nimport CategoriesNavMenu from \"../../cards/categoriesNavMenu\";\r\nimport HomeIcon from '@material-ui/icons/Home';\r\nimport { useHistory, useParams } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst CategoriesNavBar = ({feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n const history = useHistory();\r\n const {name} = useParams();\r\n\r\n const resetProducts = () => {\r\n feathersStore.setSearchCategory({}); \r\n history.push({\r\n pathname: \"/\" \r\n }); \r\n } \r\n \r\n const renderCategoryItem = (node) => ( \r\n
\r\n \r\n
\r\n );\r\n\r\n return(\r\n <>\r\n
\r\n
resetProducts()} className=\"category-nav-view-item\" > \r\n \r\n {/* \r\n \r\n */}\r\n {t('common:home')} \r\n \r\n
\r\n {feathersStore.categories ? \r\n feathersStore.categories?.map(renderCategoryItem) \r\n :\r\n
\r\n } \r\n
\r\n >\r\n )\r\n\r\n\r\n}\r\n\r\nexport default inject('feathersStore')(observer(CategoriesNavBar));","import React, { useState, useEffect } from 'react'\r\nimport SignInButton from '../../buttons/signInButton'\r\nimport CartButton from '../../buttons/cartButton/CartButton';\r\nimport AccountButton from '../../buttons/accountButton'\r\nimport { inject, observer } from \"mobx-react\";\r\nimport {Link} from 'react-router-dom';\r\nimport './TopBarBootstrap.css';\r\nimport { useTranslation } from 'react-i18next';\r\nimport CategoriesNavBar from '../categoriesBar/CategoriesNavBar'\r\n\r\nconst TopBar = ({onClickSignIn, feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n \r\n const resetProducts = () => {\r\n feathersStore.setSearchCategory({});\r\n }\r\n\r\n const toggleLanguage = lang => {\r\n feathersStore.setLanguage(lang);\r\n }\r\n\r\n const [settingsPhone, setSettingsPhone] = useState(\"\");\r\n \r\n useEffect(() => {\r\n const phoneNumber = feathersStore.settings?.phoneNumbers &&\r\n feathersStore.settings?.phoneNumbers.find(p => p.numberEnabled).phoneNumber;\r\n setSettingsPhone(phoneNumber); \r\n },[feathersStore.settings?.phoneNumbers])\r\n \r\n return(\r\n
\r\n
\r\n resetProducts()} className=\"navbar-brand nav-nav-left Artist-Name\">{t('common:artists-name')}\r\n \r\n \r\n
\r\n
\r\n {feathersStore.isAuthenticated && feathersStore.user?.firstname === \"default\" &&\r\n
\r\n \r\n
}\r\n
\r\n
\r\n
\r\n {feathersStore.isAuthenticated && feathersStore.user?.firstname !== \"default\" &&\r\n
}\r\n
\r\n
\r\n \r\n
\r\n {/*
\r\n TAMEIO\r\n */}\r\n
\r\n
\r\n
\r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(TopBar));","import React, { useState, useEffect } from 'react';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { Link } from 'react-router-dom';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';\r\nimport Menu from '@material-ui/core/Menu';\r\nimport TreeView from '@material-ui/lab/TreeView';\r\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\r\nimport ChevronRightIcon from '@material-ui/icons/ChevronRight';\r\nimport TreeItem from '@material-ui/lab/TreeItem';\r\nimport { useHistory } from 'react-router-dom';\r\nimport '../../components/screenComponents/categoriesBar/CategoriesBar.css';\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n root: {\r\n maxHeight: 350,\r\n flexGrow: 1,\r\n maxWidth: 450,\r\n marginRight: theme.spacing(2),\r\n },\r\n button: {\r\n margin: theme.spacing(1),\r\n marginLeft: theme.spacing(0),\r\n // marginRight: theme.spacing(0),\r\n width: theme.spacing(8),\r\n // backgroundColor: Colors.primary,\r\n color: \"#fff\"\r\n },\r\n menuItem: {\r\n fontSize: theme.spacing(2),\r\n }\r\n}));\r\n\r\nconst CategoriesMenu = ({node, feathersStore})=> {\r\n\r\n const classes = useStyles();\r\n const history = useHistory();\r\n\r\n const [anchorEl, setAnchorEl] = useState(null);\r\n\r\n const handleClick = (event) => {\r\n setAnchorEl(event.currentTarget);\r\n };\r\n\r\n const handleClose = () => {\r\n setAnchorEl(null);\r\n };\r\n\r\n const handlePress = item => () => {\r\n const payload = {\r\n categoryId: item.id,\r\n title: item.name,\r\n searchText: \"\"\r\n };\r\n feathersStore.setSearchCategory(payload);\r\n history.push({\r\n pathname: `/Home/${item.name}`\r\n });\r\n handleClose();\r\n }\r\n\r\n const renderTree = (nodes) => (\r\n
}\r\n expandIcon={
}\r\n >\r\n {Array.isArray(nodes.childrens) ? nodes.childrens.map((node) => renderTree(node)) : null}\r\n \r\n );\r\n\r\n return(\r\n <>\r\n
\r\n \r\n
\r\n
\r\n {node.name}\r\n \r\n {node.childrens.length > 0 && 0 ? handleClick : null}>\r\n \r\n }\r\n \r\n
\r\n >\r\n )\r\n}\r\nexport default inject('feathersStore')(observer(CategoriesMenu));\r\n","import React, { useState } from 'react';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport './CategoriesBar.css';\r\nimport { CircularProgress } from '@material-ui/core';\r\nimport { setPageStateUpdate } from '@material-ui/data-grid';\r\nimport CategoriesMenu from \"../../cards/categoriesMenu\";\r\nimport HomeIcon from '@material-ui/icons/Home';\r\nimport { useHistory, useParams } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst CategoriesBar = ({feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n const history = useHistory();\r\n const {name} = useParams();\r\n\r\n const resetProducts = () => {\r\n feathersStore.setSearchCategory({}); \r\n history.push({\r\n pathname: \"/\" \r\n }); \r\n } \r\n \r\n const renderCategoryItem = (node) => ( \r\n
\r\n \r\n
\r\n );\r\n\r\n return(\r\n <>\r\n
\r\n
resetProducts()} className=\"category-view-item\" > \r\n \r\n {/* \r\n \r\n */}\r\n {t('common:home')} \r\n \r\n
\r\n {feathersStore.categories ? \r\n feathersStore.categories?.map(renderCategoryItem) \r\n :\r\n
\r\n } \r\n
\r\n >\r\n )\r\n\r\n\r\n}\r\n\r\nexport default inject('feathersStore')(observer(CategoriesBar));","import React from 'react';\r\nimport \"./Carousel.css\";\r\n\r\nconst Carousel = ()=> {\r\n\r\n return(\r\n
\r\n )\r\n}\r\n\r\nexport default Carousel;","import React from 'react';\r\n\r\n\r\nconst CategoryPic = ({image})=> {\r\n return(\r\n
\r\n )\r\n}\r\n\r\nexport default CategoryPic;","import React, { useEffect, useState } from 'react'\r\nimport { useTranslation } from 'react-i18next';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport {Link} from 'react-router-dom';\r\nimport CategoryPic from './categoryPic';\r\nimport ReactHtmlParser from 'react-html-parser'\r\n\r\nconst ResumeComponent = ({feathersStore}) => {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n // useEffect(()=> {\r\n // i18n.changeLanguage(feathersStore.language);\r\n // },[feathersStore.language]);\r\n\r\n return (\r\n <>\r\n
\r\n
\r\n
\r\n
{t(\"common:artists-resume-name\")} \r\n
{t(\"common:short-biography\")}
\r\n
\r\n
{t(\"common:learn-more\")}
\r\n \r\n
\r\n
\r\n >\r\n )\r\n}\r\n\r\nexport default ResumeComponent;","import React from 'react'\r\nimport ShoppingCart from '@material-ui/icons/ShoppingCart'\r\n\r\nconst AddToCartSmall = ({ onClick })=> {\r\n\r\n return(\r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default AddToCartSmall;","import React from 'react'\r\nimport AddToCartSmall from '../../buttons/addToCartSmall'\r\nimport NavigateNext from '@material-ui/icons/NavigateNext'\r\nimport { CSSTransition } from 'react-transition-group';\r\nimport {Alert} from 'react-bootstrap';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport './ProductCard.css';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst ProductCard = ({stock, hasVariation, onClickForward, title, onPressAddToFavorites,\r\n warning, price, oldPrice, image, onClick, onClickCart, onCloseWarning, favorite, feathersStore, badges})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n return(\r\n
\r\n
\r\n \r\n {(badges?.includes('new')) && (\r\n )\r\n }\r\n {((badges?.includes('sale')) || oldPrice) && (\r\n )\r\n }\r\n {(badges?.includes('hot')) && (\r\n )\r\n } \r\n \r\n
\r\n
\r\n
\r\n {oldPrice &&\r\n
\r\n {oldPrice}€
\r\n }\r\n
\r\n {price}€
\r\n
\r\n {/* {feathersStore.isAuthenticated && feathersStore.user?.firstname !== \"default\" && \r\n
} */}\r\n {stock !== 0? <>{hasVariation ?\r\n
\r\n \r\n \r\n :\r\n
} >\r\n :\r\n \r\n }\r\n \r\n
\r\n \r\n {t('common:danger')} \r\n {t('common:no-more-products-in-stock')}
\r\n \r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(ProductCard));","import React, { useEffect } from 'react';\r\nimport { CSSTransition } from 'react-transition-group';\r\nimport {Alert} from 'react-bootstrap';\r\n\r\nconst SmallAlert = ({ show, styling, heading, onClose, message}) =>{\r\n\r\n \r\n return(\r\n <>\r\n
\r\n
\r\n \r\n {heading} \r\n {message}
\r\n \r\n \r\n
\r\n >\r\n )\r\n}\r\n\r\nexport default SmallAlert;","import React, {useState, useEffect} from 'react'\r\nimport ProductCard from '../cards/productCard/ProductCard'\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useHistory } from 'react-router-dom';\r\nimport * as cloneDeep from 'lodash/cloneDeep';\r\nimport SmallAlert from '../modals/smallAlert';\r\nimport { useTranslation } from 'react-i18next';\r\nimport Pagination from '@material-ui/lab/Pagination';\r\n\r\nlet initialCartBiggestId = 0;\r\nlet cart = [];\r\n\r\nconst ListProducts = ({ feathersStore })=> { \r\n\r\n const { t, i18n } = useTranslation('common');\r\n const history = useHistory();\r\n\r\n const [products, setProducts] = useState([]); \r\n const [popularProducts, setPopularProducts] = useState([]);\r\n const [cartIncreased, setCartIncreased] = useState(false);\r\n const [favoritesUpdated, setFavoritesUpdated] = useState(false);\r\n \r\n useEffect(() => {\r\n if(localStorage.getItem('fire_cart')){\r\n cart = JSON.parse(localStorage.getItem('fire_cart')); \r\n if(cart.length > 0)\r\n initialCartBiggestId = +cart.map(e => e.id).sort().reverse()[0] + 1; \r\n }\r\n }, []);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n useEffect(()=>{\r\n feathersStore.isAuthenticated && fetchProducts();\r\n },[feathersStore?.searchCategory, feathersStore.isAuthenticated, feathersStore?.favoritesArray,\r\n feathersStore.productUpdatedEvent, feathersStore.productCreatedEvent]); \r\n\r\n const fetchProducts = async() => { \r\n let feathersProducts; \r\n if(feathersStore.searchCategory?.categoryId){\r\n const { categoryId, searchText } = feathersStore?.searchCategory;\r\n feathersProducts = await feathersStore.productsPerCategory(+categoryId, searchText); \r\n }\r\n else {\r\n feathersProducts = await feathersStore.products(feathersStore.searchCategory?.searchText); \r\n }\r\n setProducts([...feathersProducts]);\r\n \r\n const feathersPopularProducts = await feathersStore.popularProducts();\r\n setPopularProducts([...feathersPopularProducts]);\r\n }\r\n\r\n \r\n\r\n const getMainImage = product => {\r\n let imageArr = [];\r\n if(product.hasVariation){\r\n imageArr = product.variations\r\n .map(variation => variation.images)\r\n .flat()\r\n .filter(image => image.focused); \r\n }else{\r\n imageArr = product.images\r\n .filter(image => image.focused); \r\n } \r\n return imageArr && imageArr[0];\r\n }\r\n\r\n const getBadges = product => { \r\n if(product.hasVariation){\r\n let vrtion = product.variations\r\n .find(variation => variation.images.map(image => image.focused));\r\n return vrtion.badges;\r\n }\r\n return product.badges;\r\n }\r\n\r\n const getOldPrice = product => {\r\n if(product.hasVariation){\r\n let vrtion = product.variations\r\n .find(variation => variation.images.map(image => image.focused));\r\n return vrtion.oldPrice;\r\n }\r\n return product.oldPrice;\r\n }\r\n\r\n const getPrice = (product) => { \r\n if(product.hasVariation){\r\n let priceArr = [];\r\n priceArr = product.variations\r\n .map(variation => +variation.retailPrice)\r\n const low = Math.min(...priceArr)\r\n const high = Math.max(...priceArr)\r\n if(low === high){\r\n return high.toFixed(2)\r\n }else{\r\n return low.toFixed(2) + \" - \" + high.toFixed(2)\r\n } \r\n }else{\r\n return (+product.retailPrice).toFixed(2)\r\n }\r\n }\r\n\r\n const handlePress = (product)=> {\r\n history.push({\r\n pathname: `/product/${product.name}`,\r\n state: {id: `${product._id}`},\r\n payload: product\r\n }); \r\n }\r\n\r\n const onPressAddToFavorites = async product => { \r\n let id = '';\r\n id = product._id;\r\n if(feathersStore.favoritesArray.includes(id)){\r\n const index = feathersStore.favoritesArray.indexOf(id);\r\n if (index > -1) {\r\n feathersStore.favoritesArray.splice(index, 1);\r\n } \r\n }else{\r\n feathersStore.favoritesArray.push(id); \r\n } \r\n if(feathersStore.wishlistId === \"\"){\r\n const data = await feathersStore.createWishlist(); \r\n data && (feathersStore.wishlistId = data._id); \r\n }else await feathersStore.updateWishlist();\r\n setFavoritesUpdated(true);\r\n };\r\n\r\n const handleAddToCart = (prod, index) => { \r\n \r\n let cartItem = {\r\n id: initialCartBiggestId,\r\n product_id: prod._id,\r\n title: prod?.name,\r\n image: prod.images?.find(img => img.focused),\r\n price: prod?.retailPrice,\r\n quantity: 1,\r\n totalPrice: (+prod.retailPrice).toFixed(2),\r\n variationTitle: null,\r\n variation: null,\r\n stock: prod?.handleStock && prod?.stock,\r\n extra: [],\r\n handleStock: prod?.handleStock\r\n }\r\n \r\n const cartSimilarItem = cart.find(item => item.product_id === cartItem.product_id ); \r\n if(cartSimilarItem){ \r\n const newQ = +cartSimilarItem.quantity + 1; \r\n if(prod.handleStock && (newQ > cartItem.stock)){\r\n setWarning(index); \r\n return;\r\n }else{\r\n const cartIndex = cart.findIndex(item => item.id === cartSimilarItem.id);\r\n cartItem.quantity = newQ;\r\n cartItem.totalPrice = (+cartItem.price * newQ).toFixed(2);\r\n cart.splice(cartIndex, 1, cartItem);\r\n } \r\n }else{ \r\n cart.push(cartItem);\r\n feathersStore.setCartLength( feathersStore.cartLength + 1); \r\n } \r\n if(!prod.warning) {\r\n localStorage.setItem(\"fire_cart\", JSON.stringify(cart));\r\n setCartIncreased(true); \r\n } \r\n }\r\n\r\n const setWarning = (index) => {\r\n let productsClone = [...products];\r\n let productClone = cloneDeep(products[index]);\r\n Object.assign(productClone, {warning: true});\r\n productsClone.splice(index, 1, productClone);\r\n setProducts([...productsClone]);\r\n }\r\n\r\n const removeWarning = (index) => {\r\n let productsClone = [...products];\r\n let productClone = cloneDeep(products[index]);\r\n Object.assign(productClone, {warning: false});\r\n productsClone.splice(index, 1, productClone);\r\n setProducts([...productsClone]);\r\n }\r\n\r\n//----------------Pagination Logic---------------------------------\r\n const [productsPerPage, setProductsPerPage] = useState(12)\r\n const [currentPage, setCurrentPage] = useState(0) \r\n const [pageCount, setPageCount] = useState(0)\r\n const [offset, setOffset] = useState(0)\r\n const [tableData, setTableData] = useState([]); \r\n \r\n useEffect(()=>{\r\n setCurrentPage(0); \r\n setOffset(0); \r\n },[feathersStore?.searchCategory]); \r\n \r\n useEffect(()=> { \r\n setPageCount(Math.ceil(products.length / productsPerPage)) \r\n },[products.length, productsPerPage])\r\n \r\n useEffect(()=> {\r\n const productsClone = [...products]; \r\n setTableData(productsClone.slice(offset, offset + productsPerPage))\r\n },[products, currentPage])\r\n\r\n const handleChange = (event, value) => {\r\n setCurrentPage(value - 1);\r\n setOffset((value - 1) * productsPerPage)\r\n };\r\n//---------------------------------------------------------------------\r\n\r\n const renderProducts = tableData.map( (product, index) => (\r\n
handlePress(product)}\r\n onClickCart={()=> handleAddToCart(product, index)}\r\n hasVariation={product.hasVariation}\r\n onClickForward={()=> handlePress(product)}\r\n warning={product.warning}\r\n onCloseWarning={() => removeWarning(index)}\r\n favorite={feathersStore.favoritesArray.includes(product._id)}\r\n onPressAddToFavorites={() => onPressAddToFavorites(product)}\r\n badges={getBadges(product)}\r\n />\r\n )\r\n);\r\n \r\n return(\r\n <>\r\n \r\n {renderProducts}\r\n
\r\n \r\n {/* {feathersStore.isAuthenticated &&\r\n } */}\r\n setCartIncreased(false)} \r\n message={t(\"common:cart-updated\")} />\r\n setFavoritesUpdated(false)} \r\n message={t(\"common:wishlist-updated\")} />\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(ListProducts));","import React, { useEffect } from 'react';\r\nimport Carousel from '../../carousel/Carousel';\r\nimport ResumeComponent from '../../cards/resumeComponent';\r\nimport ListProducts from '../listProducts';\r\nimport \"./HomeBody.css\";\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useParams, useLocation } from 'react-router-dom';\r\n\r\nconst HomeBody = ({ feathersStore })=> {\r\n\r\n const { t, i18n } = useTranslation('offers');\r\n\r\n const {name} = useParams();\r\n const { search } = useLocation();\r\n\r\n let catId;\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language);\r\n },[feathersStore.language]);\r\n\r\n //Browser BackButton and Refresh usage\r\n useEffect(()=>{\r\n let payload = {};\r\n if ((name || search) && feathersStore.categories) {\r\n searchTree(feathersStore.categories, name);\r\n name && Object.assign(payload, {categoryId: catId, title: name});\r\n search && Object.assign(payload, {searchText: search.substr(1)});\r\n }\r\n feathersStore.setSearchCategory(payload);\r\n },[name, search, feathersStore.categories]);\r\n\r\n const searchTree = (tree, name) => {\r\n tree.forEach(element => {\r\n if(element.name === name){\r\n catId = element.id\r\n }else{\r\n element.childrens && searchTree(element.childrens, name)\r\n }\r\n }) \r\n }\r\n\r\n return(\r\n <>\r\n \r\n {feathersStore?.isAuthenticated && (!name) ? (\r\n <>\r\n
\r\n \r\n
\r\n >)\r\n : null\r\n }\r\n
\r\n
\r\n \r\n \r\n
\r\n >\r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(HomeBody));","import React from 'react'\r\n\r\nconst TermsText = ()=> {\r\n return(\r\n Για την ολοκλήρωση των παραγγελιών σας θα σας ζητηθεί κάθε φορά ξεχωριστά να επιβεβαιώνετε ότι συμφωνείτε με τους κάτωθι όρους χρήσεως.\r\n\r\n – Tα πνευματικά δικαιώματα του Περιεχομένου (π.χ. προγράμματα, πληροφορίες, δεδομένα) και των Υπηρεσιών του διαδικτυακού τόπου (site) https://287arthub.com που έχουν εισαχθεί στο \r\n Δίκτυο, προστατεύονται από τους ελληνικούς, κοινοτικούς και διεθνείς νόμους περί πνευματικής ιδιοκτησίας.\r\n \r\n – Απαγορεύεται οποιαδήποτε αντιγραφή, διανομή, μεταφορά, μεταποίηση, μεταπώληση, δημιουργία παράγωγης εργασίας ή παραπλάνηση του κοινού σχετικά με τον πραγματικό παροχέα τους, \r\n του Περιεχομένου διαδικτυακού τόπου. Τυχόν αναπαραγωγή, επανέκδοση, φόρτωση, ανακοίνωση, διάδοση ή μετάδοση ή οποιαδήποτε άλλη χρήση του Περιεχομένου με οποιοδήποτε τρόπο ή μέσο \r\n για εμπορικούς ή άλλους σκοπούς επιτρέπεται μόνο κατόπιν προηγούμενης γραπτής άδειας του https://287arthub.com ή οποιουδήποτε άλλου δικαιούχου των πνευματικών δικαιωμάτων.\r\n \r\n – Το ηλεκτρονικό κατάστημα https://287arthub.com παρέχει το Περιεχόμενο (π.χ. πληροφορίες, ονόματα, φωτογραφίες, απεικονίσεις), τα προϊόντα και τις υπηρεσίες που διατίθενται μέσω του \r\n διαδικτυακού τόπου “όπως ακριβώς έχουν”. Σε καμία περίπτωση το ηλεκτρονικό κατάστημα https://287arthub.com δεν φέρει ευθύνη για τυχόν απαιτήσεις νομικής ή αστικής ή/και ποινικής φύσεως \r\n ούτε για τυχόν ζημία (θετική, ειδική ή αποθετική, η οποία ενδεικτικά και όχι περιοριστικά, διαζευκτικά ή και σωρευτικά συνίσταται σε απώλεια κερδών, δεδομένων, διαφυγόντα κέρδη, \r\n χρηματική ικανοποίηση κλπ.) από επισκέπτες του διαδικτυακού τόπου ή τρίτους από αιτία που έχει σχέση με τη λειτουργία ή μη ή και τη χρήση του διαδικτυακού τόπου ή και σε αδυναμία \r\n παροχής υπηρεσιών ή και πληροφοριών που διατίθενται από αυτόν ή και από τυχόν μη επιτρεπόμενες παρεμβάσεις τρίτων σε προϊόντα ή και υπηρεσίες ή και πληροφορίες που διατίθενται \r\n μέσω αυτού. Οι φωτογραφίες των προϊόντων είναι ενδεικτικές και δε φέρουμε καμία ευθύνη για τυχόν ορθογραφικά λάθη.\r\n \r\n – Οι τιμές μπορούν να αλλάξουν χωρίς προειδοποίηση. Δέσμευση τιμής μπορεί να γίνει μόνο ηλεκτρονικής παραγγελίας και ολοκληρώνεται με την αποστολή της επιβεβαίωσή της. Το κατάστημα \r\n με την εμπορική ονομασία https://287arthub.com δεν υποχρεούται να παράσχει ουδεμία εγγύηση για τη διαθεσιμότητά των προϊόντων του, αλλά αναλαμβάνει να ενημερώνει άμεσα τους πελάτες του \r\n για τυχόν ελλείψεις ή καθυστερημένες αποστολές.\r\n \r\n – Ο πελάτης από τη στιγμή που θα επεξεργαστεί η παραγγελία από το τμήμα παραγγελιών και έχει επιβεβαιώσει την παραγγελία του, εξασφαλίζει πως θα παραλάβει το προϊόν με την τιμή την \r\n οποία “αποδέχτηκε” τη συναλλαγή έστω και αν η τιμή στην πορεία μεταβληθεί. Σε περίπτωση που τα προϊόντα ή οι υπηρεσίες αναφέρονται στον δικτυακό τόπο με λάθος τιμή λόγω τυπογραφικού \r\n σφάλματος τότε οι παραγγελίες ακυρώνονται αυτόματα. To https://287arthub.com δεν ευθύνεται για τυχόν ζημιές που προκύψουν στον πελάτη/χρήστη του ηλεκτρονικού καταστήματος από την εκτέλεση \r\n ή μη των παραγγελιών ή από την καθυστέρηση εκτέλεσης για οποιονδήποτε λόγο.\r\n \r\n – Το ηλεκτρονικό κατάστημα https://287arthub.com διατηρεί το δικαίωμα να τροποποιεί, προσθέτει, μεταβάλλει το περιεχόμενο ή τις υπηρεσίες του διαδικτυακού τόπου, καθώς και τους όρους \r\n χρήσης, οποτεδήποτε το κρίνει αναγκαίο και χωρίς προηγούμενη προειδοποίηση, με μόνη την ανακοίνωσή τους μέσω του διαδικτυακού της τόπου.\r\n \r\n ΣΧΕΤΙΚΑ ΜΕ ΤΗΝ ΕΚΔΟΣΗ ΤΙΜΟΛΟΓΙΟΥ ΒΑΣΕΙ ΤΟΥ ΝΟΜΟΥ 39Α(Ν.2859/2000) ΑΚΟΛΟΥΘΗΣΤΕ ΤΙΣ ΠΑΡΑΚΑΤΩ ΟΔΗΓΙΕΣ:\r\n \r\n 1. ΑΠΟΣΤΟΛΗ ΤΩΝ ΑΠΑΡΑΙΤΗΤΩΝ ΕΓΓΡΑΦΩΝ ΜΕΣΩ TAXISNET ΤΗΣ ΕΤΑΙΡΙΑΣ ΣΑΣ ΣΤΟ EMAIL ΤΟΥ ΚΑΤΑΣΤΗΜΑΤΟΣ ΜΑΣ anthiaem@gmail.com.\r\n \r\n 2. ΟΣΟ ΑΦΟΡΑ ΤΗΝ ΠΛΗΡΩΜΗ ΤΩΝ ΕΝ ΛΟΓΩ ΠΑΡΑΓΓΕΛΙΩΝ ΘΑ ΓΙΝΕΤΑΙ ΑΥΣΤΗΡΑ ΜΕ ΤΡΑΠΕΖΙΚΗ ΚΑΤΑΘΕΣΗ ΑΠΟ ΕΤΑΙΡΙΚΟ ΛΟΓΑΡIΑΣΜΟ Η ΜΕΣΩ ΕΤΑΙΡΙΚΗΣ ΚΑΡΤΑΣ.\r\n \r\n 3. ΕΦΟΣΟΝ ΤΟ ΛΟΓΙΣΤΗΡΙΟ ΤΟΥ ΚΑΤΑΣΤΗΜΑΤΟΣ ΜΑΣ ΚΑΝΕΙ ΤΟΥΣ ΕΛΕΓΧΟΥΣ ΓΙΑ ΤΗΝ ΔΙΑΣΤΑΥΡΩΣΗ ΤΗΣ ΟΡΘΟΤΗΤΑΣ ΤΩΝ ΣΤΟΙΧΕΙΩΝ ΣΑΣ ΙΣΧΥΟΥΝ ΤΑ ΕΞΗΣ: ΟΣΟ ΑΦΟΡΑ ΤΗΝ ΠΑΡΑΛΑΒΗ ΤΟΥ ΠΡΟΙΟΝΤΟΣ ΘΑ \r\n ΓΙΝΕΤΑΙ ΑΠΟ ΤΟΝ ΝΟΜΙΜΟ ΕΚΠΡΟΣΩΠΟ Η ΟΠΟΙΟΔΗΠΟΤΕ ΑΛΛΟ ΜΕ ΕΞΟΥΣΙΟΔΟΤΗΣΗ ΠΟΥ ΦΕΡΕΙ ΤΟ ΓΝΗΣΙΟ ΤΗΣ ΥΠΟΓΡΑΦΗΣ ΑΠΟ ΤΗΝ ΕΔΡΑ ΤΟΥ ΚΑΤΑΣΤΗΜΑΤΟΣ ΜΑΣ ΚΑΙ ΜΕ ΕΠΙΔΕΙΞΗ ΤΑΥΤΟΤΗΤΑΣ .\r\n \r\n 4. ΟΙ ΠΕΛΑΤΕΣ ΠΡΕΠΕΙ ΝΑ ΕΙΝΑΙ ΕΝΗΜΕΡΟΙ ΠΩΣ Η ΠΑΡΑΓΓΕΛΙΑ ΤΟΥΣ ΑΦΟΡΑ ΤΗΝ ΤΙΜΗ ΠΡΟΣΦΟΡΑΣ ΚΑΙ ΕΧΟΥΝ ΔΥΝΑΤΟΤΗΤΑ ΝΑ ΠΡΟΜΗΘΕΥΤΟΥΝ ΜΕΧΡΙ 1 ΤΕΜΑΧΙΟ. ΤΕΛΟΣ, ΓΝΩΡΙΖΟΥΜΕ ΠΩΣ Η ΠΑΡΑΠΑΝΩ ΜΗ \r\n ΤΗΡΗΣΗ ΑΠΟ ΤΟΥΣ ΠΕΛΑΤΕΣ ΚΑΘΙΣΤΟΥΝ ΤΗΝ ΑΥΤΟΜΑΤΗ ΑΚΥΡΩΣΗ ΤΗΣ ΚΡΑΤΗΣΗΣ ΕΝΤΟΣ 48 ΩΡΩΝ ΑΠΟ ΤΗΝ ΤΗΛΕΦΩΝΙΚΗ ΜΑΣ ΕΠΙΒΕΒΑΙΩΣΗ.\r\n \r\n – Η εταιρεία μας και εσείς υπαγόμαστε στην αποκλειστική δικαιοδοσία των ελληνικών δικαστηρίων όσον αφορά την επίλυση διενέξεων που ενδεχομένως προκύψουν από την παρούσα Σύμβαση. \r\n Σε περίπτωση που οποιαδήποτε διάταξη της παρούσας Σύμβασης κριθεί παράνομη, άκυρη ή για οποιονδήποτε λόγο μη εφαρμόσιμη, η διάταξη αυτή θα θεωρείται διαιρετή και δεν θα επηρεάζει \r\n την εγκυρότητα και εφαρμοσιμότητα των υπόλοιπων διατάξεων.\r\n \r\n Πολιτική Επιστροφών – Δικαίωμα Υπαναχώρησης\r\n \r\n Εάν ο πελάτης είναι φυσικό πρόσωπο (καταναλωτής) που καταρτίζει την πώληση για προσωπική χρήση κι όχι για την εξυπηρέτηση της ατομικής του δραστηριότητας, τότε δικαιούται να \r\n υπαναχωρήσει από την πώληση εντός 14 ημερολογιακών ημερών, επιστρέφοντας το προϊόν στην αρχική του κατάσταση, επιβαρυνόμενος με τα έξοδα επιστροφής, σύμφωνα με την § 10 του άρθρου \r\n 4 Ν. 2251/1994.\r\n \r\n Δικαιούστε να υπαναχωρήσετε αναιτιολογήτως από την εξ’ αποστάσεως αγορά, εγγράφως, εντός 14 ημερολογιακών ημερών επιστρέφοντας το προϊόν στην αρχική του κατάσταση. Το δικαίωμα αυτό \r\n εκκινεί από την ημέρα παραλαβής των προϊόντων. Η εντός 14 ημερολογιακών ημερών αποστολή της δήλωσης υπαναχώρησης ή αποστολή των προϊόντων, θα θεωρείται αρκετή για την εμπρόθεσμη \r\n άσκηση του δικαιώματος υπαναχώρησης. Η δήλωση αποστέλλεται προς το κατάστημα με εμπορικό σήμα 287arthub.com με τη μορφή φόρμας RMA.\r\n \r\n Τα προϊόντα επιστρέφονται με έξοδα του πελάτη ή προσκομίζονται από τον ίδιο τον πελάτη στην έδρα της επιχείρησης που εδρεύει Βαλαωρίτου 4, 15452 Π. Ψυχικό.\r\n \r\n Συνέπειες υπαναχώρησης\r\n \r\n Σε περίπτωση έγκυρης άσκησης του δικαιώματος υπαναχώρησης, θα πρέπει να αποκατασταθεί με χρηματική αποζημίωση κάθε τυχόν απομείωση της αξίας του εμπορεύματος, μόνο στην περίπτωση και \r\n στον βαθμό που αυτή οφείλεται στη μεταχείριση του προϊόντος που εκφεύγει της ειθισμένης εξέτασης των χαρακτηριστικών και της λειτουργικότητας του προϊόντος. Ως «ειθισμένη εξέταση \r\n των χαρακτηριστικών και της λειτουργικότητας του προϊόντος», εννοείται η δοκιμή των σχετικών αγαθών, όπως αυτή είναι δυνατό να ελάμβανε χώρα και όπως συνηθίζεται σε ένα φυσικό \r\n κατάστημα.\r\n \r\n Ο πελάτης θα βαρύνεται με τα έξοδα επιστροφής. Κάθε χρηματική υποχρέωση για την καταβολή ποσών (π.χ. εξόδων μεταφοράς, αποζημίωσης) θα πρέπει να εκπληρώνεται εντός 30 ημερών, \r\n εκκινώντας από τον χρόνο αποστολής της δήλωσης υπαναχώρησης από εσάς ή της επιστροφής του εμπορεύματος.\r\n \r\n Το δικαίωμα υπαναχώρησης εκ του άρθρου 4 § 10 ν. 2251/1994 δεν εφαρμόζεται:\r\n \r\n Στις περιπτώσεις που το τίμημα των προϊόντων έχει καταβληθεί στο φυσικό μας κατάστημα ( Βαλαωρίτου 4, 15452 Π. Ψυχικό ) και ταυτόχρονα, αυτά έχουν παραληφθεί από το φυσικό \r\n κατάστημα, καθώς η πώληση δεν θεωρείται ότι τελέστηκε από απόσταση.\r\n \r\n Σε περίπτωση έγκυρης άσκησης του δικαιώματος υπαναχώρησης και με την προϋπόθεση ότι έχει επιστραφεί το προϊόν στην έδρα του 287arthub.com, η αξία του προϊόντος θα επιστρέφεται \r\n στον πελάτη. Ρητώς συμφωνείται και ο πελάτης παρέχει ήδη την ανέκκλητη εντολή και συναίνεσή του προς τούτο, η εταιρεία μας να δικαιούται να παρακρατά από το επιστρεφόμενο ποσό \r\n τα έξοδα επιστροφής, τα οποία βαρύνουν τον πελάτη καθώς και τυχόν αποζημίωση σε περίπτωση καταστροφής ή απομείωσης της αξίας του προϊόντος λόγω φθοράς ή βλάβης του προϊόντος \r\n οφειλόμενης σε ενέργειες του πελάτη.\r\n \r\n Ανάλογα με τον τρόπο πληρωμής που έχει επιλέξει ο πελάτης κατά την παραγγελία του θα γίνει αντίστοιχα και η επιστροφή χρημάτων:\r\n \r\n Για Πιστωτική κάρτα on-line η επιστροφή των χρημάτων θα γίνει στην κάρτα.\r\n Για Αντικαταβολή ή κατάθεση σε τράπεζα θα πρέπει να μας δώσετε το IBAN ενός τραπεζικού λογαριασμού, το ονοματεπώνυμο του δικαιούχου όπως και την τράπεζα την οποία αφορά.
\r\n )\r\n}\r\n\r\nexport default TermsText;","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport TermsText from './termsText';\r\n\r\nconst TermsNConditions = ()=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n \r\n return(\r\n \r\n
{t(\"common:terms-use\")} \r\n
\r\n \r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default TermsNConditions;","import React,{ useState, useEffect } from 'react';\r\nimport CategoryPic from '../cards/categoryPic';\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst About = ({ feathersStore })=> {\r\n const { t, i18n } = useTranslation('footer');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n return(\r\n \r\n
{t('footer:cv')} \r\n
\r\n { feathersStore.settings?.images &&\r\n
\r\n }\r\n {feathersStore.settings?.shortDescription &&\r\n \r\n {ReactHtmlParser(`
${feathersStore.settings?.shortDescription}
`)} \r\n
\r\n }\r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(About));","const Colors = {\r\n amazonColor: '#ff9900',\r\n primary: '#ea2c58',\r\n secondary: '#1fc281',\r\n process: '#c6e1c6',\r\n completed: '#c8d7e1',\r\n canceled: '#ff5c5c',\r\n refunded: '#ff9900',\r\n deleted: '#ff0000',\r\n red: '#b90039'\r\n}\r\n\r\nexport default Colors;","import React from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport Button from '@material-ui/core/Button';\r\nimport { createMuiTheme, makeStyles } from '@material-ui/core/styles';\r\nimport { green, red } from '@material-ui/core/colors';\r\nimport AppColors from '../assets/colors'\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst WishItemCartMessage = ({visible, onClick})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n const useStyles = makeStyles((theme) => ({\r\n margin: {\r\n margin: theme.spacing(1),\r\n },\r\n }));\r\n \r\n const theme = createMuiTheme({\r\n palette: {\r\n primary: red,\r\n secondary: green,\r\n },\r\n });\r\n const classes = useStyles();\r\n \r\n return (\r\n \r\n \r\n \r\n
\r\n
{t('common:product-added-cart')}
\r\n
\r\n
\r\n OK \r\n
\r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default WishItemCartMessage;","import { Payment } from '@material-ui/icons'\r\nimport React from 'react'\r\n\r\nconst PageTitle = ({title})=> {\r\n\r\n return(\r\n \r\n )\r\n}\r\n\r\nexport default PageTitle;","import React, {useState, useEffect} from 'react'\r\nimport ProductCard from '../cards/productCard/ProductCard';\r\nimport WishItemCartMessage from '../modals/wishItemCartMessage';\r\nimport PageTitle from './pageTitle';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useHistory } from 'react-router-dom';\r\nimport * as cloneDeep from 'lodash/cloneDeep';\r\nimport SmallAlert from '../modals/smallAlert';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nlet initialCartBiggestId = 0;\r\nlet cart = [];\r\n\r\nconst WishList = ({ feathersStore })=> {\r\n\r\n const history = useHistory();\r\n const { t, i18n } = useTranslation('common');\r\n \r\n const [products, setProducts] = useState([]); \r\n const [loading, setLoading] = useState(true);\r\n const [cartIncreased, setCartIncreased] = useState(false);\r\n const [favoritesUpdated, setFavoritesUpdated] = useState(false);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n useEffect(()=>{\r\n feathersStore.isAuthenticated && onLoad();\r\n products && setLoading(false);\r\n }, [feathersStore.isAuthenticated, feathersStore?.favoritesArray]);\r\n\r\n useEffect(() => {\r\n if(localStorage.getItem('fire_cart')){\r\n cart = JSON.parse(localStorage.getItem('fire_cart')); \r\n if(cart.length > 0)\r\n initialCartBiggestId = +cart.map(e => e.id).sort().reverse()[0] + 1; \r\n }\r\n }, []);\r\n\r\n\r\n const onLoad = async() => { \r\n const feathersProducts = await feathersStore.wishlistProducts(); \r\n feathersProducts && setProducts([...feathersProducts]); \r\n }\r\n\r\n const getMainImage = product => {\r\n let imageArr = [];\r\n if(product.hasVariation){\r\n imageArr = product.variations\r\n .map(variation => variation.images)\r\n .flat()\r\n .filter(image => image.focused); \r\n }else{\r\n imageArr = product.images\r\n .filter(image => image.focused); \r\n } \r\n return imageArr && imageArr[0];\r\n }\r\n\r\n const getBadges = product => { \r\n if(product.hasVariation){\r\n let vrtion = product.variations\r\n .find(variation => variation.images.map(image => image.focused));\r\n return vrtion.badges;\r\n }\r\n return product.badges;\r\n }\r\n\r\n const getOldPrice = product => {\r\n if(product.hasVariation){\r\n let vrtion = product.variations\r\n .find(variation => variation.images.map(image => image.focused));\r\n return vrtion.oldPrice;\r\n }\r\n return product.oldPrice;\r\n }\r\n\r\n const getPrice = (product)=> { \r\n if(product.hasVariation){\r\n let priceArr = [];\r\n priceArr = product.variations\r\n .map(variation => +variation.retailPrice)\r\n const low = Math.min(...priceArr)\r\n const high = Math.max(...priceArr)\r\n if(low === high){\r\n return high.toFixed(2)\r\n }else{\r\n return low.toFixed(2) + \" - \" + high.toFixed(2)\r\n } \r\n }else{\r\n return (+product.retailPrice).toFixed(2)\r\n }\r\n }\r\n\r\n const handlePress = (product)=> {\r\n history.push({\r\n pathname: `/product/${product.name}`,\r\n state: {id: `${product._id}`},\r\n payload: product\r\n }); \r\n }\r\n\r\n const onPressDeleteFromFavorites = async (product, index) => {\r\n try{\r\n let productsClone = [...products];\r\n productsClone.splice(index, 1);\r\n setProducts([...productsClone]);\r\n const ind = feathersStore.favoritesArray.indexOf(product._id); \r\n feathersStore.favoritesArray.splice(ind, 1); \r\n await feathersStore.updateWishlist(); \r\n setFavoritesUpdated(true);\r\n }catch(error){\r\n console.log(error);\r\n }\r\n \r\n };\r\n\r\n const handleAddToCart = (prod, index) => { //fromList = prod is coming from the footer list and has no variations\r\n \r\n let cartItem = {\r\n id: initialCartBiggestId,\r\n product_id: prod._id,\r\n title: prod?.name,\r\n image: prod.images?.find(img => img.focused),\r\n price: prod?.retailPrice,\r\n quantity: 1,\r\n totalPrice: (+prod.retailPrice).toFixed(2),\r\n variationTitle: null,\r\n variation: null,\r\n stock: prod?.handleStock && prod?.stock,\r\n extra: [],\r\n handleStock: prod?.handleStock\r\n }\r\n\r\n const cartSimilarItem = cart.find(item => item.product_id === cartItem.product_id ); \r\n if(cartSimilarItem){ \r\n const newQ = +cartSimilarItem.quantity + 1; \r\n if(prod.handleStock && (newQ > cartItem.stock)){\r\n setWarning(index); \r\n return;\r\n }else{\r\n const cartIndex = cart.findIndex(item => item.id === cartSimilarItem.id);\r\n cartItem.quantity = newQ;\r\n cartItem.totalPrice = (+cartItem.price * newQ).toFixed(2);\r\n cart.splice(cartIndex, 1, cartItem);\r\n } \r\n }else{ \r\n cart.push(cartItem);\r\n feathersStore.setCartLength(feathersStore.cartLength + 1); \r\n } \r\n if(!prod.warning){\r\n localStorage.setItem(\"fire_cart\", JSON.stringify(cart));\r\n setCartIncreased(true); \r\n } \r\n }\r\n\r\n const setWarning = (index) => {\r\n let productsClone = [...products];\r\n let productClone = cloneDeep(products[index]);\r\n Object.assign(productClone, {warning: true});\r\n productsClone.splice(index, 1, productClone);\r\n setProducts([...productsClone]);\r\n }\r\n\r\n const removeWarning = (index) => {\r\n let productsClone = [...products];\r\n let productClone = cloneDeep(products[index]);\r\n Object.assign(productClone, {warning: false});\r\n productsClone.splice(index, 1, productClone);\r\n setProducts([...productsClone]);\r\n }\r\n\r\n const renderProducts = products.map( (product, index) => (\r\n \r\n \r\n handlePress(product)}\r\n onClickCart={()=> handleAddToCart(product, index)}\r\n hasVariation={product.hasVariation}\r\n onClickForward={()=> handlePress(product)}\r\n warning={product.warning}\r\n onCloseWarning={() => removeWarning(index)}\r\n favorite={true}\r\n onPressAddToFavorites={() => onPressDeleteFromFavorites(product, index)}\r\n badges={getBadges(product)}\r\n />\r\n \r\n ) \r\n );\r\n\r\n return(\r\n <>\r\n \r\n
\r\n
\r\n {/*}\r\n \r\n */}\r\n \r\n \r\n {products.length === 0 ?
{t('common:no-favorites-yet')} \r\n : \r\n
\r\n {renderProducts}\r\n }\r\n
\r\n \r\n
\r\n setCartIncreased(false)} \r\n message={t(\"common:cart-updated\")} />\r\n setFavoritesUpdated(false)} \r\n message={t(\"common:wishlist-updated\")} />\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(WishList));","import React from 'react'\r\n\r\nconst PrivacyText = ()=> {\r\n return(\r\n Για την Άνθια Μαζαράκη η προστασία των προσωπικών δεδομένων έχει πρωταρχική σημασία και αντιμετωπίζεται με τη μέγιστη σοβαρότητα.\r\n Ο σεβασμός προς τα προσωπικά δεδομένα που διαχειριζόμαστε και η διασφάλιση της σωστής επεξεργασίας τους είναι μία από τις προτεραιότητες της Εταιρίας. Για το λόγο αυτό λαμβάνουμε \r\n όλα τα κατάλληλα τεχνικά και οργανωτικά μέτρα για να προστατέψουμε τα προσωπικά δεδομένα που επεξεργαζόμαστε και να διασφαλίσουμε ότι η επεξεργασία τους πραγματοποιείται πάντα \r\n σύμφωνα με τις απαιτήσεις που τίθενται από το ισχύον νομοθετικό πλαίσιο και κυρίως από το Γενικό Κανονισμό Προστασίας Δεδομένων (ΕΕ) 2016/679.\r\n \r\n 1. ΥΠΕΥΘΥΝΟΣ ΕΠΕΞΕΡΓΑΣΙΑΣ – ΣΤΟΙΧΕΙΑ ΕΠΙΚΟΙΝΩΝΙΑΣ \r\n Η Άνθια Μαζαράκη ενεργεί ως Υπεύθυνος Επεξεργασίας για όλα τα προσωπικά δεδομένα που συλλέγει, υποβάλλει σε επεξεργασία και αποθηκεύει.\r\n Όνομα: Άνθια ΜΑζαράκη\r\n Διεύθυνση: Βαλαωρίτου 4, 15452 Π. Ψυχικό \r\n Τηλέφωνο: +30 2106714123\r\n Ηλεκτρονικό Ταχυδρομείο: anthiaem@gmail.com\r\n Υπεύθυνος Επικοινωνίας: Άνθια Μαζαράκη\r\n \r\n 2. ΠΟΙΑ ΔΕΔΟΜΕΝΑ ΣΥΛΛΕΓΟΥΜΕ ΚΑΙ ΕΠΕΞΕΓΑΖΟΜΑΣΤΕ \r\n Για να σας εξυπηρετήσουμε και να σας προσφέρουμε τις υπηρεσίες και τα προϊόντα μας συλλέγουμε και επεξεργαζόμαστε όλα τα \r\n δεδομένα που γνωστοποιείτε στον εκπρόσωπο του τηλεφωνικού κέντρου όταν δίνετε την παραγγελία σας ή όσα δεδομένα συμπληρώνετε στα αντίστοιχα πεδία όταν ανοίγετε λογαριασμό χρήστη \r\n στην ιστοσελίδα μας και πιο συγκεκριμένα, ονοματεπώνυμο, ταχυδρομική διεύθυνση, τηλέφωνο επικοινωνίας (σταθερό ή κινητό), e-mail, φορολογικά στοιχεία (στην περίπτωση που επιθυμείτε έκδοση τιμολογίου).\r\n Παρακαλούμε λάβετε υπόψη σας ότι η ιστοσελίδα της Εταιρίας μας ενδέχεται να περιέχει συνδέσμους (links) προς άλλους ιστότοπους. H Εταιρία μας δεν ευθύνεται για τις πρακτικές \r\n απορρήτου και προστασίας προσωπικών δεδομένων ή/και το περιεχόμενο αυτών των ιστοτόπων. Αν είστε ηλικίας μέχρι 15 ετών, παρακαλούμε να λάβετε την άδεια του γονέα ή κηδεμόνα σας, \r\n προτού μας κοινοποιήσετε οποιαδήποτε προσωπικά στοιχεία σας.\r\n \r\n 3. ΣΚΟΠΟΙ ΕΠΕΞΕΡΓΑΣΙΑΣ & ΝΟΜΙΚΕΣ ΒΑΣΕΙΣ ΕΠΕΞΕΡΓΑΣΙΑΣ \r\n Όλα τα ανωτέρω προσωπικά δεδομένα συλλέγονται και υπόκεινται σε επεξεργασία με σκοπό καταρχήν την εκτέλεση της μεταξύ μας σύμβασης πώλησης των προϊόντων μας και πιο συγκεκριμένα \r\n για την ετοιμασία και παράδοση της παραγγελίας σας και την επικοινωνία μας μαζί σας σχετικά με αυτή. Κάποια από τα δεδομένα σας μπορεί να χρησιμοποιηθούν και για τους παρακάτω \r\n σκοπούς πάντα με τη δική σας σχετική συγκατάθεση:\r\n - Επικοινωνία μαζί σας σε σχέση με διαγωνισμούς, κληρώσεις και άλλες εκδηλώσεις\r\n - Ενημέρωση και αποστολή προσφορών και ενημερωτικού υλικού σχετικά με τα προϊόντα και τις υπηρεσίες μας\r\n - Στατιστικοί σκοποί και έρευνες\r\n - Προώθηση και προαγωγή των προϊόντων και υπηρεσιών μας\r\n Νομικές βάσεις επεξεργασίας των δεδομένων μπορεί να είναι κατά περίπτωση:\r\n i. Η εκτέλεση και ολοκλήρωση της μεταξύ μας σύμβασης για την πώληση των προϊόντων μας σε εσάς (προετοιμασία και παράδοση της παραγγελίας σας). Χωρίς τη συλλογή και χρήση των \r\n παραπάνω πληροφορίων δεν θα είναι δυνατόν να σας εξυπηρετήσουμε\r\n ii. Η συγκατάθεση που μπορεί εσείς να μας παρέχετε προκειμένου να λαμβάνετε ενημερώσεις σχετικά με προσφορές ή προωθητικό υλικό για τα προϊόντα και τις υπηρεσίες μας, \r\n τις εμπορικές δράσεις και δραστηριότητες που αναπτύσσουμε κλπ. Μπορείτε να ανακαλέσετε τη συγκατάθεσή σας όποτε εσείς το επιθυμείτε, επικοινωνώντας μαζί μας στα στοιχεία \r\n επικοινωνίας που αναφέρονται στην παράγραφο 1 ή μέσω της ιστοσελίδας μας.\r\n \r\n 4. ΠΟΥ ΚΟΙΝΟΠΟΙΟΥΜΕ ΤΑ ΠΡΟΣΩΠΙΚΑ ΔΕΔΟΜΕΝΑ ΣΑΣ \r\n Τα προσωπικά δεδομένα σας είναι πιθανό να κοινοποιηθούν στους ακόλουθους αποδέκτες:\r\n - Στους franchisees, στους υπεύθυνους καταστημάτων του δικτύου της Άνθιας Μαζαράκη και στους διανομείς προκειμένου να ετοιμάσουν και να παραδώσουν την παραγγελία\r\n - Σε εταιρία αποστολής newsletter (εφόσον έχετε δώσει τη συγκατάθεσή σας για να σας αποστέλλουμε newsletter)\r\n - Σε εταιρία αποστολής sms (στην περίπτωση που έχετε δώσει τη συγκατάθεσή σας για να λαμβάνετε ενημερώσεις)\r\n - Σε συνεργαζόμενες εταιρίες, προκειμένου να μπορέσετε να παραλάβετε το δώρο σας, εφόσον είστε νικητές σε κάποιο διαγωνισμό στον οποίο λάβατε μέρος (κάθε φορά που οργανώνουμε \r\n ένα διαγωνισμό, αναφέρουμε στους όρους του διαγωνισμού το γεγονός της κοινοποίησης των στοιχείων σας στη συνεργαζόμενη εταιρία)\r\n - Σε συνεργαζόμενες εταιρίες διοργάνωσης εκδηλώσεων (στην περίπτωση που θέλετε να διοργανώσετε κάποιο πάρτι)\r\n - Σε εξωτερικό συνεργάτη που μας υποστηρίζει σε θέματα λογισμικού\r\n - Στο συνεργαζόμενο νομικό τμήμα της εταιρίας, σε περίπτωση δικαστικής ή εξώδικης διένεξης\r\n - Σε αστυνομικές ή άλλες κρατικές αρχές εφόσον μας ζητηθεί κάτι τέτοιο επίσημα ή μετά από εισαγγελική παραγγελία\r\n \r\n 5. ΧΡΟΝΙΚΟ ΔΙΑΣΤΗΜΑ ΑΠΟΘΗΚΕΥΣΗΣ ΤΩΝ ΔΕΔΟΜΕΝΩΝ \r\n Τα δεδομένα σας τηρούνται στη βάση δεδομένων του Arthub για 5 χρόνια μετά την τελευταία συναλλαγή σας με την εταιρία ή για όσο χρόνο μπορεί να απαιτεί η νομοθεσία (π.χ. \r\n στην περίπτωση έκδοσης τιμολογίου, όσο χρόνο ορίζει το φορολογικό νομοθετικό πλαίσιο).\r\n Αν η επεξεργασία βασίζεται στη συγκατάθεσή σας, τα προσωπικά δεδομένα τηρούνται μέχρι να ανακαλέσετε τη συγκατάθεση αυτή. Διευκρινίζεται ότι η ανάκληση της συγκατάθεσης δεν \r\n θίγει τη νομιμότητα της επεξεργασίας που βασίστηκε στη συγκατάθεση πριν την ανάκλησή της.\r\n Σε κάθε περίπτωση η Άνθια Μαζαράκη εφαρμόζει όλα τα κατάλληλα τεχνικά και οργανωτικά μέτρα για να εξασφαλίζει την προστασία των προσωπικών δεδομένων που επεξεργάζεται και μεριμνά \r\n συνεχώς για την αποτροπή κάθε μη εξουσιοδοτημένης πρόσβασης στα δεδομένα αυτά.\r\n \r\n 6. ΔΙΚΑΙΩΜΑΤΑ ΠΟΥ ΕΧΕΤΕ ΣΕ ΣΧΕΣΗ ΜΕ ΤΑ ΠΡΟΣΩΠΙΚΑ ΔΕΔΟΜΕΝΑ ΣΑΣ \r\n Αναφορικά με την επεξεργασία των προσωπικών δεδομένων σας μπορείτε να ασκήσετε τα παρακάτω δικαιώματα:\r\n Δικαίωμα πρόσβασης \r\n Έχετε δικαίωμα να γνωρίζετε ποια δεδομένα σας τηρούμε και επεξεργαζόμαστε, για ποιο λόγο και άλλες συμπληρωματικές πληροφορίες σχετικά με αυτά, καθώς και να μας ζητήσετε αντίγραφό τους\r\n Δικαίωμα διόρθωσης \r\n Έχετε δικαίωμα να ζητήσετε τη διόρθωση, τροποποίηση και συμπλήρωση των προσωπικών δεδομένων σας\r\n Δικαίωμα διαγραφής («δικαίωμα στη λήθη») \r\n Έχετε δικαίωμα να ζητήσετε τη διαγραφή των προσωπικών δεδομένων σας όταν αυτά τίθενται σε επεξεργασία μετά τη σχετική συγκατάθεσή σας. Στις περιπτώσεις που η επεξεργασία \r\n βασίζεται σε άλλη νομική βάση (όπως ενδεικτικά στην εκτέλεση σύμβασης, σε έννομη υποχρέωση ή στην προστασία έννομων συμφερόντων της Εταιρίας κλπ.) το δικαίωμά σας αυτό μπορεί \r\n να υπόκειται σε περιορισμούς ή να μην υφίσταται\r\n Δικαίωμα περιορισμού της επεξεργασίας \r\n Έχετε δικαίωμα να ζητήσετε τον περιορισμό της επεξεργασίας των προσωπικών δεδομένων σας\r\n - όταν αμφισβητείται η ακρίβειά τους και μέχρι να γίνει η σχετική επαλήθευση\r\n - εναλλακτικά, αντί για τη διαγραφή τους\r\n - όταν δεν μας είναι πλέον απαραίτητα για τους σκοπούς επεξεργασίας για τους οποίους τα συλλέξαμε, είναι όμως απαραίτητα για τη θεμελίωση, άσκηση ή υποστήριξη νομικών αξιώσεων από εσάς\r\n - όταν έχετε αντιρρήσεις για την επεξεργασία τους και μέχρι να επαληθευτεί ότι υπάρχουν νόμιμοι λόγοι για την επεξεργασία αυτή από την Εταιρία\r\n Δικαίωμα εναντίωσης στην επεξεργασία \r\n Έχετε δικαίωμα να εναντιωθείτε στην επεξεργασία των προσωπικών δεδομένων σας όταν αυτή γίνεται με βάση έννομο συμφέρον, καθώς και για σκοπούς απευθείας εμπορικής προώθησης και \r\n κατάρτισης προφίλ\r\n Δικαίωμα στη φορητότητα \r\n Έχετε δικαίωμα να ζητήσετε και να λάβετε τα προσωπικά δεδομένα σας σε μορφή που σας επιτρέπει την πρόσβαση σε αυτά, τη χρήση και επεξεργασία τους με τις κοινώς διαδεδομένες \r\n μεθόδους επεξεργασίας. Επιπλέον, για τα δεδομένα σας που επεξεργαζόμαστε με αυτοματοποιημένα μέσα και με βάση τη συγκατάθεσή σας ή για την εκτέλεση σύμβασης, μπορείτε να μας \r\n ζητήσετε να τα διαβιβάσουμε απευθείας σε άλλο υπεύθυνο επεξεργασίας, εφόσον αυτό είναι τεχνικά εφικτό\r\n Δικαίωμα ανάκλησης συγκατάθεσης \r\n Αν η επεξεργασία των δεδομένων σας βασίζεται στη συγκατάθεσή σας, έχετε δικαίωμα να την ανακαλέσετε οποιαδήποτε στιγμή. Η ανάκληση της συγκατάθεσής σας δεν θίγει τη νομιμότητα \r\n της επεξεργασίας που βασίστηκε στη συγκατάθεση πριν την ανάκλησή της\r\n Για την άσκηση των παραπάνω δικαιωμάτων σας και για οποιαδήποτε ερώτημα, παράπονο ή άλλη ενημέρωση σχετικά με την επεξεργασία των προσωπικών δεδομένων σας μπορείτε να \r\n επικοινωνείτε μαζί μας στο email anthiaem@gmail.com ή στα στοιχεία επικοινωνίας που αναφέρονται στην παράγραφο 1.\r\n \r\n 7. ΔΙΚΑΙΩΜΑΤΑ ΚΑΤΑΓΓΕΛΙΑΣ ΣΤΗΝ ΑΡΧΗ ΠΡΟΣΤΑΣΙΑΣ ΔΕΔΟΜΕΝΩΝ ΠΡΟΣΩΠΙΚΟΥ ΧΑΡΑΚΤΗΡΑ (ΑΠΔΠΧ) \r\n Έχετε δικαίωμα να υποβάλετε καταγγελία στην Αρχή Προστασίας Δεδομένων Προσωπικού Χαρακτήρα (www.dpa.gr) σχετικά με θέματα που αφορούν την επεξεργασία των προσωπικών δεδομένων σας\r\n \r\n 8. ΑΛΛΑΓΕΣ ΣΤΗΝ ΠΟΛΙΤΙΚΗ ΠΡΟΣΤΑΣΙΑΣ ΠΡΟΣΩΠΙΚΩΝ ΔΕΔΟΜΕΝΩΝ \r\n Τυχόν μελλοντικές αλλαγές στην Πολιτική Προστασίας Προσωπικών Δεδομένων της Εταιρίας μας θα αναρτηθούν στην ιστοσελίδα της https://287arthub.com και όπου απαιτείται, θα σας κοινοποιηθούν.\r\n
\r\n )\r\n}\r\n\r\nexport default PrivacyText;","import React from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport PrivacyText from './privacyText';\r\n\r\nconst PrivacyPolicy = ()=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n return(\r\n \r\n {/*
\r\n \r\n
*/}\r\n
{t(\"common:privacy-policy\")} \r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default PrivacyPolicy;","export const API_URL = 'https://feathers.287arthub.com/';\r\nexport const ADMIN_ID = '5fb3b2dcad060c0a845047f3';\r\nexport const DEFAULT_EMAIL = \"defaultUser@gmail.com\";\r\nexport const DEFAULT_PSW = \")j~nKj/,N}N6,8&cVVV#G!=F*y\";\r\nexport const PHONE_REGEX =/^((\\\\+[1-9]{1,4}[ \\\\-]*)|(\\\\([0-9]{2,3}\\\\)[ \\\\-]*)|([0-9]{2,4})[ \\\\-]*)*?[0-9]{3,4}?[ \\\\-]*[0-9]{3,4}?$/ ;\r\nexport const PAYPAL_CLIENT_ID=\"Ab9xBziZRnJjCwgOIgQb-uTWsr6cWG1B5nCVup5m2EcrZib1dD7V70LViTk6rL3ZvPH0Sg3IAFQDBLFZ\"","import React from 'react';\r\nimport { Button, CircularProgress } from '@material-ui/core';\r\nimport { createMuiTheme , makeStyles, ThemeProvider } from '@material-ui/core/styles';\r\nimport { green, red } from '@material-ui/core/colors';\r\n\r\n\r\nconst GreenSubmitButton = ({ title, loading, disabled, onClick, color })=> {\r\n\r\n const useStyles = makeStyles((theme) => ({\r\n margin: {\r\n margin: theme.spacing(1),\r\n },\r\n }));\r\n \r\n const theme = createMuiTheme({\r\n palette: {\r\n primary: red,\r\n secondary: green,\r\n },\r\n });\r\n const classes = useStyles();\r\n\r\n return(\r\n \r\n \r\n {title}\r\n {loading &&\r\n \r\n }\r\n \r\n \r\n )\r\n}\r\n\r\nexport default GreenSubmitButton;","import React, { useEffect, useRef, useState } from 'react';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { Formik, Field, Form } from 'formik';\r\nimport * as Yup from 'yup';\r\nimport \"./Contact.css\";\r\nimport { useTranslation } from 'react-i18next';\r\nimport { PHONE_REGEX } from \"../../components/assets/globalConstants\";\r\nimport SmallAlert from \"../../components/modals/smallAlert\";\r\nimport GreenSubmitButton from '../../components/buttons/greenSubmitButton';\r\nimport Colors from \"../../components/assets/colors\";\r\n\r\nconst Contact = ({ feathersStore })=> {\r\n\r\n const { t, i18n } = useTranslation(['contact']);\r\n const formRef = useRef();\r\n\r\n const [showError, setShowError] = useState(false);\r\n const [ showSuccess,setShowSuccess] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n \r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language);\r\n },[feathersStore.language]);\r\n \r\n useEffect(()=> { \r\n formRef.current.resetForm(); \r\n formRef.current.validateForm(); \r\n },[feathersStore.user]);\r\n\r\n const validationSchema = Yup.object({\r\n firstName: Yup.string()\r\n .min(2, t('contact:must-have-char'))\r\n .max(255, t('contact:less255'))\r\n .required(t('contact:required')),\r\n lastName: Yup.string()\r\n .min(2, t('contact:must-have-char'))\r\n .max(255, t('contact:less255'))\r\n .required(t('contact:required')),\r\n email: Yup.string()\r\n .email(t('contact:invalidEmail'))\r\n .required(t('contact:required')),\r\n phone: Yup.string()\r\n .matches(PHONE_REGEX, t('contact:invalidPhone')),\r\n comments: Yup.string()\r\n .max(1000, t('contact:textareaMax'))\r\n .required(t('contact:required'))\r\n })\r\n\r\n const sendEmail = async (values) => {\r\n const { email, firstName, lastName, comments, phone } = values\r\n try { \r\n setLoading(true); \r\n await feathersStore.sendContactEmail( email, firstName, lastName, comments, phone); \r\n setShowSuccess(true); \r\n setLoading(false); \r\n }catch(err){\r\n setLoading(false);\r\n console.log('Could not send email FROM sendEmail method: ', err )\r\n setShowError(true); \r\n };\r\n }\r\n\r\n return(\r\n <>\r\n \r\n
{t(\"contact:contact-form\")} \r\n \r\n <>\r\n {\r\n setSubmitting(false);\r\n sendEmail(values);\r\n resetForm();\r\n validateForm();\r\n }}\r\n >\r\n {({errors, touched, isValid, isSubmitting}) => (\r\n \r\n )}\r\n \r\n >\r\n setShowSuccess(false)}\r\n message={t(\"contact:email-sent-message\")} />\r\n setShowError(false)} \r\n message={t(\"contact:email-error-message\")} /> \r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Contact));","import React from 'react'\r\nimport Close from '@material-ui/icons/Close';\r\nimport \"./CartObject.css\";\r\nimport { API_URL } from \"../../assets/globalConstants\";\r\n\r\nconst CartObject = ({ item, onChange, onClickDelete, goToProduct}) => (\r\n \r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n Προϊόν:\r\n
\r\n
\r\n {item.title}{item.variation && (\"-\" + item.variation) }\r\n \r\n
\r\n
\r\n
\r\n Τιμή:\r\n
\r\n {item.price} €\r\n
\r\n
\r\n
\r\n Ποσότητα:\r\n
\r\n
onChange(e)} onKeyDown={(event) => {event.preventDefault();}} \r\n type=\"number\" min=\"1\" max={item.handleStock ? item.stock : null} defaultValue={item.quantity} \r\n style={{width: 50, paddingLeft: 5}}/>\r\n
\r\n
\r\n
\r\n Υποσύνολο:\r\n
\r\n {item.totalPrice} €\r\n
\r\n
\r\n )\r\n\r\nexport default CartObject;","import React from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport Button from '@material-ui/core/Button';\r\nimport { createMuiTheme, withStyles, makeStyles, ThemeProvider } from '@material-ui/core/styles';\r\nimport { green, red } from '@material-ui/core/colors';\r\nimport AppColors from '../assets/colors'\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useEffect } from 'react';\r\n\r\n\r\nconst ConfirmationModal = (props)=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n const useStyles = makeStyles((theme) => ({\r\n margin: {\r\n margin: theme.spacing(1),\r\n },\r\n }));\r\n \r\n const theme = createMuiTheme({\r\n palette: {\r\n primary: red,\r\n secondary: green,\r\n },\r\n });\r\n const classes = useStyles();\r\n \r\n return (\r\n \r\n \r\n \r\n
\r\n
{t('common:delete-product1')} \r\n {props.product} \r\n {t('common:from-cart')}
\r\n
\r\n
\r\n {t('common:no')} \r\n
| \r\n {t('common:yes')} \r\n \r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default ConfirmationModal;","import React,{useState, useEffect} from 'react'\r\nimport CartObject from './cartObject/CartObject';\r\nimport { useHistory } from 'react-router-dom';\r\nimport {Link} from 'react-router-dom'\r\nimport { inject, observer } from \"mobx-react\";\r\nimport ConfirmationModal from '../modals/confirmationModal';\r\nimport * as cloneDeep from 'lodash/cloneDeep';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst CartTable = ({feathersStore})=> {\r\n\r\n const history = useHistory();\r\n\r\n const { t, i18n } = useTranslation(['common', 'cart']);\r\n\r\n const [total, setTotal] = useState(0.0);\r\n const [totalQuantity, setTotalQuantity] = useState(0.0);\r\n const [cart_products, setCart_products] = useState([]);\r\n const [itemToDelete, setItemToDelete] = useState({});\r\n\r\n //Modal Controls\r\n const [visible, setVisible] = useState(false); \r\n\r\n useEffect(() => {\r\n const cartFromStorage = JSON.parse(localStorage.getItem('fire_cart')) \r\n if(cartFromStorage){\r\n setCart_products(cartFromStorage); \r\n updateTotals(cartFromStorage); \r\n }\r\n }, []);\r\n \r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\nconst handleChangeQuantity = (e, item) => { \r\n const newQ = e.target.value;\r\n const index = cart_products.indexOf(itemToDelete);\r\n let clonedCartProducts = [...cart_products];\r\n let productClone = cloneDeep(item);\r\n Object.assign(productClone, {quantity: newQ, totalPrice: (+item.price * +newQ).toFixed(2)});\r\n clonedCartProducts.splice(index, 1, productClone); \r\n setCart_products(clonedCartProducts); \r\n localStorage.setItem(\"fire_cart\", JSON.stringify(clonedCartProducts)); \r\n updateTotals(clonedCartProducts);\r\n}\r\n\r\n \r\n const removeItem = item => {\r\n setVisible(true);\r\n setItemToDelete(item)\r\n }\r\n\r\n const deleteItem = ()=> {\r\n const index = cart_products.indexOf(itemToDelete);\r\n let clonedCartProducts = [...cart_products];\r\n clonedCartProducts.splice(index, 1); \r\n setCart_products(clonedCartProducts); \r\n localStorage.setItem(\"fire_cart\", JSON.stringify(clonedCartProducts)); \r\n updateTotals(clonedCartProducts);\r\n feathersStore.setCartLength(clonedCartProducts.length); \r\n setVisible(!visible);\r\n }\r\n\r\n const updateTotals = cartProducts => {\r\n setTotal(cartProducts.map(element => +element.totalPrice)\r\n .reduce((t, sum) => sum + t, 0)); \r\n setTotalQuantity(cartProducts.map(element => +element.quantity)\r\n .reduce((t, sum) => sum + t, 0)); \r\n };\r\n\r\n const closeConfirm = ()=> {\r\n setVisible(!visible);\r\n }\r\n\r\n const goToProduct = async (item) => {\r\n const index = cart_products.indexOf(item); \r\n const prod = await feathersStore.getProduct(item.product_id);\r\n prod && history.push({\r\n pathname: `/product/${prod._id}`,\r\n payload: prod\r\n });\r\n };\r\n\r\n const renderCartProducts = cart_products.map((item, index) => (\r\n handleChangeQuantity(e, item)} \r\n onClickDelete={()=> removeItem(item)}\r\n goToProduct={() => goToProduct(item)}\r\n />\r\n ))\r\n\r\n return(\r\n <>\r\n <>\r\n \r\n >\r\n \r\n
\r\n
\r\n
\r\n
\r\n
{t(\"common:product\")} \r\n \r\n
\r\n
{t(\"common:price\")} \r\n \r\n
\r\n
{t(\"common:quantity\")} \r\n \r\n
\r\n
{t(\"common:sub-total\")} \r\n \r\n
\r\n
\r\n {renderCartProducts}\r\n
\r\n
\r\n \r\n {t(\"cart:coupon-button\")} \r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
{t(\"cart:cart-totals\")} \r\n \r\n
\r\n
\r\n \r\n {t(\"cart:complete-order\")} \r\n \r\n
\r\n
\r\n
\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(CartTable));","import React, { useEffect } from 'react';\r\nimport CartTable from '../../components/cards/cartTable';\r\nimport PageTitle from '../../components/screenComponents/pageTitle';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport \"./Cart.css\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\n\r\nconst Cart = ({feathersStore})=> {\r\n \r\n const { t, i18n } = useTranslation('cart');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n return(\r\n \r\n
\r\n
\r\n {feathersStore.cartLength !== 0 ? \r\n : \r\n \r\n
{t('cart:empty-cart')} \r\n }\r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Cart));","import React, {useState, useEffect} from 'react';\r\nimport \"./Product.css\"\r\nimport FormControl from '@material-ui/core/FormControl';\r\nimport InputLabel from '@material-ui/core/InputLabel';\r\nimport Select from '@material-ui/core/Select';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport MenuItem from '@material-ui/core/MenuItem';\r\nimport ProductCard from '../../components/cards/productCard/ProductCard';\r\nimport ScrollMenu from 'react-horizontal-scrolling-menu';\r\nimport NavigateNext from '@material-ui/icons/NavigateNext'\r\nimport NavigateBefore from '@material-ui/icons/NavigateBefore'\r\nimport FormHelperText from '@material-ui/core/FormHelperText';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useHistory } from 'react-router-dom';\r\nimport ReactHtmlParser from 'react-html-parser';\r\nimport { API_URL } from \"../../components/assets/globalConstants\";\r\nimport SmallAlert from \"../../components/modals/smallAlert\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nlet initialCartBiggestId = 0;\r\nlet cart = [];\r\n\r\n// const GoldRating = withStyles({\r\n// iconFilled: {\r\n// color: '#ff6d75',\r\n// },\r\n// iconHover: {\r\n// color: '#ff3d47',\r\n// },\r\n// })(Rating);\r\n\r\nconst Product = ({ location, feathersStore })=> {\r\n\r\n const history = useHistory();\r\n const { t, i18n } = useTranslation('common');\r\n\r\n let paramProduct; \r\n\r\n const [product, setProduct] = useState({});\r\n const [imageList, setImageList] = useState([]);\r\n const [randomProducts, setRandomProducts] = useState([]);\r\n const [variations, setVariations] = useState([])\r\n const [variation, setVariation] = useState({});\r\n const [quantity, setQuantity] = useState(1);\r\n const [warning, setWarning] = useState(false); \r\n const [purchased, setPurchased] = useState(false);\r\n \r\n //Information Modal controls\r\n const [cartIncreased, setCartIncreased] = useState(false);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n useEffect(() => {\r\n if(localStorage.getItem('fire_cart')){\r\n cart = JSON.parse(localStorage.getItem('fire_cart')); \r\n if(cart.length > 0)\r\n initialCartBiggestId = +cart.map(e => e.id).sort().reverse()[0] + 1; \r\n }\r\n }, [location?.payload]);\r\n\r\n useEffect(() => { \r\n feathersStore.isAuthenticated && initProduct(); \r\n }, [location?.payload, feathersStore.isAuthenticated, \r\n feathersStore?.favoritesArray, feathersStore.productUpdatedEvent]); \r\n\r\n useEffect(() => { //--Real time updates\r\n paramProduct && realTimeUpdates();\r\n }, [feathersStore.productUpdatedEvent]);\r\n \r\n useEffect(() => { \r\n product && feathersStore.user?.firstname !== \"default\" && checkIfPurchased();\r\n }, [product, feathersStore.user]); \r\n\r\n const initProduct = async() => {\r\n \r\n paramProduct = location?.payload;\r\n\r\n //USAGE: for reloads\r\n if(!location?.payload){ \r\n const {id} = location.state;\r\n paramProduct = await feathersStore.getProduct(id);\r\n }\r\n setupProduct();\r\n }\r\n\r\n const setupProduct = () => {\r\n if(paramProduct?.hasVariation){\r\n setVariations(paramProduct?.variations)\r\n setVariation(paramProduct?.variations[0])\r\n }\r\n setImageList(getImageArr(paramProduct));\r\n setProduct(paramProduct);\r\n }\r\n\r\n const realTimeUpdates = async() => {\r\n if( feathersStore.productUpdatedEvent._id === paramProduct._id){\r\n paramProduct = await feathersStore.getProduct(paramProduct._id);\r\n setupProduct();\r\n }\r\n }\r\n\r\n const getImageArr = product => {\r\n let imageArr = [];\r\n if(product.hasVariation){\r\n imageArr = product.variations\r\n .map(variation => variation.images\r\n .map(image => Object.assign(image, {variation: variation.name}))) //Add variation name to the image\r\n .flat();\r\n }else{\r\n imageArr = product.images\r\n }\r\n return imageArr;\r\n }\r\n\r\n const checkIfPurchased = async() => {\r\n const orders = await feathersStore.ordersPerUser();\r\n const check = orders?.map(order => order.items).flat().find(prod => prod.product_id === product._id);\r\n setPurchased(check);\r\n }\r\n\r\n const onPressAddToFavorites = async () => {\r\n let id = '';\r\n id = product._id;\r\n if(feathersStore.favoritesArray.includes(id)){\r\n const index = feathersStore.favoritesArray.indexOf(id);\r\n if (index > -1) {\r\n feathersStore.favoritesArray.splice(index, 1);\r\n }\r\n }else{\r\n feathersStore.favoritesArray.push(id);\r\n } \r\n if(feathersStore.wishlistId === \"\"){\r\n const data = await feathersStore.createWishlist();\r\n data && (feathersStore.wishlistId = data._id); \r\n }else await feathersStore.updateWishlist();\r\n };\r\n\r\n useEffect(()=>{\r\n feathersStore.isAuthenticated && fetchProducts();\r\n },[feathersStore.isAuthenticated, feathersStore.productUpdatedEvent, feathersStore.productCreatedEvent]);\r\n\r\n const fetchProducts = async() => {\r\n const feathersProducts = \r\n await feathersStore.products();\r\n setRandomProducts([...feathersProducts]); \r\n }\r\n\r\n const getMainImage = (product)=> {\r\n let list = getImageArr(product);\r\n const mainImg = list.find(img => img.focused);\r\n return mainImg;\r\n }\r\n\r\n const handlePress = (product)=> {\r\n history.push({\r\n pathname: `/product/${product.name}`,\r\n state: {id: `${product._id}`},\r\n payload: product \r\n }); \r\n }\r\n\r\n const getPrice = (product)=> { \r\n if(product.hasVariation){\r\n let priceArr = [];\r\n priceArr = product.variations\r\n .map(variation => +variation.retailPrice)\r\n const low = Math.min(...priceArr)\r\n const high = Math.max(...priceArr)\r\n if(low === high){\r\n return high.toFixed(2)\r\n }else{\r\n return low.toFixed(2) + \" - \" + high.toFixed(2)\r\n } \r\n }else{\r\n return (+product.retailPrice).toFixed(2);\r\n }\r\n }\r\n\r\n const getBadges = product => { \r\n if(product.hasVariation){\r\n let vrtion = product.variations\r\n .find(variation => variation.images.map(image => image.focused));\r\n return vrtion.badges;\r\n }\r\n return product.badges;\r\n }\r\n\r\n const getOldPrice = product => {\r\n if(product.hasVariation){\r\n let vrtion = product.variations\r\n .find(variation => variation.images.map(image => image.focused));\r\n return vrtion.oldPrice;\r\n }\r\n return product.oldPrice;\r\n }\r\n\r\n const Menu = randomProducts.map(product => {\r\n \r\n return (\r\n \r\n handlePress(product)}\r\n onClickCart={() => handleAddToCart(product, true)}\r\n hasVariation={product.hasVariation}\r\n onClickForward={()=> handlePress(product)}\r\n badges={getBadges(product)}\r\n />\r\n \r\n );\r\n });\r\n\r\n const useStyles = makeStyles((theme) => ({\r\n formControl: {\r\n margin: theme.spacing(1),\r\n minWidth: 120,\r\n },\r\n selectEmpty: {\r\n marginTop: theme.spacing(2),\r\n },\r\n }));\r\n\r\n const classes = useStyles();\r\n\r\n const renderImages = imageList.map((image, index)=>\r\n (\r\n
selectImage(image)}>\r\n \r\n \r\n
)\r\n );\r\n\r\n const renderMainImage = imageList.map((image, index)=>( \r\n image.focused && \r\n )) \r\n \r\n const selectImage = (image)=> {\r\n const index = imageList.indexOf(image)\r\n let newList = [...imageList]\r\n newList.forEach(item => item.focused = false)\r\n newList[index].focused = true\r\n setImageList([...newList]) \r\n setVariation(variations.find(v => v.name === image.variation))\r\n }\r\n \r\n const handleChange = event => {\r\n let selectedVariation = event.target.value; \r\n setVariation(selectedVariation); \r\n setQuantity(1) \r\n let newList = [...imageList] \r\n if(selectedVariation.image === null){\r\n setSelected(true)\r\n }else{ \r\n newList.forEach(item => item.focused = false)\r\n const index = newList.findIndex(img => img.name === selectedVariation.images[0].name) \r\n newList[index].focused = true;\r\n } \r\n setImageList([...newList]); \r\n };\r\n\r\n const variationSelections = variations?.map((item, index) => (\r\n {item.name} \r\n ))\r\n\r\n //-------FEATURES LOGIC ----------------------------------------//\r\n \r\n const [featuresSelected, setFeaturesSelected] = useState([])\r\n const [featureSelectedName, setFeatureSelectedName] = useState('')\r\n const [error, setError] = useState(false)\r\n\r\n const renderFeatures = product => product.savedFeaturesTables?.map((table, index) => (\r\n \r\n {table.title} \r\n handleFeatures(e, table.title)}\r\n label={table.title}\r\n >\r\n { table.savedFeaturesArray.map((i, index) => (\r\n {i.name} \r\n ))} \r\n \r\n {featureSelectedName === '' && Κάντε μια επιλογή }\r\n {error && Κάντε μια επιλογή }\r\n \r\n ))\r\n\r\n\r\n const handleFeatures = (e, title)=> {\r\n let name = e.target.value\r\n let item = {\r\n title,\r\n name\r\n }\r\n const featuresSelectedClone = [...featuresSelected];\r\n const index = featuresSelectedClone.findIndex(val => val.title === title);\r\n index !== -1 ? featuresSelectedClone.splice(index, 1, item) : featuresSelectedClone.push(item);\r\n setFeatureSelectedName(name)\r\n setFeaturesSelected([...featuresSelectedClone]);\r\n } \r\n\r\n const handleAddToCart = (prod, fromList) => { //fromList = prod is coming from the footer list and has no variations \r\n let cartItem = {\r\n id: initialCartBiggestId,\r\n product_id: prod._id,\r\n title: prod?.name,\r\n image: fromList ? prod.images?.find(img => img.focused) : imageList?.find(img => img.focused),\r\n price: prod.hasVariation ? variation?.retailPrice : prod?.retailPrice ,\r\n quantity: fromList ? 1 : quantity,\r\n totalPrice: ((prod?.hasVariation ? +variation.retailPrice : +prod.retailPrice)*quantity).toFixed(2),\r\n variationTitle: prod?.variationTitle,\r\n variation: prod.hasVariation ? variation?.name : \"\",\r\n stock: prod.hasVariation ? variation?.handleStock && variation?.stock : prod?.handleStock && prod?.stock,\r\n extra: [...featuresSelected],\r\n handleStock: prod.hasVariation ? variation?.handleStock : prod?.handleStock\r\n }\r\n\r\n const cartSimilarItems = cart.filter(item => item.product_id === cartItem.product_id );\r\n let cartSimilarItem; \r\n if(prod.hasVariation)cartSimilarItem = cartSimilarItems.find(sim => sim.variation === cartItem.variation);\r\n else cartSimilarItem = cartSimilarItems[0];\r\n if(cartSimilarItem){ \r\n const newQ = +cartSimilarItem.quantity + +cartItem.quantity; \r\n if((prod.handleStock || variation.handleStock) && (newQ > cartItem.stock)){\r\n setWarning(true) ;\r\n return \r\n }else{\r\n const cartIndex = cart.findIndex(item => item.id === cartSimilarItem.id);\r\n cartItem.quantity = newQ;\r\n cartItem.totalPrice = (cartItem.price * newQ).toFixed(2);\r\n cart.splice(cartIndex, 1, cartItem);\r\n } \r\n }else{ \r\n cart.push(cartItem);\r\n feathersStore.setCartLength(feathersStore.cartLength + 1); \r\n } \r\n if(!warning){\r\n localStorage.setItem(\"fire_cart\", JSON.stringify(cart));\r\n setCartIncreased(true);\r\n }\r\n //!fromList && !warning && resetProduct();\r\n }\r\n\r\n const setNewQuantity = (e)=> {\r\n let count = e.target.value;\r\n setQuantity(count)\r\n }\r\n\r\n const [selected, setSelected] = useState(0)\r\n \r\n const ArrowLeft = \r\n const ArrowRight = ;\r\n\r\n return(\r\n <>\r\n \r\n
\r\n
\r\n
\r\n {renderMainImage}\r\n {((product?.badges || variation?.badges)?.includes('new')) && (\r\n
)\r\n }\r\n {(((product?.badges || variation?.badges)?.includes('sale')) || product?.oldPrice || variation?.oldPrice) && (\r\n
)\r\n }\r\n {((product?.badges || variation?.badges)?.includes('hot')) && (\r\n
)\r\n } \r\n
\r\n
\r\n {renderImages} \r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
{product?.name} \r\n \r\n {/*
\r\n {feathersStore.isAuthenticated && feathersStore.user?.firstname !== \"default\" && \r\n
}\r\n
*/}\r\n
\r\n {(variation?.oldPrice || product?.oldPrice) &&\r\n
\r\n {((product?.hasVariation ? +variation.oldPrice : +product.oldPrice)*quantity).toFixed(2)} € \r\n \r\n }\r\n {((product?.hasVariation ? +variation.retailPrice : +product.retailPrice)*quantity).toFixed(2)} € \r\n \r\n \r\n
\r\n {ReactHtmlParser(`
${product?.htmlContent}
`)} \r\n
\r\n \r\n {product?.hasVariation && \r\n
\r\n \r\n {product.variationTitle} \r\n \r\n {variations?.map((item, index) => (\r\n {item?.name} \r\n ))}\r\n \r\n \r\n
\r\n }\r\n\r\n {\r\n product?.hasOtherFeatures && \r\n
\r\n {product?.hasVariation ? renderFeatures(variation) : renderFeatures(product)}
\r\n }\r\n\r\n {product?.handleStock && !product.hasVariation &&\r\n
\r\n
{product?.stock !==0 ?
{product.stock} σε απόθεμα
:
Εξαντλημένο
}
\r\n
\r\n }\r\n\r\n {product?.hasVariation && !variation && \r\n
\r\n }\r\n\r\n {product?.hasVariation && variation?.handleStock &&
\r\n {variation.stock !== 0 ?
{variation.stock} σε απόθεμα
:
Εξαντλημένο
}\r\n
}\r\n\r\n
setWarning(false)}\r\n message={t(\"common:stock-warning\")} />\r\n\r\n \r\n \r\n handleAddToCart(product, false)} className=\"btn btn-primary btn-sm\" type=\"submit\" >Προσθήκη στο καλάθι\r\n \r\n
\r\n \r\n
\r\n \r\n
{t('common:view-more')} \r\n {feathersStore.isAuthenticated &&\r\n \r\n }\r\n \r\n setCartIncreased(false)}\r\n message={t(\"common:cart-updated\")} />\r\n \r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Product));","import React from 'react'\r\n\r\nconst CheckoutComponent = ({title, quantity, total})=> {\r\n\r\n return(\r\n \r\n
{title} x {quantity}
\r\n
{total}€
\r\n
\r\n )\r\n}\r\n\r\nexport default CheckoutComponent;","export default class Utils {\r\n \r\n static validateEmail(email) {\r\n let EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; \r\n if (EMAIL_REGEXP.test(email)){\r\n return true;\r\n }\r\n return false;\r\n }\r\n \r\n static validatePassword(password) {\r\n \r\n let PASSWORD_REGEXP =/^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/\r\n if (PASSWORD_REGEXP.test(password)) {\r\n return true;\r\n }\r\n return false;\r\n \r\n // return true;\r\n }\r\n\r\n static validatePhone(tel) {\r\n //TODO: Add more robust validation\r\n if (tel.length === 10 && !isNaN(tel)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n static validateName(name) {\r\n //TODO: Add more robust validation\r\n if (name.length > 1 && isNaN(name)) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n static validateNonEmpty(str) {\r\n //TODO: Add more robust validation\r\n if (str.length > 0) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n/*\r\n static async requestLocationPermission() {\r\n try {\r\n const granted = await PermissionsAndroid.request(\r\n PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, \r\n {\r\n 'title': 'Location Permission',\r\n 'message': 'Η Λειτουργία Οδήγησης θέλει πρόσβαση στο GPS ' +\r\n 'της συσκευής'\r\n } \r\n )\r\n if (granted === PermissionsAndroid.RESULTS.GRANTED) {\r\n console.log(\"ΟΚ Location Permission granted\")\r\n } else {\r\n console.log(\"Location permission denied\")\r\n }\r\n } catch (err) {\r\n console.warn(err)\r\n }\r\n }\r\n\r\n static async requestReadPhoneStatePermission() {\r\n try {\r\n const granted = await PermissionsAndroid.request(\r\n PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE,\r\n {\r\n 'title': 'Read Phone State Permission',\r\n 'message': 'Η Λειτουργία Οδήγησης θέλει πρόσβαση στις ρυθμίσεις ' +\r\n 'της συσκευής'\r\n }\r\n )\r\n if (granted === PermissionsAndroid.RESULTS.GRANTED) {\r\n console.log(\"ΟΚ Phone State Permission granted\")\r\n } else {\r\n console.log(\"Phone State permission denied\")\r\n }\r\n } catch (err) {\r\n console.warn(err)\r\n }\r\n }\r\n\r\n static async requestSendSmsPermission() {\r\n try {\r\n const granted = await PermissionsAndroid.request(\r\n PermissionsAndroid.PERMISSIONS.SEND_SMS,\r\n {\r\n 'title': 'Send SMS Permission',\r\n 'message': 'Η Λειτουργία Οδήγησης θέλει άδεια για να ' +\r\n 'στέλνει SMS'\r\n }\r\n )\r\n if (granted === PermissionsAndroid.RESULTS.GRANTED) {\r\n console.log(\"ΟΚ Send SMS Permission granted\")\r\n } else {\r\n console.log(\"Send SMS permission denied\")\r\n }\r\n } catch (err) {\r\n console.warn(err)\r\n }\r\n }\r\n\r\n static async requestReadSmsPermission() {\r\n try {\r\n const granted = await PermissionsAndroid.request(\r\n PermissionsAndroid.PERMISSIONS.READ_SMS,\r\n {\r\n 'title': 'Read SMS Permission',\r\n 'message': 'Η Λειτουργία Οδήγησης θέλει άδεια για να ' +\r\n 'διαβάζει SMS'\r\n }\r\n )\r\n if (granted === PermissionsAndroid.RESULTS.GRANTED) {\r\n console.log(\"ΟΚ Read SMS Permission granted\")\r\n } else {\r\n console.log(\"Read SMS permission denied\")\r\n }\r\n } catch (err) {\r\n console.warn(err)\r\n }\r\n }\r\n\r\n \r\n {'\\t'}Η εφαρμογή, Ασφαλής Οδήγηση, έχει σκοπό να ελαχιστοποιήσει την απόσπαση της προσοχής του οδηγού για τη μείωση των οδικών ατυχημάτων, εξαιτίας της χρήσης του κινητού κατά την οδήγηση{'\\n'}{'\\n'} \r\n {'\\t'}Πώς λειτουργεί:{'\\n'}\r\n {'\\t'}Ανοίγετε την εφαρμογή πριν την οδήγηση.{'\\n'} \r\n {'\\t'}Παρουσιάζεται ένας κύκλος με την αναγραφή 0 km /h και το σήμα του διακόπτη σε πράσινο χρώμα , που δηλώνει ότι η εφαρμογή είναι ON .{'\\n'} \r\n {'\\t'}Όταν το μεταφορικό μέσον που οδηγούμε, αυτοκίνητο, μηχανή ,ποδήλατο, κτλ αναπτύξει ταχύτητα πάνω από 20 km/h για ένα λεπτό, ενεργοποιείται αυτόματα η εφαρμογή.{'\\n'} \r\n {'\\t'}Σαν ένδειξη σβήνει ο κύκλος και αναγράφει, Εφαρμογή Ενεργοποιημένη.{'\\n'} \r\n {'\\t'}Με ενεργοποιημένη την εφαρμογή το τηλέφωνό σας μπαίνει σε σίγαση, ( ελαχιστοποιεί τον ήχο και τη δόνηση ) ώστε να μην παρενοχλήστε. Η εφαρμογή τίθεται αυτόματα εκτός, εάν παραμείνετε στάσιμοι πάνω από 2 λεπτά, εάν η ταχύτητα είναι για δύο λεπτά κάτω των 20 χιλ. η με πάτημα πάνω στον πράσινο σήμα του διακόπτη, κάτι που δεν σαν συνιστούμε κατά την οδήγηση.{'\\n'} \r\n {'\\t'}Με ενεργοποιημένη την εφαρμογή, όταν κάποιος σας καλεί η σας στέλνει SMS θα λαμβάνει αυτόματα ένα μήνυμα που θα έχετε επιλέξει. Εφόσον σας το επιτρέπει ο πάροχος κινητής τηλεφωνίας μπορείτε να ηχογραφήσετε και κάποιο μήνυμα.{'\\n'}\r\n {'\\t'}Βασική προϋπόθεση για την λειτουργία της εφαρμογής είναι να έχετε ενεργοποιήσει την τοποθεσία στο κινητό σας και να έχει επικοινωνία με δορυφόρο.\r\n \r\n\r\n*/\r\n }","import React, { useEffect } from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport Button from '@material-ui/core/Button';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport AppColors from '../assets/colors';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst VerificationErrorModal = ({visible, exit, resend, feathersStore})=> {\r\n const useStyles = makeStyles((theme) => ({\r\n margin: {\r\n margin: theme.spacing(1),\r\n },\r\n }));\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n return (\r\n \r\n \r\n \r\n
\r\n
{t(\"common:error-code\")}
\r\n
\r\n
\r\n {t(\"common:repeat\")} \r\n
| \r\n {t(\"common:exit\")} \r\n \r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(VerificationErrorModal));","import React, { useEffect } from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport { Button, CircularProgress } from '@material-ui/core';\r\nimport { createMuiTheme, makeStyles } from '@material-ui/core/styles';\r\nimport { green, red } from '@material-ui/core/colors';\r\nimport AppColors from '../assets/colors';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\n\r\nconst ConfirmExitModal = ({ loading, visible, no, yes, feathersStore })=> {\r\n const useStyles = makeStyles((theme) => ({\r\n margin: {\r\n margin: theme.spacing(1),\r\n },\r\n }));\r\n \r\n const theme = createMuiTheme({\r\n palette: {\r\n primary: red,\r\n secondary: green,\r\n },\r\n });\r\n const classes = useStyles();\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n return (\r\n \r\n \r\n \r\n
\r\n
{t(\"common:logout-warning\")}
\r\n
\r\n
\r\n {t(\"common:no\")} \r\n
| \r\n \r\n {t(\"common:yes\")}\r\n {loading && \r\n \r\n }\r\n \r\n \r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(ConfirmExitModal));","import React, { useEffect } from 'react'\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst RegisteredCustomer = ({onClickSignIn, feathersStore})=> {\r\n\r\n const useStyles = makeStyles((theme) => ({\r\n root: {\r\n '& > *': {\r\n margin: theme.spacing(1),\r\n },\r\n },\r\n formControl: {\r\n margin: theme.spacing(1),\r\n minWidth: 120,\r\n },\r\n selectEmpty: {\r\n marginTop: theme.spacing(2),\r\n },\r\n \r\n searchIcon: {\r\n padding: theme.spacing(0, 2),\r\n height: '100%',\r\n position: 'absolute',\r\n pointerEvents: 'none',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n },\r\n inputRoot: {\r\n color: 'inherit',\r\n },\r\n inputInput: {\r\n padding: theme.spacing(1, 1, 1, 0),\r\n // vertical padding + font size from searchIcon\r\n paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,\r\n transition: theme.transitions.create('width'),\r\n width: '100%',\r\n [theme.breakpoints.up('sm')]: {\r\n width: '21ch',\r\n '&:focus': {\r\n width: '25ch',\r\n },\r\n },\r\n },\r\n }));\r\n\r\n const { t, i18n } = useTranslation('checkout');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n return(\r\n \r\n \r\n {t(\"checkout:already-customer\")} \r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(RegisteredCustomer));","import React, {useState} from 'react';\r\nimport Prompt from '../../modals/prompt';\r\nimport RegistrationCard from '../../modals/registrationCard'\r\nimport VerificationCode from '../../modals/verificationCode'\r\nimport ResetPassword from '../../modals/resetPassword'\r\nimport ConfirmExitModal from '../../modals/confirmExitModal'\r\nimport RegisteredCustomer from '../../buttons/registeredCustomer'\r\nimport \"./Registration.css\"\r\n\r\n\r\nconst Registration = ()=> { \r\n\r\n const [visible, setModal] = useState(false);\r\n const [visibleRegister, setRegistrationModal] = useState(false);\r\n const [visibleVerification, setVisibleVerification] = useState(false);\r\n const [resetPasswordModal, setResetPasswordModal] = useState(false)\r\n const [exit, setExit] = useState(false);\r\n\r\n const handleModal = ()=> {\r\n setModal(!visible); \r\n }\r\n\r\n const openRegistrationModal = ()=> {\r\n setModal(false);\r\n setRegistrationModal(true);\r\n }\r\n\r\n const closeRegistrationModal = ()=> {\r\n setRegistrationModal(false);\r\n }\r\n\r\n const openVerification = ()=> {\r\n setRegistrationModal(false);\r\n setVisibleVerification(true);\r\n }\r\n\r\n const closeVerification = ()=> {\r\n setVisibleVerification(false); \r\n } \r\n\r\n const facebookLogin = ()=> {\r\n setModal(false); \r\n }\r\n\r\n const SubmitReset = ()=> {\r\n setResetPasswordModal(!resetPasswordModal);\r\n } \r\n\r\n const Logout = ()=> { \r\n setExit(!exit); \r\n }\r\n\r\n const NoLogout = ()=> {\r\n setExit(!exit);\r\n } \r\n\r\n return(\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default (Registration);","import React, {useState, useEffect} from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport { LoopCircleLoading } from 'react-loadingg';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst LoadingOrderModal = ({visible, whenSent, whenError, feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n \r\n useEffect(() => {\r\n visible && sendOrder();\r\n }, [visible]);\r\n\r\n const sendOrder = async() => {\r\n const orderCreated = await feathersStore.createOrder(feathersStore.orderItem);\r\n if(orderCreated){\r\n emptyCart(); \r\n feathersStore.setCartLength(0);\r\n whenSent();\r\n }else{\r\n alert(\r\n `${t('common:connection-issue')}`\r\n )\r\n whenError();\r\n }\r\n }\r\n\r\n const emptyCart = () => {\r\n const emptyItem = {\r\n 'customerId': \"\",\r\n 'bookingDate': \"\",\r\n 'status': '',\r\n 'items': [],\r\n 'paymentMethod':\"\",\r\n 'total': 0,\r\n 'processed': false,\r\n 'latitude': 0,\r\n 'longitude': 0,\r\n 'city': \"\",\r\n 'street': \"\",\r\n 'streetNumber': \"\",\r\n 'apartment': \"\",\r\n 'postcode': \"\",\r\n 'addressComments':\"\"\r\n }\r\n localStorage.setItem(\"fire_cart\", JSON.stringify([]));\r\n feathersStore.setOrderItem(emptyItem);\r\n }\r\n\r\n return (\r\n \r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(LoadingOrderModal));\r\n","import React, {useState, useEffect} from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport GreenSubmitButton from '../buttons/greenSubmitButton';\r\nimport AppColors from '../assets/colors';\r\n\r\nconst OrderCompleteModal = ({visible, onClickFinish})=> { \r\n \r\n return (\r\n \r\n \r\n \r\n
\r\n
\r\n
ΟΛΟΚΛΗΡΩΣΗ ΠΑΡΑΓΓΕΛΙΑΣ! \r\n
Η παραγγελία σας καταχωρήθηκε με επιτυχία. \r\n Ευχαριστούμε για την προτίμησή σας.
\r\n
\r\n
\r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default OrderCompleteModal;","import React,{ useState, useEffect, useRef } from 'react'\r\nimport PageTitle from '../../components/screenComponents/pageTitle'\r\nimport CheckoutComponent from '../../components/cards/checkoutComponent'\r\nimport {SlideDown} from 'react-slidedown';\r\nimport Registration from '../../components/reusable/registration/Registration'\r\nimport LoadingOrderModal from '../../components/modals/loadingOrderModal';\r\nimport OrderCompleteModal from '../../components/modals/orderCompleteModal';\r\nimport 'react-slidedown/lib/slidedown.css';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useHistory } from 'react-router-dom';\r\nimport { Formik, Field, Form, ErrorMessage } from 'formik';\r\nimport * as Yup from 'yup';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport { PayPalButton } from \"react-paypal-button-v2\";\r\nimport \"./Checkout.css\";\r\nimport { useTranslation } from 'react-i18next';\r\nimport { PHONE_REGEX, PAYPAL_CLIENT_ID } from \"../../components/assets/globalConstants\";\r\n\r\nconst Checkout = ({ feathersStore })=> {\r\n\r\n const history = useHistory();\r\n\r\n const { t, i18n } = useTranslation(['common', 'checkout']);\r\n\r\n const useStyles = makeStyles((theme) => ({\r\n formControl: {\r\n margin: theme.spacing(1),\r\n minWidth: 120,\r\n },\r\n selectEmpty: {\r\n marginTop: theme.spacing(2),\r\n }\r\n }));\r\n\r\n const formRef = useRef();\r\n\r\n const [origins, setOrigins] = useState([]);\r\n const [cartSub, setCartSub] = useState(0);\r\n const [isLoading, setLoading] = useState(false);\r\n const [isComplete, setComplete] = useState(false);\r\n const [transportation, setTransportation] =useState({}); //Object containing fields regarding transportation settings\r\n const _isMounted = useRef(true); //used in line 405 to check if component is mounted\r\n\r\n const cartItems = JSON.parse(localStorage.getItem('fire_cart'));\r\n\r\n useEffect(() => {\r\n return () => { // ComponentWillUnmount in Class Component\r\n _isMounted.current = false;\r\n }\r\n }, []);\r\n\r\n useEffect(()=> {\r\n setOrigins(feathersStore.settings?.origins);\r\n },[feathersStore.isAuthenticated && feathersStore.settings]);\r\n\r\n useEffect(()=> {\r\n const _subTotal = cartItems.map(item=> item.totalPrice)\r\n .reduce((prev, curr)=> +prev + +curr, 0).toFixed(2);\r\n setCartSub(_subTotal)\r\n },[cartItems])\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language);\r\n },[feathersStore.language]);\r\n\r\n useEffect(()=> {\r\n setTransportation(feathersStore.settings?.transportation);\r\n },[feathersStore.settings?.transportation]);\r\n\r\n useEffect(()=> {\r\n if(feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default'\r\n && formRef.current){\r\n formRef.current.setFieldValue('firstName', feathersStore.user?.firstname);\r\n formRef.current.setFieldValue('lastName', feathersStore.user?.lastname);\r\n feathersStore.user?.addresses && formRef.current.setFieldValue('street',feathersStore.user?.addresses.find(addr => addr.active)?.street);\r\n feathersStore.user?.addresses && formRef.current.setFieldValue('streetNumber',feathersStore.user?.addresses.find(addr => addr.active)?.streetNumber);\r\n feathersStore.user?.addresses && formRef.current.setFieldValue('city',feathersStore.user?.addresses.find(addr => addr.active)?.city);\r\n feathersStore.user?.addresses && formRef.current.setFieldValue('origin',feathersStore.user?.addresses.find(addr => addr.active)?.origin);\r\n feathersStore.user?.addresses && formRef.current.setFieldValue('postcode',feathersStore.user?.addresses.find(addr => addr.active)?.postcode);\r\n formRef.current.setFieldValue('phone',feathersStore.user?.phone);\r\n formRef.current.setFieldValue('email',feathersStore.user?.email);\r\n } \r\n },[feathersStore.user]);\r\n\r\n \r\n const setTitle = (item)=> {\r\n if(item.variation === null){\r\n return item.title\r\n }else{\r\n return item.title + \" - \" + item.variation\r\n + item.extra?.map(feature => \" - \" + feature.name);\r\n }\r\n }\r\n\r\n const createOrder = (data, actions) => {\r\n let values;\r\n if (formRef.current) {\r\n values = formRef.current.values;\r\n }\r\n return actions.order\r\n .create({\r\n purchase_units: [\r\n {\r\n amount: {\r\n currency: \"EUR\",\r\n value: values.grandTotal,\r\n },\r\n },\r\n ],\r\n application_context: {\r\n shipping_preference: \"NO_SHIPPING\" // default is \"GET_FROM_FILE\"\r\n }\r\n })\r\n .then((orderID) => { \r\n feathersStore.setOrderItem({paypalOrderID: orderID});\r\n return orderID;\r\n });\r\n }\r\n\r\n const approved = (data, actions) => {\r\n let values;\r\n if (formRef.current) {\r\n values = formRef.current.values;\r\n }\r\n // This function captures the funds from the transaction.\r\n return actions.order.capture().then(function(details) {\r\n // This function shows a transaction success message to your buyer.\r\n sendOrder(values);\r\n alert('Transaction completed by ' + details.payer.name.given_name);\r\n });\r\n }\r\n \r\n const onInit = (data, actions) => {\r\n let formikRef;\r\n if (formRef.current) {\r\n formikRef = formRef.current;\r\n }\r\n\r\n // Disable the buttons\r\n actions.disable();\r\n if (formikRef.isValid) {\r\n actions.enable();\r\n } else {\r\n actions.disable();\r\n }\r\n }\r\n\r\n const onClick = () => {\r\n let formikRef;\r\n if (formRef.current) {\r\n formikRef = formRef.current;\r\n }\r\n\r\n if (!formikRef.isValid) {\r\n alert(\"Please fill all fields\");\r\n }\r\n }\r\n\r\n const sendOrder = values => {\r\n const day = new Date().getDate(); //Current Date\r\n const month = new Date().getMonth() + 1; //Current Month\r\n const year = new Date().getFullYear(); //Current Year\r\n const hours = new Date().getHours(); //Current Hours\r\n const min = new Date().getMinutes(); //Current Minutes\r\n const initDate = day + '/' + month + '/' + year + ' ' + hours + ':' + min;\r\n feathersStore.setOrderItem({\r\n 'customerId': feathersStore.user._id || \"\",\r\n 'bookingDate': initDate,\r\n 'status': 'Pending',\r\n 'items': [...cartItems],\r\n 'total': values.grandTotal,\r\n 'transportationCost': values.transportationCost,\r\n 'handoverCost': values.handoverCost,\r\n 'processed': false,\r\n 'latitude': 0,\r\n 'longitude': 0,\r\n 'firstName': values.firstName,\r\n 'lastName': values.lastName,\r\n 'street': values.street,\r\n 'streetNumber': values.streetNumber,\r\n 'city': values.city, \r\n 'origin': values.origin, \r\n 'apartment' : feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default' ? feathersStore.user?.phone : \"\", \r\n 'postcode': values.postcode,\r\n 'phone': values.phone,\r\n 'email': values.email,\r\n 'hasOtherAddress': values.hasOtherAddress,\r\n 'deliveryFirstName': values.hasOtherAddress ? values.deliveryFirstName : \"\",\r\n 'deliveryLastName': values.hasOtherAddress ? values.deliveryLastName : \"\",\r\n 'deliveryStreet': values.hasOtherAddress ? values.deliveryStreet : \"\",\r\n 'deliveryCity': values.hasOtherAddress ? values.deliveryCity : \"\", \r\n 'deliveryOrigin': values.hasOtherAddress ? values.deliveryOrigin : \"\",\r\n 'deliveryPostcode': values.hasOtherAddress ? values.deliveryPostcode : \"\",\r\n 'deliveryPhone': values.hasOtherAddress ? values.deliveryPhone : \"\",\r\n 'comments':values.comments || \"\",\r\n 'paymentMethod':values.paymentMethod\r\n });\r\n setLoading(true);\r\n }\r\n\r\n const validationSchema = Yup.object({\r\n firstName: Yup.string()\r\n .max(255, t('checkout:less255'))\r\n .required(t('checkout:required')),\r\n lastName: Yup.string()\r\n .max(255, t('checkout:less255'))\r\n .required(t('checkout:required')),\r\n street: Yup.string()\r\n .max(50, t('checkout:less50'))\r\n .required(t('checkout:required')),\r\n streetNumber: Yup.string()\r\n .max(10, t('checkout:less10'))\r\n .required(t('checkout:required')),\r\n city: Yup.string()\r\n .max(50, t('checkout:less50'))\r\n .required(t('checkout:required')), \r\n grandTotal: Yup.number(),\r\n transportationCost: Yup.number(),\r\n handoverCost: Yup.number(),\r\n origin: Yup.number()\r\n .required(t('checkout:required')),\r\n postcode: Yup.string()\r\n .max(10, t('checkout:less10'))\r\n .required(t('checkout:required')), \r\n email: Yup.string()\r\n .email(t('checkout:invalidEmail'))\r\n .required(t('checkout:required')), \r\n phone: Yup.string()\r\n .matches(PHONE_REGEX, 'checkout:invalidPhone')\r\n .required(t('checkout:required')),\r\n hasOtherAddress: Yup.boolean()\r\n .required(t('checkout:required')),\r\n comments: Yup.string()\r\n .max(500, t('checkout:textareaMax')),\r\n paymentMethod: Yup.string()\r\n .required(t('checkout:required'))\r\n .oneOf([\"Cash\", \"ClickAway\",\"PayPal\"], t('checkout:invalidPayment')),\r\n acceptedTerms: Yup.boolean()\r\n .required(t('checkout:required'))\r\n .oneOf([true], t('checkout:terms')),\r\n\r\n //----- Sub - form validation ----------\r\n deliveryFirstName: Yup.string().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.string()\r\n .max(255, t('checkout:less255'))\r\n .required(t('checkout:required'))\r\n }), \r\n deliveryLastName: Yup.string().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.string()\r\n .max(255, t('checkout:less255'))\r\n .required(t('checkout:required'))\r\n }), \r\n deliveryStreet:Yup.string().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.string()\r\n .max(50, t('checkout:less50'))\r\n .required(t('checkout:required'))\r\n }),\r\n deliveryCity: Yup.string().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.string()\r\n .max(50, t('checkout:less50'))\r\n .required(t('checkout:required'))\r\n }), \r\n deliveryOrigin: Yup.number().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.number() \r\n .required(t('checkout:required'))\r\n }),\r\n deliveryPostcode: Yup.string().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.string()\r\n .max(10, t('checkout:less10'))\r\n .required(t('checkout:required'))\r\n }),\r\n deliveryPhone:Yup.string().when('hasOtherAddress', {\r\n is: true,\r\n then: Yup.string()\r\n .matches(PHONE_REGEX, 'checkout:invalidPhone') \r\n .required(t('checkout:required'))\r\n }) \r\n })\r\n\r\n const grandTotalComponent = ({field, form}) => {\r\n return(\r\n
{field.value}€
\r\n )\r\n }\r\n\r\n //----------------- LoadingOrderModal controls -----------------\r\n\r\n const whenError = () => {\r\n setLoading(!isLoading); \r\n }\r\n\r\n const CompleteOrder = ()=> {\r\n setLoading(!isLoading);\r\n setComplete(!isComplete);\r\n }\r\n\r\n const setOrder = ()=> {\r\n setComplete(!isComplete);\r\n history.push(\"/\");\r\n }\r\n\r\n const renderCartItems = cartItems.map( (item, index) => (\r\n
\r\n ))\r\n\r\n return(\r\n <>\r\n
\r\n
\r\n
\r\n \r\n <>\r\n
addr.active)?.street : \"\",\r\n streetNumber: feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default' && feathersStore.user?.addresses ?\r\n feathersStore.user?.addresses.find(addr => addr.active)?.streetNumber : \"\",\r\n city: feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default' && feathersStore.user?.addresses ?\r\n feathersStore.user?.addresses.find(addr => addr.active)?.city : \"\",\r\n origin: feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default' && feathersStore.user?.addresses ?\r\n feathersStore.user?.addresses.find(addr => addr.active)?.origin : 1,\r\n postcode: feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default' && feathersStore.user?.addresses ?\r\n feathersStore.user?.addresses.find(addr => addr.active)?.postcode : \"\",\r\n phone: feathersStore.isAuthenticated && feathersStore.user?.firstname !== 'default' ? feathersStore.user?.phone : \"\",\r\n email: feathersStore.isAuthenticated && feathersStore.user?.lastname !== 'default' ? feathersStore.user?.email : \"\",\r\n hasOtherAddress: false,\r\n deliveryFirstName: '',\r\n deliveryLastName: '',\r\n deliveryStreet: '',\r\n deliveryCity: '',\r\n deliveryOrigin: 1,\r\n deliveryPostcode: '',\r\n deliveryPhone: '',\r\n comments:'',\r\n paymentMethod:'Cash',\r\n acceptedTerms: false,\r\n grandTotal:0,\r\n transportationCost: 0,\r\n handoverCost: 0\r\n }}\r\n \r\n validationSchema= {validationSchema}\r\n \r\n onSubmit={(values, { setSubmitting }) => {\r\n sendOrder(values);\r\n setSubmitting(false);\r\n ;\r\n }}\r\n >\r\n {formik => (\r\n \r\n )}\r\n \r\n >\r\n
\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Checkout));","import React, { useState, useEffect } from \"react\";\r\nimport PhotoCameraIcon from '@material-ui/icons/PhotoCamera';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport GreenSubmitButton from '../buttons/greenSubmitButton';\r\nimport axios from 'axios';\r\nimport { API_URL } from \"../assets/globalConstants\";\r\nimport Tooltip from '@material-ui/core/Tooltip';\r\nimport Compressor from 'compressorjs';\r\nimport SmallAlert from '../modals/smallAlert';\r\n\r\nconst Camera = ({feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation(['common', 'account']);\r\n\r\n const [imageToUpload, setImageToUpload] = useState({}); \r\n const [loading, setLoading] = useState(false);\r\n const [showAlert, setShowAlert] = useState(false);\r\n const [showError, setShowError] = useState(false);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language);\r\n },[feathersStore.language]);\r\n\r\n useEffect(() => {\r\n feathersStore.user?.avatar && \r\n setImageToUpload({preview: `${API_URL}/images/${feathersStore.user?.avatar}`})\r\n },[feathersStore.user])\r\n\r\n const handleChange = e => {\r\n if (e.target.files.length === 1) {\r\n const fileToCompress = e.target.files[0]; \r\n if(fileToCompress.size > 1048576){\r\n alert(`${t(\"account:big-file\")}`);\r\n return;\r\n } \r\n new Compressor(fileToCompress, {\r\n quality: 0.95, \r\n width: 300,\r\n height: 300,\r\n success: (compressedResult) => {\r\n setImageToUpload({\r\n preview: URL.createObjectURL(fileToCompress),\r\n raw: new File([compressedResult], fileToCompress.name)\r\n }); \r\n }\r\n }); \r\n }\r\n };\r\n\r\n const uploadPhoto = async(e) => {\r\n e.preventDefault(); \r\n try{\r\n setLoading(true);\r\n const { accessToken } = await feathersStore.getAccessToken();\r\n const formData = new FormData(); \r\n formData.append(\"uri\", imageToUpload?.raw); \r\n const res = await axios.post(`${API_URL}/uploads`, formData,{\r\n headers: {\r\n 'Content-Type': 'multipart/form-data',\r\n 'Accept': 'application/json', \r\n 'Authorization': accessToken \r\n }}) \r\n await feathersStore.patchUserAvatar(feathersStore.user?._id, imageToUpload.raw?.name) ;\r\n setLoading(false); \r\n !loading && setShowAlert(true);\r\n }catch(err){\r\n setLoading(false);\r\n setShowError(true)\r\n };\r\n \r\n }\r\n\r\n return(\r\n <>\r\n
\r\n
setShowAlert(false)} \r\n message={t(\"account:upload-success\")} />\r\n setShowError(false)} \r\n message={t(\"account:upload-error\")} />\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Camera));","import React from 'react'\r\nimport Button from 'react-bootstrap/Button';\r\nimport CancelPresentationIcon from '@material-ui/icons/CancelPresentation';\r\n\r\nconst CloseButton = (props)=> {\r\n\r\n function changeCursor(e) {\r\n e.target.style.cursor = 'pointer';\r\n }\r\n\r\n return(\r\n \r\n \r\n \r\n )\r\n}\r\n\r\nexport default CloseButton;","import React from 'react';\r\nimport Button from 'react-bootstrap/Button';\r\n\r\nconst RoundedButton = (props)=> {\r\n\r\nfunction changeCursor(e) {\r\ne.target.style.cursor = 'pointer';\r\n}\r\n\r\n return (\r\n \r\n {props.icon}\r\n \r\n );\r\n}\r\n\r\nexport default RoundedButton;","import React, { useState, useEffect } from 'react';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\nimport Dialog from '@material-ui/core/Dialog';\r\nimport DialogActions from '@material-ui/core/DialogActions';\r\nimport DialogContent from '@material-ui/core/DialogContent';\r\nimport DialogContentText from '@material-ui/core/DialogContentText';\r\nimport DialogTitle from '@material-ui/core/DialogTitle';\r\nimport GreenSubmitButton from '../buttons/greenSubmitButton';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nfunction getModalStyle() {\r\n const top = 50 ;\r\n const left = 50;\r\n\r\n return {\r\n top: `${top}%`,\r\n left: `${left}%`,\r\n transform: `translate(-${top}%, -${left}%)`,\r\n };\r\n}\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n paper: {\r\n position: 'absolute',\r\n width: 400,\r\n backgroundColor: theme.palette.background.paper,\r\n border: '2px solid #000',\r\n boxShadow: theme.shadows[5],\r\n padding: theme.spacing(2, 4, 3),\r\n },\r\n}));\r\n\r\n\r\nconst AddressDeleteModal = ({visible, onClickNo, itemToDelete, feathersStore})=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n const classes = useStyles();\r\n // getModalStyle is not a pure function, we roll the style only on the first render\r\n const [modalStyle] = React.useState(getModalStyle);\r\n const [loading, setLoading] = useState(false); \r\n\r\n const deleteAddress = async () => {\r\n setLoading(true); \r\n let clonedAddresses=[...feathersStore.user?.addresses]; \r\n if(itemToDelete){\r\n const index = clonedAddresses.indexOf(itemToDelete);\r\n clonedAddresses.splice(index, 1);\r\n } \r\n try{\r\n const user = await feathersStore.patchAddresses( feathersStore.user._id, [...clonedAddresses]);\r\n feathersStore.setUser(user);\r\n setLoading(false); \r\n alert(\"Επιτυχής Διαγραφή Διεύθυνσης\");\r\n }catch (error){\r\n setLoading(false); \r\n alert(`Αποτυχία Ενημέρωσης: ${error.message}`)\r\n }\r\n };\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n return ( \r\n \r\n {t('common:danger')} \r\n \r\n \r\n {t('common:delete-address')}\r\n \r\n \r\n \r\n \r\n | \r\n \r\n \r\n \r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(AddressDeleteModal));","import React, {useState} from 'react';\r\nimport Radio from '@material-ui/core/Radio';\r\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\r\nimport Button from 'react-bootstrap/Button';\r\nimport EditIcon from '@material-ui/icons/Edit';\r\nimport CloseOutlinedIcon from '@material-ui/icons/CloseOutlined';\r\nimport AddOrEditaddressModal from '../modals/addOrEditAddressModal/AddOrEditAddressModal';\r\nimport AddressDeleteModal from '../modals/addressDeleteModal';\r\n\r\nconst AddressComponent = ({\r\n onPress,\r\n item, \r\n title,\r\n street,\r\n city,\r\n apartment,\r\n postcode,\r\n streetNumber,\r\n origin,\r\n active\r\n}) => {\r\n\r\n function changeCursor(e) {\r\n e.target.style.cursor = 'pointer';\r\n }\r\n\r\n const [visibleAddNewAddress, setAddNewAddress] = useState(false);\r\n const [visibleDeleteAddress, setDeleteAddress] = useState(false);\r\n\r\n const editAddress = () => { \r\n setAddNewAddress(true); \r\n };\r\n\r\n const closeNewAddress = () =>{\r\n setAddNewAddress(false); \r\n }\r\n\r\n const openDeleteAddressModal = () => { \r\n setDeleteAddress(true); \r\n };\r\n\r\n const closeDeleteAddressModal = () =>{\r\n setDeleteAddress(false); \r\n }\r\n \r\n return (\r\n \r\n
\r\n } \r\n classes={{ label: 'addressLabel' }} \r\n label={title} \r\n checked={active}\r\n onChange={ onPress}/> \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default AddressComponent;\r\n","import React, {useState, useEffect} from 'react';\r\nimport RadioGroup from '@material-ui/core/RadioGroup';\r\nimport FormControl from '@material-ui/core/FormControl';\r\nimport FormLabel from '@material-ui/core/FormLabel';\r\nimport AddressComponent from '../cards/addressComponent';\r\nimport AddIcon from '@material-ui/icons/Add';\r\nimport LocationOnIcon from '@material-ui/icons/LocationOn';\r\nimport HomeIcon from '@material-ui/icons/Home';\r\nimport CloseIcon from '@material-ui/icons/Close';\r\nimport RoundedButton from '../buttons/roundedButton';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport AddOrEditaddressModal from '../modals/addOrEditAddressModal/AddOrEditAddressModal';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nconst Address = ({onClickClose, onClickAddNew, onClickLocation, feathersStore}) => {\r\n\r\n const { t, i18n } = useTranslation('account');\r\n\r\n const [addresses, setAddresses] = useState([]); \r\n const [showButtons, setShowButtons] = useState(false);\r\n const [visibleAddNewAddress, setAddNewAddress] = useState(false);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]); \r\n\r\n useEffect(() => {\r\n feathersStore.user?.addresses && setAddresses([...feathersStore.user?.addresses]);\r\n }, [feathersStore.user?.addresses])\r\n\r\n const openNewAddress = () => { \r\n setAddNewAddress(true); \r\n };\r\n\r\n const closeNewAddress = () =>{\r\n setAddNewAddress(false); \r\n }\r\n\r\n const ClickAddAddress = ()=> {\r\n setShowButtons(!showButtons);\r\n }\r\n\r\n const setDeliveryAddress = item => () => { \r\n const index = addresses.indexOf(item);\r\n const activeIndex = addresses.findIndex(e => e.active === true);\r\n let clonedAddresses = [...addresses];\r\n\r\n if (activeIndex !== index) {\r\n clonedAddresses[activeIndex].active = false;\r\n clonedAddresses[index].active = true; \r\n updateUser(clonedAddresses); \r\n }\r\n };\r\n\r\n const updateUser = async newAddresses => {\r\n setAddresses([...newAddresses]); \r\n let clonedUser = JSON.parse(JSON.stringify(feathersStore.user));\r\n clonedUser.addresses = [...newAddresses];\r\n feathersStore.setUser(clonedUser); \r\n await saveActiveAddress(newAddresses); \r\n }\r\n\r\n const saveActiveAddress = async val => { \r\n await feathersStore.patchAddresses( feathersStore.user._id, [...val]); \r\n };\r\n \r\n const renderAddressItem = ( item, index ) => (\r\n \r\n \r\n );\r\n \r\n return (\r\n \r\n
\r\n \r\n \r\n \r\n {addresses.length !=0 ? addresses.map(renderAddressItem) \r\n : {t(\"account:add-address\")} }\r\n \r\n \r\n
\r\n
\r\n {showButtons &&\r\n
\r\n
\r\n
{t(\"account:add-new-address\")}
\r\n
}\r\n onClick={openNewAddress}\r\n />\r\n
\r\n \r\n
\r\n
{t(\"account:my-location\")}
\r\n
}\r\n onClick={onClickLocation}\r\n />\r\n
\r\n
}\r\n
\r\n :\r\n
}\r\n onClick={ClickAddAddress}\r\n />\r\n
\r\n
\r\n \r\n\r\n \r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Address));\r\n","import React, { useEffect } from 'react';\r\nimport { Link } from 'react-router-dom';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { inject, observer } from \"mobx-react\";\r\n\r\nconst HistoryComponent = ({date, list, total, onClick, status, orderNumber, feathersStore})=> {\r\n \r\n const { t, i18n } = useTranslation('common');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n const renderListItems = list.map((item, index)=> {\r\n return(\r\n \r\n \r\n
\r\n
item.enabled ? onClick(item.product_id) : {}} className=\"history-object-link\">\r\n {item.title} x {item.quantity}
\r\n \r\n
{item.totalPrice}€
\r\n
\r\n )\r\n })\r\n\r\n return (\r\n \r\n
\r\n
{t(\"common:order\")} #{orderNumber} {date}
\r\n
\r\n
\r\n
{t(\"common:product\")}
\r\n
{t(\"common:sub-total\")}
\r\n
\r\n
\r\n {renderListItems}\r\n
\r\n
\r\n
{t(\"common:total\")}:
\r\n
{total}€
\r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(HistoryComponent));","import React, { useEffect, useState } from 'react'\r\nimport HistoryComponent from '../cards/historyComponent';\r\nimport { useHistory } from 'react-router-dom';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useTranslation } from 'react-i18next';\r\n\r\n\r\nconst History = ({ feathersStore })=> {\r\n\r\n const { t, i18n } = useTranslation('account');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n \r\n const history = useHistory();\r\n\r\n const [orders, setOrders] = useState(null);\r\n \r\n useEffect (() => {\r\n initOrders();\r\n }, []);\r\n\r\n const initOrders = async() => {\r\n let orders = await feathersStore.ordersPerUser(); \r\n setOrders(orders);\r\n } \r\n\r\n const goToProduct = product_id => { \r\n \r\n feathersStore.getProduct(product_id).then(prod => { \r\n prod && history.push({\r\n pathname: `/product/${prod._id}`,\r\n payload: prod\r\n });\r\n }); \r\n }\r\n\r\n const renderItem = orders?.map(item=> \r\n \r\n )\r\n\r\n return(\r\n \r\n
\r\n {orders?.length === 0 ?
{t(\"account:history-placeholder\")} : renderItem}\r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(History));","import React, { useEffect } from 'react';\r\nimport GreenSubmitButton from '../buttons/greenSubmitButton';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { inject, observer } from \"mobx-react\";\r\n\r\nconst LogoutComponent = ({onClickNo, deleteItem, loading, feathersStore})=> { \r\n \r\n const { t, i18n } = useTranslation('common');\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language);\r\n },[feathersStore.language]);\r\n\r\n return (\r\n \r\n
{t(\"common:warning\")} \r\n
{t(\"common:logout-warning\")}
\r\n
\r\n \r\n
| \r\n \r\n \r\n
\r\n );\r\n}\r\n\r\nexport default inject('feathersStore')(observer(LogoutComponent));","import React, {useState, useEffect, useRef} from 'react';\r\nimport ListAltIcon from '@material-ui/icons/ListAlt';\r\nimport InfoIcon from '@material-ui/icons/Info';\r\nimport ExitToAppIcon from '@material-ui/icons/ExitToApp';\r\nimport CloseIcon from '@material-ui/icons/Close';\r\nimport ExpandMore from '@material-ui/icons/ExpandMore'\r\nimport TermsNConditions from '../screenComponents/termsnconditions'\r\nimport About from '../screenComponents/about';\r\nimport LogoutComponent from './logoutComponent';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport { useHistory } from \"react-router-dom\";\r\nimport { CSSTransition } from 'react-transition-group';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { DEFAULT_EMAIL, DEFAULT_PSW } from \"../assets/globalConstants\";\r\n\r\nconst Settings = ({ feathersStore })=> {\r\n\r\n const { t, i18n } = useTranslation('common');\r\n\r\n const [termsVisible, setTermsVisible] = useState(false);\r\n const [aboutVisible, setAboutVisible] = useState(false);\r\n const [logoutVisible, setLogoutVisible] = useState(false);\r\n const [loading, setLoading] = useState(false);\r\n\r\n const isMountedRef = useRef(null);\r\n\r\n const history = useHistory();\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n useEffect(() => {\r\n isMountedRef.current = true; \r\n // setAddresses() \r\n return () => isMountedRef.current = false;\r\n }, [])\r\n\r\n const toggleTerms = () => {\r\n setTermsVisible(!termsVisible);\r\n }\r\n\r\n const toggleAbout = () => {\r\n setAboutVisible(!aboutVisible);\r\n }\r\n\r\n const toggleLogout = () => {\r\n setLogoutVisible(!logoutVisible);\r\n }\r\n\r\n const logout = async()=> {\r\n isMountedRef.current && setLoading(true);\r\n try{\r\n await feathersStore.logout(); \r\n feathersStore.login(DEFAULT_EMAIL, DEFAULT_PSW)\r\n .then(async(auth) => { \r\n history.push('/') ; \r\n await feathersStore.setObservables(); \r\n })\r\n isMountedRef.current && setLoading(false);\r\n }catch{\r\n console.log('ERROR LOGGING OUT');\r\n isMountedRef.current && setLoading(false);\r\n } \r\n } \r\n\r\n return(\r\n\r\n \r\n
\r\n
\r\n \r\n
toggleTerms()} style={{color: '#333', cursor: 'pointer'}}>{t(\"common:terms-of-service-noun\")} \r\n \r\n {termsVisible ? \r\n
toggleTerms()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n :\r\n
toggleTerms()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n }\r\n
\r\n
\r\n \r\n \r\n {/*
\r\n
\r\n \r\n
toggleAbout()} style={{color: '333', cursor: 'pointer'}}>{t(\"common:about-us\")} \r\n \r\n {aboutVisible ? \r\n
toggleAbout()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n :\r\n
toggleAbout()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n }\r\n
*/}\r\n
\r\n {/* */}\r\n \r\n
\r\n
\r\n \r\n
toggleLogout()} style={{color: '333', cursor: 'pointer'}}>{t(\"common:logout\")} \r\n \r\n {logoutVisible ? \r\n
toggleLogout()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n :\r\n
toggleLogout()} style={{border: 'none', outline: 'none'}}>\r\n \r\n \r\n }\r\n
\r\n
\r\n \r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Settings));","import React, {useState, useEffect} from 'react';\r\nimport PageTitle from '../../components/screenComponents/pageTitle'\r\nimport AccountBox from '@material-ui/icons/AccountBox'\r\nimport HistoryIcon from '@material-ui/icons/History';\r\nimport SettingsIcon from '@material-ui/icons/Settings';\r\nimport LocationOnIcon from '@material-ui/icons/LocationOn';\r\nimport ProfileSettings from '../../components/screenComponents/profileSettings'\r\nimport Address from '../../components/screenComponents/address';\r\nimport History from '../../components/screenComponents/history';\r\nimport Settings from '../../components/screenComponents/settings';\r\nimport \"./Account.css\";\r\nimport { useTranslation } from 'react-i18next';\r\nimport { inject, observer } from \"mobx-react\";\r\n\r\nconst Account = ({ feathersStore })=> {\r\n\r\n const { t, i18n } = useTranslation('account');\r\n\r\n const [profile, setProfile] = useState(true);\r\n const [visibleAddress, setVisibleAddress] = useState(false);\r\n const [history, setHistory] = useState(false);\r\n const [settings, setSettings] = useState(false);\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language);\r\n },[feathersStore.language]);\r\n\r\n const profileClicked = () => {\r\n setProfile(true)\r\n setVisibleAddress(false)\r\n setHistory(false)\r\n setSettings(false)\r\n }\r\n \r\n const addressesClicked = () => {\r\n setProfile(false)\r\n setVisibleAddress(true);\r\n setHistory(false)\r\n setSettings(false)\r\n }\r\n\r\n const historyClicked = () => {\r\n setProfile(false)\r\n setVisibleAddress(false)\r\n setHistory(true)\r\n setSettings(false)\r\n }\r\n\r\n const settingsClicked = () => {\r\n setProfile(false)\r\n setVisibleAddress(false)\r\n setHistory(false)\r\n setSettings(true)\r\n }\r\n\r\n\r\n const handleMenuSelection = () => {\r\n\r\n if(profile) {\r\n\r\n return \r\n\r\n } else if(history){\r\n\r\n return \r\n\r\n } else if(visibleAddress){\r\n\r\n return \r\n \r\n } else if(settings){\r\n\r\n return \r\n }\r\n }\r\n\r\n return(\r\n <>\r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n {t(\"account:profile\")} \r\n \r\n
\r\n
\r\n \r\n \r\n {t(\"account:addresses\")} \r\n \r\n
\r\n
\r\n \r\n \r\n {t(\"account:history\")} \r\n \r\n
\r\n
\r\n \r\n \r\n {t(\"account:settings\")} \r\n \r\n
\r\n
\r\n
\r\n {handleMenuSelection()}\r\n
\r\n
\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Account));","import React from 'react'\r\nimport { Route, Switch, Redirect } from \"react-router-dom\"\r\nimport HomeBody from './homeBody/HomeBody';\r\nimport TermsNConditions from '../screenComponents/termsnconditions';\r\nimport About from '../screenComponents/about';\r\nimport WishList from './wishList';\r\nimport PrivacyPolicy from '../screenComponents/privacypolicy';\r\nimport Contact from '../../screens/contact/Contact'\r\nimport Cart from '../../screens/cart/Cart'\r\nimport Product from '../../screens/product/Product';\r\nimport Checkout from '../../screens/checkout/Checkout'\r\nimport Account from '../../screens/account/Account';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport ListProducts from './listProducts';\r\n\r\nconst Body = ({ feathersStore })=> {\r\n \r\nconst PrivateRoute: React.FC<{\r\n component: React.FC;\r\n path: string;\r\n exact: boolean;\r\n}> = (props) => {\r\n\r\nreturn feathersStore.isAuthenticated && feathersStore.user?.firstname !== \"default\" ? \r\n ( ) : \r\n ( );\r\n};\r\n\r\n return(\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Body));","import React, { useEffect, useState } from 'react'\r\nimport FacebookIcon from '@material-ui/icons/Facebook';\r\nimport InstagramIcon from '@material-ui/icons/Instagram';\r\nimport YouTubeIcon from '@material-ui/icons/YouTube';\r\nimport TwitterIcon from '@material-ui/icons/Twitter';\r\nimport \"./Footer.css\";\r\nimport { useTranslation } from 'react-i18next';\r\nimport { inject, observer } from \"mobx-react\";\r\nimport {Link} from 'react-router-dom';\r\n\r\nconst Footer = ({ feathersStore })=> {\r\n\r\n const { t, i18n } = useTranslation('footer');\r\n\r\n const [facebookUrl, setFacebookUrl] = useState(\"\");\r\n const [instagramUrl, setInstagramUrl] = useState(\"\");\r\n const [youtubeUrl, setYoutubeUrl] = useState(\"\");\r\n const [twitterUrl, setTwitterUrl] = useState(\"\");\r\n \r\n useEffect(() => {\r\n setFacebookUrl(feathersStore.settings?.facebookUrl);\r\n setInstagramUrl(feathersStore.settings?.instagramUrl);\r\n setYoutubeUrl(feathersStore.settings?.youtubeUrl);\r\n setTwitterUrl(feathersStore.settings?.twitterUrl);\r\n },[feathersStore.settings])\r\n\r\n useEffect(()=> {\r\n i18n.changeLanguage(feathersStore.language); \r\n },[feathersStore.language]);\r\n\r\n return (\r\n <>\r\n \r\n
\r\n
\r\n
\r\n
{t(\"footer:follow-me\")} \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n {t(\"footer:cv\")}\r\n {t(\"footer:contact-us\")}\r\n {t(\"footer:privacy-policy\")}\r\n {t(\"footer:terms-of-service\")}\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n >\r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Footer));","import React from 'react';\r\nimport Modal from 'react-awesome-modal';\r\nimport Button from '@material-ui/core/Button';\r\nimport { createMuiTheme, makeStyles } from '@material-ui/core/styles';\r\nimport { green, red } from '@material-ui/core/colors';\r\nimport AppColors from '../assets/colors'\r\n\r\n\r\nconst OverStockWarning = ({visible, onClick})=> {\r\n const useStyles = makeStyles((theme) => ({\r\n margin: {\r\n margin: theme.spacing(1),\r\n },\r\n }));\r\n \r\n const theme = createMuiTheme({\r\n palette: {\r\n primary: red,\r\n secondary: green,\r\n },\r\n });\r\n const classes = useStyles();\r\n \r\n return (\r\n \r\n \r\n \r\n
\r\n
Προσοχή!
\r\n
Δεν μπορείτε να προσθέσετε περισσότερα τεμμάχια στο καλάθι σας από το απόθεμα!
\r\n
\r\n
\r\n OK \r\n
\r\n
\r\n \r\n \r\n );\r\n}\r\n\r\nexport default OverStockWarning;","import React, {useState, useEffect} from 'react'\r\n//import TopBar from '../../components/screenComponents/topBar/TopBar';C\r\nimport TopBar from '../../components/screenComponents/topBarBootstrap/TopBarBootstrap';\r\nimport CategoriesBar from '../../components/screenComponents/categoriesBar/CategoriesBar';\r\nimport Body from '../../components/screenComponents/body'\r\nimport Footer from '../../components/screenComponents/footer/Footer'\r\nimport RegistrationCard from '../../components/modals/registrationCard'\r\nimport Prompt from '../../components/modals/prompt'\r\nimport ResetPassword from '../../components/modals/resetPassword'\r\nimport VerificationCode from '../../components/modals/verificationCode'\r\nimport ConfirmExitModal from '../../components/modals/confirmExitModal'\r\nimport OverStockWarning from '../../components/modals/overStockWarning'\r\nimport { inject, observer } from \"mobx-react\";\r\nimport \"./Home.css\";\r\n\r\nconst Home = ({feathersStore})=> {\r\n \r\n const status = localStorage.getItem(\"LogedIn\")\r\n const LogedIn = JSON.parse(status)\r\n\r\n const OverStock = localStorage.getItem(\"Warning\")\r\n const ErrorWarning = JSON.parse(OverStock)\r\n\r\n const [warning, setWarning] = useState(ErrorWarning)\r\n useEffect(()=> {\r\n setWarning(ErrorWarning)\r\n },[OverStock])\r\n\r\n useEffect(() => {\r\n const cart = localStorage.getItem('fdwa_cart');\r\n cart && feathersStore\r\n .setCartLength(JSON.parse(localStorage.getItem('fdwa_cart')).length);\r\n }, [])\r\n\r\n const [visible, setModal] = useState(false);\r\n const [visibleRegister, setRegistrationModal] = useState(false);\r\n const [visibleVerification, setVisibleVerification] = useState(false);\r\n const [payload, setPayload] = useState({}); \r\n const [resetPasswordModal, setResetPasswordModal] = useState(false)\r\n const [exit, setExit] = useState(false);\r\n\r\n const handleModal = ()=> {\r\n if(LogedIn === null || LogedIn === false){\r\n setModal(!visible);\r\n }else{\r\n setExit(true)\r\n } \r\n }\r\n\r\n const openRegistrationModal = ()=> {\r\n setModal(false);\r\n setRegistrationModal(true);\r\n }\r\n\r\n const closeRegistrationModal = ()=> {\r\n setRegistrationModal(false);\r\n }\r\n\r\n const SubmitReset = ()=> {\r\n setResetPasswordModal(!resetPasswordModal);\r\n }\r\n\r\n const facebookLogin = ()=> {\r\n setModal(false);\r\n localStorage.setItem(\"LogedIn\", true)\r\n localStorage.setItem(\"Role\", \"User\")\r\n }\r\n\r\n const openVerification = pload => {\r\n setRegistrationModal(false);\r\n setVisibleVerification(true);\r\n setPayload(pload);\r\n }\r\n \r\n const closeVerification = ()=> {\r\n setVisibleVerification(false);\r\n localStorage.setItem(\"LogedIn\", true)\r\n localStorage.setItem(\"Role\", \"User\")\r\n }\r\n\r\n const Logout = ()=> {\r\n localStorage.setItem(\"LogedIn\", false)\r\n setExit(!exit);\r\n window.location.reload(false);\r\n }\r\n\r\n const NoLogout = ()=> {\r\n setExit(!exit);\r\n }\r\n\r\n const closeWarning = ()=> {\r\n localStorage.setItem(\"Warning\", false)\r\n setWarning(false)\r\n }\r\n\r\n const clickEnter = ()=> {\r\n localStorage.setItem(\"Role\", \"Admin\")\r\n localStorage.setItem(\"LogedIn\", true)\r\n setModal(false)\r\n }\r\n \r\n return(\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
handleModal()}/>\r\n \r\n \r\n
\r\n
\r\n \r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Home));","import React, { useEffect, Fragment } from 'react';\r\nimport { useHistory } from 'react-router-dom';\r\n\r\nfunction ScrollToTop({ children }) {\r\n\r\n const history = useHistory();\r\n\r\n useEffect(() => {\r\n const unlisten = history.listen(() => {\r\n window.scrollTo(0, 0);\r\n });\r\n return () => {\r\n unlisten();\r\n }\r\n }, []);\r\n\r\n return {children} ;\r\n}\r\n\r\nexport default ScrollToTop;","import React from 'react'\r\nimport {Link} from 'react-router-dom'\r\n\r\nconst AdministrativeDashboard = ()=> {\r\n\r\n return(\r\n \r\n
Dashboard \r\n
\r\n
Back
\r\n \r\n
\r\n \r\n )\r\n}\r\n\r\nexport default AdministrativeDashboard;","import React, {useEffect} from 'react';\r\nimport { BrowserRouter as Router, Route, Switch } from 'react-router-dom'\r\nimport Home from './home/Home'\r\nimport ScrollToTop from '../components/screenComponents/scrollToTop'\r\nimport HomeBody from '../components/screenComponents/homeBody/HomeBody';\r\nimport AdministrativeDashboard from './administrativeDashboard';\r\nimport { inject, observer } from \"mobx-react\";\r\n\r\n\r\nconst Main = ({feathersStore})=> {\r\n\r\n const defaultEmail = \"defaultUser@gmail.com\";\r\n const defaultPassword = \")j~nKj/,N}N6,8&cVVV#G!=F*y\";\r\n\r\n useEffect(() => {\r\n connectToServer();\r\n createPaymentMethodLS(); \r\n }, []);\r\n\r\n const connectToServer = async() => {\r\n await feathersStore.connect(); \r\n if(!feathersStore.isAuthenticated)feathersStore.login(defaultEmail, defaultPassword)\r\n .then(async(auth) => { \r\n await feathersStore.setObservables(); \r\n })\r\n .catch(error => window.alert(`Λανθασμένο login: ${error.message}`)); \r\n }\r\n\r\n const createPaymentMethodLS = () => {\r\n !localStorage.getItem('Payment_Method') && \r\n localStorage.setItem('Payment_Method',JSON.stringify({\r\n name: 'Μετρητά κατά την παράδοση',\r\n index: 0\r\n }))\r\n }\r\n\r\n return(\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n }/>\r\n \r\n \r\n \r\n \r\n )\r\n}\r\n\r\nexport default inject('feathersStore')(observer(Main));","import { makeObservable, observable, action} from 'mobx';\r\n//import rx from 'feathers-reactive/dist/feathers-reactive';\r\nimport rx from 'feathers-reactive';\r\nimport io from 'socket.io-client'; \r\nimport feathers from '@feathersjs/feathers';\r\n//import feathersSocketIOClient from '@feathersjs/socketio-client';\r\nimport socketio from '@feathersjs/socketio-client';\r\nimport auth from '@feathersjs/authentication-client';\r\nimport * as cloneDeep from 'lodash/cloneDeep';\r\nimport { API_URL, ADMIN_ID, DEFAULT_EMAIL, DEFAULT_PSW } from \"./components/assets/globalConstants\";\r\n\r\n\r\nclass FeathersStore{ \r\n \r\n favoritesArray = [];\r\n wishlistId = \"\";\r\n hasLocationPermission= false;\r\n isAuthenticated= false;\r\n user = null;\r\n categories = [];\r\n settings = {};\r\n cartLength = 0;\r\n goToAddressHelper = false;\r\n orderItem = {};\r\n searchCategory = {}; //active search category ; \r\n language = \"en\";\r\n productUpdatedEvent = {};\r\n productCreatedEvent = {}; \r\n \r\n constructor(){\r\n makeObservable(this, {\r\n favoritesArray: observable,\r\n wishlistId: observable,\r\n hasLocationPermission: observable,\r\n isAuthenticated: observable,\r\n user: observable,\r\n categories: observable,\r\n settings: observable,\r\n cartLength: observable,\r\n goToAddressHelper: observable,\r\n orderItem: observable, \r\n searchCategory: observable, \r\n language: observable, \r\n productUpdatedEvent: observable,\r\n productCreatedEvent: observable, \r\n setFavoritesArray: action,\r\n setWishlistId: action,\r\n setHasLocationPermission: action,\r\n setIsAuthenticated: action,\r\n setUser: action,\r\n setCategories: action,\r\n setSettings: action,\r\n setObservables: action, \r\n setGoToAddressHelper: action,\r\n setOrderItem: action,\r\n setSearchCategory: action,\r\n setLanguage: action,\r\n setProductUpdatedEvent: action,\r\n setProductCreatedEvent: action \r\n })\r\n }\r\n\r\n setProductUpdatedEvent = data => { \r\n this.productUpdatedEvent = data;\r\n }\r\n\r\n setProductCreatedEvent = data => { \r\n this.productCreatedEvent = data;\r\n }\r\n\r\n setSearchCategory = data => { \r\n this.searchCategory = data;\r\n }\r\n\r\n setOrderItem = data => {\r\n const clonedOrderItem = cloneDeep(this.orderItem);\r\n const mergedObject = {...clonedOrderItem, ...data};\r\n this.orderItem = mergedObject;\r\n }\r\n\r\n setGoToAddressHelper = value => {\r\n this.goToAddressHelper = value;\r\n }\r\n\r\n setFavoritesArray = value => {\r\n this.favoritesArray = value;\r\n }\r\n\r\n setWishlistId = value => {\r\n this.wishlistId = value;\r\n }\r\n\r\n setHasLocationPermission = value => {\r\n this.hasLocationPermission = value;\r\n }\r\n\r\n setIsAuthenticated = value => {\r\n this.isAuthenticated = value;\r\n }\r\n\r\n setUser = value => {\r\n this.user = value;\r\n }\r\n \r\n setCategories = value => {\r\n this.categories = value;\r\n }\r\n\r\n setSettings = value => {\r\n this.settings = value;\r\n }\r\n\r\n setCartLength = value => {\r\n this.cartLength = value; \r\n }\r\n\r\n setLanguage = value => {\r\n this.language = value; \r\n }\r\n \r\n connect = async () => {\r\n\r\n //ESTABLISH FEATHERS CONNECTION\r\n\r\n const options = {\r\n transports: ['websocket'],\r\n forceNew: true, \r\n pingTimeout: 3000, \r\n pingInterval: 5000 \r\n };\r\n this.app = feathers(); \r\n this.socket = io(API_URL, /* options*/ ); \r\n // this.feathersAuthClient = require('@feathersjs/authentication-client').default;\r\n\r\n\r\n this.app\r\n .configure(socketio(this.socket)) \r\n // .configure(feathers.socketio(this.socket))\r\n .configure( auth({ \r\n storage: window.localStorage // To store our accessToken\r\n }))\r\n .configure(rx({ // add feathers-reactive plugin\r\n idField: '_id'\r\n }));\r\n\r\n this.isConnecting = true;\r\n \r\n await this.setObservables();\r\n \r\n this.app.io.on('connect', async () => {\r\n this.isConnecting = false;\r\n try{ \r\n await this.setObservables();\r\n console.log('authenticated after reconnection');\r\n }catch(error) {\r\n console.log('error authenticating after reconnection', error);\r\n };\r\n });\r\n\r\n this.app.io.on('disconnect', () => {\r\n console.log('disconnected');\r\n this.isConnecting = true;\r\n });\r\n\r\n //-- Add real time functionality\r\n\r\n this.app.service('products').on('patched', async message => {\r\n this.setProductUpdatedEvent(message);\r\n const user = await this.app.service('users').get(this.user?._id); //USAGE for reviews \r\n user && this.setUser(user); \r\n });\r\n this.app.service('products').on('updated', message => this.setProductUpdatedEvent(message));\r\n this.app.service('products').on('created', message => this.setProductCreatedEvent(message));\r\n }\r\n \r\n setObservables = async() => {\r\n try{\r\n const auth = await this.app.reAuthenticate();\r\n const { user } = await this.app.get('authentication');\r\n this.setUser(user); \r\n this.user && (this.setIsAuthenticated(true)); \r\n const tree = await this.app.service('categories').get(\"5d0367d6d31be01e208545a6\"); \r\n const settingsArray = await this.app.service('settings').find({query: {}}); \r\n this.setCategories(tree.youTree); \r\n this.setSettings(settingsArray[0]); \r\n const data = await this.wishlist(); \r\n data && (this.setFavoritesArray(data[0].items)); \r\n data && (this.setWishlistId(data[0]._id)); \r\n }catch{\r\n\r\n }\r\n }\r\n\r\n getAccessToken = async() => {\r\n return await this.app.get('authentication');\r\n }\r\n \r\n login = async (email, password) => { \r\n return this.app.authenticate({\r\n strategy: 'local',\r\n email,\r\n password\r\n });\r\n };\r\n\r\n \r\n \r\n logout = async () => {\r\n await this.app.logout(); \r\n this.setUser(null);\r\n this.setIsAuthenticated(false); \r\n this.setSettings({});\r\n this.setGoToAddressHelper(false);\r\n }\r\n\r\n sendApplication = (firstname, lastname, email, password, phone) => {\r\n let payload = {\r\n email: DEFAULT_EMAIL,\r\n password: DEFAULT_PSW,\r\n strategy: 'local'\r\n }\r\n return this.app.authenticate(payload).then(() => { \r\n return new Promise(async(resolve, reject) => { \r\n try{\r\n const application = await this.app.service('applications').create({\r\n firstname, lastname, email, password, phone,\r\n processed: false\r\n });\r\n return resolve(application); \r\n }\r\n catch(error){\r\n return resolve(error);\r\n }\r\n })\r\n \r\n })\r\n }\r\n\r\n facebookAuth(access_token){\r\n return this.app.authenticate({\r\n strategy: \"facebook\",\r\n access_token\r\n })\r\n }\r\n\r\n authAndGetUser = (email) => {\r\n let payload = {\r\n email: DEFAULT_EMAIL,\r\n password: DEFAULT_PSW,\r\n strategy: 'local'\r\n }\r\n return this.app.authenticate(payload).then(() => { \r\n return new Promise(async(resolve, reject) => { \r\n try{\r\n const user = await this.app.service('users').find({\r\n query: { \r\n email\r\n }\r\n }); \r\n return resolve(user); \r\n }\r\n catch(error){\r\n return reject(error);\r\n }\r\n })\r\n })\r\n }\r\n\r\n async sendEmail(userId, email, firstname, lastname){ \r\n let random4digit = Math.floor(1000 + Math.random() * 9000);\r\n const emailToSend = {\r\n userId,\r\n applicationId: 'FORGOT_PASSWORD',\r\n random4digit,\r\n from: `${this.settings.mailgunEmail}`,\r\n to: `${email}`,\r\n subject: 'ΝΕΟ PASSWORD',\r\n html: `Αγαπητέ/ή ${firstname} ${lastname} , \r\n Το νέο password είναι: ${random4digit} . \r\n Μπορείτε να κάνετε login με το email σας και το νέο password. \r\n Κατόπιν μπορείτε να αλλάξετε το password με κάποιο δικό σας.` \r\n };\r\n try{\r\n return await this.app.service('emails').create(emailToSend); \r\n }catch(err){\r\n console.log('Could not send email FROM sendEmail method: ', err )\r\n };\r\n }\r\n\r\n async sendAgain(applicationId, firstname, lastname, email){\r\n let random4digit = Math.floor(1000 + Math.random() * 9000);\r\n const emailToSend = {\r\n applicationId: applicationId,\r\n random4digit,\r\n from: `${this.settings.mailgunEmail}`,\r\n to: `${email}`,\r\n subject: 'Επαναληπτική αποστολή 4ψήφιου κωδικού',\r\n html: `\r\n \r\n \r\n \r\n \r\n \r\n \r\n
Αποστολή 4ψήφιου κωδικού \r\n
\r\n
Αγαπητέ/ή ${firstname} ${lastname} ,
\r\n
Ο 4ψήφιος κωδικός είναι: ${random4digit} .
\r\n
\r\n
\r\n \r\n `\r\n };\r\n try{\r\n await this.app.service('emails').create(emailToSend); \r\n }catch(err){\r\n console.log('Could not send email FROM sendEmail method: ', err )\r\n };\r\n }\r\n \r\n\r\n async sendContactEmail( email, firstname, lastname, message, phone){ \r\n \r\n let htmlContent = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n
Νέο μήνυμα από το e-shop σας \r\n
\r\n
Ο χρήστης ${firstname} ${lastname} ,
\r\n
με email ${email} ${phone ? `και τηλέφωνο: ${phone}` : \"\"} ,
\r\n
έστειλε το εξής μήνυμα:
\r\n
\r\n ${message}\r\n
\r\n
\r\n
\r\n `\r\n \r\n const emailToSend = { \r\n from: `${this.settings.mailgunEmail}`,\r\n to: `${this.settings.email}`,\r\n subject: 'Μήνυμα από τη φόρμα επικοινωνίας του e-shop',\r\n html: htmlContent \r\n }; \r\n return await this.app.service('emails').create(emailToSend);\r\n }\r\n\r\n newestEmail(applicationId){ \r\n let payload = {\r\n email: DEFAULT_EMAIL,\r\n password: DEFAULT_PSW,\r\n strategy: 'local'\r\n }\r\n return this.app.authenticate(payload).then(() => { \r\n return this.app.service('emaillog') \r\n .find(\r\n {\r\n query: { \r\n applicationId: applicationId, \r\n $sort: {createdAt: -1},\r\n $limit: 1\r\n }\r\n }\r\n ); \r\n })\r\n }\r\n\r\n createUser = async(firstname, lastname, email, password, phone) => {\r\n const userData = {firstname, lastname, email, password, phone, \r\n role: 'customer',\r\n enabled: true};\r\n return await this.app.service('users').create(userData); \r\n }\r\n\r\n patchUser(userId, firstname, lastname, phone){\r\n const payload = {firstname, lastname, phone};\r\n return this.app.service('users').patch(userId, payload);\r\n }\r\n\r\n \r\n patchUserAvatar(userId, avatar){ \r\n return this.app.service('users').patch(userId, {avatar});\r\n }\r\n\r\n patchProduct(productId, payload){ \r\n return this.app.service('products').patch(productId, payload);\r\n }\r\n\r\n async patchAddresses(userId, addresses){ \r\n return await this.app.service('users').patch(userId, {addresses});\r\n }\r\n\r\n async updateApplicationToProcessed(id){\r\n return await this.app\r\n .service('applications')\r\n .patch(id, { processed: true });\r\n }\r\n\r\n async changePassword(newPassword){\r\n return await this.app.service('users')\r\n .patch(this.user._id, {password: newPassword});\r\n }\r\n\r\n getCategoriesTree(){\r\n return this.app.service('categories').get(\"5d0367d6d31be01e208545a6\");\r\n }\r\n \r\n async productsPerCategoryX(depth, categoryId, searchText = \"\"){\r\n const cat = `category${depth}.id`;\r\n let query = { \r\n name: { $regex: searchText, $options: 'i' },\r\n enabled: true,\r\n $sort: {\r\n productPriority: -1\r\n }\r\n }; \r\n query[cat]=categoryId; \r\n return await this.app.service('products') \r\n .find({\r\n query\r\n }); \r\n }\r\n \r\n async productsPerCategory(categoryId, searchText = \"\"){ \r\n let query = { \r\n name: { $regex: searchText, $options: 'i' },\r\n enabled: true , \r\n $or: [\r\n {\"category1.id\": categoryId},\r\n {\"category2.id\": categoryId},\r\n {\"category3.id\": categoryId},\r\n {\"category4.id\": categoryId},\r\n {\"category5.id\": categoryId},\r\n ],\r\n $sort: {\r\n productPriority: -1\r\n }\r\n }; \r\n \r\n return await this.app.service('products') \r\n .find({\r\n query\r\n }); \r\n }\r\n\r\n async products(searchText = \"\"){ \r\n return await this.app.service('products') \r\n .find({\r\n query: { \r\n name: { $regex: searchText, $options: 'i' },\r\n enabled: true,\r\n $sort: {\r\n productPriority: -1\r\n }\r\n }\r\n }); \r\n } \r\n\r\n async getProduct(productId){\r\n return await this.app.service('products').get(productId);\r\n }\r\n\r\n async offers(){\r\n return await this.app.service('products') \r\n .find({\r\n query: { \r\n offer: true,\r\n enabled: true \r\n }\r\n }); \r\n }\r\n\r\n createWishlist = async() => {\r\n const payload = {\r\n userId : this.user._id,\r\n items : this.favoritesArray\r\n }; \r\n return await this.app.service('wishlist').create(payload); \r\n }\r\n\r\n updateWishlist = async() => {\r\n const payload = {\r\n userId: this.user._id,\r\n items: this.favoritesArray \r\n };\r\n return await this.app.service('wishlist').update(this.wishlistId, payload); \r\n }\r\n\r\n async wishlist(){\r\n return await this.app.service('wishlist') \r\n .find({\r\n query: { \r\n userId: this.user._id, \r\n }\r\n }); \r\n }\r\n\r\n async wishlistProducts(){ \r\n return await this.app.service('products') \r\n .find({\r\n query: { \r\n _id: {\r\n $in: [...this.favoritesArray] \r\n },\r\n enabled: true\r\n }\r\n }); \r\n }\r\n\r\n createOrder = async(payload) => { \r\n return await this.app.service('orders').create(payload); \r\n }\r\n\r\n ordersPerUser = async() => {\r\n return await this.app?.service('orders') \r\n .find({\r\n query: { \r\n customerId: this.user._id, \r\n }\r\n });\r\n }\r\n\r\n async popularProducts(){ \r\n return await this.app.service('popular') \r\n .find(); \r\n }\r\n \r\n getSettings = async() => {\r\n return await this.app.service('settings') \r\n .find({\r\n query: { \r\n adminId: ADMIN_ID \r\n }\r\n });\r\n }\r\n\r\n}\r\n\r\nexport default new FeathersStore()","import React from 'react';\r\nimport '../src/styles/style.css'\r\nimport Main from '../src/screens/main'\r\nimport feathersStore from './feathersStore';\r\nimport { Provider } from 'mobx-react';\r\nimport 'fontsource-roboto';\r\nimport 'bootstrap/dist/css/bootstrap.min.css';\r\n\r\nfunction App() {\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n >\r\n );\r\n}\r\n\r\nexport default App;\r\n","import i18n from 'i18next';\r\nimport { initReactI18next } from 'react-i18next';\r\n\r\nimport Backend from 'i18next-http-backend';\r\nimport LanguageDetector from 'i18next-browser-languagedetector';\r\n// don't want to use this?\r\n// have a look at the Quick start guide \r\n// for passing in lng and translations on init\r\n\r\ni18n\r\n // load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)\r\n // learn more: https://github.com/i18next/i18next-http-backend\r\n .use(Backend)\r\n // detect user language\r\n // learn more: https://github.com/i18next/i18next-browser-languageDetector\r\n .use(LanguageDetector)\r\n // pass the i18n instance to react-i18next.\r\n .use(initReactI18next)\r\n // init i18next\r\n // for all options read: https://www.i18next.com/overview/configuration-options\r\n .init({\r\n lng: \"el\",\r\n fallbackLng: 'en',\r\n //debug: true,\r\n // react i18next special options (optional)\r\n react: {\r\n useSuspense: false,\r\n wait: false,\r\n },\r\n });\r\n\r\n\r\nexport default i18n;","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport App from './App';\r\nimport './i18n';\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);\r\n"],"sourceRoot":""}