Skip to content
This repository was archived by the owner on Jun 28, 2022. It is now read-only.

New start #19

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ Most of the commits in this repository correspond to videos in the program.
Because this is a code-along project and the commits correspond to specific videos in the program, we will not be accepting pull requests.

If you feel like there's a major problem, please open an issue to discuss the problem and potential resolution.

## Contributing

MIT
33,396 changes: 33,396 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

26 changes: 20 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,28 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "1.1.1"
"escape-string-regexp": "^5.0.0",
"form-serialize": "^0.7.2",
"prop-types": "^15.8.1",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.1",
"sort-by": "^1.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
}
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
50 changes: 48 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,56 @@
import React, { Component } from 'react';

import ListContacts from './ListContacts';
import * as ContactsApi from './utils/ContactsAPI'
import { Route } from 'react-router-dom'
import CreateContact from "./createContact";
class App extends Component {

state = {
contacts: []
}
componentDidMount() {
ContactsApi.getAll().then((contacts) => {
this.setState({
contacts
})
})
}

deleteContact = (contact) => {
this.setState((currentState) => ({
contacts: currentState.contacts.filter((c) => {
return c.id !== contact.id
})
}))

ContactsApi.remove(contact)
}

createContact = (contact) => {
ContactsApi.create(contact).then((contact) => {
this.setState((currentState) => ({
contacts: currentState.contacts.concat([contact])
}
))
})
}

render() {
return (
<div>
Hello World
<Route exact path="/" render={() => (
<ListContacts contacts={this.state.contacts} onDeleteContact={this.deleteContact} />
)} >

</Route>
<Route
path="/create" render={({ history }) => (
<CreateContact onCreateContact={(contact) => {
this.createContact(contact)
history.push('/')
}} />)
}
></Route>
</div>
);
}
Expand Down
89 changes: 89 additions & 0 deletions src/ListContacts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'

class ListContacts extends Component {

state = {
query: ''
}
updateQuery = (query) => {
this.setState(() => ({
query: (query !== '' && query.length > 0) ? query.trim() : query
}))
}

static propTypes = {
contacts: PropTypes.array.isRequired,
onDeleteContact: PropTypes.func.isRequired
}

clearQuery() {
this.updateQuery('')
}


render() {
const { contacts, onDeleteContact } = this.props
const { query } = this.state

const showedContacts = query === ''
? contacts
: contacts.filter((c) => (c.name.toLowerCase().includes(query.toLowerCase()))
)

return (
<div className='list-contacts'>
<div className='list-contacts-top'>
<input type="text" className='search-contacts' placeholder='Search contacts' value={query} onChange={(event) => this.updateQuery(event.target.value)}></input>
<Link
to='/create'
className="add-contact"
>
Add Contact
</Link>
</div>
{
showedContacts.length !== contacts.length && (
<div className='showing-contacts'>
<span> Now showing {showedContacts.length} of {contacts.length}
</span>
<button onClick={() => this.clearQuery()}>
Show all
</button>
</div>
)
}
<ol className='contact-list'>
{showedContacts.map((item) =>
(
<li className='contact-list-item' key={item.id}>
<div className='contact-avatar'
style={{
backgroundImage: `url(${item.avatarURL})`
}}
>
</div>
<div className='contact-details'>
<p>
{item.name}
</p>
<p>
@{item.handle}
</p>
</div>
<button className='contact-remove' onClick={() => onDeleteContact(item)} >
</button>
</li>
)
)}
</ol>
</div>

)
}
}



export default ListContacts
39 changes: 39 additions & 0 deletions src/createContact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import ImageInput from './ImageInput'
import serializeForm from 'form-serialize'
class CreateContact extends Component {
handleOnSubmit = (e) => {
debugger
e.preventDefault();
let values = serializeForm (e.target ,{hash:true})
this.props.onCreateContact(values )
}
render() {

return (
<div>
<Link
className='close-create-contact'
to='/'
>
Close
</Link>
<form onSubmit={this.handleOnSubmit} className='create-contact-form'>
<ImageInput
className='create-contact-avatar-input'
name='avatarURL'
maxHeight={64}
/>
<div className='create-contact-details'>
<input type='text' name='name' placeholder='Name' />
<input type='text' name='handle' placeholder='Handle' />
<button>Add Contact</button>
</div>
</form>
</div>
)
}
}

export default CreateContact
5 changes: 4 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM.render(
<BrowserRouter>
<App /></BrowserRouter>, document.getElementById('root'));
registerServiceWorker();
31 changes: 31 additions & 0 deletions src/utils/ContactsAPI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const api = process.env.REACT_APP_CONTACTS_API_URL || 'http://localhost:5001'

let token = localStorage.token

if (!token)
token = localStorage.token = Math.random().toString(36).substr(-8)

const headers = {
'Accept': 'application/json',
'Authorization': token
}

export const getAll = () =>
fetch(`${api}/contacts`, { headers })
.then(res => res.json())
.then(data => data.contacts)

export const remove = (contact) =>
fetch(`${api}/contacts/${contact.id}`, { method: 'DELETE', headers })
.then(res => res.json())
.then(data => data.contact)

export const create = (body) =>
fetch(`${api}/contacts`, {
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
}).then(res => res.json())
Loading