Project Structure (Backend)
Example: Create the required files as seen on the project structure and add the following codes.
// authController.js
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
exports.register = async (req, res) => {
try {
const { username, email, password } = req.body;
let user = await User.findOne({ email });
if (user) {
console.log("User already exists:", email);
return res.status(400).json({ msg: "User already exists" });
}
user = new User({
username,
email,
password,
});
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
const token = generateJwtToken(user.id);
res.json({ token });
} catch (err) {
console.error("Error registering user:", err.message);
res.status(500).send("Server Error");
}
};
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ msg: "Invalid credentials" });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ msg: "Invalid credentials" });
}
const token = generateJwtToken(user.id);
res.status(200).json({ token });
} catch (err) {
console.error("Error logging in user:", err.message);
res.status(500).send("Server Error");
}
};
function generateJwtToken(userId) {
const payload = {
user: {
id: userId,
},
};
return jwt.sign(payload, "jwtSecret", { expiresIn: 3600 });
}
// activityController.js
const Activity = require("../models/Activity");
const jwt = require("jsonwebtoken");
const secretKey = "jwtSecret";
exports.getAllActivities = async (req, res) => {
let userId;
try {
jwt.verify(
req.headers["authorization"].substring(7),
secretKey,
(err, decodedToken) => {
if (err) {
console.error("Error decoding token:", err);
} else {
userId = decodedToken.user.id;
}
}
);
const activities = await Activity.find({ userId: userId });
res.json(activities);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
};
exports.createActivity = async (req, res) => {
try {
let activity = {};
const { activityName, duration, caloriesBurned, steps, distance, date } =
req.body;
if (
req.headers["authorization"] &&
req.headers["authorization"].startsWith("Bearer ")
) {
jwt.verify(
req.headers["authorization"].substring(7),
secretKey,
(err, decodedToken) => {
if (err) {
console.error("Error decoding token:", err);
} else {
activity = new Activity({
userId: decodedToken.user.id,
activityName,
duration,
caloriesBurned,
steps,
distance,
date,
});
}
}
);
await activity.save();
res.json(activity);
}
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
};
exports.getActivityById = async (req, res) => {
try {
const id = req.params.id;
const activities = await Activity.findById(id);
res.json(activities);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
};
exports.updateActivity = async (req, res) => {
try {
const { id } = req.params;
const { activityName, duration, caloriesBurned, steps, distance } =
req.body;
const activity = await Activity.findByIdAndUpdate(
id,
{
activityName,
duration,
caloriesBurned,
steps,
distance,
},
{ new: true }
);
res.json(activity);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
};
exports.deleteActivity = async (req, res) => {
try {
const { id } = req.params;
await Activity.findByIdAndDelete(id);
res.json({ msg: "Activity deleted" });
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
};
// models/Activity.js
const mongoose = require('mongoose');
const activitySchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
activityName: {
type: String,
required: true,
},
duration: {
type: Number,
required: true
},
caloriesBurned: {
type: Number,
required: true
},
steps: {
type: Number,
required: false
},
distance: {
type: Number,
required: false
},
date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('Activity', activitySchema);
// models/User.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
module.exports = mongoose.model('User', userSchema);
// routes/activityRoutes.js
const express = require('express');
const router = express.Router();
const activityController = require('../controllers/activityController');
router.get('/', activityController.getAllActivities);
router.post('/create', activityController.createActivity);
router.get('/:id', activityController.getActivityById);
router.put('/update/:id', activityController.updateActivity);
router.delete('/delete/:id', activityController.deleteActivity);
module.exports = router;
// routes/authRoutes.js
const express = require('express');
const router = express.Router();
const authController = require('../controllers/authController');
router.post('/register', authController.register);
router.post('/login', authController.login);
module.exports = router;
// server.js
const express = require('express');
const mongoose = require('mongoose');
const authRoutes = require('./routes/authRoutes');
const activityRoutes = require('./routes/activityRoutes');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/health-tracker', {
useNewUrlParser: true,
useUnifiedTopology: true,
family: 4,
})
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
app.use('/api/auth', authRoutes);
app.use('/api/activities', activityRoutes);
const PORT = 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
To start the backend server use the following command:
nodemon server.js
Step 4: Install the angular CLI
npm install -g @angular/cli
Step 5: Create a new angular project
ng new frontend
Step 6: Create components for various functionalities in angular application
Syntax - ng generate component <component-name>
ng generate component auth
ng generate component activities
Step 7: Create service in frontend to establish communication between frontend and backend
Syntax - ng generate service <service-name>
ng generate service auth
ng generate service activities
The updated dependencies in package.json file of frontend will look like:
"dependencies": {
"@angular/animations": "^17.2.4",
"@angular/common": "^17.2.4",
"@angular/compiler": "^17.2.4",
"@angular/core": "^17.2.4",
"@angular/forms": "^17.2.4",
"@angular/platform-browser": "^17.2.4",
"@angular/platform-browser-dynamic": "^17.2.4",
"@angular/platform-server": "^17.2.4",
"@angular/router": "^17.2.4",
"@angular/ssr": "^17.2.3",
"@auth0/angular-jwt": "^5.2.0",
"express": "^4.18.2",
"jwt-decode": "^4.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
}
Health Tracker using MEAN Stack
In the fast-paced world, maintaining a healthy lifestyle is more important than ever. Technology can play a significant role in helping individuals monitor and improve their health. In this article, we’ll explore how to use the power of the MEAN (MongoDB, Express.js, Angular, Node.js) stack to build a robust and feature-rich Health Tracker application.
Project Preview: Let us have a look at how the final output will look like.