Volunteer Management System using MERN Stack
In this article, we will explore the development of a Volunteer Management System using NodeJS and ExpressJS and MongoDB as a database for storing data and performing operations . This project will involve performing basic and advanced calculations to streamline the volunteer management process.
Output Preview: Let us have a look at how the final output will look like.
Prerequisites
Project Structure:
Steps to create the project:
Server-Side (Node.js and Express):
Step 1: Install Node.js and npm
Step 2: Set Up the Project
mkdir <<name of project>>
cd <<name of project>>
Step 3: Initialize a Node.js Project
npm init -y
Step 4: Install Required Packages
npm install express body-parser cors
Step 5: The server code uses MongoDB as the database. Make sure you have MongoDB installed and running.
npm install mongoose
Step 6: Create the index.js File and to connect to MongoDB (replace ‘your_database_uri’ with your actual MongoDB URI)
// server/index.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const app = express();
const port = 5000;
app.use(cors());
app.use(express.json());
// Connect to MongoDB
// (replace 'your_database_uri' with your actual MongoDB URI)
mongoose.connect("your_database_uri", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
// Define a schema for the volunteer model
const volunteerSchema = new mongoose.Schema({
id: Number,
name: String,
event: String,
date: String,
startTime: String,
endTime: String,
status: String,
});
// Create a Volunteer model based on the schema
const Volunteer = mongoose.model("Volunteer", volunteerSchema);
// Dummy data insertion function
async function insertDummyData() {
try {
const dummyData = [
{
id: 1,
name: "User 1",
event: "Event 1",
date: "2024-03-05",
startTime: "09:00",
endTime: "12:00",
status: "request",
},
{
id: 2,
name: "User 2",
event: "Event 2",
date: "2024-03-08",
startTime: "13:00",
endTime: "16:00",
status: "request",
},
{
id: 3,
name: "User 3",
event: "Event 3",
date: "2024-03-10",
startTime: "10:30",
endTime: "14:30",
status: "request",
},
{
id: 4,
name: "User 4",
event: "Event 4",
date: "2024-03-12",
startTime: "08:00",
endTime: "11:00",
status: "request",
},
{
id: 5,
name: "User 5",
event: "Event 5",
date: "2024-03-15",
startTime: "14:00",
endTime: "17:00",
status: "request",
},
];
await Volunteer.insertMany(dummyData);
console.log("Dummy data inserted successfully");
} catch (error) {
console.error("Error inserting dummy data:", error);
}
}
// Call the dummy data insertion function
insertDummyData();
// Fetch and load volunteer data from the database
app.get("/vols", async (req, res) => {
try {
const volunteerRequests = await Volunteer.find();
res.json(volunteerRequests);
} catch (error) {
res.status(500).json({ message: "Internal Server Error" });
}
});
// Add a new volunteer
app.post("/addVolunteer", async (req, res) => {
const newVolunteer = req.body;
newVolunteer.status = "request";
try {
await Volunteer.create(newVolunteer);
res.json({ message: "Volunteer added successfully" });
} catch (error) {
res.status(500).json({ message: "Internal Server Error" });
}
});
// Approve a volunteer
app.post("/approveVolunteer", async (req, res) => {
const volunteerId = req.body.id;
try {
const result = await Volunteer.updateOne(
{ id: volunteerId },
{ status: "approved" }
);
if (result.nModified === 1) {
res.json({ message: "Volunteer approved successfully" });
} else {
res.status(404).json({ message: "Volunteer not found" });
}
} catch (error) {
res.status(500).json({ message: "Internal Server Error" });
}
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Step 6: Open web-browser and type the following URL
http://localhost:5000/vols
Run the Server
node index.js
FRONTEND(REACT based)
Step 1: Create a new React app:
npx create-react-app <<Name_of_project>>
cd <<Name_of_project>>
Step 2:Install Axios to make HTTP requests:
npm install axios
Step 3:
- Replace the contents of src/App.js with the following:
- Create a new file src/Navbar.js with the following content:
- Create index.css and App.css for styling
/*App.css*/
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.App {
text-align: center;
}
.navbar {
background-color: #333;
color: white;
padding: 1em;
text-align: center;
}
.hero-section {
display: flex;
}
.buttons {
width: 30%;
background-color: #f0f0f0;
padding: 1em;
border-right: 1px solid #ccc;
}
button {
display: block;
width: 100%;
padding: 0.5em;
margin-bottom: 1em;
background-color: #3498db;
color: white;
border: none;
cursor: pointer;
}
.data-display {
flex-grow: 1;
padding: 1em;
}
form {
display: flex;
flex-direction: column;
align-items: center;
}
form label, form input, form button {
margin-bottom: 1em;
}
/*index.css*/
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
background-color: #3498db;
color: white;
}
.volunteer-request-btn {
background-color: #2ecc71;
color: white;
padding: 10px;
cursor: pointer;
border: none;
border-radius: 5px;
}
/* src/Home.css */
.home {
margin: 20px;
}
.volunteer-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.volunteer-item {
background-color: #ecf0f1;
padding: 15px;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
// App.js
import React, { useState, useEffect } from "react";
import "./App.css";
import AddVolunteerForm from "./AddVolunteerForm";
import VolunteerRequests from "./VolunteerRequests";
const App = () => {
const [volunteerData, setVolunteerData] = useState([]);
const [currentSection, setCurrentSection] = useState("");
useEffect(() => {
fetchVolunteerData();
}, []);
const fetchVolunteerData = async () => {
try {
const response = await fetch("http://localhost:5000/vols", {
headers: {
Authorization: localStorage.getItem("token"),
},
});
if (!response.ok) {
throw new Error("Failed to fetch volunteer data");
}
const data = await response.json();
setVolunteerData(data);
} catch (error) {
console.error("Error:", error);
}
};
const openAddVolunteerForm = () => {
setCurrentSection("addVolunteer");
};
const loadVolunteerRequests = () => {
setCurrentSection("volunteerRequests");
};
const handleApprove = async (volunteerId) => {
try {
const approveResponse = await fetch(
"http://localhost:5000/approveVolunteer",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: localStorage.getItem("token"),
},
body: JSON.stringify({ id: volunteerId }),
}
);
if (!approveResponse.ok) {
throw new Error("Failed to approve volunteer");
}
await fetchVolunteerData();
} catch (error) {
console.error("Error:", error);
}
};
const handleRemoveFromRequests = async (volunteerId) => {
try {
const response = await fetch(
"http://localhost:5000/removeFromRequests",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: localStorage.getItem("token"),
},
body: JSON.stringify({ id: volunteerId }),
}
);
if (!response.ok) {
throw new Error(`Failed to remove
volunteer from requests`);
}
await fetchVolunteerData();
} catch (error) {
console.error("Error:", error);
}
};
return (
<div className="App">
<div className="navbar">
<h1>Volunteer Management System</h1>
</div>
<div className="hero-section">
<div className="buttons">
<button onClick={openAddVolunteerForm}>
Add Volunteer
</button>
<button onClick={loadVolunteerRequests}>
Volunteer Requests
</button>
</div>
<div className="data-display">
{currentSection === "addVolunteer" && (
<AddVolunteerForm
fetchVolunteerData={fetchVolunteerData}
/>
)}
{currentSection === "volunteerRequests" && (
<VolunteerRequests
volunteerData={volunteerData}
setVolunteerData={setVolunteerData}
handleApprove={handleApprove}
handleRemoveFromRequests=
{handleRemoveFromRequests}
/>
)}
</div>
</div>
</div>
);
};
export default App;
//AddVolunteerForm.js
import React, { useState } from "react";
const AddVolunteerForm = ({ fetchVolunteerData }) => {
const [formData, setFormData] = useState({
name: "",
event: "",
date: "",
});
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch(
`http://localhost:5000/addVolunteer`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
if (!response.ok) {
throw new Error("Failed to add volunteer");
}
await fetchVolunteerData();
setFormData({
name: "",
event: "",
date: "",
});
} catch (error) {
console.error("Error:", error);
}
};
return (
<div>
<h2>Add Volunteer</h2>
<form onSubmit={handleSubmit}>
<label>
Name:
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
/>
</label>
<br />
<label>
Event:
<input
type="text"
name="event"
value={formData.event}
onChange={handleChange}
/>
</label>
<br />
<label>
Date:
<input
type="text"
name="date"
value={formData.date}
onChange={handleChange}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
</div>
);
};
export default AddVolunteerForm;
//VolunteerRequests.js
import React, { useEffect } from "react";
const VolunteerRequests = ({ volunteerData, setVolunteerData }) => {
const handleApprove = async (volunteerId) => {
try {
const response = await fetch(
"http://localhost:5000/approveVolunteer",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: volunteerId }),
}
);
if (!response.ok) {
throw new Error("Failed to approve volunteer");
}
const updatedVolunteerData = await response.json();
setVolunteerData(updatedVolunteerData);
} catch (error) {
console.error("Error:", error);
}
};
useEffect(() => {
fetchVolunteerData();
}, [volunteerData]);
const fetchVolunteerData = async () => {
try {
const response = await fetch("http://localhost:5000/vols");
if (!response.ok) {
throw new Error("Failed to fetch volunteer data");
}
const data = await response.json();
setVolunteerData(data);
} catch (error) {
console.error("Error:", error);
}
};
return (
<div>
<h2>Volunteer Requests</h2>
<ul>
{Array.isArray(volunteerData) && volunteerData.length > 0 ? (
volunteerData.map((volunteer) => (
<li key={volunteer.id}>
{volunteer.name} - {volunteer.event} -{" "}
{volunteer.date} - Status: {volunteer.status}
{volunteer.status === "request" && (
<button
onClick={
()=>handleApprove(volunteer.id)
}
>
Approve
</button>
)}
</li>
))
) : (
<p>No volunteer requests available.</p>
)}
</ul>
</div>
);
};
export default VolunteerRequests;
// src/navbar.js
import React from 'react';
const Navbar = () => {
return <div className="navbar">Volunteer Management System</div>;
};
export default Navbar;
Output:
Contact Us