tasks-mockup/src/App.js

241 lines
6.6 KiB
JavaScript

import React from 'react'
import axios from 'axios'
import { About, Tasks, Profile, Projects, Project, Navbar } from './components'
const api = process.env.REACT_APP_API || 'http://localhost:1337'
//console.log(process.env)
console.log('Using api at ' + api)
const defaultState = {
user: { name: 'Scott' },
loading: true,
tasks: [],
search: '',
newTask: '',
newProject: '',
project: {},
projects: [],
component: 'projects',
}
class App extends React.Component {
constructor() {
super()
this.state = defaultState
this.navigate = this.navigate.bind(this)
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.addTask = this.addTask.bind(this)
this.deleteTask = this.deleteTask.bind(this)
this.completeTask = this.completeTask.bind(this)
this.createProject = this.createProject.bind(this)
this.selectProject = this.selectProject.bind(this)
this.deleteProject = this.deleteProject.bind(this)
}
async fetchTasks() {
try {
const { data } = await axios.get(api + '/api/tasks')
return data
} catch (error) {
console.log(error)
this.setState({ error })
}
}
async fetchProjects() {
try {
const { data } = await axios.get(api + '/api/projects')
return data
} catch (error) {
console.log(error)
this.setState({ error })
}
}
async fetchData() {
const tasks = await this.fetchTasks()
const projects = await this.fetchProjects()
await this.setState({ loading: false, tasks, projects })
}
componentDidMount() {
this.fetchData()
}
navigate(component) {
this.setState({ component })
}
handleChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
handleSubmit(e) {
e.preventDefault()
console.log('Search term: ', this.state.search)
this.setState({ search: '' })
}
async addTask(e) {
e.preventDefault()
const newTask = {
desc: this.state.newTask,
projectName: this.state.selectedProject,
// 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
}
if (newTask.desc === '') {
alert('Task description is empty.')
return
} else if (!newTask.projectName) {
alert('Select a project for new task.')
return
}
try {
console.log('Adding task: ', newTask)
const { data, error } = await axios.post(api + '/api/tasks', newTask)
if (error) {
alert('Received error when adding task: ', error)
} else if (data.desc && data.projectId) {
console.log('Successfully added task:', data)
this.setState({ tasks: this.state.tasks.concat(data), newTask: '' })
} else {
console.log('Received malformed data for added task: ', data)
}
} catch (e) {
alert('Failed to add task: ', e)
}
}
async deleteTask(id) {
this.setState({ tasks: this.state.tasks.filter(t => t.id !== id) })
try {
const { data, error } = await axios.post(api + `/api/tasks/${id}/delete`)
if (error) {
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: '' })
}
} catch (e) {
alert('Failed to delete task: ', e)
}
}
completeTask(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) })
}
createProject(e) {
e.preventDefault()
this.setState({
projects: this.state.projects.concat({
id: this.state.projects.length,
name: this.state.newProject,
}),
newProject: '',
})
}
selectProject(selectedProjectId) {
this.setState({ selectedProjectId })
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
}
renderLoading() {
return <div>Loading...</div>
}
renderError() {
return <div>Something went wrong. Please try again.</div>
}
renderProfile() {
return <Profile {...this.state} />
}
renderProjects() {
return (
<Projects
navigate={this.navigate}
handleChange={this.handleChange}
createProject={this.createProject}
selectProject={this.selectProject}
deleteProject={this.deleteProject}
{...this.state}
/>
)
}
renderProject() {
return (
<Project
handleChange={this.handleChange}
createProject={this.createProject}
selectProject={this.selectProject}
deleteProject={this.deleteProject}
addTask={this.addTask}
completeTask={this.completeTask}
deleteTask={this.deleteTask}
{...this.state}
/>
)
}
renderAbout() {
return <About {...this.state} />
}
renderTasks(filtered, completed) {
return (
<Tasks
handleChange={this.handleChange}
handleSubmit={this.handleSubmit}
addTask={this.addTask}
completeTask={this.completeTask}
deleteTask={this.deleteTask}
filtered={filtered}
completed={completed}
selectProject={this.selectProject}
{...this.state}
/>
)
}
render() {
console.log(this.state)
const completed = this.state.tasks.filter(task => task.completed === true)
const filtered = this.state.tasks.filter(
task =>
task.completed !== true &&
this.state.search === task.desc.slice(0, this.state.search.length),
)
const renderComponent = () =>
this.state.loading
? this.renderLoading()
: this.state.component === 'tasks'
? this.renderTasks(filtered, completed)
: this.state.component === 'about'
? this.renderAbout()
: this.state.component === 'profile'
? this.renderProfile()
: this.state.component === 'projects'
? this.renderProjects()
: this.state.component === 'project'
? this.renderProject()
: this.renderError()
return (
<div>
<Navbar handleChange={this.handleChange} navigate={this.navigate} {...this.state} />
{renderComponent()}
</div>
)
}
}
export default App