Skip to content

Commit

Permalink
edited routes and loadings
Browse files Browse the repository at this point in the history
  • Loading branch information
sofiialives committed Nov 1, 2023
1 parent 7e2c7cb commit 0b621c9
Show file tree
Hide file tree
Showing 20 changed files with 279 additions and 140 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.0",
"nanoid": "^5.0.1",
"notiflix": "^3.2.6",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-loader-spinner": "^5.4.5",
Expand Down
35 changes: 28 additions & 7 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { AppBar } from './AppBar/AppBar';
import { useDispatch, useSelector } from 'react-redux';
import { refreshUser } from 'redux/auth/operations';
import { selectIsRefreshing } from 'redux/auth/selectors';


import { PrivateRoute } from './PrivateRoute';
import { RestrictedRoute } from './RestrictedRoute ';
import { Loading } from './Loading';

const Welcome = lazy(() => import('pages/Welcome/Welcome'));
const Register = lazy(() => import('pages/Register/Register'));
const Login= lazy(() => import('pages/Login/Login'));
const Login = lazy(() => import('pages/Login/Login'));
const Contacts = lazy(() => import('pages/Contacts/Contacts'));
const Error = lazy(() => import('pages/Error404/Error'))

export function App() {
const isRefreshing = useSelector(selectIsRefreshing);
Expand All @@ -25,13 +27,32 @@ export function App() {
!isRefreshing && (
<>
<AppBar />
<Suspense fallback={<Loading/>}>
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Layout />} />
<Route index path="/" element={<Welcome />} />
<Route path="/register" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route path="/contacts" element={<Contacts />} />
<Route
path="/register"
element={
<RestrictedRoute
redirectTo="/contacts"
component={<Register />}
/>
}
/>
<Route
path="/login"
element={
<RestrictedRoute redirectTo="/contacts" component={<Login />} />
}
/>
<Route
path="/contacts"
element={
<PrivateRoute redirectTo="/login" component={<Contacts />} />
}
/>
<Route path="*" element={<Error/>} />
</Routes>
</Suspense>
</>
Expand Down
2 changes: 0 additions & 2 deletions src/components/ContactForm/ContactForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ export function ContactForm() {
<input
type="tel"
name="number"
pattern="[0-9]{3}-[0-9]{2}-[0-9]{2}"
title="xxx-xx-xx"
id={id}
value={number}
onChange={handleChange}
Expand Down
31 changes: 31 additions & 0 deletions src/components/ContactItem/ContactItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useState } from 'react';
import { useDispatch } from 'react-redux';
import { deleteContact } from 'redux/contacts/operations';
import { LoadingDelete } from '../ContactsList/LoadingDelete';
import css from './ContactItem.module.css';

export const ContactItem = ({ contact }) => {
const [isDelete, setIsDelete] = useState(false);
const dispatch = useDispatch();

const handleDelete = id => {
setIsDelete(true);
dispatch(deleteContact(id))
.unwrap()
.then(() => setIsDelete(false));
};

return (
<li>
<span>
{contact.name}: {contact.number || contact.phone}
</span>
<button
onClick={() => handleDelete(contact.id)}
className={css.buttonFilter}
>
{isDelete ? <LoadingDelete /> : '\u2716'}
</button>
</li>
);
};
20 changes: 20 additions & 0 deletions src/components/ContactItem/ContactItem.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.buttonFilter {
border-radius: 50%;
font-size: 18px;
color: rgb(240, 27, 27);
background-color: rgb(250, 181, 181);
border: 1px red solid;
width: 40px;
height: 40px;
box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2);
cursor: pointer;
transition: background-color 200ms ease-in-out, transform 200ms,
box-shadow 200ms;
margin-left: 10px;
}
.buttonFilter:hover,
.buttonFilter:focus {
transform: scale(1.1);
background-color: rgb(246, 150, 150);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
}
23 changes: 8 additions & 15 deletions src/components/ContactsList/ContactList.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import css from './ContactList.module.css';
import { deleteContact } from 'redux/contacts/operations';
import { useDispatch, useSelector } from 'react-redux';
import { useSelector } from 'react-redux';
import { useMemo } from 'react';
import { selectItems, selectFilter, selectError } from 'redux/contacts/selectors';
import {
selectItems,
selectFilter,
selectError,
} from 'redux/contacts/selectors';
import { ContactItem } from 'components/ContactItem/ContactItem';

export const ContactsList = () => {
const error = useSelector(selectError);
const contacts = useSelector(selectItems);
const filter = useSelector(selectFilter);
const dispatch = useDispatch();

const filteredContacts = useMemo(() => {
if (filter === '') return contacts;
Expand All @@ -23,17 +26,7 @@ export const ContactsList = () => {
{error && 'something went wrong'}
<ul className={css.list}>
{filteredContacts.map(contact => (
<li key={contact.id}>
<span>
{contact.name}: {contact.number || contact.phone}
</span>
<button
onClick={() => dispatch(deleteContact(contact.id))}
className={css.buttonFilter}
>
&#10060;
</button>
</li>
<ContactItem key={contact.id} contact={contact} />
))}
</ul>
</div>
Expand Down
20 changes: 0 additions & 20 deletions src/components/ContactsList/ContactList.module.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
.buttonFilter {
border-radius: 50%;
font-size: 18px;
color: rgb(240, 27, 27);
background-color: rgb(250, 181, 181);
border: 1px red solid;
width: 40px;
height: 40px;
box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2);
cursor: pointer;
transition: background-color 200ms ease-in-out, transform 200ms,
box-shadow 200ms;
margin-left: 10px;
}
.buttonFilter:hover,
.buttonFilter:focus {
transform: scale(1.1);
background-color: rgb(246, 150, 150);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
}
.list{
display: flex;
flex-direction: column;
Expand Down
13 changes: 13 additions & 0 deletions src/components/ContactsList/LoadingDelete.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { RotatingLines } from "react-loader-spinner";

export const LoadingDelete = () => {
return (
<RotatingLines
strokeColor="red"
strokeWidth="5"
animationDuration="0.75"
width="20px"
visible={true}
/>
);
};
20 changes: 10 additions & 10 deletions src/components/Loading.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Audio } from 'react-loader-spinner';
import { ColorRing } from 'react-loader-spinner';

export const Loading = () => {
return (
<Audio
height="100"
width="100"
color="#4fa94d"
ariaLabel="audio-loading"
wrapperStyle={{}}
wrapperClass="wrapper-class"
visible={true}
/>
<ColorRing
visible={true}
height="80"
width="80"
ariaLabel="blocks-loading"
wrapperStyle={{}}
wrapperClass="blocks-wrapper"
colors={['#e15b64', '#f47e60', '#f8b26a', '#abbd81', '#849b87']}
/>
);
};
11 changes: 11 additions & 0 deletions src/components/PrivateRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Navigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { selectIsLoggedIn, selectIsRefreshing } from 'redux/auth/selectors';

export const PrivateRoute = ({ component: Component, redirectTo = '/' }) => {
const isLoggedIn = useSelector(selectIsLoggedIn)
const isRefreshing = useSelector(selectIsRefreshing)
const shouldRedirect = !isLoggedIn && !isRefreshing;

return shouldRedirect ? <Navigate to={redirectTo} /> : Component;
};
9 changes: 9 additions & 0 deletions src/components/RestrictedRoute .js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Navigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { selectIsLoggedIn } from 'redux/auth/selectors';

export const RestrictedRoute = ({ component: Component, redirectTo = '/' }) => {
const isLoggedIn = useSelector(selectIsLoggedIn);

return isLoggedIn ? <Navigate to={redirectTo} /> : Component;
};
22 changes: 10 additions & 12 deletions src/pages/Contacts/Contacts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { ContactsList } from 'components/ContactsList/ContactList';
import { Filter } from 'components/Filter/Filter';
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Navigate } from 'react-router-dom';
import { selectIsLoggedIn } from 'redux/auth/selectors';
import { fetchContacts } from 'redux/contacts/operations';
import css from './Contacts.module.css';
import { selectError } from 'redux/contacts/selectors';

const Contacts = () => {
const error = useSelector(selectError);
const isLoggedIn = useSelector(selectIsLoggedIn);
const dispatch = useDispatch();

Expand All @@ -20,17 +21,14 @@ const Contacts = () => {

return (
<>
{isLoggedIn ? (
<div className={css.div}>
<h1 className={css.title}>Phonebook</h1>
<ContactForm />
<h2 className={css.title2}>Contacts</h2>
<Filter />
<ContactsList />
</div>
) : (
<Navigate to="/login" />
)}
{error && 'something went wrong'}
<div className={css.div}>
<h1 className={css.title}>Phonebook</h1>
<ContactForm />
<h2 className={css.title2}>Contacts</h2>
<Filter />
<ContactsList />
</div>
</>
);
};
Expand Down
18 changes: 18 additions & 0 deletions src/pages/Error404/Error.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Loading } from 'components/Loading';
import css from './Error.module.css';
import { useSelector } from 'react-redux';
import { selectError, selectLoading } from 'redux/contacts/selectors';

const Error = () => {
const isLoading = useSelector(selectLoading);
const error = useSelector(selectError);
return (
<div className={css.div}>
{isLoading && <Loading />}
{error && 'something went wrong'}
<h1 className={css.title}>THE PAGE NOT FOUND 404</h1>
</div>
);
};

export default Error;
10 changes: 10 additions & 0 deletions src/pages/Error404/Error.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.div {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.title {
font-size: 40px;
color: red;
}
Loading

0 comments on commit 0b621c9

Please sign in to comment.