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

checking out starter-files-added #5

Open
wants to merge 30 commits into
base: starter-files-added
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c1bc05e
Add default contacts and the ListContacts component
tylermcginnis Mar 1, 2018
59e929c
Render default contacts
tylermcginnis Mar 2, 2018
7e77074
Display contact avatar, name, email, and remove button
tylermcginnis Mar 2, 2018
b7b51c9
Convert ListContacts to a Stateless Functional Component
tylermcginnis Mar 2, 2018
d3d6eee
Move default contacts into App component as state
tylermcginnis Mar 2, 2018
4b65612
Hook up delete button to remove contacts
tylermcginnis Mar 2, 2018
094067a
Add PropTypes package to verify ListContacts props
tylermcginnis Mar 2, 2018
df432ab
Convert ListContacts to a controlled component with a search field
tylermcginnis Mar 2, 2018
1671c5c
Filter and sort the contacts that are searched for
tylermcginnis Mar 2, 2018
4e1e41b
Adds 'Now showing' section with link to clear the search query
tylermcginnis Mar 2, 2018
bcd703a
Uh. I forgot this file
tylermcginnis Mar 2, 2018
30cd650
Use componentDidMount to fetch contacts from the server
tylermcginnis Mar 2, 2018
c85cb59
Remove contact from database when deleted in the app
tylermcginnis Mar 2, 2018
e4a527d
Add CreateContact component that's displayed based on state
tylermcginnis Mar 2, 2018
93ff543
Add button to create contacts
tylermcginnis Mar 2, 2018
fbd0cea
Install the react-router-dom package
tylermcginnis Mar 2, 2018
d1b067f
Wrap App in BrowserRouter component
tylermcginnis Mar 2, 2018
1197d9d
Turn create contact link into a Link component
tylermcginnis Mar 2, 2018
66dcafc
Use Routes to control page content
tylermcginnis Mar 2, 2018
4b1693f
Build form to create new contacts
tylermcginnis Mar 2, 2018
69c8b52
Serialize new contact fields and pass to parent component
tylermcginnis Mar 2, 2018
f876f2d
Save new contact to the server
tylermcginnis Mar 2, 2018
3e2f90a
Updated README.md
veronikabenkeser Nov 19, 2018
139b052
Updated dependencies.
veronikabenkeser Nov 19, 2018
0f6798e
Update dependencies
veronikabenkeser Nov 20, 2018
87b1565
Update README.md
veronikabenkeser Nov 20, 2018
d2d9c26
Update README.
hbkwong Dec 4, 2018
108f89f
git adds- learning this tool.
TreeStrepek Apr 24, 2019
35b3bcc
Update App.js
TreeStrepek Apr 24, 2019
6009b98
Merge branch 'master' of https://github.com/TreeStrepek/reactnd-conta…
TreeStrepek Apr 24, 2019
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
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ Most of the commits in this repository correspond to videos in the program.

## Project Setup

* clone the Project - `git clone https://github.com/udacity/reactnd-contacts-complete.git`
* install the dependencies - `npm install`
- Clone the project - `git clone https://github.com/udacity/reactnd-contacts-complete.git`
- Install the dependencies - `npm install`

## Backend Server

The backend server for this in-class project can be found [here](https://github.com/udacity/reactnd-contacts-server).

## Contributing

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.

## License

MIT
14,944 changes: 14,944 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

24 changes: 18 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "1.1.1"
"form-serialize": "^0.7.2",
"prop-types": "^15.6.2",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.1"
},
"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"
]
}
54 changes: 50 additions & 4 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,59 @@
import React, { Component } from 'react';
import React, { Component } from 'react'
import ListContacts from './ListContacts'
import * as ContactsAPI from './utils/ContactsAPI'
import CreateContact from './CreateContact'
import { Route } from 'react-router-dom'

// testing a little comment to change file.
class App extends Component {
state = {
contacts: []
}
componentDidMount() {
ContactsAPI.getAll()
.then((contacts) => {
this.setState(() => ({
contacts
}))
})
}
removeContact = (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.removeContact}
/>
)} />
<Route path='/create' render={({ history }) => (
<CreateContact
onCreateContact={(contact) => {
this.createContact(contact)
history.push('/')
}}
/>
)} />
</div>
);
)
}
}

export default App;
export default App
40 changes: 40 additions & 0 deletions src/CreateContact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import ImageInput from './ImageInput'
import serializeForm from 'form-serialize'

class CreateContact extends Component {
handleSubmit = (e) => {
e.preventDefault()
const values = serializeForm(e.target, { hash: true })

if (this.props.onCreateContact) {
this.props.onCreateContact(values)
}
}
render() {
return (
<div>
<Link
className='close-create-contact'
to='/'>
Close
</Link>
<form onSubmit={this.handleSubmit} 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
1 change: 1 addition & 0 deletions src/ImageInput.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'

//added a little comment to test my version control
const readFileAsDataURL = (file) =>
new Promise(resolve => {
const reader = new FileReader()
Expand Down
80 changes: 80 additions & 0 deletions src/ListContacts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'

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.updateQuery('')
}
render() {
const { query } = this.state
const { contacts, onDeleteContact } = this.props

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

return (
<div className='list-contacts'>
<div className='list-contacts-top'>
<input
className='search-contacts'
type='text'
placeholder='Search Contacts'
value={query}
onChange={(event) => this.updateQuery(event.target.value)}
/>
<Link
to='/create'
className='add-contact'
>Add Contact</Link>
</div>

{showingContacts.length !== contacts.length && (
<div className='showing-contacts'>
<span>Now showing {showingContacts.length} of {contacts.length}</span>
<button onClick={this.clearQuery}>Show all</button>
</div>
)}

<ol className='contact-list'>
{showingContacts.map((contact) => (
<li key={contact.id} className='contact-list-item'>
<div
className='contact-avatar'
style={{
backgroundImage: `url(${contact.avatarURL})`
}}
></div>
<div className='contact-details'>
<p>{contact.name}</p>
<p>{contact.handle}</p>
</div>
<button
onClick={() => onDeleteContact(contact)}
className='contact-remove'>
Remove
</button>
</li>
))}
</ol>
</div>
)
}
}

export default ListContacts
6 changes: 5 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom'
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

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