Horje
Event Management Web App using MERN

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.

Screenshot-2566-12-29-at-152922

Final Output of Event Management App

Prerequisite

Approach 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 Express

Step 1: Creating express app:

npm init -y

Step 2: Installing the required packages

npm install express mongoose body-parser cors

Project Structure:

Screenshot-2566-12-29-at-155011

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 React

Step 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:

Screenshot-2566-12-29-at-154953

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:




Reffered: https://www.geeksforgeeks.org


Geeks Premier League

Related
Creating Your Own Node HTTP Request Router Creating Your Own Node HTTP Request Router
How to generate webpages using CGI scripts? How to generate webpages using CGI scripts?
How to Install Matplotlib on Anaconda? How to Install Matplotlib on Anaconda?
List of Coding languages supported by ChatGPT List of Coding languages supported by ChatGPT
How To Enable or Disable CGI Scripts in Apache? How To Enable or Disable CGI Scripts in Apache?

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
11