General File Structure
General File Structure
Since the ByteXL environment already has packages installed, you can focus on where to write the code.
Here’s a suggestion for the project structure:
2. Frontend (React):
This file defines the MongoDB schema for tasks, including fields for name, description, due date, and
priority.
priority: {
type: String,
required: true,
});
try {
});
res.json(tasks);
} catch (err) {
});
module.exports = router;
try {
const task = new Task({ name, description, dueDate, priority });
await task.save();
res.status(201).json(task);
} catch (err) {
});
// Delete a task
try {
if (!task) {
} catch (err) {
});
const [task, setTask] = useState({ name: '', description: '', dueDate: '', priority: 'medium' });
useEffect(() => {
setTasks(response.data);
};
fetchTasks();
}, []);
};
e.preventDefault();
setTasks([...tasks, response.data]);
};
// Delete a task
await axios.delete(`/tasks/${id}`);
};
return (
<div>
<h1>Task Manager</h1>
<form onSubmit={addTask}>
<option value="high">High</option>
<option value="low">Low</option>
</select>
</form>
<ul>
{tasks.map(task => (
<li key={task._id}>
</li>
))}
</ul>
</div>
);
};
export default TaskManager;
project-folder/
├── models/
├── app.js <-- Your main backend file (where you connect MongoDB)
2 Got it! I'll provide the step-by-step codes for your Recipe Book with Category Filter project in a clear
and simple way so you can write them down before execution. Here's how to proceed:
File: models/recipeModel.js
javascript
Copy code
});
module.exports = mongoose.model('Recipe', recipeSchema);
File: routes/recipeRoutes.js
try {
await recipe.save();
res.status(201).json(recipe);
} catch (error) {
});
try {
res.status(200).json(recipes);
} catch (error) {
}
});
try {
res.status(200).json(recipes);
} catch (error) {
});
module.exports = router;
File: app.js
require('dotenv').config();
app.use(express.json());
// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
// Use Routes
app.use('/api', recipeRoutes);
File: frontend/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Recipe Book</title>
</head>
<body>
<h1>Recipe Book</h1>
<form id="recipeForm">
<option value="Dessert">Dessert</option>
<option value="Appetizer">Appetizer</option>
</select>
</form>
<div>
<select id="filter">
<option value="">All</option>
<option value="Dessert">Dessert</option>
<option value="Appetizer">Appetizer</option>
</select>
</div>
<div id="recipes"></div>
<script src="script.js"></script>
</body>
</html>
File: frontend/styles.css
body {
margin: 20px;
h1 {
text-align: center;
form, #filter {
form input, form textarea, form select, form button, #filter select {
display: block;
width: 100%;
margin: 10px 0;
padding: 10px;
#recipes {
max-width: 600px;
.recipe {
padding: 10px;
margin: 10px 0;
File: frontend/script.js
<div class="recipe">
<h3>${recipe.name}</h3>
<p><strong>Ingredients:</strong> ${recipe.ingredients}</p>
<p><strong>Category:</strong> ${recipe.category}</p>
</div>
`).join('');
};
e.preventDefault();
await fetch(API_URL, {
method: 'POST',
});
recipeForm.reset();
fetchRecipes();
});
// Filter recipes by category
fetchRecipes(category);
});
// Initial fetch
fetchRecipes();
Backend:
Frontend:
recipe-book/
├── backend/
│ ├── models/
│ │ └── recipeModel.js
│ ├── routes/
│ │ └── recipeRoutes.js
│ └── app.js
├── frontend/
│ ├── index.html
│ ├── styles.css
│ └── script.js
Task (a): Develop an app where users can add items to their favorites list after logging in.
1. Create a User model and a Favorite model.
User model will contain fields for username and password.
Favorite model will contain fields for name, category, and a reference to the user.
Task (b): Use JWT for authentication, allowing access to the favorites list only after login.
2. Implement user authentication (login and registration) with JWT:
Register a new user with username and password.
Login the user and issue a JWT token for subsequent requests.
User Authentication Routes (userRoutes.js):
User Registration Route:
const express = require('express');
const bcrypt = require('bcryptjs');
const User = require('../models/userModel');
const router = express.Router();
module.exports = router;
Task (c): Save favorite items in MongoDB, associated with the user account.
3. Create routes to add, view, and delete favorite items.
Add Favorite Route (Authenticated):
const Favorite = require('../models/favoriteModel');
router.post('/add', authenticateToken, async (req, res) => {
const { name, category } = req.body;
const newFavorite = new Favorite({ name, category, user: req.userId });
await newFavorite.save();
res.status(201).json(newFavorite);
});
javascript
Copy code
router.get('/favorites', authenticateToken, async (req, res) => {
const favorites = await Favorite.find({ user: req.userId });
res.json(favorites);
});
javascript
Copy code
router.delete('/delete/:id', authenticateToken, async (req, res) => {
await Favorite.findByIdAndDelete(req.params.id);
res.json({ message: 'Favorite deleted' });
});
Authentication Middleware:
const authenticateToken = (req, res, next) => {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) return res.status(403).json({ message: 'Access denied' });
jwt.verify(token, 'secretKey', (err, decoded) => {
if (err) return res.status(403).json({ message: 'Invalid token' });
req.userId = decoded.userId;
next();
});
};
A form that allows users to log in and stores the JWT token for future requests.
import { useState } from 'react';
import axios from 'axios';
const Login = ({ onLogin }) => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.post('http://localhost:5000/api/users/login', { username,
password });
localStorage.setItem('token', data.token);
onLogin();
} catch (error) {
console.error('Login error:', error.response?.data?.message);
}
};
return (
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Username" value={username} onChange={(e) =>
setUsername(e.target.value)} />
<input type="password" placeholder="Password" value={password} onChange={(e) =>
setPassword(e.target.value)} />
<button type="submit">Login</button>
</form>
);
};
export default Login;
2. Favorites Component (Favorites.js):
Allows users to add, view, and delete favorite items, with authentication.
javascript
Copy code
import { useState, useEffect } from 'react';
import axios from 'axios';
const Favorites = () => {
const [name, setName] = useState('');
const [category, setCategory] = useState('');
const [favorites, setFavorites] = useState([]);
useEffect(() => {
const fetchFavorites = async () => {
const token = localStorage.getItem('token');
const { data } = await axios.get('http://localhost:5000/api/favorites/favorites', {
headers: { Authorization: `Bearer ${token}` }
});
setFavorites(data);
};
fetchFavorites();
}, []);
const handleAddFavorite = async () => {
const token = localStorage.getItem('token');
await axios.post('http://localhost:5000/api/favorites/add', { name, category }, {
headers: { Authorization: `Bearer ${token}` }
});
setName('');
setCategory('');
const { data } = await axios.get('http://localhost:5000/api/favorites/favorites', {
headers: { Authorization: `Bearer ${token}` }
});
setFavorites(data);
};
const handleDeleteFavorite = async (id) => {
const token = localStorage.getItem('token');
await axios.delete(`http://localhost:5000/api/favorites/delete/${id}`, {
headers: { Authorization: `Bearer ${token}` }
});
const { data } = await axios.get('http://localhost:5000/api/favorites/favorites', {
headers: { Authorization: `Bearer ${token}` }
});
setFavorites(data);
};
return (
<div>
<h1>Your Favorites</h1>
<input type="text" placeholder="Item Name" value={name} onChange={(e) =>
setName(e.target.value)} />
<input type="text" placeholder="Category" value={category} onChange={(e) =>
setCategory(e.target.value)} />
<button onClick={handleAddFavorite}>Add Favorite</button>
<ul>
{favorites.map((favorite) => (
<li key={favorite._id}>
{favorite.name} - {favorite.category}
<button onClick={() => handleDeleteFavorite(favorite._id)}>Delete</button>
</li>
))}
</ul>
</div>
);
};
export default Favorites;
Summary:
1. Backend:
Create User and Favorite models.
Implement JWT authentication for secure login.
Set up routes for user registration, login, and managing favorite items (add, view, delete).
2. Frontend:
Login Component handles user login and stores the JWT token.
Favorites Component displays the favorites list and allows users to add or delete items.
3. Expense Tracker with Monthly View a. Set up an expense tracker where users can add
expenses with a description, amount, and date. b. Display expenses for the current month,
grouped by day. c. Store expenses in MongoDB and show a summary of total expenses for the
month.
Here’s how you can write the code on paper for the Expense Tracker with Monthly View task:
Task (a): Set up an expense tracker where users can add expenses with a description, amount,
and date.
1. Create an Expense Model to store the expenses in MongoDB:
module.exports = router;
Task (b): Display expenses for the current month, grouped by day.
3. Create an API route to fetch expenses for the current month, grouped by day:
const moment = require('moment');
res.json(expenses);
});
Here’s how you can write the code on paper for the Expense Tracker with Monthly
View task:
Task (c): Store expenses in MongoDB and show a summary of total expenses for the
month.
4. Create an API route to fetch the total expenses for the current month:
router.get('/monthly-summary', async (req, res) => {
const startOfMonth = moment().startOf('month').toDate();
const endOfMonth = moment().endOf('month').toDate();
useEffect(() => {
// Fetch monthly expenses grouped by day
axios.get('http://localhost:5000/api/expenses/monthly-expenses')
.then(response => setExpenses(response.data));
// Fetch total expenses for the month
axios.get('http://localhost:5000/api/expenses/monthly-summary')
.then(response => setTotalAmount(response.data.totalAmount));
}, []);
return (
<div>
<h1>Monthly Expenses</h1>
<h2>Total Expenses: ${totalAmount}</h2>
{expenses.map((dayExpense) => (
<div key={dayExpense._id}>
<h3>Day {dayExpense._id}</h3>
<ul>
{dayExpense.expenses.map((expense, index) => (
<li key={index}>
{expense.description}: ${expense.amount}
</li>
))}
</ul>
<p>Total for the day: ${dayExpense.totalAmount}</p>
</div>
))}
</div>
);
};
user.favorites.push(item);
await user.save();
res.json({ message: "Item added to favorites", favorites: user.favorites });
} catch (err) {
res.status(500).json({ message: "Error adding favorite" });
}
});
module.exports = router;
try {
const decoded = jwt.verify(token, "secret"); // Use a secret key
req.user = decoded;
next();
} catch (err) {
res.status(403).json({ message: "Invalid token" });
}
};
Backend: routes/auth.js
Handles login and returns a JWT token.
javascript
Copy code
const express = require('express');
const router = express.Router();
const User = require('../models/userModel');
const jwt = require('jsonwebtoken');
const token = jwt.sign({ username }, "secret", { expiresIn: '1h' }); // Secret key
res.json({ token });
});
module.exports = router;
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/favoritesApp', { useNewUrlParser: true,
useUnifiedTopology: true })
.then(() => console.log("MongoDB Connected"))
.catch(err => console.error(err));
// Routes
app.use('/api/auth', authRoutes);
app.use('/api/favorites', favoritesRoutes);
This is the most simplified structure possible for your task. Focus on understanding these small
blocks to write and remember them for your exam. 😊
4o