Refactor code, split routes, change url in backend and update in frontend. Still have bugs, infinite loading after signup?

This commit is contained in:
estherdev03
2025-03-19 02:09:30 -06:00
parent 3ac9ed00a2
commit c75fa01392
14 changed files with 582 additions and 510 deletions

View File

@@ -17,6 +17,12 @@ CREATE TABLE UserRole (
FOREIGN KEY (UserID) REFERENCES User (UserID) ON DELETE CASCADE FOREIGN KEY (UserID) REFERENCES User (UserID) ON DELETE CASCADE
); );
-- Category Entity (must be created before Product or else error)
CREATE TABLE Category (
CategoryID INT PRIMARY KEY,
Name VARCHAR(255) NOT NULL
);
-- Product Entity -- Product Entity
CREATE TABLE Product ( CREATE TABLE Product (
ProductID INT PRIMARY KEY, ProductID INT PRIMARY KEY,
@@ -35,11 +41,6 @@ CREATE TABLE Image_URL (
FOREIGN KEY (ProductID) REFERENCES Product (ProductID) FOREIGN KEY (ProductID) REFERENCES Product (ProductID)
) )
-- Category Entity
CREATE TABLE Category (
CategoryID INT PRIMARY KEY,
Name VARCHAR(255) NOT NULL
);
-- Review Entity (Many-to-One with User, Many-to-One with Product) -- Review Entity (Many-to-One with User, Many-to-One with Product)
CREATE TABLE Review ( CREATE TABLE Review (

View File

@@ -0,0 +1,70 @@
const db = require("../utils/database");
exports.addToFavorite = (req, res) => {
const { userID, productsID } = req.body;
// Use parameterized query to prevent SQL injection
db.execute(
"INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)",
[userID, productsID],
(err, result) => {
if (err) {
console.error("Error adding favorite product:", err);
return res.json({ error: "Could not add favorite product" });
}
res.json({
success: true,
message: "Product added to favorites successfully",
});
}
);
};
//Get all products
exports.getAllProducts = (req, res) => {
const query = "SELECT * FROM Product";
db.execute(query, (err, data) => {
if (err) {
console.error("Error finding user:", err);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
res.json({
success: true,
message: "Product added to favorites successfully",
data,
});
});
};
// db_con.query(
// "SELECT ProductID FROM product WHERE ProductID = ?",
// [productID],
// (err, results) => {
// if (err) {
// console.error("Error checking product:", err);
// return res.json({ error: "Database error" });
// }
// if (results.length === 0) {
// return res.json({ error: "Product does not exist" });
// }
// },
// );
// db_con.query(
// "INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)",
// [userID, productID],
// (err, result) => {
// if (err) {
// console.error("Error adding favorite product:", err);
// return res.json({ error: "Could not add favorite product" });
// }
// res.json({
// success: true,
// message: "Product added to favorites successfully",
// });
// },
// );

311
backend/controllers/user.js Normal file
View File

@@ -0,0 +1,311 @@
const crypto = require("crypto");
const db = require("../utils/database");
const { sendVerificationEmail } = require("../utils/helper");
exports.sendVerificationCode = async (req, res) => {
const { email } = req.body;
if (!email) {
return res.status(400).json({ error: "Email is required" });
}
try {
// Generate a random 6-digit code
const verificationCode = crypto.randomInt(100000, 999999).toString();
console.log(
`Generated verification code for ${email}: ${verificationCode}`
);
// Check if email already exists in verification table
db.execute(
"SELECT * FROM AuthVerification WHERE Email = ?",
[email],
async (err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length > 0) {
// Update existing record
db.execute(
`UPDATE AuthVerification SET VerificationCode = ?, Authenticated = FALSE, Date = CURRENT_TIMESTAMP
WHERE Email = ?`,
[verificationCode, email],
async (err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
}
);
} else {
// Insert new record
db.execute(
"INSERT INTO AuthVerification (Email, VerificationCode, Authenticated) VALUES (?, ?, FALSE)",
[email, verificationCode],
async (err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
}
);
}
}
);
} catch (error) {
console.error("Error:", error);
res.status(500).json({ error: "Server error" });
}
};
exports.verifyCode = (req, res) => {
const { email, code } = req.body;
if (!email || !code) {
return res.status(400).json({ error: "Email and code are required" });
}
console.log(`Attempting to verify code for ${email}: ${code}`);
// Check verification code
db.execute(
"SELECT * FROM AuthVerification WHERE Email = ? AND VerificationCode = ? AND Authenticated = 0 AND Date > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
[email, code],
(err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length === 0) {
console.log(`Invalid or expired verification code for email ${email}`);
return res
.status(400)
.json({ error: "Invalid or expired verification code" });
}
const userId = results[0].UserID;
// Mark as authenticated
db.execute(
"UPDATE AuthVerification SET Authenticated = TRUE WHERE Email = ?",
[email],
(err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
console.log(`Email ${email} successfully verified`);
res.json({
success: true,
message: "Verification successful",
userId,
});
}
);
}
);
};
exports.completeSignUp = (req, res) => {
const data = req.body;
db.execute(
`SELECT * FROM AuthVerification WHERE Email = '${data.email}' AND Authenticated = 1;`,
(err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length === 0) {
return res.status(400).json({ error: "Email not verified" });
}
// Create the user
db.execute(
`INSERT INTO User (Name, Email, UCID, Password, Phone, Address)
VALUES ('${data.name}', '${data.email}', '${data.UCID}', '${data.password}', '${data.phone}', '${data.address}')`,
(err, result) => {
if (err) {
console.error("Error creating user:", err);
return res.status(500).json({ error: "Could not create user" });
}
// Insert role using the user's ID
db.execute(
`INSERT INTO UserRole (UserID, Client, Admin)
VALUES (LAST_INSERT_ID(), ${data.client || true}, ${
data.admin || false
})`,
(roleErr) => {
if (roleErr) {
console.error("Error creating role:", roleErr);
return res.status(500).json({ error: "Could not create role" });
}
// Delete verification record
db.execute(
`DELETE FROM AuthVerification WHERE Email = '${data.email}'`,
(deleteErr) => {
if (deleteErr) {
console.error("Error deleting verification:", deleteErr);
}
res.json({
success: true,
message: "User registration completed successfully",
name: data.name,
email: data.email,
UCID: data.UCID,
});
}
);
}
);
}
);
}
);
};
exports.getAllUser = (req, res) => {
db.execute("SELECT * FROM User;", (err, data) => {
if (err) {
console.error("Errors: ", err);
return res.status(500).json({ error: "\nCould not fetch users!" });
}
res.json({ Users: data });
});
};
exports.findUserByEmail = (req, res) => {
const { email } = req.body;
// Input validation
if (!email) {
return res.status(400).json({
found: false,
error: "Email is required",
});
}
// Query to find user with matching email and password
const query = "SELECT * FROM User WHERE email = ?";
db.execute(query, [email], (err, data) => {
if (err) {
console.error("Error finding user:", err);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
// Check if user was found
if (data && data.length > 0) {
console.log(data);
const user = data[0];
// Return all user data except password
return res.json({
found: true,
userID: user.UserID,
name: user.Name,
email: user.Email,
UCID: user.UCID,
phone: user.Phone,
address: user.Address,
// Include any other fields your user might have
// Make sure the field names match exactly with your database column names
});
} else {
// User not found or invalid credentials
return res.json({
found: false,
error: "Invalid email or password",
});
}
});
};
exports.updateUser = (req, res) => {
const { userId, ...updateData } = req.body;
if (!userId) {
return res.status(400).json({ error: "User ID is required" });
}
//query dynamically based on provided fields
const updateFields = [];
const values = [];
Object.entries(updateData).forEach(([key, value]) => {
// Only include fields that are actually in the User table
if (["Name", "Email", "Password", "Phone", "UCID"].includes(key)) {
updateFields.push(`${key} = ?`);
values.push(value);
}
});
if (updateFields.length === 0) {
return res.status(400).json({ error: "No valid fields to update" });
}
// Add userId to values array
values.push(userId);
const query = `UPDATE User SET ${updateFields.join(", ")} WHERE UserID = ?`;
db.execute(query, values, (err, result) => {
if (err) {
console.error("Error updating user:", err);
return res.status(500).json({ error: "Could not update user" });
}
if (result.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ success: true, message: "User updated successfully" });
});
};
exports.deleteUser = (req, res) => {
const { userId } = req.body;
if (!userId) {
return res.status(400).json({ error: "User ID is required" });
}
// Delete from UserRole first (assuming foreign key constraint)
db.execute("DELETE FROM UserRole WHERE UserID = ?", [userId], (err) => {
if (err) {
console.error("Error deleting user role:", err);
return res.status(500).json({ error: "Could not delete user role" });
}
// Then delete from User table
db.execute("DELETE FROM User WHERE UserID = ?", [userId], (err, result) => {
if (err) {
console.error("Error deleting user:", err);
return res.status(500).json({ error: "Could not delete user" });
}
if (result.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ success: true, message: "User deleted successfully" });
});
});
};

View File

@@ -1,41 +1,20 @@
import express, { json } from "express"; const express = require("express");
import cors from "cors"; const cors = require("cors");
import mysql from "mysql2"; //Get the db connection
import nodemailer from "nodemailer"; const db = require("./utils/database");
import crypto from "crypto";
const userRouter = require("./routes/user");
const productRouter = require("./routes/product");
const { generateEmailTransporter } = require("./utils/mail");
const { cleanupExpiredCodes } = require("./utils/helper");
const app = express(); const app = express();
app.use(cors()); app.use(cors());
app.use(express.json()); app.use(express.json());
//TODO: Connect with the database:
const db_con = mysql.createConnection({
host: "localhost",
user: "root",
password: "12345678",
database: "marketplace",
enableKeepAlive: true, // false by default.
});
db_con.connect((err) => {
if (err) {
console.error("Database connection failed: " + err.stack);
return;
}
console.log("Connected to MySQL database.");
});
// Configure email transporter for Zoho // Configure email transporter for Zoho
const transporter = nodemailer.createTransport({ const transporter = generateEmailTransporter();
host: "smtp.zohocloud.ca",
secure: true,
port: 465,
auth: {
user: "campusplug@zohomailcloud.ca", //Zoho email
pass: "e0YRrNSeJZQd", //Zoho password
},
});
// Test the email connection // Test the email connection
transporter transporter
.verify() .verify()
@@ -45,420 +24,13 @@ transporter
.catch((error) => { .catch((error) => {
console.error("Email connection failed:", error); console.error("Email connection failed:", error);
}); });
// Generate and send verification code for signup
app.post("/send-verification", async (req, res) => {
const { email } = req.body;
if (!email) { //Routes
return res.status(400).json({ error: "Email is required" }); app.use("/api/user", userRouter); //prefix with /api/user
} app.use("/api/product", productRouter); //prefix with /api/product
try {
// Generate a random 6-digit code
const verificationCode = crypto.randomInt(100000, 999999).toString();
console.log(
`Generated verification code for ${email}: ${verificationCode}`,
);
// Check if email already exists in verification table
db_con.query(
"SELECT * FROM AuthVerification WHERE Email = ?",
[email],
async (err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length > 0) {
// Update existing record
db_con.query(
`UPDATE AuthVerification SET VerificationCode = ?, Authenticated = FALSE, Date = CURRENT_TIMESTAMP
WHERE Email = ?`,
[verificationCode, email],
async (err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
},
);
} else {
// Insert new record
db_con.query(
"INSERT INTO AuthVerification (Email, VerificationCode, Authenticated) VALUES (?, ?, FALSE)",
[email, verificationCode],
async (err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
// Send email and respond
await sendVerificationEmail(email, verificationCode);
res.json({ success: true, message: "Verification code sent" });
},
);
}
},
);
} catch (error) {
console.error("Error:", error);
res.status(500).json({ error: "Server error" });
}
});
// Helper function to send email
async function sendVerificationEmail(email, verificationCode) {
// Send the email with Zoho
await transporter.sendMail({
from: "campusplug@zohomailcloud.ca",
to: email,
subject: "Campus Plug: Signup Verification Code",
text: `Your verification code is: ${verificationCode}. This code will expire in 15 minutes.`,
html: `<p>Your verification code is: <strong>${verificationCode}</strong></p><p>This code will expire in 15 minutes.</p>`,
});
console.log(`Verification code sent to ${email}`);
}
// Verify the code
app.post("/verify-code", (req, res) => {
const { email, code } = req.body;
if (!email || !code) {
return res.status(400).json({ error: "Email and code are required" });
}
console.log(`Attempting to verify code for ${email}: ${code}`);
// Check verification code
db_con.query(
"SELECT * FROM AuthVerification WHERE Email = ? AND VerificationCode = ? AND Authenticated = 0 AND Date > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
[email, code],
(err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length === 0) {
console.log(`Invalid or expired verification code for email ${email}`);
return res
.status(400)
.json({ error: "Invalid or expired verification code" });
}
const userId = results[0].UserID;
// Mark as authenticated
db_con.query(
"UPDATE AuthVerification SET Authenticated = TRUE WHERE Email = ?",
[email],
(err) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
console.log(`Email ${email} successfully verified`);
res.json({
success: true,
message: "Verification successful",
userId,
});
},
);
},
);
});
// Create a users and Complete user registration after verification
app.post("/complete-signup", (req, res) => {
const data = req.body;
db_con.query(
`SELECT * FROM AuthVerification WHERE Email = '${data.email}' AND Authenticated = 1;`,
(err, results) => {
if (err) {
console.error("Database error:", err);
return res.status(500).json({ error: "Database error" });
}
if (results.length === 0) {
return res.status(400).json({ error: "Email not verified" });
}
// Create the user
db_con.query(
`INSERT INTO User (Name, Email, UCID, Password, Phone, Address)
VALUES ('${data.name}', '${data.email}', '${data.UCID}', '${data.password}', '${data.phone}', '${data.address}')`,
(err, result) => {
if (err) {
console.error("Error creating user:", err);
return res.status(500).json({ error: "Could not create user" });
}
// Insert role using the user's ID
db_con.query(
`INSERT INTO UserRole (UserID, Client, Admin)
VALUES (LAST_INSERT_ID(), ${data.client || true}, ${data.admin || false})`,
(roleErr) => {
if (roleErr) {
console.error("Error creating role:", roleErr);
return res.status(500).json({ error: "Could not create role" });
}
// Delete verification record
db_con.query(
`DELETE FROM AuthVerification WHERE Email = '${data.email}'`,
(deleteErr) => {
if (deleteErr) {
console.error("Error deleting verification:", deleteErr);
}
res.json({
success: true,
message: "User registration completed successfully",
name: data.name,
email: data.email,
UCID: data.UCID,
});
},
);
},
);
},
);
},
);
});
// Clean up expired verification codes (run this periodically)
function cleanupExpiredCodes() {
db_con.query(
"DELETE FROM AuthVerification WHERE Date < DATE_SUB(NOW(), INTERVAL 15 MINUTE) AND Authenticated = 0",
(err, result) => {
if (err) {
console.error("Error cleaning up expired codes:", err);
} else {
console.log(`Cleaned up ${result} expired verification codes`);
}
},
);
}
// Set up a scheduler to run cleanup every hour // Set up a scheduler to run cleanup every hour
setInterval(cleanupExpiredCodes, 60 * 60 * 1000); setInterval(cleanupExpiredCodes, 60 * 60 * 1000);
//Fetch all users data:
app.get("/fetch_all_users", (req, res) => {
db_con.query("SELECT * FROM User;", (err, data) => {
if (err) {
console.error("Errors: ", err);
return res.status(500).json({ error: "\nCould not fetch users!" });
}
res.json({ Users: data });
});
});
//Fetch One user Data with all fields:
app.post("/find_user", (req, res) => {
const { email } = req.body;
// Input validation
if (!email) {
return res.status(400).json({
found: false,
error: "Email is required",
});
}
// Query to find user with matching email and password
const query = "SELECT * FROM User WHERE email = ?";
db_con.query(query, [email], (err, data) => {
if (err) {
console.error("Error finding user:", err);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
// Check if user was found
if (data && data.length > 0) {
console.log(data);
const user = data[0];
// Return all user data except password
return res.json({
found: true,
userID: user.UserID,
name: user.Name,
email: user.Email,
UCID: user.UCID,
phone: user.Phone,
address: user.Address,
// Include any other fields your user might have
// Make sure the field names match exactly with your database column names
});
} else {
// User not found or invalid credentials
return res.json({
found: false,
error: "Invalid email or password",
});
}
});
});
//Update A uses Data:
app.post("/update", (req, res) => {
const { userId, ...updateData } = req.body;
if (!userId) {
return res.status(400).json({ error: "User ID is required" });
}
//query dynamically based on provided fields
const updateFields = [];
const values = [];
Object.entries(updateData).forEach(([key, value]) => {
// Only include fields that are actually in the User table
if (["Name", "Email", "Password", "Phone", "UCID"].includes(key)) {
updateFields.push(`${key} = ?`);
values.push(value);
}
});
if (updateFields.length === 0) {
return res.status(400).json({ error: "No valid fields to update" });
}
// Add userId to values array
values.push(userId);
const query = `UPDATE User SET ${updateFields.join(", ")} WHERE UserID = ?`;
db_con.query(query, values, (err, result) => {
if (err) {
console.error("Error updating user:", err);
return res.status(500).json({ error: "Could not update user" });
}
if (result.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ success: true, message: "User updated successfully" });
});
});
//Delete A uses Data:
app.post("/delete", (req, res) => {
const { userId } = req.body;
if (!userId) {
return res.status(400).json({ error: "User ID is required" });
}
// Delete from UserRole first (assuming foreign key constraint)
db_con.query("DELETE FROM UserRole WHERE UserID = ?", [userId], (err) => {
if (err) {
console.error("Error deleting user role:", err);
return res.status(500).json({ error: "Could not delete user role" });
}
// Then delete from User table
db_con.query(
"DELETE FROM User WHERE UserID = ?",
[userId],
(err, result) => {
if (err) {
console.error("Error deleting user:", err);
return res.status(500).json({ error: "Could not delete user" });
}
if (result.affectedRows === 0) {
return res.status(404).json({ error: "User not found" });
}
res.json({ success: true, message: "User deleted successfully" });
},
);
});
});
app.post("/add_fav_product", (req, res) => {
const { userID, productsID } = req.body;
// Use parameterized query to prevent SQL injection
db_con.query(
"INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)",
[userID, productsID],
(err, result) => {
if (err) {
console.error("Error adding favorite product:", err);
return res.json({ error: "Could not add favorite product" });
}
res.json({
success: true,
message: "Product added to favorites successfully",
});
},
);
});
app.get("/get_product", (req, res) => {
const query = "SELECT * FROM Product";
db_con.query(query, (err, data) => {
if (err) {
console.error("Error finding user:", err);
return res.status(500).json({
found: false,
error: "Database error occurred",
});
}
res.json({
success: true,
message: "Product added to favorites successfully",
data,
});
});
});
// db_con.query(
// "SELECT ProductID FROM product WHERE ProductID = ?",
// [productID],
// (err, results) => {
// if (err) {
// console.error("Error checking product:", err);
// return res.json({ error: "Database error" });
// }
// if (results.length === 0) {
// return res.json({ error: "Product does not exist" });
// }
// },
// );
// db_con.query(
// "INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)",
// [userID, productID],
// (err, result) => {
// if (err) {
// console.error("Error adding favorite product:", err);
// return res.json({ error: "Could not add favorite product" });
// }
// res.json({
// success: true,
// message: "Product added to favorites successfully",
// });
// },
// );
app.listen(3030, () => { app.listen(3030, () => {
console.log(`Running Backend on http://localhost:3030/`); console.log(`Running Backend on http://localhost:3030/`);

View File

@@ -2,7 +2,7 @@
"name": "server", "name": "server",
"version": "1.0.0", "version": "1.0.0",
"main": "index.js", "main": "index.js",
"type": "module", "type": "commonjs",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"dev": "node index.js" "dev": "node index.js"

10
backend/routes/product.js Normal file
View File

@@ -0,0 +1,10 @@
const express = require("express");
const { addToFavorite, getAllProducts } = require("../controllers/product");
const router = express.Router();
router.post("/add_fav_product", addToFavorite);
router.get("/get_product", getAllProducts);
module.exports = router;

35
backend/routes/user.js Normal file
View File

@@ -0,0 +1,35 @@
const express = require("express");
const {
sendVerificationCode,
verifyCode,
completeSignUp,
getAllUser,
findUserByEmail,
updateUser,
deleteUser,
} = require("../controllers/user");
const router = express.Router();
// Generate and send verification code for signup
router.post("/send-verification", sendVerificationCode);
// Verify the code
router.post("/verify-code", verifyCode);
// Create a users and Complete user registration after verification
router.post("/complete-signup", completeSignUp);
//Fetch all users data:
router.get("/fetch_all_users", getAllUser);
//Fetch One user Data with all fields:
router.post("/find_user", findUserByEmail);
//Update A uses Data:
router.post("/update", updateUser);
//Delete A uses Data:
router.post("/delete", deleteUser);
module.exports = router;

11
backend/utils/database.js Normal file
View File

@@ -0,0 +1,11 @@
const mysql = require("mysql2");
//Create a pool of connection to allow multiple query happen at the same time
const pool = mysql.createPool({
host: "localhost",
user: "root",
database: "marketplace",
password: "12345678",
});
module.exports = pool.promise();

33
backend/utils/helper.js Normal file
View File

@@ -0,0 +1,33 @@
const { generateEmailTransporter } = require("./mail");
// Helper function to send email
async function sendVerificationEmail(email, verificationCode) {
const transporter = generateEmailTransporter();
// Send the email with Zoho
await transporter.sendMail({
from: "campusplug@zohomailcloud.ca",
to: email,
subject: "Campus Plug: Signup Verification Code",
text: `Your verification code is: ${verificationCode}. This code will expire in 15 minutes.`,
html: `<p>Your verification code is: <strong>${verificationCode}</strong></p><p>This code will expire in 15 minutes.</p>`,
});
console.log(`Verification code sent to ${email}`);
}
// Clean up expired verification codes (run this periodically)
function cleanupExpiredCodes() {
db_con.query(
"DELETE FROM AuthVerification WHERE Date < DATE_SUB(NOW(), INTERVAL 15 MINUTE) AND Authenticated = 0",
(err, result) => {
if (err) {
console.error("Error cleaning up expired codes:", err);
} else {
console.log(`Cleaned up ${result} expired verification codes`);
}
}
);
}
module.exports = { sendVerificationEmail, cleanupExpiredCodes };

12
backend/utils/mail.js Normal file
View File

@@ -0,0 +1,12 @@
const nodemailer = require("nodemailer");
exports.generateEmailTransporter = () =>
nodemailer.createTransport({
host: "smtp.zohocloud.ca",
secure: true,
port: 465,
auth: {
user: "campusplug@zohomailcloud.ca", //Zoho email
pass: "e0YRrNSeJZQd", //Zoho password
},
});

View File

@@ -59,7 +59,9 @@ function App() {
console.log("Sending verification code to:", userData.email); console.log("Sending verification code to:", userData.email);
// Make API call to send verification code // Make API call to send verification code
const response = await fetch("http://localhost:3030/send-verification", { const response = await fetch(
"http://localhost:3030/api/user/send-verification",
{
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -68,7 +70,8 @@ function App() {
email: userData.email, email: userData.email,
// Add any other required fields // Add any other required fields
}), }),
}); }
);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to send verification code"); throw new Error("Failed to send verification code");
@@ -105,7 +108,9 @@ function App() {
console.log("Verifying code:", code); console.log("Verifying code:", code);
// Make API call to verify code // Make API call to verify code
const response = await fetch("http://localhost:3030/verify-code", { const response = await fetch(
"http://localhost:3030/api/user/verify-code",
{
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -114,7 +119,8 @@ function App() {
email: tempUserData.email, email: tempUserData.email,
code: code, code: code,
}), }),
}); }
);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to verify code"); throw new Error("Failed to verify code");
@@ -149,13 +155,16 @@ function App() {
console.log(userData); console.log(userData);
// Make API call to complete signup // Make API call to complete signup
const response = await fetch("http://localhost:3030/complete-signup", { const response = await fetch(
"http://localhost:3030/api/user/complete-signup",
{
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify(userData), body: JSON.stringify(userData),
}); }
);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to complete signup"); throw new Error("Failed to complete signup");
@@ -245,7 +254,9 @@ function App() {
}); });
// Make API call to localhost:3030/find_user // Make API call to localhost:3030/find_user
const response = await fetch("http://localhost:3030/find_user", { const response = await fetch(
"http://localhost:3030/api/user/find_user",
{
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -254,7 +265,8 @@ function App() {
email: formValues.email, email: formValues.email,
password: formValues.password, password: formValues.password,
}), }),
}); }
);
if (!response.ok) { if (!response.ok) {
throw new Error("Network response was not ok"); throw new Error("Network response was not ok");

View File

@@ -1,10 +1,10 @@
import { StrictMode } from 'react' import { StrictMode } from "react";
import { createRoot } from 'react-dom/client' import { createRoot } from "react-dom/client";
import './index.css' import "./index.css";
import App from './App.jsx' import App from "./App.jsx";
createRoot(document.getElementById('root')).render( createRoot(document.getElementById("root")).render(
<StrictMode> <StrictMode>
<App /> <App />
</StrictMode>, </StrictMode>
) );

View File

@@ -10,7 +10,9 @@ const Home = () => {
useEffect(() => { useEffect(() => {
const fetchProducts = async () => { const fetchProducts = async () => {
try { try {
const response = await fetch("http://localhost:3030/get_product"); const response = await fetch(
"http://localhost:3030/api/product/get_product"
);
if (!response.ok) throw new Error("Failed to fetch products"); if (!response.ok) throw new Error("Failed to fetch products");
const data = await response.json(); const data = await response.json();
@@ -27,7 +29,7 @@ const Home = () => {
seller: "Unknown", // Modify if seller info is available seller: "Unknown", // Modify if seller info is available
datePosted: "Just now", datePosted: "Just now",
isFavorite: false, isFavorite: false,
})), }))
); );
} else { } else {
throw new Error(data.message || "Error fetching products"); throw new Error(data.message || "Error fetching products");
@@ -48,8 +50,8 @@ const Home = () => {
prevListings.map((listing) => prevListings.map((listing) =>
listing.id === id listing.id === id
? { ...listing, isFavorite: !listing.isFavorite } ? { ...listing, isFavorite: !listing.isFavorite }
: listing, : listing
), )
); );
}; };

View File

@@ -33,7 +33,9 @@ const Settings = () => {
} }
// Make API call to fetch user data // Make API call to fetch user data
const response = await fetch("http://localhost:3030/find_user", { const response = await fetch(
"http://localhost:3030/api/user/find_user",
{
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
@@ -41,7 +43,8 @@ const Settings = () => {
body: JSON.stringify({ body: JSON.stringify({
email: storedUser.email, email: storedUser.email,
}), }),
}); }
);
const data = await response.json(); const data = await response.json();
console.log(data); console.log(data);
@@ -67,7 +70,7 @@ const Settings = () => {
} catch (error) { } catch (error) {
console.error("Error fetching user data:", error); console.error("Error fetching user data:", error);
setError( setError(
error.message || "An error occurred while loading your profile", error.message || "An error occurred while loading your profile"
); );
} finally { } finally {
setIsLoading(false); setIsLoading(false);
@@ -153,7 +156,7 @@ const Settings = () => {
const handleDeleteAccount = async () => { const handleDeleteAccount = async () => {
if ( if (
window.confirm( window.confirm(
"Are you sure you want to delete your account? This action cannot be undone.", "Are you sure you want to delete your account? This action cannot be undone."
) )
) { ) {
try { try {
@@ -166,7 +169,7 @@ const Settings = () => {
} }
// Make API call to delete the account // Make API call to delete the account
const response = await fetch("http://localhost:3030/delete", { const response = await fetch("http://localhost:3030/api/user/delete", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",