From 89a997cad606bc4d3cccc2f8ad5b662c6f94f346 Mon Sep 17 00:00:00 2001
From: Pallavi Sarwar Recipe Manager
+
+
+Add Recipe
+
+
+
+All Recipes
+
+
+
+
+
+
diff --git a/controllers/recipe.js b/controllers/recipe.js
index 0d945d0..6ae2a56 100644
--- a/controllers/recipe.js
+++ b/controllers/recipe.js
@@ -1,11 +1,65 @@
import query from '../config/db.js';
const recipeControllers = {
- getAllRecipes: async (req, res) => {},
- getOneRecipe: async (req, res) => {},
- postRecipe: async (req, res) => {},
- updateRecipe: async (req, res) => {},
- deleteRecipe: async (req, res) => {},
+ getAllRecipes: async (req, res) => {
+ try {
+ const recipes = await query('SELECT * FROM recipes');
+ res.json(recipes);
+ } catch (error) {
+ res.status(500).send('Error retrieving recipes');
+ }
+ },
+
+ getOneRecipe: async (req, res) => {
+ const { id } = req.params;
+ try {
+ const recipes = await query('SELECT * FROM recipes WHERE id = ?', [id]);
+ if (recipes.length === 0) {
+ return res.status(404).send('Recipe not found');
+ }
+ res.json(recipes[0]);
+ } catch (error) {
+ res.status(500).send('Error retrieving the recipe');
+ }
+ },
+
+ postRecipe: async (req, res) => {
+ const { title, description } = req.body;
+ try {
+ await query('INSERT INTO recipes (title, description) VALUES (?, ?)', [title, description]);
+ res.status(201).send('Recipe created successfully');
+ } catch (error) {
+ res.status(500).send('Error creating the recipe');
+ }
+ },
+
+ updateRecipe: async (req, res) => {
+ const { id } = req.params;
+ const { title, description } = req.body;
+ try {
+ const result = await query('UPDATE recipes SET title = ?, description = ? WHERE id = ?', [title, description, id]);
+ if (result.affectedRows === 0) {
+ return res.status(404).send('Recipe not found');
+ }
+ res.send('Recipe updated successfully');
+ } catch (error) {
+ res.status(500).send('Error updating the recipe');
+ }
+ },
+
+ deleteRecipe: async (req, res) => {
+ const { id } = req.params;
+ try {
+ const result = await query('DELETE FROM recipes WHERE id = ?', [id]);
+ if (result.affectedRows === 0) {
+ return res.status(404).send('Recipe not found');
+ }
+ res.send('Recipe deleted successfully');
+ } catch (error) {
+ res.status(500).send('Error deleting the recipe');
+ }
+ },
};
export default recipeControllers;
+
diff --git a/controllers/user.js b/controllers/user.js
index b0fe546..fa382e8 100644
--- a/controllers/user.js
+++ b/controllers/user.js
@@ -8,11 +8,67 @@ import hashPassword from '../utils/hashPassword.js';
import query from '../config/db.js';
const userControllers = {
- register: async (req, res) => {},
+ register: async (req, res) => {
+ const { email, password } = req.body;
- login: async (req, res) => {},
+ // Validate email and password
+ if (!validateEmail(email)) {
+ return res.status(400).send('Invalid email format');
+ }
+ if (!validatePassword(password)) {
+ return res.status(400).send('Password does not meet complexity requirements');
+ }
- logout: async (req, res) => {},
+ // Check if the user already exists
+ const existingUser = await query('SELECT * FROM users WHERE email = ?', [email]);
+ if (existingUser.length > 0) {
+ return res.status(409).send('User already exists');
+ }
+
+ // Hash the password
+ const hashedPassword = await hashPassword(password);
+
+ // Save the user to the database
+ await query('INSERT INTO users (email, password) VALUES (?, ?)', [email, hashedPassword]);
+ res.status(201).send('User registered successfully');
+ },
+
+ login: async (req, res) => {
+ const { email, password } = req.body;
+
+
+
+ // Validate email and password
+ if (!validateEmail(email)) {
+ return res.status(400).send('Invalid email or password');
+ }
+
+
+ // Check if the user exists
+ const users = await query('SELECT * FROM users WHERE email = ?', [email]);
+ if (users.length === 0) {
+ return res.status(401).send('Invalid email or password');
+ }
+
+
+ const user = users[0];
+
+ // Check if the password matches
+ const passwordMatches = await matchPasswords(password, user.password);
+ if (!passwordMatches) {
+ return res.status(401).send('Invalid email or password');
+ }
+
+ // Generate a token
+ const token = jwt.sign({ id: user.id }, process.env.SECRET_KEY, { expiresIn: '1h' });
+ res.cookie('token', token, { httpOnly: true });
+ res.send('Logged in successfully');
+ },
+
+ logout: (req, res) => {
+ res.clearCookie('token');
+ res.send('Logged out successfully');
+ }
};
export default userControllers;
diff --git a/database/shop.sql b/database/shop.sql
new file mode 100644
index 0000000..a3d8b6d
--- /dev/null
+++ b/database/shop.sql
@@ -0,0 +1,27 @@
+-- MySQL dump 10.13 Distrib 8.0.19, for osx10.14 (x86_64)
+--
+-- Host: 127.0.0.1 Database: world
+-- ------------------------------------------------------
+-- Server version 8.0.19-debug
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+SET @old_autocommit=@@autocommit;
+
+--
+-- Current Database: `world`
+--
+
+/*!40000 DROP DATABASE IF EXISTS `world`*/;
+
+CREATE DATABASE `shop` DEFAULT CHARACTER SET utf8mb4;
+
+USE `shop`;
\ No newline at end of file
diff --git a/index.js b/index.js
index dfe2189..d4e86e6 100644
--- a/index.js
+++ b/index.js
@@ -11,6 +11,7 @@ import createRecipeTable from './models/recipe.js';
import userRoutes from './routes/user.js';
import recipeRoutes from './routes/recipe.js';
+
// set port
const PORT = process.env.PORT || 5009;
@@ -37,6 +38,13 @@ createRecipeTable();
app.use(userRoutes);
app.use(recipeRoutes);
+app.get('/', (req,res) => {
+
+ res.sendFile(path.join(PATH,'controllers','index.html'));
+
+});
+
+
// error
app.use((err, req, res, next) => {
console.error(err);
diff --git a/models/recipe.js b/models/recipe.js
index 1db0496..bb94da4 100644
--- a/models/recipe.js
+++ b/models/recipe.js
@@ -2,7 +2,19 @@ import query from '../config/db.js';
const createRecipeTable = async () => {
try {
- } catch (err) {}
+ const sql = `
+ CREATE TABLE IF NOT EXISTS recipes (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ title VARCHAR(255) NOT NULL,
+ description TEXT NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ )
+ `;
+ await query(sql);
+ console.log('Recipes table created successfully');
+ } catch (err) {
+ console.error('Error creating recipes table:', err);
+ }
};
-export default createRecipeTable;
\ No newline at end of file
+export default createRecipeTable;
diff --git a/models/user.js b/models/user.js
index 1c80be7..b393385 100644
--- a/models/user.js
+++ b/models/user.js
@@ -2,7 +2,19 @@ import query from '../config/db.js';
const createUserTable = async () => {
try {
- } catch (err) {}
+ const sql = `
+ CREATE TABLE IF NOT EXISTS users (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ email VARCHAR(255) NOT NULL UNIQUE,
+ password VARCHAR(255) NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ )
+ `;
+ await query(sql);
+ console.log('Users table created successfully');
+ } catch (err) {
+ console.error('Error creating users table:', err);
+ }
};
export default createUserTable;
diff --git a/public/css/style.css b/public/css/style.css
index e69de29..cd70313 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -0,0 +1,65 @@
+body {
+ font-family: Arial, sans-serif;
+ margin: 20px;
+ background-color: #f9f9f9;
+}
+
+h1 {
+ text-align: center;
+ color: #333;
+}
+
+h2 {
+ color: #555;
+}
+
+form {
+ margin-bottom: 20px;
+ background-color: #fff;
+ padding: 20px;
+ border-radius: 5px;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+input,
+textarea {
+ width: 100%;
+ padding: 10px;
+ margin: 5px 0;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ box-sizing: border-box;
+}
+
+button {
+ padding: 10px;
+ color: white;
+ background-color: #28a745;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+}
+
+button:hover {
+ background-color: #218838;
+}
+
+ul {
+ list-style-type: none;
+ padding: 0;
+}
+
+li {
+ background-color: #fff;
+ margin: 5px 0;
+ padding: 10px;
+ border-radius: 5px;
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+strong {
+ color: #333;
+}
diff --git a/routes/recipe.js b/routes/recipe.js
index 946531f..c5979f3 100644
--- a/routes/recipe.js
+++ b/routes/recipe.js
@@ -4,6 +4,18 @@ import recipeControllers from '../controllers/recipe.js';
const router = express.Router();
-// routes
+// Public routes
+router.get('/api/recipes', recipeControllers.getAllRecipes);
+router.get('/api/recipes/:id', recipeControllers.getOneRecipe);
+router.post('/api/recipes', recipeControllers.postRecipe);
+router.put('/api/recipes/:id', recipeControllers.updateRecipe);
+router.delete('/api/recipes/:id', recipeControllers.deleteRecipe);
+
+
+// Protected routes
+// router.post('/api/recipes', verifyToken,recipeControllers.postRecipe);
+// router.put('/api/recipes/:id', verifyToken, recipeControllers.updateRecipe);
+// router.delete('/api/recipes/:id', verifyToken, recipeControllers.deleteRecipe);
export default router;
+
diff --git a/routes/user.js b/routes/user.js
index 33313ee..38c553d 100644
--- a/routes/user.js
+++ b/routes/user.js
@@ -3,7 +3,9 @@ import userControllers from '../controllers/user.js';
const router = express.Router();
-
-// routes
+// User routes
+router.post('/api/register', userControllers.register);
+router.post('/api/login', userControllers.login);
+router.post('/api/logout', userControllers.logout);
export default router;
From bf18764a3181fd07fdd475216d0b079468d73e35 Mon Sep 17 00:00:00 2001
From: Pallavi Sarwar
Add Recipe
+
+All Recipes
@@ -78,6 +82,23 @@
All Recipes
// Initial fetch
fetchRecipes();
+
+ // Handle login form submission
+ logout.addEventListener('logout', async (e) => {
+ e.preventDefault();
+
+ const response = await fetch('/api/logout', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' }
+ });
+
+ if (response.ok) {
+ // Redirect to the main page after successful login
+ window.location.href = '/';
+ } else {
+ alert('Logout failed. Please try agin.');
+ }
+ });
diff --git a/public/login.html b/public/login.html new file mode 100644 index 0000000..d5f8210 --- /dev/null +++ b/public/login.html @@ -0,0 +1,47 @@ + + +
+ + +
+ + +
+