async requests + error handling
This commit is contained in:
parent
c0f136bee3
commit
07f79c1006
96
src/App.js
96
src/App.js
@ -73,7 +73,6 @@ class App extends React.Component {
|
||||
}
|
||||
handleSubmit(e) {
|
||||
e.preventDefault()
|
||||
console.log('Search term: ', this.state.search)
|
||||
this.setState({ search: '' })
|
||||
}
|
||||
|
||||
@ -81,7 +80,8 @@ class App extends React.Component {
|
||||
e.preventDefault()
|
||||
const newTask = {
|
||||
desc: this.state.newTask,
|
||||
projectName: this.state.selectedProject,
|
||||
projectName: this.state.projects.find(p => p.id === this.state.selectedProjectId)['name'],
|
||||
// TODO
|
||||
// the backend expects projectName because it creates the project on the fly if none exists with that name
|
||||
// this feature comes at the price that there can't be two independent projects with the same name
|
||||
// which could be handy if users want to have private projects
|
||||
@ -105,7 +105,7 @@ class App extends React.Component {
|
||||
console.log('Received malformed data for added task: ', data)
|
||||
}
|
||||
} catch (e) {
|
||||
alert('Failed to add task: ', e)
|
||||
alert(`Failed to add task: ${e}`)
|
||||
}
|
||||
}
|
||||
async deleteTask(id) {
|
||||
@ -122,23 +122,48 @@ class App extends React.Component {
|
||||
alert('Failed to delete task: ', e)
|
||||
}
|
||||
}
|
||||
completeTask(id) {
|
||||
async completeTask(id) {
|
||||
const task = this.state.tasks.find(t => t.id === id)
|
||||
if (!task.id) {
|
||||
alert(`Couldn't find task with id ${id}`)
|
||||
return
|
||||
}
|
||||
try {
|
||||
task.completed = !task.completed
|
||||
const { data, error } = await axios.put(api + `/api/tasks/${task.id}`, task)
|
||||
if (error) {
|
||||
alert(`Received error when completing task ${task.desc}: ${error}`)
|
||||
} else if (data.id) {
|
||||
const otherTasks = this.state.tasks.filter(t => t.id !== id)
|
||||
const completedTask = this.state.tasks.find(t => t.id === id)
|
||||
completedTask.completed = !completedTask.completed
|
||||
console.log(completedTask)
|
||||
this.setState({ tasks: otherTasks.concat(completedTask) })
|
||||
this.setState({ tasks: otherTasks.concat(data) })
|
||||
console.log(`Completed task:`, data)
|
||||
} else {
|
||||
alert(`Failed to complete task with id ${id}`)
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`Failed to complete task ${task.desc}: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
createProject(e) {
|
||||
async createProject(e) {
|
||||
e.preventDefault()
|
||||
const project = { name: this.state.newProject }
|
||||
try {
|
||||
const { data, error } = await axios.post(api + '/api/projects', project)
|
||||
if (error) {
|
||||
alert(`Received error when creating project ${project.name}: ${error}`)
|
||||
} else if (data.id) {
|
||||
this.setState({
|
||||
projects: this.state.projects.concat({
|
||||
id: this.state.projects.length,
|
||||
name: this.state.newProject,
|
||||
}),
|
||||
projects: this.state.projects.concat(data),
|
||||
newProject: '',
|
||||
})
|
||||
console.log(`Added project: `, data)
|
||||
} else {
|
||||
alert(`Failed to add project '${project}'.`)
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`Failed to add project '${this.state.newProject}'.`)
|
||||
}
|
||||
}
|
||||
|
||||
selectProject(selectedProjectId) {
|
||||
@ -146,9 +171,34 @@ class App extends React.Component {
|
||||
this.navigate('project')
|
||||
}
|
||||
async deleteProject(id) {
|
||||
//this.setState({ projects: this.state.projects.filter(p => p.id !== id) })
|
||||
await axios.post(`/api/projects/${id}/delete`)
|
||||
// TODO: some delete success function
|
||||
const project = this.state.projects.find(p => p.id === id)
|
||||
if (!project.id) {
|
||||
alert(`Could not find project with id ${id}.`)
|
||||
return
|
||||
}
|
||||
const tasks = this.state.tasks.filter(t => t.projectId === project.id)
|
||||
if (tasks.length > 0) {
|
||||
if (window.confirm(`Project ${project.name} has ${tasks.length} tasks. Are you sure?`)) {
|
||||
this.setState({ tasks: this.state.tasks.filter(t => t.projectId !== project.id) })
|
||||
console.log(`Removed ${tasks.length} tasks of project '${project.name}'.`)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
try {
|
||||
const { data, error } = await axios.post(api + `/api/projects/${project.id}/delete`)
|
||||
if (error) {
|
||||
alert(`Received error when deleting project ${project.name}: ${error}`)
|
||||
} else if (data.name) {
|
||||
console.log('Deleted project:', data)
|
||||
this.setState({ projects: this.state.projects.filter(p => p.id !== project.id) })
|
||||
this.navigate('projects')
|
||||
} else {
|
||||
alert(`Failed to delete project '${project.name}'.`)
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`Failed to delete project '${project.name}': ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
renderLoading() {
|
||||
@ -182,6 +232,7 @@ class App extends React.Component {
|
||||
addTask={this.addTask}
|
||||
completeTask={this.completeTask}
|
||||
deleteTask={this.deleteTask}
|
||||
navigate={this.navigate}
|
||||
{...this.state}
|
||||
/>
|
||||
)
|
||||
@ -205,13 +256,18 @@ class App extends React.Component {
|
||||
)
|
||||
}
|
||||
render() {
|
||||
console.log(this.state)
|
||||
const completed = this.state.tasks.filter(task => task.completed === true)
|
||||
const filtered = this.state.tasks.filter(
|
||||
//console.log(this.state)
|
||||
// TODO refactor task filtering
|
||||
const completed =
|
||||
(this.state.tasks && this.state.tasks.filter(task => task.completed === true)) || []
|
||||
const filtered =
|
||||
(this.state.tasks &&
|
||||
this.state.tasks.filter(
|
||||
task =>
|
||||
task.completed !== true &&
|
||||
this.state.search === task.desc.slice(0, this.state.search.length),
|
||||
)
|
||||
)) ||
|
||||
[]
|
||||
|
||||
const renderComponent = () =>
|
||||
this.state.loading
|
||||
|
@ -11,22 +11,29 @@ function FilterTask(props) {
|
||||
value={props.newTask}
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
{props.component === 'project' ? null : (
|
||||
{props.component === 'project' ? (
|
||||
''
|
||||
) : (
|
||||
<select
|
||||
className="form-control custom-select col"
|
||||
name="selectedProject"
|
||||
value={props.project.name}
|
||||
name="selectedProjectId"
|
||||
value={props.selectedProjectId}
|
||||
onChange={props.handleChange}
|
||||
>
|
||||
<option value='' defaultValue>select project</option>
|
||||
{props.projects.map(p => (
|
||||
<option key={p.id} value={p.name}>
|
||||
<option value="" defaultValue>
|
||||
select project
|
||||
</option>
|
||||
{props.projects &&
|
||||
props.projects.map(p => (
|
||||
<option key={p.id} value={p.id}>
|
||||
{p.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
<button className="form-control col-sm-1 btn" type="submit" onClick={props.addTask}>Add</button>
|
||||
<button className="form-control col-sm-1 btn" type="submit" onClick={props.addTask}>
|
||||
Add
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
)
|
||||
|
@ -2,20 +2,23 @@ import React from 'react'
|
||||
import Tasks from './tasks'
|
||||
|
||||
function Project(props) {
|
||||
if (!props.selectedProjectId) {
|
||||
props.navigate('projects')
|
||||
return null
|
||||
}
|
||||
// TODO re-fetch project list if no project name is found instead of setting 'Default'
|
||||
const projectName =
|
||||
props.projects.find(p => p.id === props.selectedProjectId).name || 'Default'
|
||||
const filtered = props.tasks.filter(
|
||||
t => t.projectId === props.selectedProjectId && !t.completed
|
||||
)
|
||||
props.projects.find(p => p.id === props.selectedProjectId)['name'] || 'Default'
|
||||
|
||||
const filtered = props.tasks.filter(t => t.projectId === props.selectedProjectId && !t.completed)
|
||||
const completed = props.tasks.filter(
|
||||
t =>
|
||||
(t.projectId === props.selectedProjectId && t.completed === true) || null
|
||||
t => (t.projectId === props.selectedProjectId && t.completed === true) || null,
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>{projectName}</h2>
|
||||
<Tasks {...props} filtered={filtered} completed={completed} />
|
||||
<Tasks filtered={filtered} completed={completed} {...props} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React from 'react'
|
||||
|
||||
function Projects(props) {
|
||||
console.log('PROJECTS PROPS', props)
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mt-4">Projects</h3>
|
||||
<ul className="list-group">
|
||||
{props.projects.map(project => (
|
||||
{props.projects &&
|
||||
props.projects.map(project => (
|
||||
<li className="list-group-item" key={project.id}>
|
||||
<button
|
||||
className="btn btn-outline-danger mr-1"
|
||||
@ -14,11 +14,7 @@ function Projects(props) {
|
||||
>
|
||||
X
|
||||
</button>
|
||||
{props.selectedProjectId ? null : (
|
||||
<span onClick={() => props.selectProject(project.id)}>
|
||||
{project.name}{' '}
|
||||
</span>
|
||||
)}
|
||||
<span onClick={() => props.selectProject(project.id)}>{project.name} </span>
|
||||
</li>
|
||||
))}
|
||||
<form className="" onSubmit={props.createProject}>
|
||||
|
@ -11,7 +11,7 @@ const TaskRow = props => {
|
||||
</button>
|
||||
|
||||
<span>{task.desc}</span>
|
||||
{props.selectedProjectId ? null : (
|
||||
{props.component === 'project' ? null : (
|
||||
<button
|
||||
className="btn btn-outline-dark ml-5"
|
||||
onClick={() => props.selectProject(task.projectId)}
|
||||
|
@ -4,7 +4,7 @@ import FilterTask from './filter-task'
|
||||
import TaskList from './task-list'
|
||||
|
||||
function Tasks(props) {
|
||||
const { tasks } = props
|
||||
const tasks = props.tasks || []
|
||||
const filtered = props.filtered || []
|
||||
const completed = props.completed || []
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user