React - todoApp
by Van Hai Le
HTML
<div id="app"></div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
display: flex;
align-items: center;
}
.delete-btn:hover {
opacity: 1;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
span {
padding-left: 16px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 16px;
margin-bottom: 16px;
}
.filter-btn {
border: none;
background: #02b3e4;
padding: 4px 16px;
border-radius: 4px;
color: #fff;
box-shadow: 0 0 8px 0 rgba(17,22,26,.16), 0 4px 8px 0 rgba(17,22,26,.08), 0 8px 16px 0 rgba(17,22,26,.08);
transition: all .3s ease;
cursor: pointer;
margin-right: 4px;
}
.filter-btn:hover {
box-shadow: 0 4px 16px 4px rgba(17,22,26,.16), 0 4px 8px 0 rgba(17,22,26,.08), 0 16px 24px 0 rgba(17,22,26,.08);
}
.custom-input {
border: none;
box-shadow: 0 0 8px 0 rgba(17,22,26,.16), 0 4px 8px 0 rgba(17,22,26,.08), 0 8px 16px 0 rgba(17,22,26,.08);
border-radius: 4px;
transition: all .3s ease;
outline: none;
padding: 8px;
}
.custom-input:focus {
box-shadow: 0 4px 16px 4px rgba(17,22,26,.16), 0 4px 8px 0 rgba(17,22,26,.08), 0 16px 24px 0 rgba(17,22,26,.08);
}
.delete-btn, .check-btn {
cursor: pointer;
}
.delete-btn {
opacity: 0;
transition: all .3s ease;
}
.active {
background: #018cb2;
}
React
class TodoApp extends React.Component {
constructor(props) {
super(props)
this.state = {
filterState: 'all', // all, active, completed
newInput: '',
items: [
{ id: 1, text: "Learn JavaScript", done: false },
{ id: 2, text: "Learn React", done: false },
{ id: 3, text: "Play around in JSFiddle", done: true },
{ id: 4, text: "Build something awesome", done: true }
]
}
this.onChangeState = this.onChangeState.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.onChange = this.onChange.bind(this);
this.filterItem = this.filterItem.bind(this);
}
onKeyUp(event) {
let text = event.target.value;
let ENTER_KEY = 13;
if (event.keyCode === ENTER_KEY) {
text = text.trim();
if (!text) {
return;
}
this.setState({
newInput: '',
items: [
{text: text, done: false},
...this.state.items
]
});
}
}
onChange(event) {
this.setState({
newInput: event.target.value
});
}
onChangeState(item) {
const done = item.done;
const {items} = this.state;
const index = items.indexOf(item);
this.setState({
items: [
...items.slice(0, index),
{
id: item.id,
text: item.text,
done: !done
},
...items.slice(index + 1)
]
});
}
delItem(item) {
const {items} = this.state;
let index = items.indexOf(item);
this.setState({
items: [
...items.slice(0, index),
...items.slice(index + 1)
]
});
}
filterItem(event) {
let filter = event.target.innerHTML.toLowerCase();
this.setState({
filterState: filter
});
}
render() {
let del = <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width={48} height={48} viewBox="0 0 224 224" style={{fill: '#000000'}}><g fill="none" fillRule="nonzero" stroke="none" strokeWidth={1} strokeLinecap="butt" strokeLinejoin="miter" strokeMiterlimit={10} strokeDasharray strokeDashoffset={0} fontFamily="none" fontWeight="none" fontSize="none" textAnchor="none"...