Skip to content

Commit 8b3668a

Browse files
shsonshson
authored andcommitted
first commit
1 parent 5163fa4 commit 8b3668a

10 files changed

Lines changed: 4915 additions & 0 deletions

File tree

package-lock.json

Lines changed: 4462 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "codelab-tut",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {
6+
"test": "echo \"Error: no test specified\" && exit 1",
7+
"dev-server": "webpack-dev-server"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"description": "",
12+
"dependencies": {
13+
"babel-preset-stage-0": "^6.5.0",
14+
"react": "^15.3.1",
15+
"react-addons-update": "^15.3.1",
16+
"react-dom": "^15.3.1"
17+
},
18+
"devDependencies": {
19+
"babel-core": "^6.13.2",
20+
"babel-loader": "^6.2.4",
21+
"babel-preset-es2015": "^6.13.2",
22+
"babel-preset-react": "^6.11.1",
23+
"react-hot-loader": "^1.3.0",
24+
"webpack": "^1.13.1",
25+
"webpack-dev-server": "^1.14.1"
26+
}
27+
}

public/index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<title>React App</title>
7+
</head>
8+
9+
<body>
10+
<div id="root"></div>
11+
<script src="bundle.js"></script>
12+
</body>
13+
14+
</html>

src/components/App.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
import Contact from './Contact';
3+
4+
class App extends React.Component {
5+
render() {
6+
return (
7+
<Contact/>
8+
);
9+
}
10+
}
11+
12+
export default App;

src/components/Contact.js

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import React from 'react';
2+
import ContactInfo from './ContactInfo';
3+
import ContactDetails from './ContactDetails';
4+
import ContactCreate from './ContactCreate';
5+
6+
import update from 'react-addons-update';
7+
8+
export default class Contact extends React.Component {
9+
10+
constructor(props) {
11+
super(props);
12+
this.state = {
13+
selectedKey: -1,
14+
keyword: '',
15+
nextId: 4,
16+
contactData: [{
17+
id: 0,
18+
name: 'Abet',
19+
phone: '010-0000-0001'
20+
}, {
21+
id: 1,
22+
name: 'Betty',
23+
phone: '010-0000-0002'
24+
}, {
25+
id: 2,
26+
name: 'Charlie',
27+
phone: '010-0000-0003'
28+
}, {
29+
id: 3,
30+
name: 'David',
31+
phone: '010-0000-0004'
32+
}]
33+
};
34+
35+
this.handleChange = this.handleChange.bind(this);
36+
this.handleClick = this.handleClick.bind(this);
37+
38+
this.handleCreate = this.handleCreate.bind(this);
39+
this.handleRemove = this.handleRemove.bind(this);
40+
this.handleEdit = this.handleEdit.bind(this);
41+
42+
}
43+
44+
componentWillMount() {
45+
const contactData = localStorage.contactData;
46+
const nextId = localStorage.nextId;
47+
48+
if(contactData) {
49+
this.setState({
50+
contactData: JSON.parse(contactData),
51+
nextId
52+
})
53+
}
54+
}
55+
56+
componentDidUpdate(prevProps, prevState) {
57+
if(JSON.stringify(prevState.contactData) != JSON.stringify(this.state.contactData)) {
58+
localStorage.contactData = JSON.stringify(this.state.contactData);
59+
}
60+
61+
if(prevState.nextId !== this.state.nextId){
62+
localStorage.nextId = this.state.nextId;
63+
}
64+
}
65+
66+
67+
handleChange(e) {
68+
this.setState({
69+
keyword: e.target.value
70+
});
71+
}
72+
73+
handleClick(id) {
74+
this.setState({
75+
selectedId: id
76+
});
77+
78+
console.log(id, 'is selected');
79+
}
80+
81+
handleCreate(contact) {
82+
contact.id = this.state.nextId;
83+
84+
this.setState({
85+
contactData: update(this.state.contactData, { $push: [contact] }),
86+
nextId: this.state.nextId + 1
87+
});
88+
}
89+
90+
handleRemove() {
91+
if(this.state.selectedId < 0) {
92+
return;
93+
}
94+
95+
this.setState({
96+
contactData: update(this.state.contactData,
97+
{ $splice: [[this.state.selectedId, 1]] }
98+
),
99+
selectedId: -1
100+
});
101+
}
102+
103+
handleEdit(name, phone) {
104+
this.setState({
105+
contactData: update(this.state.contactData,
106+
{
107+
[this.state.selectedId]: {
108+
name: { $set: name },
109+
phone: { $set: phone }
110+
}
111+
}
112+
)
113+
});
114+
}
115+
116+
render() {
117+
const mapToComponents = (data) => {
118+
data = data.slice().sort((a,b) => a.name > b.name);
119+
data = data.filter(
120+
(contact) => {
121+
return contact.name.toLowerCase()
122+
.indexOf(this.state.keyword.toLowerCase()) > -1;
123+
}
124+
);
125+
return data.map((contact, i) => {
126+
return (<ContactInfo
127+
contact={contact}
128+
key={i}
129+
onClick={() => this.handleClick(contact.id)}/>);
130+
});
131+
};
132+
133+
return (
134+
<div>
135+
<h1>Contacts</h1>
136+
<input
137+
name="keyword"
138+
placeholder="Search"
139+
value={this.state.keyword}
140+
onChange={this.handleChange}
141+
/>
142+
<div>{mapToComponents(this.state.contactData)}</div>
143+
<ContactDetails
144+
isSelected={this.state.selectedId != -1}
145+
contact={this.state.contactData[this.state.selectedId]}
146+
onRemove={this.handleRemove}
147+
onEdit={this.handleEdit}
148+
/>
149+
<ContactCreate
150+
onCreate={this.handleCreate}
151+
/>
152+
</div>
153+
);
154+
}
155+
}

src/components/ContactCreate.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React from 'react';
2+
3+
export default class ContactCreate extends React.Component {
4+
constructor(props) {
5+
super(props);
6+
this.state = {
7+
name: '',
8+
phone: ''
9+
};
10+
this.handleChange = this.handleChange.bind(this);
11+
this.handleClick = this.handleClick.bind(this);
12+
this.handleKeyPress = this.handleKeyPress.bind(this);
13+
}
14+
15+
handleChange(e) {
16+
let nextState = {};
17+
nextState[e.target.name] = e.target.value;
18+
this.setState(nextState)
19+
}
20+
21+
handleClick() {
22+
const contact = {
23+
name: this.state.name,
24+
phone: this.state.phone
25+
};
26+
27+
this.props.onCreate(contact);
28+
29+
this.setState({
30+
name: '',
31+
phone: ''
32+
});
33+
34+
this.nameInput.focus();
35+
}
36+
37+
handleKeyPress(e) {
38+
if(e.charCode===13) {
39+
this.handleClick();
40+
}
41+
}
42+
43+
render() {
44+
return (
45+
<div>
46+
<h2>Create Contact</h2>
47+
<p>
48+
<input
49+
type="text"
50+
name="name"
51+
placeholder="name"
52+
value={this.state.name}
53+
onChange={this.handleChange}
54+
ref={(ref) => { this.nameInput = ref }}
55+
/>
56+
<input
57+
type="text"
58+
name="phone"
59+
placeholder="phone"
60+
value={this.state.phone}
61+
onChange={this.handleChange}
62+
onKeyPress={this.handleKeyPress}
63+
/>
64+
</p>
65+
<button onClick={this.handleClick}>Create</button>
66+
</div>
67+
)
68+
}
69+
}
70+
71+
ContactCreate.propTypes = {
72+
onCreate: React.PropTypes.func
73+
};
74+
75+
ContactCreate.defaultProps = {
76+
onCreate: () => { console.error('onCreate not defined'); }
77+
}

0 commit comments

Comments
 (0)