Example output
Creating a task management application in JavaScript using **React** for the front end and **Node.js** with **Express** for the back end is a fantastic project. Here's an example source code that includes all the features you mentioned, with comments to explain the code logic.
We'll use **MongoDB** as the database for persistence and **Mongoose** as the ORM for easier data handling.
## Setup and Prerequisites
You'll need to have Node.js, MongoDB, and npm installed. Create a project folder, and inside it, set up the client and server folders:
```bash
mkdir task-manager
cd task-manager
npx create-react-app client
mkdir server
cd server
npm init -y
npm install express mongoose cors body-parser
```
## Server Side: Node.js & Express
### server/app.js
```javascript
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const bodyParser = require("body-parser");
const app = express();
const PORT = 5000;
// Middleware
app.use(cors());
app.use(bodyParser.json());
// Connect to MongoDB
mongoose.connect("mongodb://localhost:27017/taskManager", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
// Task Schema
const taskSchema = new mongoose.Schema({
title: String,
description: String,
dueDate: Date,
priority: { type: String, enum: ["Low", "Medium", "High"], default: "Medium" },
status: { type: String, enum: ["Pending", "Completed"], default: "Pending" },
});
const Task = mongoose.model("Task", taskSchema);
// Routes
// Create a new task
app.post("/tasks", async (req, res) => {
const task = new Task(req.body);
try {
const savedTask = await task.save();
res.status(201).json(savedTask);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
// Get all tasks
app.get("/tasks", async (req, res) => {
try {
const tasks = await Task.find();
res.json(tasks);
} catch (error) {
res.status(500).json({ message: error.message });
}
});
// Update a task by ID
app.put("/tasks/:id", async (req, res) => {
try {
const task = await Task.findByIdAndUpdate(req.params.id, req.body, { new: true });
res.json(task);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
// Delete a task by ID
app.delete("/tasks/:id", async (req, res) => {
try {
await Task.findByIdAndDelete(req.params.id);
res.json({ message: "Task deleted successfully" });
} catch (error) {
res.status(500).json({ message: error.message });
}
});
// Start server
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
```
### Explanation
- We define a `taskSchema` with fields like `title`, `description`, `dueDate`, `priority`, and `status`.
- We define routes for creating, reading, updating, and deleting tasks.
- Each route is connected to a specific URL path, such as `/tasks` for getting all tasks, and `/tasks/:id` for operations on a specific task.
- **CORS** is enabled for allowing requests from the front end.
## Frontend: React
Inside the `client/src` folder, create components and services for managing tasks.
### client/src/services/taskService.js
```javascript
import axios from "axios";
const API_URL = "http://localhost:5000/tasks";
export const getTasks = () => axios.get(API_URL);
export const createTask = (task) => axios.post(API_URL, task);
export const updateTask = (id, updatedTask) => axios.put(`${API_URL}/${id}`, updatedTask);
export const deleteTask = (id) => axios.delete(`${API_URL}/${id}`);
```
### client/src/App.js
```javascript
import React, { useState, useEffect } from "react";
import { getTasks, createTask, updateTask, deleteTask } from "./services/taskService";
function App() {
const [tasks, setTasks] = useState([]);
const [taskForm, setTaskForm] = useState({ title: "", description: "", dueDate: "", priority: "Medium", status: "Pending" });
useEffect(() => {
fetchTasks();
}, []);
const fetchTasks = async () => {
const response = await getTasks();
setTasks(response.data);
};
const handleChange = (e) => {
setTaskForm({ ...taskForm, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
await createTask(taskForm);
setTaskForm({ title: "", description: "", dueDate: "", priority: "Medium", status: "Pending" });
fetchTasks();
};
const handleUpdate = async (id) => {
const updatedTask = { ...taskForm, status: taskForm.status === "Pending" ? "Completed" : "Pending" };
await updateTask(id, updatedTask);
fetchTasks();
};
const handleDelete = async (id) => {
await deleteTask(id);
fetchTasks();
};
return (
<div>
<h1>Task Management</h1>
<form onSubmit={handleSubmit}>
<input name="title" placeholder="Title" value={taskForm.title} onChange={handleChange} required />
<input name="description" placeholder="Description" value={taskForm.description} onChange={handleChange} />
<input name="dueDate" type="date" value={taskForm.dueDate} onChange={handleChange} />
<select name="priority" value={taskForm.priority} onChange={handleChange}>
<option value="Low">Low</option>
<option value="Medium">Medium</option>
<option value="High">High</option>
</select>
<button type="submit">Add Task</button>
</form>
<ul>
{tasks.map((task) => (
<li key={task._id}>
<h3>{task.title}</h3>
<p>{task.description}</p>
<p>Due Date: {new Date(task.dueDate).toLocaleDateString()}</p>
<p>Priority: {task.priority}</p>
<p>Status: {task.status}</p>
<button onClick={() => handleUpdate(task._id)}>{task.status === "Pending" ? "Complete" : "Undo"}</button>
<button onClick={() => handleDelete(task._id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default App;
```
### Explanation
- `fetchTasks` loads tasks from the database.
- `handleSubmit` creates a new task based on the form inputs.
- `handleUpdate` toggles the status between "Pending" and "Completed."
- `handleDelete` removes a task from the list and database.
- Each task displays information like title, description, due date, priority, and status.
## Running the Application
1. Start MongoDB (typically `mongod` in the terminal).
2. Run the Express server from the `server` folder:
```bash
node app.js
```
3. Run the React client from the `client` folder:
```bash
npm start
```
The application should now be accessible at `http://localhost:3000`, and the server is running on `http://localhost:5000`. This setup provides a complete task management app with CRUD operations, status tracking, prioritization, and due date features.