Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## Contact List

This project has been created by a student at Parsity, an online software engineering course. The work in this repository is wholly of the student based on a sample starter project that can be accessed by looking at the repository that this project forks.
This project has been created by Paul Johnson, a student at Parsity, an online software engineering course. The work in this repository is wholly mine based on a sample starter project that can be accessed by looking at the repository that this project forks.

If you have any questions about this project or the program in general, visit [parsity.io](https://parsity.io/) or email hello@parsity.io.
45,577 changes: 20,283 additions & 25,294 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^12.8.3",
"bootstrap": "^5.2.3",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"react-router-dom": "^5.3.0",
"react-scripts": "^5.0.1",
"web-vitals": "^1.1.1"
},
"scripts": {
Expand Down
80 changes: 80 additions & 0 deletions src/AddContact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.css';

const AddContact = ({ addContact }) => {
const [newContact, setNewContact] = useState({ photo_url: '', name: '', email: '', phone_number: '', });
const history = useHistory();
//using state and history to create the new contact and allowing it to be passed into the contactList state

const handleAddContact = () => {
const contact = {
id: Math.round(Math.random() * 100000000),
photo_url: newContact.photo_url,
name: newContact.name,
email: newContact.email,
phone_number: newContact.phone_number,
};
//button functionality to add desired info

addContact(contact);

setNewContact({ photo_url: '', name: '', email: '', phone_number: '', id: ''});

history.push('./contactlist');
//adding the contact to the contact list history
};

return (//creating form and input fields for user to add contact info
<form>
<div className='form-add'>
<input
type="text"
placeholder="Photo"
value={newContact.photo_url}
onChange={(e) => setNewContact({ ...newContact, photo_url: e.target.value })}
/>
</div>
<div className='form-add'>
<input
type="text"
placeholder="Name"
value={newContact.name}
onChange={(e) => setNewContact({ ...newContact, name: e.target.value })}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't feel the need to abbreviate to single letters - its better to spell the whole thing out so that others have more context to what your parameters are.

/>
</div>
<div className='form-add'>
<input
type="text"
placeholder="Email"
value={newContact.email}
onChange={(e) => setNewContact({ ...newContact, email: e.target.value })}
/>
</div>
<div className='form-add'>
<input
type="text"
placeholder="Phone Number"
value={newContact.phone_number}
onChange={(e) => setNewContact({ ...newContact, phone_number: e.target.value })}
/>
</div>
<div class='hidden'>
{/* //hiding this input field because math.random will create this info above */}
<input
type="text"
placeholder="ID"
value={newContact.id}
onChange={(e) => setNewContact({ ...newContact, id: e.target.value })}
/>
</div>
<button class="btn btn-light"
data-toggle="button"
aria-pressed="false"
autoComplete="off"
onClick={handleAddContact}>Save New Contact</button>
</form>
);
};

export default AddContact;
33 changes: 33 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
text-align: center;
}

* {
background-color: rgb(152, 152, 173);
}

.App-logo {
height: 40vmin;
pointer-events: none;
Expand Down Expand Up @@ -36,3 +40,32 @@
transform: rotate(360deg);
}
}

h1 {
color: rgb(1, 1, 3);
text-align: center;
font-size: 50px;

}

.form-add {
margin: 18px;

}

form {
text-align: center;
}

input {
background-color: rgb(255, 255, 255);
}

a {
background-color: transparent;
}

.hidden {
visibility: hidden;
}

90 changes: 71 additions & 19 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,77 @@
import logo from './logo.svg';
import './App.css';
import AddContact from './AddContact';
import ContactInfo from './ContactInfo';
import ContactList from './ContactList';
import React, { useState } from 'react';
import { Route, Switch } from "react-router-dom";
import 'bootstrap/dist/css/bootstrap.css';
import PropTypes from 'prop-types'
//mucho importing

function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>

const App = () => {
const [contacts, setContacts] = useState (
[
{
id: 70219577,
name: "Albert Einstein",
photo_url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSeVHlg2A2iP8rkLDDlZasabaW67-oCMv-ExrLzyWbjrjLigtVCcYTa50_8eQ3B_BiK6Fc&usqp=CAU",
email: "aeinstein@example.com",
phone_number: "15555555555"
},
{
id: Math.round(Math.random() * 100000000),
name: "Alby Einy",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice default contacts!

photo_url: "https://media-cldnry.s-nbcnews.com/image/upload/t_fit-1500w,f_auto,q_auto:best/msnbc/Components/Photos/z_Projects_in_progress/050418_Einstein/050405_einstein_tongue.jpg",
email: "aeinstein@example.com",
phone_number: "15555555556"
},
{
id: Math.round(Math.random() * 100000000),
name: 'Derek Zoolander',
photo_url: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8rqZ7FsLUzzqSJ9brWjJ5-3RuBdWw4mQpzA&usqp=CAU',
email: 'DerekZ@Zoolandy.com',
phone_number: '3245673332'
}
]
)

const addContact = (newContact) => {
setContacts([...contacts, newContact]);
};

const deleteContact = (contactId) => {
const updatedContacts = contacts.filter((c) => c.id !== contactId);
setContacts(updatedContacts)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget semi-colons at the end of the line

}//want to make sure these are available for children componenets

return (//creating the routes and header for the page. making sure to pass all the components/functions to necessary routes
<div className='App-container'>
<div className='row'>
<header>
<h1>Contact List</h1>
</header>
<div>
<Switch>
<Route exact path='/contactlist' render = {() => (<ContactList contacts={contacts} addContact={addContact} deleteContact={deleteContact}/>)}/>
<Route path='/contactlist/:Profile' render = {(routerProps) => (<ContactInfo id={routerProps.match.params.Profile} contacts={contacts}></ContactInfo>)}/>
<Route path='/addcontact' render= {() => <AddContact addContact={addContact}></AddContact>}/>
</Switch>
</div>
</div>
);
</div>
)
}

App.propTypes = {
contacts: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
phone_number: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
photo_url: PropTypes.string.isRequired,
})
).isRequired,
}

export default App;
export default App;
43 changes: 43 additions & 0 deletions src/ContactInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//view contact profile for each person showing name, email, etc.
//have a way back that returns to './contactlist (i'll use Link)

import React from 'react';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import _ from 'lodash'

function ContactInfo ({ contacts, id }) {
const index = parseInt(id, 10);
const contact = _.find(contacts,{id: parseInt(id)});

if (!contact) {
return <div>Could not find this contact</div>;
};
//have a statement stating if the contact clicked is not found (which shouldn't happen if everything is working well)

return (//return the template to display the contact's info within
<div className='contact-card align-items-center justify-content-center'>
<div className='card-row'>
<ul>
<li><img src={contact.photo_url} width={95} height={125} alt='Contact lost their face in a freak gasoline fight accident' /></li>
<li>Name: {contact.name}</li>
<li>Email: {contact.email}</li>
<li>Number: {contact.phone_number}</li>
<li>ID: {contact.id}</li>
</ul>
</div>
<div className='link-row'>
{/* add a link back to contactlist */}
<Link to='/contactlist'>Return to Contact List</Link>
</div>
</div>
);
}

ContactInfo.propTypes = {
contacts:
PropTypes.arrayOf(PropTypes.object).isRequired,
id: PropTypes.string.isRequired,
};

export default ContactInfo
78 changes: 78 additions & 0 deletions src/ContactList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import './App.css';
import React, { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import { Link, useHistory } from "react-router-dom";
import PropTypes from 'prop-types'

const ContactList = ({contacts, deleteContact}) => {
//make sure contact list displays contacts and removes contacts with delete button
const [contactList, setContactList] = useState (contacts)
//setting state for the list
const history = useHistory();

const goToAddContactRoute = () => {history.push('/addcontact')}
//adding function for button below to go to add contact page
const handleDeleteContact = (contactId) => {
const updatedContacts = contactList.filter((c) => c.id !== contactId);

setContactList(updatedContacts);

deleteContact(contactId)
//this function deletes contact and updates contactList after click
}

return(//returning a template for the contacts to display in
<div className='contact-container'>
<div className='row'>
<div className='col-md-10 offset-1'>
<table className='table table-hover table-bordered table-striped table-dark'>
<thead className='thead-dark'>
<tr>
<th scope='col'></th>
<th scope='col'>Photo</th>
<th scope='col'>Name</th>
<th scope='col'>Number</th>
<th scope='col'>Email</th>
<th scope='col'>ID #</th>
</tr>
</thead>
<tbody>
{contacts.map((c) => //mapping the contact data to plug into the table created above
<tr key={c.id}>
<td><button type='button' className='btn btn-danger' onClick={() => handleDeleteContact(c.id)}>Delete Contact</button></td>
<td><img src={c.photo_url} width={60} height={60} alt='No Photo to display'/></td>
<td><Link to={`/contactlist/${c.id}`}>{c.name}</Link></td>
<td>{c.phone_number}</td>
<td>{c.email}</td>
<td>{c.id}</td>
</tr>
)}
</tbody>
</table>
<div>
{/* made a button to go to add contact page and utilzied function above in order to implement click functionality */}
<button type="button"
className="btn btn-light"
data-toggle="button"
aria-pressed="false"
autoComplete="off"
onClick={goToAddContactRoute}>Create New Contact</button>
</div>
</div>
</div>
</div>
)
};

ContactList.propTypes = {
contacts: PropTypes.arrayOf(PropTypes.shape(
{id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
phone_number: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
photo_url: PropTypes.string.isRequired,
})
).isRequired,
};

export default ContactList
17 changes: 8 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { BrowserRouter } from 'react-router-dom';
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap';
import App from './App.js';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';


ReactDOM.render(
<React.StrictMode>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
);