simplify app logic
This commit is contained in:
parent
c348a515de
commit
a63011a996
2 changed files with 72 additions and 70 deletions
16
src/App.css
16
src/App.css
|
|
@ -202,10 +202,7 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
.todo__text {
|
|
||||||
color: #135156;
|
|
||||||
transition: all 0.4s linear 0.4s;
|
|
||||||
}
|
|
||||||
.todo__icon {
|
.todo__icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
@ -219,6 +216,7 @@
|
||||||
stroke-width: 2;
|
stroke-width: 2;
|
||||||
stroke-linejoin: round;
|
stroke-linejoin: round;
|
||||||
stroke-linecap: round;
|
stroke-linecap: round;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo__box,
|
.todo__box,
|
||||||
|
|
@ -265,11 +263,7 @@
|
||||||
animation-delay: 0.56s;
|
animation-delay: 0.56s;
|
||||||
animation-duration: 0.56s;
|
animation-duration: 0.56s;
|
||||||
}
|
}
|
||||||
.todo__state:checked + .todo__text {
|
|
||||||
transition-delay: 0s;
|
|
||||||
color: #5EBEC1;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
.todo__state:checked ~ .todo__icon .todo__box {
|
.todo__state:checked ~ .todo__icon .todo__box {
|
||||||
stroke-dashoffset: 56.1053;
|
stroke-dashoffset: 56.1053;
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
|
|
@ -282,3 +276,7 @@
|
||||||
.todo__state:checked ~ .todo__icon .todo__circle {
|
.todo__state:checked ~ .todo__icon .todo__circle {
|
||||||
animation-name: explode;
|
animation-name: explode;
|
||||||
}
|
}
|
||||||
|
.todo-completed .todo__state:checked ~ .todo__icon .todo__circle {
|
||||||
|
animation-name: none;
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
|
||||||
126
src/App.js
126
src/App.js
|
|
@ -1,8 +1,9 @@
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
|
import api from './utils/api'
|
||||||
|
import ContentEditable from './components/ContentEditable'
|
||||||
|
import deployButton from './deploy-to-netlify.svg'
|
||||||
import logo from './logo.svg'
|
import logo from './logo.svg'
|
||||||
import github from './github.svg'
|
import github from './github.svg'
|
||||||
import deployButton from './deploy-to-netlify.svg'
|
|
||||||
import ContentEditable from './components/ContentEditable'
|
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
|
|
@ -10,21 +11,16 @@ class App extends Component {
|
||||||
todos: []
|
todos: []
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
console.log('fetch items')
|
// Fetch all todos
|
||||||
fetch('/.netlify/functions/todos-read-all')
|
api.readAll().then((response) => {
|
||||||
.then((response) => {
|
console.log('all todos', response)
|
||||||
console.log(response)
|
|
||||||
return response.json()
|
|
||||||
})
|
|
||||||
.then((myJson) => {
|
|
||||||
console.log(myJson)
|
|
||||||
this.setState({
|
this.setState({
|
||||||
todos: myJson
|
todos: response
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
saveTodo = (e) => {
|
saveTodo = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
const { todos } = this.state
|
const { todos } = this.state
|
||||||
const todoValue = this.inputElement.value
|
const todoValue = this.inputElement.value
|
||||||
|
|
||||||
|
|
@ -36,35 +32,26 @@ class App extends Component {
|
||||||
// reset input to empty
|
// reset input to empty
|
||||||
this.inputElement.value = ''
|
this.inputElement.value = ''
|
||||||
|
|
||||||
// Optimistically add todo to UI
|
const todoInfo = {
|
||||||
const temporaryValue = {
|
title: todoValue,
|
||||||
data: {
|
completed: false
|
||||||
title: todoValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const optimisticTodoState = todos.concat(temporaryValue)
|
// Optimistically add todo to UI
|
||||||
|
const optimisticTodoState = todos.concat({
|
||||||
|
data: todoInfo
|
||||||
|
})
|
||||||
this.setState({
|
this.setState({
|
||||||
todos: optimisticTodoState
|
todos: optimisticTodoState
|
||||||
})
|
})
|
||||||
|
|
||||||
// Make API request to create new todo
|
// Make API request to create new todo
|
||||||
fetch('/.netlify/functions/todos-create', {
|
api.create(todoInfo).then((response) => {
|
||||||
body: JSON.stringify({
|
console.log(response)
|
||||||
title: todoValue
|
|
||||||
}),
|
|
||||||
method: 'POST',
|
|
||||||
// mode: 'cors', // no-cors, cors, *same-origin
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then((json) => {
|
|
||||||
console.log(json)
|
|
||||||
// remove temporaryValue from state and persist API response
|
// remove temporaryValue from state and persist API response
|
||||||
const persistedState = removeOptimisticTodo(todos).concat(json)
|
const persistedState = removeOptimisticTodo(todos).concat(response)
|
||||||
// Set persisted value to state
|
// Set persisted value to state
|
||||||
this.setState({
|
this.setState({
|
||||||
todos: persistedState
|
todos: persistedState
|
||||||
})
|
})
|
||||||
// fin
|
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
console.log('An API error occurred', e)
|
console.log('An API error occurred', e)
|
||||||
const revertedState = removeOptimisticTodo(todos)
|
const revertedState = removeOptimisticTodo(todos)
|
||||||
|
|
@ -77,7 +64,7 @@ class App extends Component {
|
||||||
deleteTodo = (e) => {
|
deleteTodo = (e) => {
|
||||||
const { todos } = this.state
|
const { todos } = this.state
|
||||||
const todoId = e.target.dataset.id
|
const todoId = e.target.dataset.id
|
||||||
console.log(`Delete todo ${todoId}`)
|
|
||||||
// Optimistically remove todo from UI
|
// Optimistically remove todo from UI
|
||||||
const filteredTodos = todos.reduce((acc, current) => {
|
const filteredTodos = todos.reduce((acc, current) => {
|
||||||
const currentId = getTodoId(current)
|
const currentId = getTodoId(current)
|
||||||
|
|
@ -97,13 +84,10 @@ class App extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
todos: filteredTodos.optimisticState
|
todos: filteredTodos.optimisticState
|
||||||
})
|
})
|
||||||
|
|
||||||
// Make API request to delete todo
|
// Make API request to delete todo
|
||||||
fetch(`/.netlify/functions/todos-delete/${todoId}`, {
|
api.delete(todoId).then(() => {
|
||||||
method: 'POST',
|
console.log(`deleted todo id ${todoId}`)
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then((json) => {
|
|
||||||
console.log(json)
|
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
console.log(`There was an error removing ${todoId}`, e)
|
console.log(`There was an error removing ${todoId}`, e)
|
||||||
// Add item removed back to list
|
// Add item removed back to list
|
||||||
|
|
@ -112,37 +96,44 @@ class App extends Component {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
updateTodo = (id, todoValue) => {
|
handleTodoCheckbox = (event) => {
|
||||||
// Make API request to update todo
|
const { target } = event
|
||||||
fetch(`/.netlify/functions/todos-update/${id}`, {
|
const todoCompleted = target.checked
|
||||||
body: JSON.stringify({
|
const todoId = target.dataset.id
|
||||||
title: todoValue
|
|
||||||
}),
|
const updatedTodos = this.state.todos.map((todo, i) => {
|
||||||
method: 'POST',
|
const { data } = todo
|
||||||
// mode: 'cors', // no-cors, cors, *same-origin
|
const id = getTodoId(todo)
|
||||||
|
if (id === todoId && data.completed !== todoCompleted) {
|
||||||
|
data.completed = todoCompleted
|
||||||
|
}
|
||||||
|
return todo
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
|
||||||
.then((json) => {
|
// only set state if input different
|
||||||
console.log(json)
|
this.setState({
|
||||||
// fin
|
todos: updatedTodos
|
||||||
}).catch((e) => {
|
}, () => {
|
||||||
console.log('An API error occurred', e)
|
api.update(todoId, {
|
||||||
|
completed: todoCompleted
|
||||||
|
}).then(() => {
|
||||||
|
console.log(`update todo ${todoId}`, todoCompleted)
|
||||||
|
}).catch((e) => {
|
||||||
|
console.log('An API error occurred', e)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handleTodoToggle = (e) => {
|
|
||||||
console.log('checkbox changed')
|
|
||||||
console.log(e.target.checked);
|
|
||||||
}
|
|
||||||
handleDataChange = (event, currentValue) => {
|
handleDataChange = (event, currentValue) => {
|
||||||
// save on change debounced?
|
// save on change debounced?
|
||||||
}
|
}
|
||||||
handleBlur = (event, currentValue) => {
|
handleBlur = (event, currentValue) => {
|
||||||
|
console.log('blur')
|
||||||
let isDifferent = false
|
let isDifferent = false
|
||||||
const key = event.target.dataset.key
|
const todoId = event.target.dataset.key
|
||||||
|
|
||||||
const updatedTodos = this.state.todos.map((todo, i) => {
|
const updatedTodos = this.state.todos.map((todo, i) => {
|
||||||
const id = getTodoId(todo)
|
const id = getTodoId(todo)
|
||||||
if (id === key && todo.data.title !== currentValue) {
|
if (id === todoId && todo.data.title !== currentValue) {
|
||||||
todo.data.title = currentValue
|
todo.data.title = currentValue
|
||||||
isDifferent = true
|
isDifferent = true
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +145,13 @@ class App extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
todos: updatedTodos
|
todos: updatedTodos
|
||||||
}, () => {
|
}, () => {
|
||||||
this.updateTodo(key, currentValue)
|
api.update(todoId, {
|
||||||
|
title: currentValue
|
||||||
|
}).then(() => {
|
||||||
|
console.log(`update todo ${todoId}`, currentValue)
|
||||||
|
}).catch((e) => {
|
||||||
|
console.log('An API error occurred', e)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -172,10 +169,17 @@ class App extends Component {
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
const completedClass = (data.completed) ? 'todo-completed' : ''
|
||||||
return (
|
return (
|
||||||
<div key={i} className='todo-item'>
|
<div key={i} className={`todo-item ${completedClass}`}>
|
||||||
<label className="todo">
|
<label className="todo">
|
||||||
<input className="todo__state" type="checkbox" onChange={this.handleTodoToggle} />
|
<input
|
||||||
|
data-id={id}
|
||||||
|
className="todo__state"
|
||||||
|
type="checkbox"
|
||||||
|
onChange={this.handleTodoCheckbox}
|
||||||
|
checked={data.completed}
|
||||||
|
/>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 25" className="todo__icon">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 25" className="todo__icon">
|
||||||
<use xlinkHref="#todo__box" className="todo__box"></use>
|
<use xlinkHref="#todo__box" className="todo__box"></use>
|
||||||
<use xlinkHref="#todo__check" className="todo__check"></use>
|
<use xlinkHref="#todo__check" className="todo__check"></use>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue