From 47dc857e2220e76bbe76a3098f2be1f84cae9a06 Mon Sep 17 00:00:00 2001 From: Yevhenii Datsenko Date: Thu, 15 Feb 2024 22:28:38 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20Final=20Version=20Commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/App/App.jsx | 99 ++++++++++++---------- src/components/App/App.module.css | 10 +++ src/components/ContactForm/ContactForm.jsx | 60 +++++++------ src/components/ContactList/ContactList.jsx | 42 ++++----- src/components/Filter/Filter.jsx | 13 ++- 5 files changed, 128 insertions(+), 96 deletions(-) diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx index 61dcc8c..8c53120 100644 --- a/src/components/App/App.jsx +++ b/src/components/App/App.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { Component } from 'react'; import { nanoid } from 'nanoid'; import styles from './App.module.css'; @@ -6,18 +6,19 @@ import ContactForm from '../ContactForm/ContactForm'; import ContactList from '../ContactList/ContactList'; import Filter from '../Filter/Filter'; -const App = () => { - const [contacts, setContacts] = useState([ - { id: 'id-1', name: 'Beyoncé', number: '342-12-44' }, - { id: 'id-2', name: 'Drake', number: '440-22-78' }, - { id: 'id-3', name: 'Taylor Swift', number: '897-11-20' }, - { id: 'id-4', name: 'Shawn Mendes', number: '284-91-51' }, - ]); - - const [filter, setFilter] = useState(''); +class App extends Component { + state = { + contacts: [ + { id: 'id-1', name: 'Beyoncé', number: '342-12-44' }, + { id: 'id-2', name: 'Drake', number: '440-22-78' }, + { id: 'id-3', name: 'Taylor Swift', number: '897-11-20' }, + { id: 'id-4', name: 'Shawn Mendes', number: '284-91-51' }, + ], + filter: '', + }; - const addContact = contact => { - const isInContacts = contacts.some( + addContact = contact => { + const isInContacts = this.state.contacts.some( ({ name }) => name.toLowerCase() === contact.name.toLowerCase() ); @@ -25,18 +26,17 @@ const App = () => { alert(`${contact.name} is already in contacts`); return; } - - setContacts(prevContacts => [ - { id: nanoid(), ...contact }, - ...prevContacts, - ]); + this.setState(prevState => ({ + contacts: [{ id: nanoid(), ...contact }, ...prevState.contacts], + })); }; - const changeFilter = event => { - setFilter(event.target.value); + changeFilter = event => { + this.setState({ filter: event.target.value }); }; - const getVisibleContacts = () => { + getVisibleContacts = () => { + const { filter, contacts } = this.state; const normalizedFilter = filter.toLowerCase(); return contacts.filter(contact => @@ -44,34 +44,41 @@ const App = () => { ); }; - const removeContact = contactId => { - setContacts(prevContacts => - prevContacts.filter(({ id }) => id !== contactId) - ); + removeContact = contactId => { + this.setState(prevState => { + return { + contacts: prevState.contacts.filter(({ id }) => id !== contactId), + }; + }); }; - const visibleContacts = getVisibleContacts(); + render() { + const visibleContacts = this.getVisibleContacts(); + const { filter } = this.state; - return ( -
-

Phonebook

- - {contacts.length > 0 ? ( - <> -

Contacts

- - - ) : ( -

Your phonebook is empty. Add first contact!

- )} - {contacts.length > 0 && ( - - )} -
- ); -}; + return ( +
+

Phonebook

+ + + +

Contacts

+ {this.state.contacts.length > 0 ? ( + + ) : ( +

+ Your phonebook is empty. Add first contact! +

+ )} + {this.state.contacts.length > 0 && ( + + )} +
+ ); + } +} export default App; diff --git a/src/components/App/App.module.css b/src/components/App/App.module.css index 8a0dbc7..55f6210 100644 --- a/src/components/App/App.module.css +++ b/src/components/App/App.module.css @@ -5,3 +5,13 @@ text-align: center; margin-top: 20px; } + +.noContacts { + text-align: center; + margin-top: 20px; + font-family: -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, + sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; + font-size: 18px; + font-weight: 600; + line-height: 40px; +} diff --git a/src/components/ContactForm/ContactForm.jsx b/src/components/ContactForm/ContactForm.jsx index 944d222..64c1c05 100644 --- a/src/components/ContactForm/ContactForm.jsx +++ b/src/components/ContactForm/ContactForm.jsx @@ -1,54 +1,60 @@ -import React, { useState } from 'react'; +import React from 'react'; import { nanoid } from 'nanoid'; import styles from './ContactForm.module.css'; -const ContactForm = ({ onSubmit }) => { - const [name, setName] = useState(''); - const [number, setNumber] = useState(''); +class ContactForm extends React.Component { + state = { + name: '', + number: '', + }; + + nameInputId = nanoid(); + numberInputId = nanoid(); - const handleSubmit = event => { + handleSubmit = event => { event.preventDefault(); - onSubmit({ name, number }); - setName(''); - setNumber(''); + + this.props.onSubmit({ name: this.state.name, number: this.state.number }); + + this.reset(); }; - const handleChange = event => { + handleChange = event => { const { name, value } = event.target; - if (name === 'name') { - setName(value); - } else if (name === 'number') { - setNumber(value); - } + this.setState({ [name]: value }); + }; + + reset = () => { + this.setState({ number: '', name: '' }); }; - return ( -
-
-
- ); -}; + ); + } +} export default ContactForm; diff --git a/src/components/ContactList/ContactList.jsx b/src/components/ContactList/ContactList.jsx index ca5ce8b..43658cb 100644 --- a/src/components/ContactList/ContactList.jsx +++ b/src/components/ContactList/ContactList.jsx @@ -1,26 +1,30 @@ import React from 'react'; +import PropTypes from 'prop-types'; import styles from './ContactList.module.css'; const ContactList = ({ contacts, onRemoveContact }) => ( -
- -
+ ); +ContactList.propTypes = { + contacts: PropTypes.object.isRequired, + onRemoveContact: PropTypes.func.isRequired, +}; + export default ContactList; diff --git a/src/components/Filter/Filter.jsx b/src/components/Filter/Filter.jsx index 5b06430..263ee6f 100644 --- a/src/components/Filter/Filter.jsx +++ b/src/components/Filter/Filter.jsx @@ -1,7 +1,8 @@ import React from 'react'; +import PropTypes from 'prop-types'; import styles from './Filter.module.css'; -const Filter = ({ value, onChangeFilter }) => { +function Filter({ value, onChangeFilter }) { return (
); +} + +Filter.propTypes = { + value: PropTypes.string.isRequired, + onChangeFilter: PropTypes.func.isRequired, }; export default Filter;