In this guide, we’ll walk through the step-by-step process of building a feature-rich Event Management Web App. We will make use of the MERN stack to build this project.
Preview of final output: Let us have a look at how the final output will look like.
 Final Output of Event Management App PrerequisiteApproach to create Event Management Application- Define the structure of an event using Mongoose schemas in a model file (e.g., `Event.js`).
- Develop routes for handling Create, Read, Update, and Delete (CRUD) operations in a dedicated `eventRoutes.js` file.
- Set up a MongoDB database and establish a connection in your Express application.
- Create a server file (e.g., `server.js`) where Express is configured to listen on a specific port.
- Design and implement a form component (`EventForm.js`) for adding new events.
- Develop a component (`EventList.js`) to display a list of events fetched from the server.
- Create a detailed event display component (`EventItem.js`) with features like editing, toggling reminders, and deleting.
- Style your components for an engaging user interface. You can utilize CSS .
Steps to Setup Backend with Node.js and ExpressStep 1: Creating express app:
npm init -y Step 2: Installing the required packages
npm install express mongoose body-parser cors Project Structure:
 Backend Project Structure The updated dependencies in package.json file for backend will look like:
"dependencies": { "body-parser": "^1.20.2", "cors": "^2.8.5", "express": "^4.18.2", "mongoose": "^8.0.0", } Example: Below is the code example of the backend.
JavaScript
// server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');
const eventRoutes = require('./routes/eventRoutes');
const app = express();
const PORT = process.env.PORT || 5000;
// Middleware
app.use(cors());
app.use(bodyParser.json());
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/event_management', {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => {
console.log('Connected to MongoDB')
});
// Routes
app.use('/api/events', eventRoutes);
// Start server
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
JavaScript
// routes/eventRoutes.js
const express = require('express');
const router = express.Router();
const Event = require('../models/Event');
// Get all events
router.get('/', async (req, res) => {
try {
const events = await Event.find();
res.json(events);
} catch (error) {
res.status(500).json({ message: error.message });
}
});
// Create a new event
router.post('/', async (req, res) => {
const event = new Event({
title: req.body.title,
date: req.body.date,
reminder: req.body.reminder || false,
});
try {
const newEvent = await event.save();
res.status(201).json(newEvent);
} catch (error) {
res.status(400).json({ message: error.message });
}
});
// Delete an event
router.delete('/:id', async (req, res) => {
console.log('****** Deleting event ******');
try {
console.log('Delete route called');
// Use findByIdAndDelete instead of findByIdAndRemove
await Event.findByIdAndDelete(req.params.id);
console.log('Event deleted');
res.json({ message: 'Event deleted' });
} catch (error) {
console.error('Error deleting event:', error);
res.status(500).json({ message: error.message });
}
});
// Update an event by ID
router.put('/:id', async (req, res) => {
const eventId = req.params.id;
const { title, date, reminder } = req.body;
console.log('reminder', reminder);
try {
// Find the event by ID in the database
const event = await Event.findById(eventId);
if (!event) {
return res.status(404).json({ message: 'Event not found' });
}
// Update the event properties
event.date = date;
event.title = title;
event.reminder = reminder;
console.log('event updated', event.reminder);
// Save the updated event
await event.save();
// You can send the updated event in the response if needed
res.json(event);
} catch (error) {
console.error('Error updating event:', error);
res.status(500).json({ message: 'Internal Server Error' });
}
});
module.exports = router;
JavaScript
// models/Event.js
const mongoose = require('mongoose');
const eventSchema = new mongoose.Schema({
title: { type: String, required: true },
date: { type: Date, required: true },
reminder: { type: Boolean, default: false },
});
const Event = mongoose.model('Event', eventSchema);
module.exports = Event;
Steps to run the backend:
node server.js Steps to Setup Frontend with ReactStep 1: Create React App:
npx create-react-app event-management-frontend Step 2: Switch to the project directory:
cd event-management-frontend Step 3: Installing the required packages:
npm install axios Project Structure:
 Frontend Project Structure The updated dependencies in package.json for frontend will look like:
"dependencies": { "axios": "^1.5.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" } Example: Below is the code example of the frontend.
CSS
/* src/EventList.css */
.event-list {
display: flex;
flex-wrap: wrap;
}
.event-card {
background-color: #D2E3C8;
border: 1px solid #ddd;
border-radius: 8px;
margin: 10px;
padding: 15px;
width: 200px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.event-card:hover {
box-shadow: 0 4px 8px green;
}
.event-info {
margin-bottom: 10px;
}
.event-title {
font-weight: bold;
}
.event-date {
color: #555;
}
.event-actions {
display: flex;
justify-content: space-between;
}
.delete-btn:hover {
background-color: red;
color: white;
}
.rem-para {
background-color: green;
color: white;
padding: 2px;
width: fit-content;
position: relative;
left: -1px;
bottom: 22px;
}
.gfg {
padding: 15px;
color: white;
background-color: rgb(6, 162, 6);
border-radius: 25px;
}
/* form
*/
input {
padding: 5px;
width: 500px;
}
form {
display: flex;
flex-direction: column;
justify-content: center;
border: 2px solid red;
padding: 20px;
border-radius: 10px;
gap: 5px;
background: linear-gradient(to right, #FFA500, #FF6347);
;
}
.main-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
label {
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
font-weight: 500;
}
JavaScript
// src/App.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import EventForm from './components/EventForm';
import EventList from './components/EventList';
import './App.css'
const App = () => {
const [events, setEvents] = useState([]);
useEffect(() => {
// Fetch events from the server
axios.get('http://localhost:5000/api/events')
.then(response => setEvents(response.data))
.catch(error => console.error(error));
}, []);
const handleEventAdd = (newEvent) => {
setEvents([...events, newEvent]);
};
const handleEventDelete = (id) => {
console.log("delete event " + id)
// Delete an event
axios.delete(`http://localhost:5000/api/events/${id}`)
.then(
() =>
setEvents(events.filter(event => event._id !== id)))
.catch(error => console.error(error));
};
const handleToggleReminder = (eventId) => {
// console.log('HI');
// Find the event by ID
const selectedEvent =
events.find(event => event._id === eventId);
// Toggle the reminder status
const updatedEvent =
{
...selectedEvent,
reminder: !selectedEvent.reminder
};
// console.log('Updated',updatedEvent);
// Update the event in the database
axios.put(`http://localhost:5000/api/events/${eventId}`, updatedEvent)
.then(response => {
// console.log('res',response.data);
// If the update is successful, update the events in the state
const updatedEvents = events.map(event =>
event._id === eventId ? updatedEvent : event
);
setEvents(updatedEvents);
})
.catch(
error =>
console.error(`Error updating reminder status for
event with ID ${eventId}:`, error));
};
const onEventEdit = (eventId, updatedData) => {
// Update the event in the database
axios.put(`http://localhost:5000/api/events/${eventId}`, updatedData)
.then(response => {
// If the update is successful, update the events in the state
const updatedEvents = events.map(event =>
event._id ===
eventId ?
{ ...event, ...updatedData } : event
);
setEvents(updatedEvents);
})
.catch(
error =>
console.error(`Error updating event with
ID ${eventId}:`, error)
);
};
return (
<div className='main-container'>
<h1 className='gfg'>
GFG
</h1>
<h2>Event Management App</h2>
<EventForm onEventAdd={handleEventAdd} />
<EventList
events={events}
onEventDelete={handleEventDelete}
onToggleReminder={handleToggleReminder}
onEventEdit={onEventEdit}
/>
</div>
);
};
export default App;
JavaScript
// src/EventList.js
import React, { useState } from 'react';
// Import the new EventItem component
import EventItem from './EventItem';
const EventList = (
{ events, onEventDelete,
onToggleReminder, onEventEdit
}
) => {
const [editedEvents, setEditedEvents] = useState([]);
const handleEventEdit = (eventId, updatedData) => {
// Find the index of the event being edited
const eventIndex =
editedEvents
.findIndex(
event =>
event._id === eventId
);
if (eventIndex !== -1) {
// Update the edited event in the local state
const updatedEditedEvents = [...editedEvents];
updatedEditedEvents[eventIndex] = {
...updatedEditedEvents[eventIndex],
...updatedData,
};
setEditedEvents(updatedEditedEvents);
} else {
// If the event is not already in the local state, add it
setEditedEvents(
[...editedEvents,
{ _id: eventId, ...updatedData }
]
);
}
// Pass the edit request to the parent component
onEventEdit(eventId, updatedData);
};
return (
<div className="event-list">
{events.map(event => (
<EventItem
key={event._id}
event={
editedEvents
.find(
editedEvent =>
editedEvent._id === event._id) || event
}
onToggleReminder={onToggleReminder}
onEventDelete={onEventDelete}
onEventEdit={handleEventEdit}
/>
))}
</div>
);
};
export default EventList;
JavaScript
// src/EventItem.js
import React, { useEffect, useState } from 'react';
import moment from 'moment';
const EventItem = (
{ event, onEventDelete,
onToggleReminder, onEventEdit
}) => {
const [isEditing, setIsEditing] = useState(false);
const [editedTitle, setEditedTitle] = useState(event.title);
const [editedDate, setEditedDate] =
useState(moment(event.date).format("YYYY-MM-DD"));
const [rem, setRem] = useState("")
useEffect(() => {
if (event) {
setRem(event.reminder ? "" : "Reminder On");
// Check if the event is today and has a reminder
const today = new Date();
const eventDate = new Date(event.date);
today.setHours(0, 0, 0, 0);
eventDate.setHours(0, 0, 0, 0);
if (today.getTime() ===
eventDate.getTime() &&
event.reminder) {
alert(`Today is the day of the event:
${event.title}`);
}
} else {
setRem("Reminder On");
}
}, [event, event.reminder]);
const handleEditClick = () => {
setIsEditing(true);
};
const handleSaveClick = () => {
// Perform the update in the database (you may use an API request here)
onEventEdit(event._id,
{
title: editedTitle,
date: editedDate
});
// Exit the edit mode
setIsEditing(false);
};
const handleCancelClick = () => {
// Reset the edited values and exit the edit mode
setEditedTitle(event.title);
setEditedDate(moment(event.date)
.format("YYYY-MM-DD"));
setIsEditing(false);
};
return (
<div className="event-card">
<p className='rem-para'>
{
event.reminder ? "Reminder On" : ""
}
</p>
<div className="event-info">
{isEditing ? (
<>
<input
type="text"
value={editedTitle}
onChange={
(e) =>
setEditedTitle(e.target.value)
}
/>
<input
type="date"
value={editedDate}
onChange={
(e) =>
setEditedDate(e.target.value)
}
/>
</>
) : (
<>
<h3 className="event-title">{event.title}</h3>
<hr />
<span className="event-date">
<span style={{ "fontWeight": "700" }}>
Event On:
</span>
{
moment(event.date)
.add(1, 'days').calendar()
};
</span>
</>
)}
</div>
<div className="event-actions">
{isEditing ? (
<>
<button onClick={handleSaveClick}>
Save
</button>
<button onClick={handleCancelClick}>
Cancel
</button>
</>
) : (
<>
<button onClick={
() => onToggleReminder(event._id)
}>
{
event.reminder ?
'Disable Reminder' : 'Enable Reminder'
}
</button>
<button className='delete-btn'
onClick={
() => onEventDelete(event._id)}>
Delete
</button>
<button onClick={handleEditClick}>
Edit
</button>
</>
)}
</div>
</div>
);
};
export default EventItem;
JavaScript
// src/EventForm.js
import React, { useState } from 'react';
import axios from 'axios';
import './EventForm.css';
const EventForm = ({ onEventAdd }) => {
const [newEvent, setNewEvent] =
useState({ title: '', date: '', reminder: false });
const handleInputChange = (e) => {
setNewEvent(
{
...newEvent,
[e.target.name]: e.target.value
}
);
};
const handleSubmit = (e) => {
e.preventDefault();
// Create a new event
axios.post('http://localhost:5000/api/events', newEvent)
.then(response => {
onEventAdd(response.data);
setNewEvent({ title: '', date: '', reminder: false });
})
.catch(error => console.error(error));
};
return (
<form onSubmit={handleSubmit}>
<label>Title:</label>
<input type="text" name="title"
value={newEvent.title}
onChange={handleInputChange} required />
<label>Date:</label>
<input type="date"
name="date" value={newEvent.date}
onChange={handleInputChange} required />
<button type="submit">Add Event</button>
</form>
);
};
export default EventForm;
Steps to run the app:
npm start Output:
|