Skip to content

Commit

Permalink
Merge pull request #64 from Yura-Platonov/ChangePass
Browse files Browse the repository at this point in the history
Change pass
  • Loading branch information
LaPaNu4 authored Jan 4, 2024
2 parents 5f2edd9 + 5de6374 commit aeb6268
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 58 deletions.
20 changes: 16 additions & 4 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,22 @@ export function App() {
}
/>
<Route path="/search" element={<SearchPage />} />
<Route path="/AdvertisementPage" element={<AdvertisementPage />} />
<Route path="/" element={<PrivateRoute />}>
<Route path="/account" element={<AccountPage />} />
</Route>
<Route
path="/AdvertisementPage"
element={
<PrivateRoute redirectTo="/authorization">
<AdvertisementPage />
</PrivateRoute>
}
/>
<Route
path="/account"
element={
<PrivateRoute redirectTo="/authorization">
<AccountPage />
</PrivateRoute>
}
/>
</Routes>
</Suspense>
</main>
Expand Down
131 changes: 130 additions & 1 deletion src/components/ChangePass/ChangePass.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,132 @@
import { useDispatch, useSelector } from 'react-redux';
import * as Yup from 'yup';
import { Formik } from 'formik';
import { useEffect, useState } from 'react';
import { selectError } from 'redux/auth/selectors';
import { selectUser } from 'redux/user/selectors';
import { changePass } from 'redux/user/opetations';
import { Button, ErrorMessage, Field, Form, Label, Wraper } from 'components/ForgotPass/ForgotPass.styled';
import { HidePassword, PasswordInput } from 'components/LoginForm/LoginForm.styled';
import { ErrorSVG, ViewSVG } from 'components/LoginForm/chackBox';

const userSchema = Yup.object().shape({
password: Yup.string()
.required('Введіть пароль')
.min(5, 'Пароль повинен містити принаймні 5 символів')
.matches(
/^[^\u0400-\u04FF]*$/,
'Пароль не повинен містити кириличні символи'
)
.matches(
/^(?=.*[A-Z])/,
'Пароль повинен містити принаймні одну велику літеру'
)
.matches(
/^(?=.*[a-z])/,
'Пароль повинен містити принаймні одну малу літеру'
)
.matches(/^(?=.*\d)/, 'Пароль повинен містити принаймні одну цифру')
.matches(/^[^\s]*$/, 'Пароль не повинен містити пробіли'),
password2: Yup.string()
.required('Повторіть новий пароль')
.test('passwords-match', 'Паролі повинні співпадати', function (value) {
return value === this.parent.password;
}),
});

export default function ChangePass() {
return <div></div>;
const [showPassword, setShowPassword] = useState(false);
const [showPassword2, setShowPassword2] = useState(false);
const dispatch = useDispatch();
const [refError, setRefError] = useState(false);
const requestError = useSelector(selectError);
const userInfo = useSelector(selectUser);

const handleSubmit = (values, { resetForm, setSubmitting }) => {
const { password } = values;
try {
dispatch(changePass({ email: userInfo.email, password: password }));
resetForm();
setSubmitting(false);
} catch (error) {
console.error('Error submitting form:', error);
}
};

const handleShowPassword = () => {
setShowPassword(!showPassword);
};
const handleShowPassword2 = () => {
setShowPassword2(!showPassword2);
};

useEffect(() => {
if (requestError) setRefError(true);
}, [requestError]);

return (
<Formik
onSubmit={handleSubmit}
initialValues={{ password: '' }}
validationSchema={userSchema}
>
{values => {
return (
<Wraper>
<h4 className="title">Заміна паролю</h4>
<p className="text">
Спочатку введіть новий пароль. А потім повторіть його
</p>
<Form>
<Label className={` marg8`}>
<PasswordInput>
<Field
type={showPassword ? 'text' : 'password'}
className={refError ? 'is-invalid' : ''}
name="password"
placeholder="Ввеліть новий пароль"
value={values.password}
/>

{refError ? (
<span className="errorSVG">
<ErrorSVG />
</span>
) : null}

<HidePassword type="button" onClick={handleShowPassword}>
<ViewSVG />
</HidePassword>
</PasswordInput>
<ErrorMessage name="password" component="div" />
</Label>
<Label style={{marginTop:'24px'}}>
<PasswordInput>
<Field
type={showPassword2 ? 'text' : 'password'}
className={refError ? 'is-invalid' : ''}
name="password2"
placeholder="Повторіть новий пароль"
value={values.password2}
/>

{refError ? (
<span className="errorSVG">
<ErrorSVG />
</span>
) : null}

<HidePassword type="button" onClick={handleShowPassword2}>
<ViewSVG />
</HidePassword>
</PasswordInput>
<ErrorMessage name="password2" component="div" />
</Label>
<Button type="submit">Зберегти</Button>
</Form>
</Wraper>
);
}}
</Formik>
);
}
56 changes: 30 additions & 26 deletions src/components/Header/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,37 @@ const Header = () => {
<img src={Logo} alt="Logo" />
</NavLink>
<Navigation>
<ul>
<li>
<StyledLink to="/search">Нові</StyledLink>
</li>
<li>
<StyledLink to="/">Вживані</StyledLink>
</li>
<li>
<StyledLink to="/">Під пригон</StyledLink>
</li>
</ul>
</Navigation>
<User>
<NavLink to="/AdvertisementPage">
<ButtonSale>
<StyledAddSVG />
<ButtonText>Продати</ButtonText>
</ButtonSale>
</NavLink>
<UserIcon>
<StyledHeartSVG />
<NavLink to={isLoggedIn ? '/account' : '/authorization'}>
<StyledUserSVG />
<ul>
<li>
<StyledLink to="/search?status=New">Нові</StyledLink>
</li>
<li>
<StyledLink to="/search?status=Used">Вживані</StyledLink>
</li>
<li>
<StyledLink to="/search?status=Servitude">
Під пригон
</StyledLink>
</li>
</ul>
</Navigation>
<User>
<NavLink to="/AdvertisementPage">
<ButtonSale>
<StyledAddSVG />
<ButtonText>Продати</ButtonText>
</ButtonSale>
</NavLink>
</UserIcon>
</User>
</HeaderWrapper>
<UserIcon>
<NavLink to="/account?favourites=true">
<StyledHeartSVG />
</NavLink>
<NavLink to={isLoggedIn ? '/account' : '/authorization'}>
<StyledUserSVG />
</NavLink>
</UserIcon>
</User>
</HeaderWrapper>
</Container>
);
};
Expand Down
6 changes: 3 additions & 3 deletions src/components/PrivateRoute.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useSelector } from 'react-redux';
import { Navigate, Outlet } from 'react-router-dom';
import { Navigate } from 'react-router-dom';
import { selectIsLoggedIn } from '../redux/auth/selectors';

export const PrivateRoute = () => {
export const PrivateRoute = ({ children, redirectTo = '/' }) => {
const IsLoggedIn = useSelector(selectIsLoggedIn);

return IsLoggedIn ? <Outlet /> : <Navigate to="/" replace />;
return IsLoggedIn ? children : <Navigate to={redirectTo} />;
};
14 changes: 11 additions & 3 deletions src/components/SearchForm/SearchForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { useEffect, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import { setIsOpen } from 'redux/modal/modalSlice';
import { Arrow, DropArrow } from './SearchFormSVG';
import { useLocation } from 'react-router-dom';

export const SearchForm = ({ initialValues, onSubmit }) => {
const [selectedBrand, setSelectedBrand] = useState('');
const [selectedModel, setSelectedModel] = useState('');
const location = useLocation();
const carMark = {
BMW: ['X5', 'M3', 'I3'],
Toyota: ['Camry', 'Corolla', 'Avalon'],
Expand All @@ -32,6 +34,14 @@ export const SearchForm = ({ initialValues, onSubmit }) => {
formikRef.current.resetForm({ values: initialValues });
}
}, [initialValues]);
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
const favouritesParam = searchParams.get('status');
console.log(favouritesParam);
if (favouritesParam) {
formikRef.current.setFieldValue('status', favouritesParam);
}
}, [location.search]);

const clearForm = () => {
distatch(setIsOpen(true));
Expand Down Expand Up @@ -336,8 +346,6 @@ export const SearchForm = ({ initialValues, onSubmit }) => {
};
export default SearchForm;



// {/* <div className="shortDiv marg16">
// <label>
// <Field
Expand All @@ -356,4 +364,4 @@ export default SearchForm;
// placeholder="Введіть пробіг до"
// />
// </label>
// </div>; */}
// </div>; */}
13 changes: 9 additions & 4 deletions src/pages/AccountPage/AccountPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@ import ProfileForm from '../../components/ProfileForm/ProfileForm';
import { getUser } from 'redux/user/opetations';
import { selectUser } from 'redux/user/selectors';
import { SVG1 } from './AccPageSVG';
import { useLocation } from 'react-router-dom';

const AccountPage = () => {
const dispatch = useDispatch();
const [selectedNavItem, setSelectedNavItem] = useState('personal');

const [selectedNavItem, setSelectedNavItem] = useState('personal');
const location = useLocation();
const userInfo = useSelector(selectUser)

useEffect(() => {
dispatch(getUser());
}, [dispatch]);

const searchParams = new URLSearchParams(location.search);
const favouritesParam = searchParams.get('favourites');

if (favouritesParam === 'true') {
setSelectedNavItem('favourites');
}
}, [dispatch, location.search]);


const handleLogout = () => {
Expand Down
12 changes: 6 additions & 6 deletions src/redux/auth/operations.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
import { Notify } from 'notiflix/build/notiflix-notify-aio';
// import { Notify } from 'notiflix/build/notiflix-notify-aio';


export const instance = axios.create({
Expand All @@ -21,11 +21,11 @@ export const register = createAsyncThunk(
async (credentials, { rejectWithValue }) => {
try {
const response = await instance.post('api/auth/signup', credentials);
Notify.success(`Welcome!!!`);
console.log(`Welcome!!!`);
return response.data;

} catch (error) {
Notify.failure(`This email is already in use`);
console.log(`This email is already in use`);
return rejectWithValue(error.message);
}
}
Expand All @@ -38,10 +38,10 @@ export const login = createAsyncThunk(
const response = await instance.post('api/auth/login', credentials);
setToken(response.data.data.jwtAccessToken);
console.log(response);
Notify.success(`Welcome back!!!`);
console.log(`Welcome back!!!`);
return response.data;
} catch (error) {
Notify.failure(`Login failed. Try again`);
console.log(`Login failed. Try again`);
return rejectWithValue(error.message);
}
}
Expand Down Expand Up @@ -94,7 +94,7 @@ export const logoutOperation = createAsyncThunk(
// async (credentials, { rejectWithValue }) => {
// try {
// const { data } = await instance.patch('api/auth/update', credentials);
// Notify.success(`Your profile has been updated`);
// console.log(`Your profile has been updated`);
// return data;
// } catch (error) {
// return rejectWithValue(error.message);
Expand Down
Loading

0 comments on commit aeb6268

Please sign in to comment.