From 89c98815016db74402035a41addbf4b3444be0ba Mon Sep 17 00:00:00 2001 From: IrynaSlavinska <133566139+IrynaSlavinska@users.noreply.github.com> Date: Sat, 6 Jan 2024 17:04:15 +0200 Subject: [PATCH] groups --- src/components/App.jsx | 60 ++++++++-------- src/components/ContactForm/ContactForm.jsx | 69 +++++++++++++------ .../ContactForm/ContactForm.styled.jsx | 3 +- src/components/ContactsList/ContactsList.jsx | 3 +- src/components/Filter/Filter.jsx | 56 ++++++++++++++- src/components/Filter/Filter.styled.jsx | 14 ++++ src/components/Layout/Layout.jsx | 3 +- src/hooks/useAuth.js | 2 + src/redux/auth/authSelectors.js | 1 + src/redux/group/groupFilters.js | 7 ++ src/redux/group/groupSlice.js | 17 +++++ src/redux/reducer.js | 2 + src/redux/selectors.js | 6 +- 13 files changed, 183 insertions(+), 60 deletions(-) create mode 100644 src/redux/group/groupFilters.js create mode 100644 src/redux/group/groupSlice.js diff --git a/src/components/App.jsx b/src/components/App.jsx index 2cd575e..2af6b8a 100644 --- a/src/components/App.jsx +++ b/src/components/App.jsx @@ -8,8 +8,6 @@ import { PublicRoute } from '../routes/PublicRoute'; import { useAuth } from '../hooks/useAuth'; import operations from '../redux/auth/authOperations'; -import { HourglassLoader } from './Loader/Loader'; - const HomePage = lazy(() => import('pages/HomePage/HomePage')); const LoginPage = lazy(() => import('pages/LoginPage/LoginPage')); const ContactsPage = lazy(() => import('pages/ContactsPage/ContactsPage')); @@ -25,35 +23,35 @@ const App = () => { dispatch(operations.refreshUser()); }, [dispatch]); - return isRefreshing ? ( - - ) : ( - - }> - } /> - - } />} - /> - } />} - /> - } /> - } - /> - } - /> - - }> - - + return ( + !isRefreshing && ( + + }> + } /> + + } />} + /> + } />} + /> + } /> + } + /> + } + /> + + }> + + + ) ); }; diff --git a/src/components/ContactForm/ContactForm.jsx b/src/components/ContactForm/ContactForm.jsx index f412f79..1a97615 100644 --- a/src/components/ContactForm/ContactForm.jsx +++ b/src/components/ContactForm/ContactForm.jsx @@ -10,28 +10,28 @@ import { Label, Input, SubmitButton, - // Group, - // RadioContainer, - // RaioDiv, - // RadioInput, + Group, + RadioContainer, + RadioInput, } from './ContactForm.styled'; export const ContactForm = () => { const [name, setName] = useState(''); const [number, setNumber] = useState(''); + const [group, setGroup] = useState('others'); const contacts = useSelector(selectContacts); const dispatch = useDispatch(); const handleSubmit = e => { e.preventDefault(); + const form = e.currentTarget; + dispatch(addContactAction({ name, number, group })); const isExist = contacts.some(contact => contact.name === name); if (isExist) { Notiflix.Notify.warning(`${name} is already in your phonebook`); return; } - dispatch(addContactAction({ name, number })); - setName(''); - setNumber(''); + form.reset(); }; const handleChange = e => { @@ -43,6 +43,9 @@ export const ContactForm = () => { case 'number': setNumber(value); break; + case 'group': + setGroup(value); + break; default: break; } @@ -72,28 +75,52 @@ export const ContactForm = () => { /> - {/* Group + Group - + + + - + + + - + + + - + - */} + + + Add contact diff --git a/src/components/ContactForm/ContactForm.styled.jsx b/src/components/ContactForm/ContactForm.styled.jsx index 89ae3cd..472b86e 100644 --- a/src/components/ContactForm/ContactForm.styled.jsx +++ b/src/components/ContactForm/ContactForm.styled.jsx @@ -49,6 +49,7 @@ export const Group = styled.p` export const RadioContainer = styled.div` display: flex; justify-content: space-between; + margin-bottom: 16px; `; export const RaioDiv = styled.div` @@ -81,5 +82,5 @@ export const RaioDiv = styled.div` `; export const RadioInput = styled.input` - display: none; + margin-left: 6px; `; diff --git a/src/components/ContactsList/ContactsList.jsx b/src/components/ContactsList/ContactsList.jsx index 5a12f7f..33d21e9 100644 --- a/src/components/ContactsList/ContactsList.jsx +++ b/src/components/ContactsList/ContactsList.jsx @@ -55,7 +55,7 @@ export const ContactsList = () => { {error &&

Something went wrong!. Try again later

} {visibleContacts.length > 0 && ( - {visibleContacts.map(({ id, name, number }) => ( + {visibleContacts.map(({ id, name, number, group }) => ( @@ -63,6 +63,7 @@ export const ContactsList = () => { {name} {number} + {group} { - const { filter } = useSelector(selectFilterValue); const dispatch = useDispatch(); + const { filter } = useSelector(selectFilterValue); + + const group = useSelector(selectGroupFilters); + + const handleGroupChange = group => dispatch(setGroupFilters(group)); const filterChange = e => { dispatch(setSearchFilterAction(e.target.value)); @@ -24,6 +38,44 @@ export const Filter = () => { onChange={filterChange} /> + + + handleGroupChange(groupFilters.all)} + > + All + + handleGroupChange(groupFilters.family)} + > + Family + + handleGroupChange(groupFilters.friends)} + > + Friends + + handleGroupChange(groupFilters.work)} + > + Work + + handleGroupChange(groupFilters.others)} + > + Oters + + ); }; diff --git a/src/components/Filter/Filter.styled.jsx b/src/components/Filter/Filter.styled.jsx index d17a4d6..666cc7e 100644 --- a/src/components/Filter/Filter.styled.jsx +++ b/src/components/Filter/Filter.styled.jsx @@ -13,6 +13,7 @@ export const Label = styled.label` display: flex; align-items: center; gap: 20px; + margin-bottom: 10px; `; export const Input = styled.input` @@ -29,3 +30,16 @@ export const Input = styled.input` border-color: #e9af3d; } `; + +export const SortContainer = styled.div` + display: flex; + justify-content: space-between; + gap: 6px; +`; + +export const SortButton = styled.button` + padding: 8px 12px; + font-size: 16px; + color: #000000; + background-color: #e9af3d; +`; diff --git a/src/components/Layout/Layout.jsx b/src/components/Layout/Layout.jsx index 933400d..ac30d49 100644 --- a/src/components/Layout/Layout.jsx +++ b/src/components/Layout/Layout.jsx @@ -2,13 +2,14 @@ import { Outlet } from 'react-router-dom'; import { Suspense } from 'react'; import { AppBar } from 'components/AppBar/AppBar'; import { Container, Main } from './Layout.styled'; +import { HourglassLoader } from 'components/Loader/Loader'; const Layout = () => { return (
- + }>
diff --git a/src/hooks/useAuth.js b/src/hooks/useAuth.js index 019e308..98d2c7d 100644 --- a/src/hooks/useAuth.js +++ b/src/hooks/useAuth.js @@ -4,9 +4,11 @@ import { authSelectors } from '../redux/auth/authSelectors'; export const useAuth = () => { const isLoggedIn = useSelector(authSelectors.selectIsLoggedIn); const user = useSelector(authSelectors.selectUserName); + const isRefreshing = useSelector(authSelectors.selectIsRefreshing); return { isLoggedIn, user, + isRefreshing, }; }; diff --git a/src/redux/auth/authSelectors.js b/src/redux/auth/authSelectors.js index 160c542..c67f7ba 100644 --- a/src/redux/auth/authSelectors.js +++ b/src/redux/auth/authSelectors.js @@ -7,4 +7,5 @@ export const selectIsRefreshing = state => state.auth.isRefreshing; export const authSelectors = { selectIsLoggedIn, selectUserName, + selectIsRefreshing, }; diff --git a/src/redux/group/groupFilters.js b/src/redux/group/groupFilters.js new file mode 100644 index 0000000..71cbe62 --- /dev/null +++ b/src/redux/group/groupFilters.js @@ -0,0 +1,7 @@ +export const groupFilters = Object.freeze({ + all: 'all', + family: 'family', + friends: 'friends', + work: 'work', + others: 'others', +}); diff --git a/src/redux/group/groupSlice.js b/src/redux/group/groupSlice.js new file mode 100644 index 0000000..e1dd5a2 --- /dev/null +++ b/src/redux/group/groupSlice.js @@ -0,0 +1,17 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { groupFilters } from './groupFilters'; + +const groupSlice = createSlice({ + name: 'group', + initialState: { + group: groupFilters.all, + }, + reducers: { + setGroupFilters(state, action) { + state.group = action.payload; + }, + }, +}); + +export const { setGroupFilters } = groupSlice.actions; +export const sortReducer = groupSlice.reducer; diff --git a/src/redux/reducer.js b/src/redux/reducer.js index a6ca202..a67b962 100644 --- a/src/redux/reducer.js +++ b/src/redux/reducer.js @@ -4,6 +4,7 @@ import storage from 'redux-persist/lib/storage'; import { contactsReducer } from './contacts/contactsSlice'; import { filterReducer } from './filter/filterSlice'; import { authReducer } from './auth/authSlice'; +import { sortReducer } from './group/groupSlice.js'; const authPersistConfig = { key: 'auth', @@ -14,5 +15,6 @@ const authPersistConfig = { export const reducer = { contacts: contactsReducer, filter: filterReducer, + sort: sortReducer, auth: persistReducer(authPersistConfig, authReducer), }; diff --git a/src/redux/selectors.js b/src/redux/selectors.js index 78ffa42..06ec274 100644 --- a/src/redux/selectors.js +++ b/src/redux/selectors.js @@ -1,7 +1,7 @@ export const selectContacts = state => state.contacts.contacts; +export const selectError = state => state.contacts.error; +export const selectIsLoading = state => state.contacts.isLoading; export const selectFilterValue = state => state.filter.filter; -export const selectError = state => state.contacts.error; - -export const selectIsLoading = state => state.contacts.isLoading; +export const selectGroupFilters = state => state.filter.status;