diff --git a/backend/index.js b/backend/index.js index 17ee0be..516e82e 100644 --- a/backend/index.js +++ b/backend/index.js @@ -2,9 +2,7 @@ import express, { json } from "express"; import cors from "cors"; import mysql from "mysql2"; import nodemailer from "nodemailer"; - import crypto from "crypto"; -import jwt from "jsonwebtoken"; const app = express(); app.use(cors()); @@ -120,7 +118,7 @@ async function sendVerificationEmail(email, verificationCode) { await transporter.sendMail({ from: "campusplug@zohomailcloud.ca", to: email, - subject: "Your Verification Code", + subject: "Campus Plug: Signup Verification Code", text: `Your verification code is: ${verificationCode}. This code will expire in 15 minutes.`, html: `

Your verification code is: ${verificationCode}

This code will expire in 15 minutes.

`, }); @@ -215,6 +213,11 @@ app.post("/complete-signup", (req, res) => { return res.status(500).json({ error: "Could not create role" }); } + db_con.query( + `SELECT * FROM User WHERE Email='${data.Email}'`, + (err, userID), + ); + // Delete verification record db_con.query( `DELETE FROM AuthVerification WHERE Email = '${data.email}'`, @@ -225,10 +228,10 @@ app.post("/complete-signup", (req, res) => { res.json({ success: true, message: "User registration completed successfully", + userID: userID, name: data.name, email: data.email, UCID: data.UCID, - phone: data.phone, }); }, ); @@ -248,7 +251,7 @@ function cleanupExpiredCodes() { if (err) { console.error("Error cleaning up expired codes:", err); } else { - console.log(`Cleaned up ${results} expired verification codes`); + console.log(`Cleaned up ${result} expired verification codes`); } }, ); @@ -267,22 +270,21 @@ app.get("/fetch_all_users", (req, res) => { }); }); -//Fetch One user Data: +//Fetch One user Data with all fields: app.post("/find_user", (req, res) => { - const { email, password } = req.body; + const { email } = req.body; // Input validation - if (!email || !password) { + if (!email) { return res.status(400).json({ found: false, - error: "Email and password are required", + error: "Email is required", }); } // Query to find user with matching email and password - const query = "SELECT * FROM User WHERE email = ? AND password = ?"; - - db_con.query(query, [email, password], (err, data) => { + 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({ @@ -296,11 +298,17 @@ app.post("/find_user", (req, res) => { console.log(data); const user = data[0]; - // Return user data without sensitive information + // 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 diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e89937a..57c38bb 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -16,10 +16,10 @@ import ProductDetail from "./pages/ProductDetail"; function App() { // Authentication state - initialize from localStorage if available const [isAuthenticated, setIsAuthenticated] = useState(() => { - return localStorage.getItem("isAuthenticated") === "true"; + return sessionStorage.getItem("isAuthenticated") === "true"; }); const [user, setUser] = useState(() => { - const savedUser = localStorage.getItem("user"); + const savedUser = sessionStorage.getItem("user"); return savedUser ? JSON.parse(savedUser) : null; }); @@ -32,7 +32,6 @@ function App() { // New verification states const [verificationStep, setVerificationStep] = useState("initial"); // 'initial', 'code-sent', 'verifying' const [tempUserData, setTempUserData] = useState(null); - const [verificationCode, setVerificationCode] = useState(""); // Auto-hide image on smaller screens useEffect(() => { @@ -166,10 +165,10 @@ function App() { if (result.success) { // Create user object from API response const newUser = { + ID: result.userID, name: result.name || userData.name, email: result.email || userData.email, UCID: result.UCID || userData.ucid, - phone: result.phone || userData.phone, }; // Set authenticated user @@ -177,8 +176,8 @@ function App() { setIsAuthenticated(true); // Save to localStorage to persist across refreshes - localStorage.setItem("isAuthenticated", "true"); - localStorage.setItem("user", JSON.stringify(newUser)); + sessionStorage.setItem("isAuthenticated", "true"); + sessionStorage.setItem("user", JSON.stringify(newUser)); // Reset verification steps setVerificationStep("initial"); @@ -265,7 +264,8 @@ function App() { if (userData && userData.found) { // Create user object const userObj = { - name: userData.name || userData.email, + ID: userData.userID, + name: userData.name, email: userData.email, // Add any other user data returned from the API }; @@ -275,8 +275,10 @@ function App() { setIsAuthenticated(true); // Save to localStorage to persist across refreshes - localStorage.setItem("isAuthenticated", "true"); - localStorage.setItem("user", JSON.stringify(userObj)); + sessionStorage.setItem("isAuthenticated", "true"); + sessionStorage.setItem("user", JSON.stringify(userObj)); + + sessionStorage.getItem("user"); console.log("Login successful for:", userData.email); } else { @@ -314,8 +316,9 @@ function App() { setTempUserData(null); // Clear localStorage - localStorage.removeItem("isAuthenticated"); - localStorage.removeItem("user"); + // + sessionStorage.removeItem("user"); + sessionStorage.removeItem("isAuthenticated"); console.log("User logged out"); }; @@ -592,14 +595,12 @@ function App() { {isAuthenticated && ( )} - {/* Public routes */} : } /> - {/* Protected routes */} } /> - } /> - } /> - } /> - } /> - {/* Redirect to login for any unmatched routes */} { const [userData, setUserData] = useState({ - name: '', - email: '', - phone: '', - ucid: '', - currentPassword: '', - newPassword: '', - confirmPassword: '' + userId: "", + name: "", + email: "", + phone: "", + UCID: "", + address: "", + currentPassword: "", + newPassword: "", + confirmPassword: "", }); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + // Fetch user data when component mounts + useEffect(() => { + const fetchUserData = async () => { + try { + setIsLoading(true); + setError(null); + + // Get the user's data from localStorage + const storedUser = JSON.parse(sessionStorage.getItem("user")); + console.log(storedUser); + + if (!storedUser || !storedUser.email) { + throw new Error("User details not found. Please log in again."); + } + + // Make API call to fetch user data + const response = await fetch("http://localhost:3030/find_user", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + email: storedUser.email, + }), + }); + + const data = await response.json(); + console.log(data); + + if (data.found) { + // Update state with fetched data + setUserData((prevData) => ({ + ...prevData, + userId: data.userId || storedUser.id || "", // Try both sources + name: data.name || storedUser.name || "", + email: data.email || storedUser.email || "", + UCID: data.UCID || storedUser.UCID || "", + phone: data.phone || storedUser.phone || "", + address: data.address || storedUser.address || "", + // Reset password fields + currentPassword: "", + newPassword: "", + confirmPassword: "", + })); + } else { + throw new Error(data.error || "Failed to retrieve user data"); + } + } catch (error) { + console.error("Error fetching user data:", error); + setError( + error.message || "An error occurred while loading your profile", + ); + } finally { + setIsLoading(false); + } + }; + + fetchUserData(); + }, []); + const handleInputChange = (e) => { const { id, value } = e.target; - setUserData(prevData => ({ + setUserData((prevData) => ({ ...prevData, - [id]: value + [id]: value, })); }; - const handleProfileUpdate = (e) => { + const handleProfileUpdate = async (e) => { e.preventDefault(); - // TODO: updated profile data to a server - console.log('Profile updated:', userData); - alert('Profile updated successfully!'); - }; + try { + // TODO: Implement the actual update API call + console.log("Profile updated:", userData); - const handlePasswordUpdate = (e) => { - e.preventDefault(); - // TODO: validate and update password - if (userData.newPassword !== userData.confirmPassword) { - alert('New passwords do not match!'); - return; + // Update localStorage with new user data + const storedUser = JSON.parse(localStorage.getItem("user")); + const updatedUser = { + ...storedUser, + name: userData.name, + phone: userData.phone, + UCID: userData.UCID, + address: userData.address, + }; + localStorage.setItem("user", JSON.stringify(updatedUser)); + + alert("Profile updated successfully!"); + } catch (error) { + console.error("Error updating profile:", error); + alert("Failed to update profile: " + error.message); + } + }; + + const handlePasswordUpdate = async (e) => { + e.preventDefault(); + try { + // Validate passwords match + if (userData.newPassword !== userData.confirmPassword) { + alert("New passwords do not match!"); + return; + } + + // TODO: Implement the actual password update API call + console.log("Password updated"); + + // Update password in localStorage + const storedUser = JSON.parse(localStorage.getItem("user")); + const updatedUser = { + ...storedUser, + password: userData.newPassword, + }; + localStorage.setItem("user", JSON.stringify(updatedUser)); + + // Reset password fields + setUserData((prevData) => ({ + ...prevData, + currentPassword: "", + newPassword: "", + confirmPassword: "", + })); + + alert("Password updated successfully!"); + } catch (error) { + console.error("Error updating password:", error); + alert("Failed to update password: " + error.message); } - console.log('Password updated'); - // Reset password fields - setUserData(prevData => ({ - ...prevData, - currentPassword: '', - newPassword: '', - confirmPassword: '' - })); - alert('Password updated successfully!'); }; const handleDeleteHistory = (type) => { @@ -51,24 +150,91 @@ const Settings = () => { alert(`${type} history deleted successfully!`); }; + const handleDeleteAccount = async () => { + if ( + window.confirm( + "Are you sure you want to delete your account? This action cannot be undone.", + ) + ) { + try { + // Get user ID from state or localStorage + const storedUser = JSON.parse(sessionStorage.getItem("user")); + const userId = storedUser.ID; + + if (!userId) { + throw new Error("User ID not found"); + } + + // Make API call to delete the account + const response = await fetch("http://localhost:3030/delete", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userId: userId, + }), + }); + + const data = await response.json(); + + if (data.success) { + alert("Account deleted successfully. You will be logged out."); + // Clear user data from localStorage and redirect to login + sessionStorage.removeItem("user"); + sessionStorage.removeItem("isAuthenticated"); + window.location.href = "/login"; + } else { + throw new Error(data.error || "Failed to delete account"); + } + } catch (error) { + console.error("Error deleting account:", error); + alert("Failed to delete account: " + error.message); + } + } + }; + + // Show loading state + if (isLoading) { + return ( +
+
+
+ ); + } + return (
-

Account Settings

- +

+ Account Settings +

+ + {/* Error message if any */} + {error && ( +
+ {error} +
+ )} + {/* Profile Information Section */}
-

Profile Information

+

+ Profile Information +

- +
-
- +
-
- +
-
- +
-
+ +
+ + +
- -
- + {/* Security Section */}
@@ -141,12 +333,15 @@ const Settings = () => {

Password

- +
-
- +
-
- +
-
- -
- + {/* Privacy Section */}
@@ -206,7 +407,7 @@ const Settings = () => {

Privacy

- +
@@ -214,28 +415,34 @@ const Settings = () => {

Search History

-

Delete all your search history on StudentMarket

+

+ Delete all your search history on StudentMarket +

-
- +
-

Browsing History

-

Delete all your browsing history on StudentMarket

+

+ Browsing History +

+

+ Delete all your browsing history on StudentMarket +

-
- + {/* Delete Account (Danger Zone) */}

Danger Zone

- +

Delete Account

- Once you delete your account, there is no going back. Please be certain. + Once you delete your account, there is no going back. Please be + certain.

- @@ -278,4 +481,4 @@ const Settings = () => { ); }; -export default Settings; \ No newline at end of file +export default Settings;