DIY Home Improvement Guide using MERN Stack
Last Updated :
19 Mar, 2024
This project aims to provide users with a platform to perform various calculations related to home improvement tasks. From simple calculations like measuring wall paint requirements to advanced calculations like estimating material costs for renovations, our application will serve as a handy tool for DIY enthusiasts.
Output Preview: Let us have a look at how the final output will look like.
Project PreviewPrerequisites
Approach to create DIY Home Improvement Guide:
- Create React components for adding, editing, and deleting projects.
- Implement forms for project details input.
- Set up routes and controllers in the backend to handle CRUD operations for projects.
- Use Fetch API to send requests from the frontend to the backend.
- Add functionality for adding, editing, and deleting projects.
Steps to Create the Project
Step 1: Create a new directory for your project and initialize a new Node.js project using npm init.
mkdir diy-home-improvement-guide
cd diy-home-improvement-guide
Step 2: Initialize the Node project
npm init -y
Step 3: Install required dependencies like Express.js, React.js, and other necessary packages using npm.
npm install express mongoose body-parser cors
Project Structure(Backend):

The updated dependencies in package.json file will look like:
"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.3",
"mongoose": "^8.2.1"
}
Step 4: Create server.js file for setting up Express.js server. Implement routes for user authentication, CRUD operations, and any additional functionalities.
JavaScript
//server.js
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(bodyParser.json());
const mongoURI = 'mongodb://localhost:27017/diy-home-improvement';
mongoose
.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('MongoDB connected'))
.catch(err => console.log(err));
const Project = mongoose.model('project', {
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
category: {
type: String,
required: true
},
steps: {
type: [String],
required: true
}
});
app.get('/api/projects', (req, res) => {
Project.find()
.then(projects => res.json(projects))
.catch(err => res.status(404)
.json({ noProjectsFound: 'No projects found' }));
});
app.post('/api/projects', (req, res) => {
const { title, description, category, steps } = req.body;
const newProject = new Project({
title,
description,
category,
steps
});
newProject.save()
.then(project => res.json(project))
.catch(err => console.log(err));
});
app.delete('/api/projects/:id', (req, res) => {
const { id } = req.params;
Project.findByIdAndDelete(id)
.then(deletedProject => {
if (!deletedProject) {
return res.status(404)
.json({ error: 'Project not found' });
}
res.json(deletedProject);
})
.catch(err => res.status(500)
.json({ error: 'Internal server error' }));
});
app.put('/api/projects/:id', (req, res) => {
const { id } = req.params;
const { title, description, category, steps } = req.body;
Project.findByIdAndUpdate(id,
{ title, description, category, steps },
{ new: true })
.then(updatedProject => {
if (!updatedProject) {
return res.status(404)
.json({ error: 'Project not found' });
}
res.json(updatedProject);
})
.catch(err => res.status(500)
.json({ error: 'Internal server error' }));
});
const port = process.env.PORT || 5000;
app.listen(port, () =>
console.log(`Server running on port ${port}`));
Step 5: Set up the React.js frontend by creating components for user interface elements, forms, and data visualization.
npx create-react-app diy-home-improvement-frontend
cd diy-home-improvement-frontend
Project Structure(Frontend):

The updated dependencies in package.json file will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
Step 6: Implement the desired functionalities such as ProjectList and AddProject components.
CSS
/* App.css */
body {
margin: 2%;
}
.full {
display: flex;
flex-direction: row;
justify-content: space-evenly;
}
.project-list {
padding: 20px;
background-color: #fcfefe;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.project {
margin-bottom: 20px;
padding: 20px;
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
.project h3 {
color: #f76b8a;
}
.project p {
color: #555555;
}
.project ul {
margin-top: 10px;
padding-left: 20px;
}
.project li {
color: #777777;
}
.add-project-form {
width: 100%;
padding: 20px;
}
.add-project-form label {
color: #f76b8a;
}
.add-project-form input[type='text'],
.add-project-form textarea {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #dddddd;
border-radius: 5px;
}
.add-project-form button {
padding: 10px 20px;
background-color: #f76b8a;
color: #ffffff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.add-project-form button:hover {
background-color: #e25e7f;
}
.edit-btn,
.delete-btn {
margin-right: 10px;
padding: 8px 16px;
background-color: #f76b8a;
color: #ffffff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.edit-btn:hover,
.delete-btn:hover {
background-color: #e25e7f;
}
.edit-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.edit-form-container {
background-color: #ffffff;
padding: 50px;
width: 700px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
.edit-form-container h2 {
margin-bottom: 20px;
}
.edit-form-container form label {
display: block;
margin-bottom: 10px;
}
.edit-form-container form input,
.edit-form-container form textarea {
width: 100%;
padding: 8px;
margin-bottom: 10px;
}
.edit-form-container form button {
padding: 8px 16px;
background-color: #f76b8a;
color: #ffffff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.edit-form-container form button:hover {
background-color: #e25e7f;
}
JavaScript
import React, { useState } from 'react';
import ProjectList from './ProjectList';
import AddProjectForm from './AddProjectForm';
import AreaCalculator from './AreaCalculator';
function App() {
const [roomInfo, setRoomInfo] = useState(null);
const handleRoomInfo = info => {
setRoomInfo(info);
};
return (
<div>
<h1>DIY Home Improvement Guide</h1>
<div className='full'>
<AreaCalculator onRoomInfo={handleRoomInfo} />
<AddProjectForm />
</div>
<hr />
<ProjectList />
</div>
);
}
export default App;
JavaScript
//AreaCalculator.js
import React, { useState } from 'react';
const AreaCalculator = () => {
const [area, setArea] = useState('');
const [error, setError] = useState('');
const [suggestedResult, setSuggestedResult] = useState(null);
const handleChange = event => {
setArea(event.target.value);
};
const handleSubmit = event => {
event.preventDefault();
if (!area || isNaN(area) || area <= 0) {
setError('Please enter a valid positive number for the area.');
setSuggestedResult(null);
return;
}
const roomArea = 150;
const hallArea = 200;
const bathroomArea = 60;
const kitchenArea = 100;
const maxRooms = Math.floor(area / roomArea);
const maxHalls = Math.floor(area / hallArea);
const maxBathrooms = Math.floor(area / bathroomArea);
const maxKitchens = Math.floor(area / kitchenArea);
setSuggestedResult({
rooms: maxRooms,
halls: maxHalls,
kitchens: maxKitchens,
bathrooms: maxBathrooms,
});
setError('');
};
return (
<div style={styles.container}>
<h2 style={styles.title}>Area Calculator</h2>
<form onSubmit={handleSubmit} style={styles.form}>
<label style={styles.label}>
Enter Area (in square feet):
<input type="number" value={area}
onChange={handleChange} style={styles.input} />
</label>
<button type="submit" style={styles.button}>Calculate</button>
</form>
{error && <p style={styles.error}>{error}</p>}
{suggestedResult && (
<div style={styles.result}>
<h3 style={styles.resultTitle}>Suggested Configuration</h3>
<p>Maximum number of rooms: {suggestedResult.rooms}</p>
<p>Maximum number of halls: {suggestedResult.halls}</p>
<p>Maximum number of kitchens: {suggestedResult.kitchens}</p>
<p>Maximum number of bathrooms: {suggestedResult.bathrooms}</p>
</div>
)}
</div>
);
};
const styles = {
container: {
maxWidth: '500px',
padding: '20px',
},
title: {
textAlign: 'center',
marginBottom: '20px',
},
form: {
display: 'flex',
flexDirection: 'column',
},
label: {
marginBottom: '10px',
},
input: {
padding: '8px',
marginBottom: '15px',
border: '1px solid #ccc',
borderRadius: '3px',
},
button: {
padding: '10px',
backgroundColor: 'pink',
color: 'black',
border: 'none',
borderRadius: '3px',
cursor: 'pointer',
},
error: {
color: 'red',
textAlign: 'center',
marginTop: '15px',
},
result: {
marginTop: '20px',
},
resultTitle: {
marginBottom: '10px',
},
};
export default AreaCalculator;
JavaScript
//ProjectList.js
import React, { useState, useEffect } from 'react';
import './App.css';
import GetColor from './GetColor';
const ProjectList = () => {
const [projects, setProjects] = useState([]);
const [error, setError] = useState(null);
const [editFormData, setEditFormData] = useState({
id: '',
title: '',
description: '',
category: '',
steps: ''
});
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
useEffect(() => {
fetch('http://localhost:5000/api/projects')
.then(response => response.json())
.then(data => setProjects(data))
.catch(error => console.error('Error fetching projects:', error));
}, []);
const handleDelete = id => {
fetch(`http://localhost:5000/api/projects/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(alert("Deleted Sucessfully !!"))
.then(data => {
setProjects(projects.filter(project => project._id !== id));
})
.catch(error => console.error('Error deleting project:', error));
};
const handleEdit = project => {
setEditFormData({
id: project._id,
title: project.title,
description: project.description,
category: project.category,
steps: project.steps.join('\n')
});
setIsEditModalOpen(true);
};
const handleSubmitEdit = event => {
event.preventDefault();
fetch(`http://localhost:5000/api/projects/${editFormData.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: editFormData.title,
description: editFormData.description,
category: editFormData.category,
steps: editFormData.steps.split('\n')
})
})
.then(response => response.json())
.then(data => {
setProjects(projects.map(project => (project._id ===
editFormData.id ? data : project)));
setEditFormData({
id: '',
title: '',
description: '',
category: '',
steps: ''
});
setIsEditModalOpen(false);
})
.catch(error => console.error('Error editing project:', error));
};
if (error) {
return <div>Error: {error}</div>;
}
return (
<div className="project-list">
<h2>Projects</h2>
{projects.map(project => (
<div key={project._id} className="project">
<h3>{project.title}</h3>
<p>{project.description}</p>
<p>Category: {project.category}</p>
<ul>
{project.steps.map((step, index) => (
<li key={index}>{step}</li>
))}
</ul>
<div>
<button className="edit-btn" onClick={() =>
handleEdit(project)}>Edit</button>
<button className="delete-btn" onClick={() =>
handleDelete(project._id)}>Delete</button>
</div>
<GetColor project={project} />
</div>
))}
{isEditModalOpen && (
<div className="edit-modal">
<div className="edit-form-container">
<h2>Edit Project</h2>
<form onSubmit={handleSubmitEdit}>
<label>
Title:
<input
type="text"
name="title"
value={editFormData.title}
onChange={event => setEditFormData(
{ ...editFormData, title: event.target.value })}
/>
</label>
<br />
<label>
Description:
<textarea
name="description"
value={editFormData.description}
onChange={event => setEditFormData(
{ ...editFormData, description: event.target.value })}
/>
</label>
<br />
<label>
Category:
<input
type="text"
name="category"
value={editFormData.category}
onChange={event => setEditFormData(
{ ...editFormData, category: event.target.value })}
/>
</label>
<br />
<label>
Steps:
<textarea
name="steps"
value={editFormData.steps}
onChange={event => setEditFormData(
{ ...editFormData, steps: event.target.value })}
/>
</label>
<br />
<button type="submit">Save Changes</button>
</form>
</div>
</div>
)}
</div>
);
};
export default ProjectList;
JavaScript
//GetColor.js
import React, { useState } from 'react';
import './App.css';
const colorData = {
colors: [
{ name: 'Red', hex: '#f95959' },
{ name: 'Green', hex: '#cbf078' },
{ name: 'Blue', hex: '#93deff' },
{ name: 'Yellow', hex: '#f8f398' },
{ name: 'Purple', hex: '#7c73e6' },
{ name: 'Orange', hex: '#ff9a3c' },
{ name: 'Pink', hex: '#ffb5b5' },
{ name: 'Black', hex: '#141010' },
{ name: 'White', hex: '#fcfefe' },
{ name: 'Gray', hex: '#ececec' }
]
};
const GetColor = ({ project }) => {
const [GetColor, setGetColor] = useState(null);
const handleGetColor = () => {
const randomIndex = Math.floor(Math.random() *
colorData.colors.length);
const selectedColor = colorData.colors[randomIndex];
setGetColor(selectedColor);
};
return (
<div>
<button onClick={handleGetColor} className='edit-btn'
style={{ marginTop: "1%" }}>Get Color Recommendation</button>
{GetColor && (
<div style={{
backgroundColor: GetColor.hex, padding: '10px',
marginTop: '10px', margin: '2%', border: "2px solid black"
}}>
<p>Name: {GetColor.name}</p>
<p>Hex: {GetColor.hex}</p>
</div>
)}
</div>
);
};
export default GetColor;
JavaScript
import React, { useState } from 'react';
import './App.css';
const AddProjectForm = () => {
const [formData, setFormData] = useState({
title: '',
description: '',
category: '',
steps: ''
});
const handleChange = event => {
setFormData({ ...formData, [event.target.name]: event.target.value });
};
const handleSubmit = event => {
event.preventDefault();
fetch('http://localhost:5000/api/projects', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(response => response.json())
.then(data => alert("Added Sucessfully !!"))
.catch(error => console.error('Error adding project:', error));
};
return (
<div className="add-project-form">
<h2>Add New Project</h2>
<form onSubmit={handleSubmit}>
<label>
Title:
<input type="text" name="title"
value={formData.title} onChange={handleChange} />
</label>
<br />
<label>
Description:
<textarea name="description"
value={formData.description} onChange={handleChange} />
</label>
<br />
<label>
Category:
<input type="text" name="category"
value={formData.category} onChange={handleChange} />
</label>
<br />
<label>
Steps:
<textarea name="steps"
value={formData.steps} onChange={handleChange} />
</label>
<br />
<button type="submit">Add Project</button>
</form>
</div>
);
};
export default AddProjectForm;
Steps to Run the Application
- Step 1: Navigate to the project directory in your terminal.
- Step 2: Start the backend server by running
node server.js
- Step 3: Navigate to the client directory.
- Step 4: Start the frontend development server by running
npm start
- Step 5: Open your web browser and go to http://localhost:3000 to access the application.
Output:
DIY Home Improvement Guide with MERN Stack
Similar Reads
DIY Home Improvement Guide using MERN Stack
This project aims to provide users with a platform to perform various calculations related to home improvement tasks. From simple calculations like measuring wall paint requirements to advanced calculations like estimating material costs for renovations, our application will serve as a handy tool fo
9 min read
Expense Tracker (Budget Management) using MERN
An Expense Tracker or Budget Management application using the MERN stack (MongoDB, Express, React, Node) is a powerful and versatile solution for individuals or businesses looking to manage their finances effectively. This stack provides a seamless and efficient way to build a full-fledged web appli
6 min read
Expense Management System using MERN Stack
In this article, weâll walk through the step-by-step process of creating a Expense Management System using the MERN (MongoDB, ExpressJS, React, NodeJS) stack. This project will showcase how to set up a full-stack web application where users can add their budget and put daily expenses that get deduct
14 min read
Bookstore Ecommerce App using MERN Stack
Bookstore E-commerce project is a great way to showcase your understanding of full-stack development. In this article, we'll walk through the step-by-step process of creating a Bookstore E-commerce using the MERN (MongoDB, Express.js, React, Node.js) stack. This project will showcase how to set up a
8 min read
Community Marketplace App using MERN Stack
Building a community Marketplace App will help you understand the foundational concepts of full-stack development using the MERN(MongoDB, ExpressJS, React, NodeJS) stack. This tutorial will guide you to set up the backend server for the project and demonstrate the integration of frontend functionali
6 min read
Text-based Adventure Game using MERN Stack
Text-based adventure games, where players navigate a story through choices and text, have a unique charm in gaming. With modern web development tools like MERN (MongoDB, Express.js, React.js, and Node.js), building these games is easier and more powerful than ever. Using MERN, developers can create
7 min read
E-commerce Website using MERN Stack
The project is an E-commerce website built using the MERN (MongoDB, Express.js, React, Node.js) stack. It provides a platform for users to view and purchase various products. The server-side (Node.js with Express) manages the API for product data stored in a MongoDB database. The client-side (React)
7 min read
Real Estate Management using MERN
In this article, we will guide you through the process of building a Real Estate Management Application using the MERN stack. MERN stands for MongoDB, Express, React, and Node. MongoDB will serve as our database, Express will handle the backend, React will create the frontend, and Node.js will be th
9 min read
Bookstore Ecommerce App using MEAN Stack
In this article, we will build a simple yet powerful bookstore application using Angular for the front end and Node.js for the back end. This project application will showcase how to set up a full-stack web application where users can view, filter, and purchase various books. Project Preview: Prereq
8 min read
Restaurant App using MERN Stack
Creating a Restaurant app will cover a lot of features of the MERN stack. In this tutorial, we'll guide you through the process of creating a restaurant application using the MERN stack. The application will allow users to browse through a list of restaurants, view their menus, and add items to a sh
11 min read