diff --git a/contacts/package.json b/contacts/package.json
index 47a3a6d..630d416 100644
--- a/contacts/package.json
+++ b/contacts/package.json
@@ -3,9 +3,11 @@
"version": "0.1.0",
"private": true,
"dependencies": {
+ "escape-string-regexp": "^1.0.5",
"react": "^15.6.1",
"react-dom": "^15.6.1",
- "react-scripts": "1.0.12"
+ "react-scripts": "1.0.12",
+ "sort-by": "^1.2.0"
},
"scripts": {
"start": "react-scripts start",
@@ -13,4 +15,4 @@
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
-}
\ No newline at end of file
+}
diff --git a/contacts/src/ListContacts.js b/contacts/src/ListContacts.js
index 92849eb..30cb713 100644
--- a/contacts/src/ListContacts.js
+++ b/contacts/src/ListContacts.js
@@ -1,28 +1,76 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
+import escapeRegExp from 'escape-string-regexp'
+import sortBy from 'sort-by'
-const ListContacts = ({contacts, onDeleteContact}) =>
-
- {contacts.map( (contact) =>
- -
-
-
-
{contact.name}
-
{contact.email}
-
-
-
- )}
-
+class ListContacts extends Component {
+ static propTypes = {
+ contacts: PropTypes.array.isRequired,
+ onDeleteContact: PropTypes.func.isRequired
+ }
+
+ state = {
+ query: ''
+ }
+
+ updateQuery = (query) => {
+ this.setState({query: query.trim() })
+ }
+
+ clearQuery = () => {
+ this.setState({ query: ''})
+ }
+ render() {
+ const {contacts, onDeleteContact} = this.props
+ const {query} = this.state
-ListContacts.propTypes = {
- contacts: PropTypes.array.isRequired,
- onDeleteContact: PropTypes.func.isRequired
+ let showingContacts
+ if (query) {
+ const match = new RegExp(escapeRegExp(query), 'i')
+ showingContacts = contacts.filter((contact)=>match.test(contact.name))
+ } else {
+ showingContacts = contacts
+ }
+
+ showingContacts.sort(sortBy('name'))
+
+ return (
+
+
+ this.updateQuery(event.target.value)}
+ />
+
+ {showingContacts.length !== contacts.length && (
+
+ Now showing {showingContacts.length} of {contacts.length}
+
+
+ )}
+
+ {showingContacts.map( (contact) =>
+ -
+
+
+
{contact.name}
+
{contact.email}
+
+
+
+ )}
+
+
+ )
+ }
}
export default ListContacts
\ No newline at end of file
diff --git a/contacts/src/index.css b/contacts/src/index.css
index 8eec922..e1d4b23 100644
--- a/contacts/src/index.css
+++ b/contacts/src/index.css
@@ -114,7 +114,7 @@ body, .app {
font-size: 0;
}
-.showing-contact {
+.showing-contacts {
text-align: center;
margin: 20px 0;
}
diff --git a/contacts/yarn.lock b/contacts/yarn.lock
index 1e8de4a..9171d35 100644
--- a/contacts/yarn.lock
+++ b/contacts/yarn.lock
@@ -4302,6 +4302,10 @@ object-keys@^1.0.8:
version "1.0.11"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
+object-path@0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.6.0.tgz#b69a7d110937934f336ca561fd9be1ad7b7e0cb7"
+
object.omit@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
@@ -5055,7 +5059,7 @@ react-dev-utils@^4.0.0:
strip-ansi "3.0.1"
text-table "0.2.0"
-react-dom@15.6.1, "react-dom@^15 || ^16":
+"react-dom@^15 || ^16", react-dom@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.1.tgz#2cb0ed4191038e53c209eb3a79a23e2a4cf99470"
dependencies:
@@ -5119,7 +5123,7 @@ react-scripts@1.0.12:
optionalDependencies:
fsevents "1.1.2"
-react@15.6.1, "react@^15 || ^16":
+"react@^15 || ^16", react@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"
dependencies:
@@ -5616,6 +5620,12 @@ sockjs@0.3.18:
faye-websocket "^0.10.0"
uuid "^2.0.2"
+sort-by@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/sort-by/-/sort-by-1.2.0.tgz#ed92bbff9fd2284b41f6503e38496607b225fe6f"
+ dependencies:
+ object-path "0.6.0"
+
sort-keys@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"