| @@ -250,5 +250,5 @@ | |||
| text-align: left; | |||
| } | |||
| .w-289.f { | |||
| margin-top: 35px !important; | |||
| margin-top: 25px !important; | |||
| } | |||
| @@ -7,19 +7,21 @@ import { | |||
| IconButton, | |||
| InputAdornment, | |||
| TextField, | |||
| Typography, | |||
| // Typography, | |||
| } from "@mui/material"; | |||
| import Button from "../Button/Button"; | |||
| import { useState } from "react"; | |||
| import googleLogo from "../../assets/images/google1.png"; | |||
| // import googleLogo from "../../assets/images/google1.png"; | |||
| import DiligLogo from "../../assets/images/logo_horizontal_black.png"; | |||
| import { Box } from "@mui/system"; | |||
| import { FormContext } from "../../context/FormContext"; | |||
| import { useLocation } from "react-router-dom"; | |||
| function FirstStepForm() { | |||
| const { activeStepIndex, setActiveStepIndex, formData, setFormData } = | |||
| useContext(FormContext); | |||
| const { search } = useLocation(); | |||
| const { t } = useTranslation(); | |||
| const [showPassword, setShowPassword] = useState(false); | |||
| @@ -27,22 +29,48 @@ function FirstStepForm() { | |||
| const handleMouseDownPassword = () => setShowPassword(!showPassword); | |||
| const submitHandler = (values) => { | |||
| const data = { ...formData, ...values }; | |||
| const data = { | |||
| ...formData, | |||
| ...values, | |||
| token: search.split("&")[0].split("=")[1], | |||
| }; | |||
| setFormData(data); | |||
| setActiveStepIndex(activeStepIndex + 1); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| email: "", | |||
| email: search.split("&")[1].split("=")[1], | |||
| password: "", | |||
| confirm: "", | |||
| }, | |||
| validationSchema: yup.object().shape({ | |||
| email: yup | |||
| .string() | |||
| .required(t("login.emailRequired")) | |||
| .matches(/^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/, t("login.invalidEmail")), | |||
| password: yup.string().required(t("login.passwordRequired")), | |||
| password: yup | |||
| .string() | |||
| .required(t("login.passwordRequired")) | |||
| .matches( | |||
| // eslint-disable-next-line | |||
| /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+/, | |||
| "Paswword must contain atleast one special character" | |||
| ) | |||
| .matches(/[0-9]/g, "Paswword must contain atleast one number") | |||
| .matches( | |||
| /[a-z]/g, | |||
| "Paswword must contain at least one lowercase character" | |||
| ) | |||
| .matches( | |||
| /[A-Z]/g, | |||
| "Paswword must contain at least one uppercase character" | |||
| ) | |||
| .min(8, "Password must contain at least 8 characters"), | |||
| confirm: yup | |||
| .string() | |||
| .required("Please retype your password.") | |||
| .oneOf([yup.ref("password")], "Your passwords do not match."), | |||
| }), | |||
| onSubmit: submitHandler, | |||
| validateOnBlur: true, | |||
| @@ -62,9 +90,11 @@ function FirstStepForm() { | |||
| <> | |||
| <TextField | |||
| name="email" | |||
| label={"E-mail"} | |||
| // label={"E-mail"} | |||
| margin="normal" | |||
| disabled | |||
| fullWidth | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.email && Boolean(formik.errors.email)} | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| @@ -92,17 +122,40 @@ function FirstStepForm() { | |||
| ), | |||
| }} | |||
| /> | |||
| <TextField | |||
| className="rounded-input" | |||
| name="confirm" | |||
| label={"Potvrda šifre"} | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| fullWidth | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.confirm && Boolean(formik.errors.confirm)} | |||
| helperText={formik.touched.confirm && formik.errors.confirm} | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| > | |||
| {showPassword ? <Visibility /> : <VisibilityOff />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| ), | |||
| }} | |||
| /> | |||
| </> | |||
| <Button | |||
| variant="contained" | |||
| sx={{ mt: 3, mb: 2 }} | |||
| sx={{ mt: 2, mb: 2 }} | |||
| fullWidth | |||
| className="c-btn c-btn--primary w-289 f" | |||
| type="submit" | |||
| > | |||
| Nastavi | |||
| </Button> | |||
| <div className="flex-center"> | |||
| {/* <div className="flex-center"> | |||
| <div className="hr hr-s"></div> | |||
| <div className="hr-mid">{t("common.or")}</div> | |||
| <div className="hr hr-e"></div> | |||
| @@ -119,7 +172,7 @@ function FirstStepForm() { | |||
| </Typography> | |||
| </Button> | |||
| <div id="signInDiv"></div> | |||
| </div> | |||
| </div> */} | |||
| <div className="flex-center"> | |||
| <img src={DiligLogo} style={{ margin: "50px auto 30px auto" }} /> | |||
| </div> | |||
| @@ -1,27 +1,41 @@ | |||
| import { useFormik } from "formik"; | |||
| import React from "react"; | |||
| import React, { useContext } from "react"; | |||
| import * as yup from "yup"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { | |||
| TextField, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import { TextField } from "@mui/material"; | |||
| import Button from "../Button/Button"; | |||
| import googleLogo from "../../assets/images/google1.png"; | |||
| // import googleLogo from "../../assets/images/google1.png"; | |||
| import DiligLogo from "../../assets/images/logo_horizontal_black.png"; | |||
| import { Box } from "@mui/system"; | |||
| import { FormContext } from "../../context/FormContext"; | |||
| import { useDispatch } from "react-redux"; | |||
| import { registerRequest } from "../../store/actions/register/registerActions"; | |||
| import { BASE_PAGE } from "../../constants/pages"; | |||
| import { useHistory } from "react-router-dom"; | |||
| function SecondStepForm() { | |||
| // const { activeStepIndex, setActiveStepIndex, formData, setFormData } = | |||
| // useContext(FormContext); | |||
| const { formData } = useContext(FormContext); | |||
| const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| const history = useHistory(); | |||
| const submitHandler = (values) => { | |||
| console.log(values) | |||
| // const data = { ...formData, ...values }; | |||
| // setFormData(data); | |||
| // setActiveStepIndex(activeStepIndex + 1); | |||
| alert('Done') | |||
| const data = { ...formData, ...values }; | |||
| dispatch( | |||
| registerRequest({ | |||
| model: data, | |||
| handleApiResponseSuccess, | |||
| }) | |||
| ); | |||
| }; | |||
| const handleApiResponseSuccess = () => { | |||
| history.push({ | |||
| pathname: BASE_PAGE, | |||
| state: { | |||
| from: history.location.pathname, | |||
| }, | |||
| }); | |||
| }; | |||
| const formik = useFormik({ | |||
| @@ -31,11 +45,9 @@ function SecondStepForm() { | |||
| linkedin: "", | |||
| }, | |||
| validationSchema: yup.object().shape({ | |||
| phone: yup | |||
| .string() | |||
| .required('Required'), | |||
| position: yup.string().required('Required'), | |||
| linkedin: yup.string().required('Required'), | |||
| phone: yup.string().required("Required"), | |||
| position: yup.string().required("Required"), | |||
| linkedin: yup.string().required("Required"), | |||
| }), | |||
| onSubmit: submitHandler, | |||
| validateOnBlur: true, | |||
| @@ -90,7 +102,7 @@ function SecondStepForm() { | |||
| > | |||
| Registruj se | |||
| </Button> | |||
| <div className="flex-center"> | |||
| {/* <div className="flex-center"> | |||
| <div className="hr hr-s"></div> | |||
| <div className="hr-mid">{t("common.or")}</div> | |||
| <div className="hr hr-e"></div> | |||
| @@ -107,7 +119,7 @@ function SecondStepForm() { | |||
| </Typography> | |||
| </Button> | |||
| <div id="signInDiv"></div> | |||
| </div> | |||
| </div> */} | |||
| <div className="flex-center"> | |||
| <img src={DiligLogo} style={{ margin: "50px auto 30px auto" }} /> | |||
| </div> | |||
| @@ -115,4 +127,4 @@ function SecondStepForm() { | |||
| ); | |||
| } | |||
| export default SecondStepForm; | |||
| export default SecondStepForm; | |||
| @@ -3,7 +3,7 @@ import React, { useEffect, useState, useContext } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { useFormik } from "formik"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { NavLink } from "react-router-dom"; | |||
| import { NavLink, useLocation } from "react-router-dom"; | |||
| import * as Yup from "yup"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import HrLogo from "../../assets/images/hrcenter.png"; | |||
| @@ -14,7 +14,11 @@ import { | |||
| fetchGoogleUser, | |||
| } from "../../store/actions/login/loginActions"; | |||
| import { selectLoginError } from "../../store/selectors/loginSelectors"; | |||
| import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages"; | |||
| import { | |||
| ADS_PAGE, | |||
| FORGOT_PASSWORD_PAGE, | |||
| HOME_PAGE, | |||
| } from "../../constants/pages"; | |||
| import { | |||
| Box, | |||
| Button, | |||
| @@ -38,11 +42,13 @@ import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers"; | |||
| import { JWT_TOKEN } from "../../constants/localStorage"; | |||
| import Step from "../../components/Registration/Step"; | |||
| import { FormContext, FormProvider } from "../../context/FormContext"; | |||
| import { selectIsUserAuthenticated } from "../../store/selectors/userSelectors"; | |||
| const RegisterPage = ({ history }) => { | |||
| // const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| // const error = useSelector(selectLoginError); | |||
| const { search } = useLocation(); | |||
| const { activeStepIndex } = useContext(FormContext); | |||
| @@ -74,11 +80,17 @@ const RegisterPage = ({ history }) => { | |||
| selectIsLoadingByActionType(LOGIN_GOOGLE_USER_LOADING) | |||
| ); | |||
| const isUserAuthenticated = useSelector(selectIsUserAuthenticated); | |||
| useEffect(() => { | |||
| if (isInit) { | |||
| setIsInit(false); | |||
| return; | |||
| } | |||
| if (!isUserAuthenticated) { | |||
| history.push({ pathname: ADS_PAGE }); | |||
| } | |||
| }, [isInit]); | |||
| return ( | |||
| @@ -102,31 +114,40 @@ const RegisterPage = ({ history }) => { | |||
| }} | |||
| > | |||
| <img src={HrLogo} className="login-logo" /> | |||
| <Typography variant="h5" sx={{ m: 1, mt: 3 }}> | |||
| {t("login.welcome")} | |||
| </Typography> | |||
| <Typography variant="p" sx={{ mb: 2 }}> | |||
| Dva koraka do HR Centra. | |||
| </Typography> | |||
| <div className="steps-cont"> | |||
| <div | |||
| className={`step ${activeStepIndex && activeStepIndex === 1 ? "done" : "current"}`} | |||
| > | |||
| 1 | |||
| </div> | |||
| <div className="line-btw"></div> | |||
| <div | |||
| className={`step ${ | |||
| activeStepIndex && activeStepIndex === 1 ? "current" : "disallowed" | |||
| }`} | |||
| > | |||
| 2 | |||
| </div> | |||
| </div> | |||
| {/* {error && <ErrorMessage error={error} />} */} | |||
| {/* THIS SHOULD BE COPIED */} | |||
| <Step /> | |||
| {search.split("&")[1]?.split("=")[1] ? ( | |||
| <> | |||
| <Typography variant="h5" sx={{ m: 1, mt: 3 }}> | |||
| {t("login.welcome")} | |||
| </Typography> | |||
| <Typography variant="p" sx={{ mb: 2 }}> | |||
| Dva koraka do HR Centra. | |||
| </Typography> | |||
| <div className="steps-cont"> | |||
| <div | |||
| className={`step ${ | |||
| activeStepIndex && activeStepIndex === 1 | |||
| ? "done" | |||
| : "current" | |||
| }`} | |||
| > | |||
| 1 | |||
| </div> | |||
| <div className="line-btw"></div> | |||
| <div | |||
| className={`step ${ | |||
| activeStepIndex && activeStepIndex === 1 | |||
| ? "current" | |||
| : "disallowed" | |||
| }`} | |||
| > | |||
| 2 | |||
| </div> | |||
| </div> | |||
| <Step /> | |||
| </> | |||
| ) : ( | |||
| <h3 style={{ margin: "50px 0px" }}>There was a mistake...</h3> | |||
| )} | |||
| </Box> | |||
| </Container> | |||
| </> | |||
| @@ -257,8 +257,8 @@ const UserDetails = ({ history }) => { | |||
| <div className="flex-center" style={{ justifyContent: "flex-start" }}> | |||
| <p style={{ width: "85px" }}>LinkedIn:</p> | |||
| <p className="text-blue"> | |||
| {user?.socialMedias | |||
| ? user.socialMedias | |||
| {user?.linkedIn | |||
| ? user.linkedIn | |||
| : "User takes not part in any social media."} | |||
| </p> | |||
| </div> | |||
| @@ -239,7 +239,7 @@ const UsersPage = () => { | |||
| )} | |||
| </td> | |||
| <td>{n.email}</td> | |||
| <td className='profession'>HR Specialist</td> | |||
| <td className='profession'>{n.position}</td> | |||
| {editEnable && ( | |||
| <td> | |||
| <> | |||
| @@ -8,6 +8,7 @@ export default { | |||
| logout: base + "/authentications/logout?userId={userId}", | |||
| forgetPassword: base + "/authentications/ForgotPassword", | |||
| resetPassword: base + "/authentications/RessetPassword", | |||
| register: base + "/authentications/register", | |||
| }, | |||
| users: { | |||
| allUsers: base + "/users", | |||
| @@ -0,0 +1,5 @@ | |||
| import { postRequest } from "."; | |||
| import apiEndpoints from "./apiEndpoints"; | |||
| export const register = (payload) => | |||
| postRequest(apiEndpoints.authentications.register, payload); | |||
| @@ -0,0 +1,3 @@ | |||
| export const REGISTER_REQUEST = 'REGISTER_REQUEST' | |||
| export const REGISTER_SUCCESS = 'REGISTER_SUCCESS' | |||
| export const REGISTER_ERROR = 'REGISTER_ERROR' | |||
| @@ -0,0 +1,20 @@ | |||
| import { | |||
| REGISTER_ERROR, | |||
| REGISTER_REQUEST, | |||
| REGISTER_SUCCESS, | |||
| } from "./registerActionConstants"; | |||
| export const registerRequest = (payload) => ({ | |||
| type: REGISTER_REQUEST, | |||
| payload, | |||
| }); | |||
| export const registerError = (payload) => ({ | |||
| type: REGISTER_ERROR, | |||
| payload, | |||
| }); | |||
| export const registerSuccess = (payload) => ({ | |||
| type: REGISTER_SUCCESS, | |||
| payload, | |||
| }); | |||
| @@ -25,6 +25,7 @@ import updatePatternReducer from "./pattern/updatePatternReducer"; | |||
| import statsReducer from "./stats/statsReducer"; | |||
| import scheduleReducer from "./schedule/scheduleReducer"; | |||
| import archiveActiveAdReducer from "./ad/archiveActiveAdReducer"; | |||
| import registerReducer from "./register/registerReducer"; | |||
| export default combineReducers({ | |||
| login: loginReducer, | |||
| @@ -52,5 +53,6 @@ export default combineReducers({ | |||
| createPattern: createPatternReducer, | |||
| updatePattern: updatePatternReducer, | |||
| stats: statsReducer, | |||
| schedule:scheduleReducer | |||
| schedule:scheduleReducer, | |||
| register: registerReducer | |||
| }); | |||
| @@ -0,0 +1,32 @@ | |||
| import createReducer from "../../utils/createReducer"; | |||
| import { | |||
| REGISTER_ERROR, | |||
| REGISTER_SUCCESS, | |||
| } from "../../actions/register/registerActionConstants"; | |||
| const initialState = { | |||
| isSuccess: false, | |||
| errorMessage: "", | |||
| }; | |||
| export default createReducer( | |||
| { | |||
| [REGISTER_SUCCESS]: setSuccess, | |||
| [REGISTER_ERROR]: setError, | |||
| }, | |||
| initialState | |||
| ); | |||
| function setSuccess(state) { | |||
| return { | |||
| ...state, | |||
| isSuccess: true, | |||
| }; | |||
| } | |||
| function setError(state, action) { | |||
| return { | |||
| ...state, | |||
| errorMessage: action.payload, | |||
| }; | |||
| } | |||
| @@ -8,6 +8,7 @@ import processesSaga from "./processSaga"; | |||
| import patternsSage from "./patternsSaga"; | |||
| import statsSaga from "./statsSaga"; | |||
| import scheduleSaga from "./scheduleSaga"; | |||
| import registerSaga from "./registerSaga"; | |||
| export default function* rootSaga() { | |||
| yield all([ | |||
| @@ -19,6 +20,7 @@ export default function* rootSaga() { | |||
| processesSaga(), | |||
| patternsSage(), | |||
| statsSaga(), | |||
| scheduleSaga() | |||
| scheduleSaga(), | |||
| registerSaga(), | |||
| ]); | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| import { all, call, put, takeEvery } from "redux-saga/effects"; | |||
| import { register } from "../../request/registerRequest"; | |||
| import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; | |||
| import { REGISTER_REQUEST } from "../actions/register/registerActionConstants"; | |||
| import { registerError, registerSuccess } from "../actions/register/registerActions"; | |||
| export function* registerUser({payload}) { | |||
| try { | |||
| yield call(register, payload.model); | |||
| yield put(registerSuccess()); | |||
| console.log('ovde 1') | |||
| if(payload.handleApiResponseSuccess){ | |||
| console.log('ovde 2') | |||
| yield call(payload.handleApiResponseSuccess) | |||
| } | |||
| } catch (error) { | |||
| if (error.response && error.response.data) { | |||
| const errorMessage = yield call(rejectErrorCodeHelper, error); | |||
| yield put(registerError(errorMessage)); | |||
| } | |||
| } | |||
| } | |||
| export default function* registerSaga() { | |||
| yield all([ | |||
| takeEvery(REGISTER_REQUEST, registerUser), | |||
| ]); | |||
| } | |||
| @@ -12,7 +12,6 @@ export function* getAppStats() { | |||
| const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN); | |||
| yield call(addHeaderToken, JwtToken); | |||
| const result = yield call(getStats); | |||
| console.log(result) | |||
| yield put(getStatsSuccess(result.data)); | |||
| } catch (error) { | |||
| if (error.response && error.response.data) { | |||