Parcourir la source

Finished refactoring

pull/4/head
Djordje Mitrovic il y a 3 ans
Parent
révision
a3c2b584ae

+ 0
- 3
src/AppRoutes.js Voir le fichier

@@ -12,7 +12,6 @@ import {
REGISTER_PAGE,
REGISTER_SUCCESSFUL_PAGE,
RESET_PASSWORD_PAGE,
CREATE_OFFER_PAGE,
} from './constants/pages';
import LoginPage from './pages/LoginPage/LoginPage';
import HomePage from './pages/HomePage/HomePageMUI';
@@ -24,7 +23,6 @@ import MailSent from './pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent
import Register from './pages/RegisterPages/Register/Register';
import RegisterSuccessful from './pages/RegisterPages/RegisterSuccessful.js/RegisterSuccessful';
import ResetPasswordPage from './pages/ResetPasswordPage/ResetPasswordPage';
import CreateOffer from './pages/CreateOffer/CreateOffer';


const AppRoutes = () => {
@@ -39,7 +37,6 @@ const AppRoutes = () => {
<Route path={FORGOT_PASSWORD_MAIL_SENT} component={MailSent} />
<Route path={FORGOT_PASSWORD_PAGE} component={ForgotPasswordPage} />
<Route path={RESET_PASSWORD_PAGE} component={ResetPasswordPage}/>
<Route path={CREATE_OFFER_PAGE} component={CreateOffer}/>
<PrivateRoute
exact

+ 1
- 0
src/i18n/resources/rs.js Voir le fichier

@@ -88,6 +88,7 @@ export default {
terms: "Uslove Korišćenja",
success: 'Registracija Uspešna',
PIBTaken: "PIB je zauzet!",
PIBnoOfCharacters: "PIB mora imati 9 karaktera!",
welcome: 'Dobro došli na trampu, želimo vam uspešno trampovanje!',
},
forgotPassword: {

+ 3
- 0
src/initialValues/forgotPasswordInitialValues.js Voir le fichier

@@ -0,0 +1,3 @@
export default {
email: "",
};

+ 4
- 0
src/initialValues/loginInitialValues.js Voir le fichier

@@ -0,0 +1,4 @@
export default {
email: "",
password: "",
};

+ 4
- 0
src/initialValues/registerInitialValues/firstPartInitialValues.js Voir le fichier

@@ -0,0 +1,4 @@
export default {
mail: "",
password: "",
};

+ 4
- 0
src/initialValues/registerInitialValues/secondPartInitialValues.js Voir le fichier

@@ -0,0 +1,4 @@
export default {
nameOfFirm: "",
PIB: "",
};

+ 5
- 0
src/initialValues/registerInitialValues/thirdPartInitialValues.js Voir le fichier

@@ -0,0 +1,5 @@
export default {
phoneNumber: "",
location: "",
website: "",
};

+ 4
- 0
src/initialValues/resetPasswordInitialValues.js Voir le fichier

@@ -0,0 +1,4 @@
export default {
password: "",
passwordConfirm: "",
};

+ 0
- 26
src/pages/CreateOffer/CreateOffer.js Voir le fichier

@@ -1,26 +0,0 @@
/* eslint-disable */
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import {
CreateOfferContainer,
} from "./CreateOffer.styled";
import CreateOffer from "../../components/Cards/CreateOfferCard/CreateOffer";

const CreateOfferPage = ({ history }) => {
return (
<CreateOfferContainer>
<CreateOffer/>
</CreateOfferContainer>
);
};

CreateOfferPage.propTypes = {
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
};
export default CreateOfferPage;

+ 0
- 56
src/pages/CreateOffer/CreateOffer.styled.js Voir le fichier

@@ -1,56 +0,0 @@
import { Box, Container, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../themes";

export const CreateOfferContainer = styled(Container)`
margin-top: 0px;
display: flex;
width: 380px;
flex-direction: column;
align-items: center;
`;
export const CreateOfferTitle = styled(Typography)`
font-family: "Open Sans";
width: 328px;
height: 33px;
text-align: center;
flex: 1;
font-style: normal;
font-weight: 700;
font-size: 24px;
line-height: 33px;
color: ${selectedTheme.primaryPurple};
margin-top: 36px;
margin-bottom: 40px;
`;
export const CreateOfferDescription = styled(Typography)`
font-family: "Open Sans";
margin-top: 9px;
width: 221px;
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 22px;
display: flex;
align-items: center;
text-align: center;
color: ${selectedTheme.primaryGrayText};
margin-bottom: 20px;
`;
export const CreateOfferFormContainer = styled(Box)`
width: 335px;
height: 216px;
`;
export const RegisterAltText = styled(Typography)`
font-family: "Poppins";
color: ${selectedTheme.primaryText};
font-size: 14px;
padding-right: 6px;
line-height: 14px;
`
export const RegisterTextContainer = styled(Box)`
display: flex;
flex-direction: row;
margin-top: 36px;
justify-content: center;
`

+ 4
- 63
src/pages/HomePage/HomePageMUI.js Voir le fichier

@@ -1,70 +1,11 @@
import React, { useEffect } from "react";
import Navbar from "../../components/MUI/NavbarComponent";
// import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import { HomePageContainer } from "./HomePage.styled";
// import MarketPlace from "../../components/MarketPlace/MarketPlace";
// import MainLayout from "../../layouts/MainLayout/MainLayout";
import { useDispatch } from "react-redux";
// import { logoutUser } from "../../store/actions/login/loginActions";
import Mockupdata from "../../components/Cards/FilterCard/Mockupdata";
import qs from "query-string";
import { useHistory } from "react-router-dom";
import { setFilters } from "../../store/actions/filters/filtersActions";
// import ProfileLayout from "../../layouts/ProfileLayout/ProfileLayout";
import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import MainLayout from "../../layouts/MainLayout/MainLayout";
import MarketPlace from "../../components/MarketPlace/MarketPlace";
import React from "react";

const HomePage = () => {
const dispatch = useDispatch();

const history = useHistory();
useEffect(() => {
let category = null, subcategory = null, cities = [], _des_date = false, _des_popular = false, page, size;
const queryString = history.location.search.substring(1);
const queryObject = qs.parse(queryString);

if (queryObject.category) {
category = Mockupdata[1].find(
(item) => item.string === queryObject.category.toString()
).id;
}
if (queryObject.subcategory) {
subcategory = Mockupdata[1].find(
(item) => item.string === queryObject.subcategory.toString()
).id;
}
if (queryObject.city) {
if (Array.isArray(queryObject.city)) {
queryObject.city.forEach((item) => {
cities.push(Mockupdata[0].find((p) => p.string === item).id);
});
} else {
cities.push(
Mockupdata[0].find((p) => p.string === queryObject.city).id
);
}
}
if (queryObject.sortBy) {
if (queryObject.sortBy === "dateAsc") _des_date = false;
if (queryObject.sortBy === "dateDesc") _des_date = true;
if (queryObject.sortBy === "popular") _des_popular = true;
}
if (queryObject.page) {
page = queryObject.page;
}
if (queryObject.size) {
size = queryObject.size;
}

dispatch(setFilters({ category, subcategory, cities, _des_date, _des_popular, page, size }));
}, [history.location.search]);

return (
<HomePageContainer>
<Navbar />
<MainLayout leftCard={<FilterCard />} content={<MarketPlace />} />
</HomePageContainer>
<div>
Home page
</div>
);
};


+ 4
- 10
src/pages/LoginPage/LoginPage.js Voir le fichier

@@ -32,6 +32,8 @@ import {
ErrorMessage,
} from "./Login.styled";
import selectedTheme from "../../themes";
import loginValidation from "../../validations/loginValidation";
import loginInitialValues from "../../initialValues/loginInitialValues";

const LoginPage = ({ history }) => {
const dispatch = useDispatch();
@@ -83,16 +85,8 @@ const LoginPage = ({ history }) => {
};

const formik = useFormik({
initialValues: {
email: "",
password: "",
},
validationSchema: Yup.object().shape({
email: Yup.string().required(t("login.mailRequired")),
password: Yup.string()
.required(t("login.passwordRequired"))
.min(8, t("login.passwordLength")),
}),
initialValues: loginInitialValues,
validationSchema: loginValidation,
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,

+ 0
- 250
src/pages/LoginPage/LoginPageMUI.js Voir le fichier

@@ -1,250 +0,0 @@
/* eslint-disable */
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { useFormik } from "formik";
import { useDispatch, useSelector } from "react-redux";
import { NavLink } from "react-router-dom";
import * as Yup from "yup";
import { useTranslation } from "react-i18next";
import i18next from "i18next";
import {
clearLoginErrors,
fetchUser,
} from "../../store/actions/login/loginActions";
import { selectLoginError } from "../../store/selectors/loginSelectors";
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages";
import {
Box,
Button,
Container,
Grid,
InputAdornment,
Link,
Typography,
} from "@mui/material";
import {
LocationOn,
LocationOnOutlined,
Visibility,
VisibilityOff,
} from "@mui/icons-material";
import Backdrop from "../../components/MUI/BackdropComponent";
import ErrorMessage from "../../components/MUI/ErrorMessageComponent";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { LOGIN_USER_LOADING } from "../../store/actions/login/loginActionConstants";
import { TextField } from "../../components/TextFields/TextField/TextField";
import { PrimaryButton } from "../../components/Buttons/PrimaryButton/PrimaryButton";
import { IconButton } from "../../components/Buttons/IconButton/IconButton";
import { Icon } from "../../components/Icon/Icon";
import PrimaryButtonWithIcon from "../../components/Buttons/PrimaryButtonWithIcon/PrimaryButtonWithIcon";
import TextFieldWithIcon from "../../components/TextFields/TextFieldWithIcon/TextFieldWithIcon";
import DropdownList from "../../components/Dropdown/DropdownList/DropdownList";
import DropdownItem from "../../components/Dropdown/DropdownItem/DropdownItem";
import { CheckBox } from "../../components/CheckBox/CheckBox";
import selectedTheme from "../../themes";

const LoginPage = ({ history }) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const error = useSelector(selectLoginError);

const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);

// When user refreshes page
// useEffect(() => {
// function redirectClient() {
// if (!tokens.RefreshToken && !tokens.JwtToken) {
// return;
// }
// }

// redirectClient();
// }, [history, tokens]);

const isLoading = useSelector(
selectIsLoadingByActionType(LOGIN_USER_LOADING)
);

const handleApiResponseSuccess = () => {
history.push({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};

const handleSubmit = (values) => {
const { username: Username, password: Password } = values;
dispatch(clearLoginErrors());
dispatch(
fetchUser({
Username,
Password,
handleApiResponseSuccess,
})
);
};

const formik = useFormik({
initialValues: {
username: "",
password: "",
},
validationSchema: Yup.object().shape({
username: Yup.string().required(t("login.usernameRequired")),
password: Yup.string().required(t("login.passwordRequired")),
}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

return (
<Container component="main" maxWidth="md">
<Box
sx={{
marginTop: 32,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Typography component="h1" variant="h5">
{t("login.logInTitle")}
</Typography>
{error && <ErrorMessage error={error} />}
<Box
component="form"
onSubmit={formik.handleSubmit}
sx={{ position: "relative", mt: 1, p: 1 }}
>
<Backdrop position="absolute" isLoading={isLoading} />
<TextField
name="username"
placeholder={t("common.labelUsername")}
margin="normal"
value={formik.values.username}
onChange={formik.handleChange}
error={formik.touched.username && Boolean(formik.errors.username)}
helperText={formik.touched.username && formik.errors.username}
autoFocus
fullWidth
/>
<TextField
name="password"
placeholder={t("common.labelPassword")}
margin="normal"
type={showPassword ? "text" : "password"}
value={formik.values.password}
onChange={formik.handleChange}
error={formik.touched.password && Boolean(formik.errors.password)}
helperText={formik.touched.password && formik.errors.password}
fullWidth
InputProps={{
endAdornment: (
<IconButton
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
),
}}
/>

<DropdownList
title="Naslov"
toggleIconOpened={<Visibility />}
toggleIconClosed={<VisibilityOff />}
dropdownIcon={<LocationOnOutlined />}
fullWidth
defaultOpen={false}
>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
<DropdownItem>
<CheckBox fullWidth leftText="Kategorija" rightText="124" />
</DropdownItem>
</DropdownList>

<PrimaryButtonWithIcon
icon={<Visibility />}
sx={{ mt: 3, mb: 2 }}
buttonProps={{
type: "submit",
variant: "contained",
height: "40px",
fullWidth: true,
buttoncolor: selectedTheme.primaryPurple,
textcolor: "white",
}}
>
{t("login.logIn")}
</PrimaryButtonWithIcon>
<Grid container>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: "center", md: "left" } }}
>
<Link
to={FORGOT_PASSWORD_PAGE}
component={NavLink}
variant="body2"
underline="hover"
>
{t("login.forgotYourPassword")}
</Link>
</Grid>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: "center", md: "right" } }}
>
<Link
to="#"
component={NavLink}
variant="body2"
underline="hover"
>
{t("login.dontHaveAccount")}
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
);
};

LoginPage.propTypes = {
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
};
export default LoginPage;

+ 5
- 7
src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.js Voir le fichier

@@ -68,12 +68,6 @@ const FirstPartOfRegistration = (props) => {
fullWidth
/>

{formik.errors.mail && formik.touched.mail ? (
<ErrorMessage>{formik.errors.mail}</ErrorMessage>
) : (
<></>
)}

<TextField
name="password"
placeholder={t("common.labelPassword")}
@@ -94,11 +88,15 @@ const FirstPartOfRegistration = (props) => {
),
}}
/>
{formik.errors.password && formik.touched.password ? (

{formik.errors.mail && formik.touched.mail ? (
<ErrorMessage>{formik.errors.mail}</ErrorMessage>
) : formik.errors.password && formik.touched.password ? (
<ErrorMessage>{formik.errors.password}</ErrorMessage>
) : (
<></>
)}
{props.error && <ErrorMessage>{props.errorMessage}</ErrorMessage>}

<PrimaryButton

+ 0
- 4
src/store/reducers/index.js Voir le fichier

@@ -6,8 +6,6 @@ import randomDataReducer from "./randomData/randomDataReducer";
import storage from "redux-persist/lib/storage";
import createFilter from "redux-persist-transform-filter";
import persistReducer from "redux-persist/es/persistReducer";
import filtersReducer from "./filters/filtersReducer";
import offersReducer from "./offers/offersReducer";

const loginPersistConfig = {
key: "login",
@@ -41,7 +39,5 @@ export default combineReducers({
login: persistReducer(loginPersistConfig, loginReducer),
user: persistReducer(userPersistConfig, userReducer),
loading: loadingReducer,
filters: filtersReducer,
randomData: persistReducer(randomDataPersistConfig, randomDataReducer),
offers: offersReducer
});

+ 0
- 2
src/store/saga/index.js Voir le fichier

@@ -1,7 +1,6 @@
import { all } from 'redux-saga/effects';
import forgotPasswordSaga from './forgotPasswordSaga';
import loginSaga from './loginSaga';
import offersSaga from './offersSaga';
import registerSaga from './registerSaga';

export default function* rootSaga() {
@@ -9,6 +8,5 @@ export default function* rootSaga() {
loginSaga(),
registerSaga(),
forgotPasswordSaga(),
offersSaga()
]);
}

+ 8
- 0
src/validations/forgotPasswordValidation.js Voir le fichier

@@ -0,0 +1,8 @@
import * as Yup from "yup";
import i18n from "../i18n";

export default Yup.object().shape({
email: Yup.string()
.required(i18n.t("forgotPassword.emailRequired"))
.email(i18n.t("forgotPassword.emailFormat")),
});

+ 9
- 0
src/validations/loginValidation.js Voir le fichier

@@ -0,0 +1,9 @@
import * as Yup from "yup";
import i18n from "../i18n";

export default Yup.object().shape({
email: Yup.string().email(i18n.t("login.emailFormat")).required(i18n.t("login.mailRequired")),
password: Yup.string()
.required(i18n.t("login.passwordRequired"))
.min(8, i18n.t("login.passwordLength")),
});

+ 10
- 0
src/validations/registerValidations/firstPartValidation.js Voir le fichier

@@ -0,0 +1,10 @@
import * as Yup from "yup";
import i18n from "../../i18n";
export default Yup.object().shape({
mail: Yup.string()
.email(i18n.t("forgotPassword.emailFormat"))
.required(i18n.t("login.usernameRequired")),
password: Yup.string()
.required(i18n.t("login.passwordRequired"))
.min(8, i18n.t("login.passwordLength")),
});

+ 10
- 0
src/validations/registerValidations/secondPartValidation.js Voir le fichier

@@ -0,0 +1,10 @@
import * as Yup from "yup";
import i18n from "../../i18n";

export default Yup.object().shape({
nameOfFirm: Yup.string().required(i18n.t("login.usernameRequired")),
PIB: Yup.number()
.required(i18n.t("login.passwordRequired"))
.min(100000000, i18n.t("register.PIBnoOfCharacters"))
.max(999999999, i18n.t("register.PIBnoOfCharacters")),
});

+ 10
- 0
src/validations/registerValidations/thirdPartValidation.js Voir le fichier

@@ -0,0 +1,10 @@
import * as Yup from "yup";
import i18n from "../../i18n";

export default Yup.object().shape({
phoneNumber: Yup.number().required(i18n.t("login.usernameRequired")),
location: Yup.string().required(i18n.t("login.passwordRequired")),
website: Yup.string().matches(
/^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm
),
});

+ 6
- 0
src/validations/resetPasswordValidation.js Voir le fichier

@@ -0,0 +1,6 @@
import * as Yup from "yup";

export default Yup.object().shape({
password: Yup.string().required().min(8),
passwordConfirm: Yup.string().oneOf([Yup.ref("password"), null]),
});

Chargement…
Annuler
Enregistrer