edit add task update functionality

This commit is contained in:
notnull 2019-06-22 16:31:34 -04:00
parent 82d1bb966b
commit 2c27754d88
3 changed files with 177 additions and 78 deletions

View File

@ -1,7 +1,15 @@
import React from 'react'
import axios from 'axios'
import { About, Tasks, Task, Profile, Projects, Project, Navbar } from './components'
import {
About,
Tasks,
UpdateTask,
Profile,
Projects,
Project,
Navbar,
} from './components'
const api = process.env.REACT_APP_API || 'http://localhost:1337'
//console.log(process.env)
@ -82,7 +90,9 @@ class App extends React.Component {
e.preventDefault()
const newTask = {
desc: this.state.newTask,
projectName: this.state.projects.find(p => p.id === this.state.selectedProjectId)['name'],
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
@ -111,19 +121,24 @@ class App extends React.Component {
}
}
async updateTask(e) {
async updateTask(e, updatedTask) {
e.preventDefault()
const task = this.state.tasks.find(t => t.id === this.state.selectedTaskId)
// TODO update properties from form
console.log(e.target)
console.log('updatedTask:', updatedTask)
const oldTask = this.state.tasks.find(
t => t.id === this.state.selectedTaskId,
)
if (JSON.stringify(oldTask) === JSON.stringify(updatedTask)) return
try {
const { data, error } = await axios.put(api + `/api/tasks/${task.id}`, task)
console.log('Tried to update task.')
const { data, error } = await axios.put(
api + `/api/tasks/${oldTask.id}`,
updatedTask,
)
if (error) {
alert('Received error when updating task: ', error)
} else if (data.desc && data.projectId) {
const oldTasks = this.state.tasks.filter(t => t.id !== updatedTask.id)
this.setState({ tasks: oldTasks.concat(updatedTask) })
console.log('Successfully updated task:', data)
// TODO this.setState({ tasks: this.state.tasks.concat(data), newTask: '' })
} else {
console.log('Received malformed data when updating task: ', data)
}
@ -140,7 +155,10 @@ class App extends React.Component {
alert('Received error when deleting task: ', error)
} else {
console.log('Successfully deleted task: ', data)
this.setState({ tasks: this.state.tasks.filter(t => t.id !== data.id), newTask: '' })
this.setState({
tasks: this.state.tasks.filter(t => t.id !== data.id),
newTask: '',
})
}
} catch (e) {
alert('Failed to delete task: ', e)
@ -154,7 +172,10 @@ class App extends React.Component {
}
try {
task.completed = !task.completed
const { data, error } = await axios.put(api + `/api/tasks/${task.id}`, task)
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) {
@ -206,20 +227,32 @@ class App extends React.Component {
}
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}'.`)
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`)
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.setState({
projects: this.state.projects.filter(p => p.id !== project.id),
})
this.navigate('projects')
} else {
alert(`Failed to delete project '${project.name}'.`)
@ -285,9 +318,9 @@ class App extends React.Component {
/>
)
}
renderTask() {
renderUpdateTask() {
return (
<Task
<UpdateTask
handleChange={this.handleChange}
updateTask={this.updateTask}
navigate={this.navigate}
@ -299,7 +332,9 @@ class App extends React.Component {
//console.log(this.state)
// TODO refactor task filtering
const completed =
(this.state.tasks && this.state.tasks.filter(task => task.completed === true)) || []
(this.state.tasks &&
this.state.tasks.filter(task => task.completed === true)) ||
[]
const filtered =
(this.state.tasks &&
this.state.tasks.filter(
@ -315,7 +350,7 @@ class App extends React.Component {
: this.state.component === 'tasks'
? this.renderTasks(filtered, completed)
: this.state.component === 'task'
? this.renderTask()
? this.renderUpdateTask()
: this.state.component === 'about'
? this.renderAbout()
: this.state.component === 'profile'
@ -328,7 +363,11 @@ class App extends React.Component {
return (
<div>
<Navbar handleChange={this.handleChange} navigate={this.navigate} {...this.state} />
<Navbar
handleChange={this.handleChange}
navigate={this.navigate}
{...this.state}
/>
{renderComponent()}
</div>
)

View File

@ -1,7 +1,7 @@
export { default as Navbar } from './navbar'
export { default as About } from './about'
export { default as Tasks } from './tasks'
export { default as Task } from './task'
export { default as UpdateTask } from './update-task'
export { default as Profile } from './profile'
export { default as Projects } from './projects'
export { default as Project } from './project'

View File

@ -1,61 +1,121 @@
import React from 'react'
function Task(props) {
if (!props.selectedTaskId) {
props.navigate('tasks')
return null
// TODO
// if (!this.props.selectedTaskId) {
// props.navigate('tasks')
// return null
// }
class UpdateTask extends React.Component {
constructor(props) {
super(props)
const task = props.tasks.find(t => t.id === props.selectedTaskId)
this.state = task
this.handleChange = this.handleChange.bind(this)
}
const task = props.tasks.find(t => t.id === props.selectedTaskId)
console.log(task)
return (
<div>
<h2>Task: {task.desc}</h2>
<form className="form-group" name="task">
<ul className="list-group">
<li className="list-group-item row">
<span className="col">completed:</span>
<input
className="col"
type="checkbox"
name="completed"
value={task.completed}
onChange={props.handleChange}
/>
</li>
<li className="list-group-item row">
<span className="col">created:</span>
<span className="col">{task.createdAt}</span>
</li>
<li className="list-group-item row">
<span className="col-sm-1">project:</span>
<select
className="col-sm-6"
name="taskNewProjectId"
onChange={props.handleChange}
defaultValue={task.projectId}
>
{props.projects.map(p => {
return (
<option key={p.id} value={p.id} onChange={props.handleChange}>
{p.name}
</option>
)
})}
</select>
</li>
<li className="list-group-item row">
<input
className="btn btn-outline-success col"
type="submit"
onClick={props.updateTask}
value="Save"
/>
</li>
</ul>
</form>
</div>
)
handleChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
render() {
console.log('inside of the task form: ', this.state)
const oldDesc = this.props.tasks.find(t => t.id === this.state.id)['desc']
return (
<div>
<h2>Task: {oldDesc}</h2>
<form>
<div className="form-group row">
<label htmlFor="desc" className="col-sm-2 col-form-label">
Task Description:
</label>
<div className="col-sm-10">
<input
type="text"
className="form-control"
name="desc"
value={this.state.desc}
onChange={this.handleChange}
/>
</div>
</div>
<div className="form-group row">
<label htmlFor="projectName" className="col-sm-2 col-form-label">
Project
</label>
<div className="col-sm-10">
<select
className="form-control col-sm-6"
name="taskNewProjectId"
onChange={this.handleChange}
defaultValue={this.state.projectId}
>
{this.props.projects.map(p => {
return (
<option
key={p.id}
value={p.id}
onChange={this.props.handleChange}
>
{p.name}
</option>
)
})}
</select>
</div>
</div>
<div className="form-group row">
<label htmlFor="completed" className="col-sm-2 col-form-label">
completed
</label>
<div className="col-sm-10">
<button
type="button"
className={`form-control btn ${
this.state.completed
? 'btn-outline-secondary'
: 'btn-outline-success'
}`}
name="completed"
value={this.state.completed}
onClick={() =>
this.setState({ completed: !this.state.completed })
}
>
{this.state.completed ? 'Mark Incomplete' : 'Mark Complete'}
</button>
</div>
</div>
<div className="form-group row">
<label htmlFor="createdAt" className="col-sm-2 col-form-label">
CreatedAt
</label>
<div className="col-sm-10">
<input
className="form-control"
name="createdAt"
value={this.state.createdAt}
readOnly
/>
</div>
</div>
<div className="form-group row">
<div className="col-sm-10">
<button
type="submit"
className="btn btn-primary"
onClick={e => this.props.updateTask(e, this.state)}
>
Save
</button>
</div>
</div>
</form>
</div>
)
}
}
export default Task
export default UpdateTask