Skip to content

Commit

Permalink
Merge pull request #4 from iVladyuser/redux_Persist
Browse files Browse the repository at this point in the history
Redux persist
  • Loading branch information
iVladyuser committed Nov 16, 2023
2 parents 76fdd0b + 0e3810c commit 494bfaf
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 122 deletions.
55 changes: 3 additions & 52 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,6 @@
import { nanoid } from 'nanoid';

import { ContactForm, ContactList, Filter } from 'components';
import { useDispatch, useSelector } from 'react-redux';
import { addContact, deleteContact } from 'redux/contacts/phoneBookSlice';
import { filterContact } from 'redux/contacts/filterSlice';

const App = () => {
const dispatch = useDispatch();
const contacts = useSelector(state => state.contactsStore.contacts);

const filter = useSelector(state => state.filterStore);

const handleDeleteContact = contactId => {
dispatch(deleteContact(contactId));
};

const handleAddContact = newContact => {
const isExist = contacts.some(
({ name }) => name.toLowerCase() === newContact.name.toLowerCase()
);

if (isExist) {
alert(`Oops, contact '${newContact.name}' is already in contacts!`);
return;
}
const readyToAddContact = {
...newContact,
id: nanoid(),
};

// const addContactAction = {
// type: 'contacts/addContact',
// payload: readyToAddContact,
// };
dispatch(addContact(readyToAddContact));
};

const changeFilter = value => {
dispatch(filterContact(value));
};

const getFilteredContacts = () => {
const normalizedFilter = filter.toLowerCase();
return contacts.filter(contact =>
contact.name.toLowerCase().includes(normalizedFilter)
);
};

return (
<div
style={{
Expand All @@ -58,13 +12,10 @@ const App = () => {
}}
>
<h1 style={{ color: '#3645ab' }}>Phonebook</h1>
<ContactForm onSubmit={handleAddContact} />
<ContactForm />
<h2>Contacts</h2>
<Filter value={filter} onChange={changeFilter} />
<ContactList
contacts={getFilteredContacts()}
onDeleteContact={handleDeleteContact}
/>
<Filter />
<ContactList />
</div>
);
};
Expand Down
14 changes: 0 additions & 14 deletions src/components/ContactCard/ContactCard.jsx

This file was deleted.

32 changes: 0 additions & 32 deletions src/components/ContactCard/ContactCard.styled.js

This file was deleted.

43 changes: 30 additions & 13 deletions src/components/ContactForm/ContactForm.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
import React, { useState } from 'react';
import { nanoid } from 'nanoid';
import { useDispatch, useSelector } from 'react-redux';
import { addContact } from 'redux/contacts/phoneBookSlice';
import { FormInput, Form, FormButton, FormLabel } from './ContactForm.styled';

const ContactForm = ({ onSubmit }) => {
const ContactForm = () => {
const [name, setName] = useState('');
const [number, setNumber] = useState('');

const dispatch = useDispatch();
const contacts = useSelector(state => state.contactsStore.contacts);

const onSubmitAddContact = e => {
e.preventDefault();
const data = {
name,
number: Number.parseFloat(number) || alert(`Number is not correct`),
};
const newContact = { ...data, id: nanoid() };

const isExist = contacts.some(
({ name }) => name.toLowerCase() === newContact.name.toLowerCase()
);

if (isExist) {
alert(`Oops, contact '${newContact.name}' is already in contacts!`);
return;
}

dispatch(addContact(newContact));
setName('');
setNumber('');
};

const handleInputChange = e => {
const { name, value } = e.currentTarget;
switch (name) {
Expand All @@ -20,19 +48,8 @@ const ContactForm = ({ onSubmit }) => {
}
};

const handleSubmit = e => {
e.preventDefault();
const contactSchema = {
name,
number: Number.parseFloat(number) || alert(`Number is not correct`),
};
onSubmit(contactSchema);
setName('');
setNumber('');
};

return (
<Form onSubmit={handleSubmit}>
<Form onSubmit={onSubmitAddContact}>
<FormLabel htmlFor="name">Name</FormLabel>
<FormInput
type="text"
Expand Down
41 changes: 34 additions & 7 deletions src/components/ContactList/ContactList.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,44 @@
import React from 'react';
import { List, ContactItem } from './ContactList.styled';
import ContactCard from '../ContactCard/ContactCard';
import { List, ContactItem, CardWrapper, ButtonDelete, Info } from './ContactList.styled';
import { useDispatch, useSelector } from 'react-redux';
import { deleteContact } from '../../redux/contacts/phoneBookSlice';


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

const contacts = useSelector(state => state.contactsStore.contacts);
const filter = useSelector(state => state.filterStore);

const normalizedFilter = filter.toLowerCase();
const visibleContacts = contacts.filter(contact =>
contact.name.toLowerCase().includes(normalizedFilter)
);

const handleDeleteContact = contactId => {
dispatch(deleteContact(contactId));
};




const ContactList = ({ contacts, onDeleteContact }) => {
return (
<List>
{contacts.map( contact => (
<ContactItem key={contact.id}>
<ContactCard contact={contact} onDeleteContact={onDeleteContact} />
<List>
{visibleContacts.map(({ name, number, id }) => (
<ContactItem key={id}>
<CardWrapper>
<Info>{name}</Info>
<Info>{number}</Info>
<ButtonDelete onClick={() => handleDeleteContact(id)}>
Delete
</ButtonDelete>
</CardWrapper>
</ContactItem>
))}
</List>
);
};

export default ContactList;


31 changes: 31 additions & 0 deletions src/components/ContactList/ContactList.styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,34 @@ max-width: 400px;
&:hover {
transform: scale(1.05);
}`;

export const CardWrapper = styled.div`
display: flex;
height: 100px;
flex-direction: row;
align-items: center;
gap: 8px;
justify-content: space-between;
`;

export const Info = styled.p`
font-size: 18px;
font-weight: 500;
letter-spacing: -0.3px;
`;

export const ButtonDelete = styled.button`
width: 70px;
height: 40px;
margin-left: 5px;
border-width: inherit;
border-radius: 5px;
outline: none;
background-color: #e22626;
color: white;
cursor: pointer;
&:focus {
background-color: #c72323;
}
`;
18 changes: 14 additions & 4 deletions src/components/Filter/Filter.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import React from 'react';
import { useDispatch, useSelector } from "react-redux";
import { filterContact} from '../../redux/contacts/filterSlice'
import { FilterContainer, FilterLabel, FilterInput } from './Filter.styled'

const Filter = ({ value, onChange }) => (
const Filter = () => {
const dispatch = useDispatch();
const filter = useSelector(state => state.filterStore);

const changeFilter = event => {
const { value } = event.currentTarget;
dispatch(filterContact(value));
};

<FilterContainer>
<FilterLabel>
Find contact by name
<FilterInput
type="text"
value={value}
value={filter}
placeholder="Enter name..."
onChange={e => onChange(e.target.value)}
onChange={changeFilter}
/>
</FilterLabel>
</FilterContainer>
);
};

export default Filter;

0 comments on commit 494bfaf

Please sign in to comment.