Repository: kalviumcommunity/S84_Avinash_Capstone_FokuSpace
Pull request #42: implemented update and delete functionality
Author: login: AvinashGuleria0
Labels: name: Review effort 3/5
Created: 2025-05-20T08:36:01Z | Merged: 2025-05-20T08:47:27Z

### **PR Type**
Enhancement


___

### **Description**
- Implemented user account deletion (frontend & backend)
  - Added delete account API endpoint and handler
  - Integrated delete account form in profile page
  - Added error/success handling for deletion

- Improved UI/UX for login and profile components
  - Password visibility toggle in login form
  - Added styles for delete button and success messages

- Minor code formatting and CSS improvements


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>6 files</summary><table>
<tr>
  <td><strong>index.js</strong><dd><code>Add delete account API method</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-717e0b88e7596d4f99008a8921b55cc50c523ca23d50462c68129c5533439e76">+2/-1</a>&nbsp; &nbsp; &nbsp; </td>

</tr>

<tr>
  <td><strong>route.js</strong><dd><code>Implement backend route for account deletion</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-2451323074e1b7e39e7f2d4e446fba58ed1ba0100f904d330d368b1a49c1a506">+46/-0</a>&nbsp; &nbsp; </td>

</tr>

<tr>
  <td><strong>Profile.jsx</strong><dd><code>Add delete account form and logic to profile</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-ec0f9b0e192357c8f217de96db181d439d4a4615b48abc031e235431eb5e2052">+131/-80</a></td>

</tr>

<tr>
  <td><strong>Login.jsx</strong><dd><code>Add password visibility toggle to login form</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-e30fa8978949227725a84b74a09b40fe042af42657a30641a59bf0a80782407e">+15/-6</a>&nbsp; &nbsp; </td>

</tr>

<tr>
  <td><strong>index.css</strong><dd><code>Add styles for delete button and success messages</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-9ba564eb566d9d518337365ff59440cd64b7217d0ddb75f1c2524003735b99ad">+24/-1</a>&nbsp; &nbsp; </td>

</tr>

<tr>
  <td><strong>main.jsx</strong><dd><code>Update BrowserRouter with future options</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-9ed080e814be9926dd5a5e07248cc746fe8aa81ef8f1ab91ac01f733ecf4a7b8">+7/-2</a>&nbsp; &nbsp; &nbsp; </td>

</tr>
</table></details></td></tr><tr><td><strong>Formatting</strong></td><td><details><summary>2 files</summary><table>
<tr>
  <td><strong>Login.css</strong><dd><code>Minor formatting and whitespace adjustments</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-ae03e0de8011d22cce5e1e6937de43ec1262242d6afffdbb98f45f3bcbdb4394">+93/-92</a>&nbsp; </td>

</tr>

<tr>
  <td><strong>otp.js</strong><dd><code>Code formatting: indentation adjustments</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
  <td><a href="https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-cc28bf7e5a03c8e641f7ee766565804310a2e8718be43f418cac437b8c26dfd4">+10/-10</a>&nbsp; </td>

</tr>
</table></details></td></tr></tr></tbody></table>

___

> <details> <summary>  Need help?</summary><li>Type <code>/help how to ...</code> in the comments thread for any questions about Qodo Merge usage.</li><li>Check out the <a href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a> for more information.</li></details>


Diff:
diff --git a/client/src/api/index.js b/client/src/api/index.js
index 453f9f5..9df6cea 100644
--- a/client/src/api/index.js
+++ b/client/src/api/index.js
@@ -77,4 +77,5 @@ import axios from 'axios';
    export const changePassword = async (data) => API.put('/change-password', data);
    export const resetPasswordRequest = async (data) => API.post('/reset-password-request', data);
    export const resetPassword = async (data) => API.post('/reset-password', data);
-   export const getUsers = async () => API.get('/users');
\ No newline at end of file
+   export const getUsers = async () => API.get('/users');
+   export const deleteAccount = async (data) => API.delete('/delete', { data });
\ No newline at end of file
diff --git a/client/src/components/Login.jsx b/client/src/components/Login.jsx
index 00cec7f..1b9bfaa 100644
--- a/client/src/components/Login.jsx
+++ b/client/src/components/Login.jsx
@@ -2,11 +2,14 @@ import React, { useState } from 'react';
 import { useNavigate, useLocation } from 'react-router-dom';
 import { login, googleLogin } from '../api';
 import '../index.css';
+import { FaEye, FaEyeSlash } from 'react-icons/fa';
+
 
 const Login = () => {
   const [formData, setFormData] = useState({ email: '', password: '' });
   const [error, setError] = useState('');
   const [isLoading, setIsLoading] = useState(false);
+    const [showPassword, setShowPassword] = useState(false); // 👁️ toggle state
   const navigate = useNavigate();
   const location = useLocation();
 
@@ -50,7 +53,7 @@ const Login = () => {
   };
 
   return (
-    <div className="form-container">
+       <div className="login-container">
       <h2>Login</h2>
       {error && <p className="error-message">{error}</p>}
       {location.state?.error && (
@@ -68,28 +71,34 @@ const Login = () => {
             disabled={isLoading}
           />
         </div>
-        <div className="form-group">
+        <div className="form-group password-group">
           <label>Password:</label>
           <input
-            type="password"
+            type={showPassword ? 'text' : 'password'}
             name="password"
             value={formData.password}
             onChange={handleChange}
             required
             disabled={isLoading}
           />
+          <span
+            className="password-toggle-icon"
+            onClick={() => setShowPassword(!showPassword)}
+          >
+            {showPassword ? <FaEyeSlash /> : <FaEye />}
+          </span>
         </div>
-        <button type="submit" disabled={isLoading}>
+        <button type="submit" className="Login__button" disabled={isLoading}>
           {isLoading ? 'Logging in...' : 'Login'}
         </button>
       </form>
       <button onClick={googleLogin} className="google-btn" disabled={isLoading}>
         Login with Google
       </button>
-      <p>
+      <p className="register-link">
         Forgot password? <a href="/reset-password-request">Reset it</a>
       </p>
-      <p>
+      <p className="register-link">
         Don't have an account? <a href="/register">Register here</a>
       </p>
     </div>
diff --git a/client/src/components/Profile.jsx b/client/src/components/Profile.jsx
index 9d25cea..2b2afb6 100644
--- a/client/src/components/Profile.jsx
+++ b/client/src/components/Profile.jsx
@@ -1,13 +1,15 @@
 import React, { useState, useEffect } from 'react';
    import { useNavigate } from 'react-router-dom';
-   import { getProfile, updateProfile, changePassword } from '../api';
+   import { getProfile, updateProfile, changePassword, deleteAccount} from '../api';
    import '../index.css';
 
    const Profile = () => {
      const [user, setUser] = useState(null);
      const [profileData, setProfileData] = useState({ name: '', age: '', profession: '' });
      const [passwordData, setPasswordData] = useState({ currentPassword: '', newPassword: '' });
+      const [deletePassword, setDeletePassword] = useState('');
      const [error, setError] = useState('');
+       const [success, setSuccess] = useState('');
      const [isLoading, setIsLoading] = useState(false);
      const navigate = useNavigate();
 
@@ -92,6 +94,38 @@ import React, { useState, useEffect } from 'react';
          setIsLoading(false);
        }
      };
+     
+     const handleDeleteSubmit = async (e) => {
+    e.preventDefault();
+    setError('');
+    setSuccess('');
+    setIsLoading(true);
+
+    console.log('Deleting account');
+    if (!deletePassword) {
+      setError('Please enter your password');
+      setIsLoading(false);
+      return;
+    }
+
+    try {
+      await deleteAccount({ password: deletePassword });
+      console.log('Account deleted');
+      setSuccess('Account deleted successfully');
+      localStorage.removeItem('token');
+      localStorage.removeItem('pendingVerificationEmail');
+      setSuccess('Account deleted successfully');
+      localStorage.removeItem('token');
+      localStorage.removeItem('pendingVerificationEmail');
+      navigate('/login');
+    } catch (err) {
+      console.error('Delete account error:', err);
+      setError(err || 'Failed to delete account');
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
 
      const handleLogout = () => {
        console.log('Logging out from profile');
@@ -104,85 +138,105 @@ import React, { useState, useEffect } from 'react';
 
      return (
        <div className="form-container">
-         <h2>Profile</h2>
-         {error && <p className="error-message">{error}</p>}
-         <p>Email: {user.email}</p>
-         <button onClick={handleLogout}>Logout</button>
-
-         <h3>Update Profile</h3>
-         <form onSubmit={handleProfileSubmit}>
-           <div className="form-group">
-             <label>Name:</label>
-             <input
-               type="text"
-               name="name"
-               value={profileData.name}
-               onChange={(e) => handleChange(e, setProfileData)}
-               required
-               disabled={isLoading}
-             />
-           </div>
-           <div className="form-group">
-             <label>Age:</label>
-             <input
-               type="number"
-               name="age"
-               value={profileData.age}
-               onChange={(e) => handleChange(e, setProfileData)}
-               required
-               min="18"
-               disabled={isLoading}
-             />
-           </div>
-           <div className="form-group">
-             <label>Profession:</label>
-             <input
-               type="text"
-               name="profession"
-               value={profileData.profession}
-               onChange={(e) => handleChange(e, setProfileData)}
-               required
-               disabled={isLoading}
-             />
-           </div>
-           <button type="submit" disabled={isLoading}>
-             {isLoading ? 'Updating...' : 'Update Profile'}
-           </button>
-         </form>
-
-         {!user.isGoogleAccount && (
-           <>
-             <h3>Change Password</h3>
-             <form onSubmit={handlePasswordSubmit}>
-               <div className="form-group">
-                 <label>Current Password:</label>
-                 <input
-                   type="password"
-                   name="currentPassword"
-                   value={passwordData.currentPassword}
-                   onChange={(e) => handleChange(e, setPasswordData)}
-                   required
-                   disabled={isLoading}
-                 />
-               </div>
-               <div className="form-group">
-                 <label>New Password:</label>
-                 <input
-                   type="password"
-                   name="newPassword"
-                   value={passwordData.newPassword}
-                   onChange={(e) => handleChange(e, setPasswordData)}
-                   required
-                   disabled={isLoading}
-                 />
-               </div>
-               <button type="submit" disabled={isLoading}>
-                 {isLoading ? 'Changing...' : 'Change Password'}
-               </button>
-             </form>
-           </>
-         )}
-       </div>
+      <h2>Profile</h2>
+      {error && <p className="error-message">{error}</p>}
+      {success && <p className="success-message">{success}</p>}
+      <p>Email: {user.email}</p>
+      <button onClick={handleLogout}>Logout</button>
+
+      <h3>Update Profile</h3>
+      <form onSubmit={handleProfileSubmit}>
+        <div className="form-group">
+          <label>Name:</label>
+          <input
+            type="text"
+            name="name"
+            value={profileData.name}
+            onChange={(e) => handleChange(e, setProfileData)}
+            required
+            disabled={isLoading}
+          />
+        </div>
+        <div className="form-group">
+          <label>Age:</label>
+          <input
+            type="number"
+            name="age"
+            value={profileData.age}
+            onChange={(e) => handleChange(e, setProfileData)}
+            required
+            min="18"
+            disabled={isLoading}
+          />
+        </div>
+        <div className="form-group">
+          <label>Profession:</label>
+          <input
+            type="text"
+            name="profession"
+            value={profileData.profession}
+            onChange={(e) => handleChange(e, setProfileData)}
+            required
+            disabled={isLoading}
+          />
+        </div>
+        <button type="submit" disabled={isLoading}>
+          {isLoading ? 'Updating...' : 'Update Profile'}
+        </button>
+      </form>
+
+      {!user.isGoogleAccount && (
+        <>
+          <h3>Change Password</h3>
+          <form onSubmit={handlePasswordSubmit}>
+            <div className="form-group">
+              <label>Current Password:</label>
+              <input
+                type="password"
+                name="currentPassword"
+                value={passwordData.currentPassword}
+                onChange={(e) => handleChange(e, setPasswordData)}
+                required
+                disabled={isLoading}
+              />
+            </div>
+            <div className="form-group">
+              <label>New Password:</label>
+              <input
+                type="password"
+                name="newPassword"
+                value={passwordData.newPassword}
+                onChange={(e) => handleChange(e, setPasswordData)}
+                required
+                disabled={isLoading}
+              />
+            </div>
+            <button type="submit" disabled={isLoading}>
+              {isLoading ? 'Changing...' : 'Change Password'}
+            </button>
+          </form>
+
+          <h3>Delete Account</h3>
+          <form onSubmit={handleDeleteSubmit}>
+            <div className="form-group">
+              <label>Confirm Password:</label>
+              <input
+                type="password"
+                name="password"
+                value={deletePassword}
+                onChange={(e) => setDeletePassword(e.target.value)}
+                required
+                disabled={isLoading}
+                placeholder="Enter your password to confirm"
+              />
+            </div>
+            <button type="submit" disabled={isLoading} className="delete-btn">
+              {isLoading ? 'Deleting...' : 'Delete Account'}
+            </button>
+          </form>
+        </>
+      )}
+    </div>
      );
    };
 
diff --git a/client/src/index.css b/client/src/index.css
index 88a9285..8909d0e 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -173,4 +173,27 @@ body {
     margin-bottom: 10px;
     border-radius: 4px;
     box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-  }
\ No newline at end of file
+  }
+  .success-message {
+  color: green;
+  margin-bottom: 1rem;
+}
+
+.delete-btn {
+  background-color: #dc3545;
+  color: white;
+  padding: 0.5rem 1rem;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+  margin-top: 1rem;
+}
+
+.delete-btn:hover:not(:disabled) {
+  background-color: #c82333;
+}
+
+.delete-btn:disabled {
+  background-color: #6c757d;
+  cursor: not-allowed;
+}
\ No newline at end of file
diff --git a/client/src/main.jsx b/client/src/main.jsx
index 4c521bb..5be9fc5 100644
--- a/client/src/main.jsx
+++ b/client/src/main.jsx
@@ -10,9 +10,14 @@ const root = ReactDOM.createRoot(document.getElementById("root"));
 root.render(
   <GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}>
     <React.StrictMode>
-      <BrowserRouter>
+      <BrowserRouter
+        future={{
+          v7_startTransition: true,
+          v7_relativeSplatPath: true,
+        }}
+      >
         <App />
       </BrowserRouter>
     </React.StrictMode>
   </GoogleOAuthProvider>
-);
\ No newline at end of file
+);
diff --git a/client/src/styles/Login.css b/client/src/styles/Login.css
index 14cd94a..9d285b5 100644
--- a/client/src/styles/Login.css
+++ b/client/src/styles/Login.css
@@ -1,107 +1,108 @@
-/* src/styles/Login.css */
-.login-container,
-.otp-container {
-    max-width: 400px;
-    margin: 50px auto;
-    padding: 20px;
-    background-color: #f9f9f9;
-    border-radius: 8px;
-    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
-}
+    /* src/styles/Login.css */
+    .login-container,
+    .otp-container {
+        max-width: 400px;
+        margin: 50px auto;
+        padding: 20px;
+        background-color: #f9f9f9;
+        border-radius: 8px;
+        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+    }
 
-.login-container h2,
-.otp-container h2 {
-    text-align: center;
-    margin-bottom: 20px;
-    color: #333;
-}
+    .login-container h2,
+    .otp-container h2 {
+        text-align: center;
+        margin-bottom: 20px;
+        color: #333;
+    }
 
-.error-message {
-    color: #d32f2f;
-    text-align: center;
-    margin-bottom: 15px;
-}
+    .error-message {
+        color: #d32f2f;
+        text-align: center;
+        margin-bottom: 15px;
+    }
 
-.form-group {
-    margin-bottom: 15px;
-}
+    .form-group {
+        margin-bottom: 15px;
+    }
 
-.form-group label {
-    display: block;
-    margin-bottom: 5px;
-    color: #555;
-    font-weight: 500;
-}
+    .form-group label {
+        display: block;
+        margin-bottom: 5px;
+        color: #555;
+        font-weight: 500;
+    }
 
-.form-group input {
-    width: 100%;
-    padding: 10px;
-    border: 1px solid #ddd;
-    border-radius: 4px;
-    font-size: 16px;
-    transition: border-color 0.3s;
-}
+    .form-group input {
+        width: 100%;
+        padding: 10px;
+        border: 1px solid #ddd;
+        border-radius: 4px;
+        font-size: 16px;
+        transition: border-color 0.3s;
+    }
 
-.form-group input:focus {
-    outline: none;
-    border-color: #007bff;
-}
+    .form-group input:focus {
+        outline: none;
+        border-color: #007bff;
+    }
 
-.Login__button,
-.verify-button,
-.resend-button {
-    width: 100%;
-    padding: 12px;
-    background-color: #007bff;
-    color: white;
-    border: none;
-    border-radius: 4px;
-    font-size: 16px;
-    cursor: pointer;
-    transition: background-color 0.3s;
-    margin-bottom: 10px;
-}
+    .Login__button,
+    .verify-button,
+    .resend-button {
+        width: 100%;
+        padding: 12px;
+        background-color: #007bff;
+        color: white;
+        border: none;
+        border-radius: 4px;
+        font-size: 16px;
+        cursor: pointer;
+        transition: background-color 0.3s;
+        margin-bottom: 10px;
+    }
 
-.Login__button:hover,
-.verify-button:hover,
-.resend-button:hover {
-    background-color: #0056b3;
-}
+    .Login__button:hover,
+    .verify-button:hover,
+    .resend-button:hover {
+        background-color: #0056b3;
+    }
 
-.Login__button:focus,
-.verify-button:focus,
-.resend-button:focus {
-    outline: none;
-    box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.3);
-}
+    .Login__button:focus,
+    .verify-button:focus,
+    .resend-button:focus {
+        outline: none;
+        box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.3);
+    }
 
-.Login__button:disabled,
-.verify-button:disabled,
-.resend-button:disabled {
-    background-color: #cccccc;
-    cursor: not-allowed;
-}
+    .Login__button:disabled,
+    .verify-button:disabled,
+    .resend-button:disabled {
+        background-color: #cccccc;
+        cursor: not-allowed;
+    }
 
-.resend-button {
-    background-color: #6c757d;
-}
+    .resend-button {
+        background-color: #6c757d;
+    }
 
-.resend-button:hover {
-    background-color: #5a6268;
-}
+    .resend-button:hover {
+        background-color: #5a6268;
+    }
 
-.register-link {
-    text-align: center;
-    margin-top: 20px;
-    color: #666;
-}
+    .register-link {
+        text-align: center;
+        margin-top: 20px;
+        color: #666;
+    }
 
-.register-link a {
-    color: #007bff;
-    text-decoration: none;
-    font-weight: 500;
-}
+    .register-link a {
+        color: #007bff;
+        text-decoration: none;
+        font-weight: 500;
+    }
 
-.register-link a:hover {
-    text-decoration: underline;
-}
\ No newline at end of file
+    .register-link a:hover {
+        text-decoration: underline;
+    }
+    
\ No newline at end of file
diff --git a/server/helpers/otp.js b/server/helpers/otp.js
index 4a397db..1e0fe47 100644
--- a/server/helpers/otp.js
+++ b/server/helpers/otp.js
@@ -1,12 +1,12 @@
-const otpGenerator = require('otp-generator');
+  const otpGenerator = require('otp-generator');
 
-const generateOTP = () => {
-  const otp = otpGenerator.generate(6, {
-    digits: true,
-    lowerCaseAlphabets: false,
-  });
-  console.log('Generated OTP:', otp); // Remove in production
-  return otp;
-};
+  const generateOTP = () => {
+    const otp = otpGenerator.generate(6, {
+      digits: true,
+      lowerCaseAlphabets: false,
+    });
+    console.log('Generated OTP:', otp); // Remove in production
+    return otp;
+  };
 
-module.exports = generateOTP;
\ No newline at end of file
+  module.exports = generateOTP;
\ No newline at end of file
diff --git a/server/routes/route.js b/server/routes/route.js
index d267596..f68b6c4 100644
--- a/server/routes/route.js
+++ b/server/routes/route.js
@@ -528,4 +528,50 @@ router.post(
   }
 );
 
+// Delete Request
+router.delete(
+  '/delete',
+  authenticate,
+  [
+    body('password').notEmpty().withMessage('Password is required.'),
+  ],
+  async (req, res) => {
+    console.log('Delete account request for user:', req.user.id);
+    const errors = validationResult(req);
+    if (!errors.isEmpty()) {
+      console.warn('Validation errors:', errors.array());
+      return res.status(400).json({ error: { message: errors.array()[0].msg } });
+    }
+
+    try {
+      const { password } = req.body;
+      const user = await User.findById(req.user.id);
+      if (!user) {
+        console.warn('User not found:', req.user.id);
+        return res.status(404).json({ error: { message: 'User not found.' } });
+      }
+
+      if (user.isGoogleAccount) {
+        console.warn('Google account deletion attempted:', req.user.id);
+        return res
+          .status(400)
+          .json({ error: { message: 'Google accounts cannot be deleted this way.' } });
+      }
+
+      const isMatch = await bcrypt.compare(password, user.password);
+      if (!isMatch) {
+        console.warn('Incorrect password for:', req.user.id);
+        return res.status(400).json({ error: { message: 'Incorrect password.' } });
+      }
+
+      await User.deleteOne({ _id: req.user.id });
+      console.log('Account deleted for:', req.user.id);
+      res.status(200).json({ message: 'Account deleted successfully.' });
+    } catch (err) {
+      console.error('Delete account error:', err);
+      res.status(500).json({ error: { message: 'Server error.' } });
+    }
+  }
+);
+
 module.exports = router;
\ No newline at end of file


Reviews:
user: login: qodo-code-review[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:37:49Z
user: login: qodo-free-for-open-source-projects[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:37:49Z
user: login: qodo-code-review[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:39:00Z
user: login: qodo-free-for-open-source-projects[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:39:00Z

Review comments:
diff_hunk: @@ -68,28 +71,34 @@ const Login = () => {
             disabled={isLoading}
           />
         </div>
-        <div className="form-group">
+        <div className="form-group password-group">
           <label>Password:</label>
           <input
-            type="password"
+            type={showPassword ? 'text' : 'password'}
             name="password"
             value={formData.password}
             onChange={handleChange}
             required
             disabled={isLoading}
           />
+          <span
+            className="password-toggle-icon"
+            onClick={() => setShowPassword(!showPassword)}
+          >
+            {showPassword ? '🙈' : '👁️'}
+          </span>
path: client/src/components/Login.jsx
user: login: qodo-code-review[bot]
body: **Suggestion:** Use imported icons
```suggestion
          <span
            className="password-toggle-icon"
            onClick={() => setShowPassword(!showPassword)}
          >
            {showPassword ? <FaEyeSlash /> : <FaEye />}
          </span>
```

<!-- manually_applied -->
created_at: 2025-05-20T08:37:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,28 +71,34 @@ const Login = () => {
             disabled={isLoading}
           />
         </div>
-        <div className="form-group">
+        <div className="form-group password-group">
           <label>Password:</label>
           <input
-            type="password"
+            type={showPassword ? 'text' : 'password'}
             name="password"
             value={formData.password}
             onChange={handleChange}
             required
             disabled={isLoading}
           />
+          <span
+            className="password-toggle-icon"
+            onClick={() => setShowPassword(!showPassword)}
+          >
+            {showPassword ? '🙈' : '👁️'}
+          </span>
path: client/src/components/Login.jsx
user: login: qodo-free-for-open-source-projects[bot]
body: **Suggestion:** Use imported icons
```suggestion
          <span
            className="password-toggle-icon"
            onClick={() => setShowPassword(!showPassword)}
          >
            {showPassword ? <FaEyeSlash /> : <FaEye />}
          </span>
```

<!-- manually_applied -->
created_at: 2025-05-20T08:37:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -92,6 +94,35 @@ import React, { useState, useEffect } from 'react';
          setIsLoading(false);
        }
      };
+     
+     const handleDeleteSubmit = async (e) => {
+    e.preventDefault();
+    setError('');
+    setSuccess('');
+    setIsLoading(true);
+
+    console.log('Deleting account');
+    if (!deletePassword) {
+      setError('Please enter your password');
+      setIsLoading(false);
+      return;
+    }
+
+    try {
+      await deleteAccount({ password: deletePassword });
+      console.log('Account deleted');
+      setSuccess('Account deleted successfully');
+      localStorage.removeItem('token');
+      localStorage.removeItem('pendingVerificationEmail');
+      setTimeout(() => navigate('/login'), 2000);
path: client/src/components/Profile.jsx
user: login: qodo-code-review[bot]
body: **Suggestion:** Improve post-deletion navigation
```suggestion
      setSuccess('Account deleted successfully');
      localStorage.removeItem('token');
      localStorage.removeItem('pendingVerificationEmail');
      navigate('/login');
```

<!-- manually_applied -->
created_at: 2025-05-20T08:39:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -92,6 +94,35 @@ import React, { useState, useEffect } from 'react';
          setIsLoading(false);
        }
      };
+     
+     const handleDeleteSubmit = async (e) => {
+    e.preventDefault();
+    setError('');
+    setSuccess('');
+    setIsLoading(true);
+
+    console.log('Deleting account');
+    if (!deletePassword) {
+      setError('Please enter your password');
+      setIsLoading(false);
+      return;
+    }
+
+    try {
+      await deleteAccount({ password: deletePassword });
+      console.log('Account deleted');
+      setSuccess('Account deleted successfully');
+      localStorage.removeItem('token');
+      localStorage.removeItem('pendingVerificationEmail');
+      setTimeout(() => navigate('/login'), 2000);
path: client/src/components/Profile.jsx
user: login: qodo-free-for-open-source-projects[bot]
body: **Suggestion:** Improve post-deletion navigation
```suggestion
      setSuccess('Account deleted successfully');
      localStorage.removeItem('token');
      localStorage.removeItem('pendingVerificationEmail');
      navigate('/login');
```

<!-- manually_applied -->
created_at: 2025-05-20T08:39:00Z
author_association: CONTRIBUTOR

PR comments:
user: login: netlify[bot]
created_at: 2025-05-20T08:36:07Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *fokuspace* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | c69a8ad6e4604ecf28557f52ab0dcc9c1870ebd1 |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/projects/fokuspace/deploys/682c3fbfb39293000878c178 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-42--fokuspace.netlify.app](https://deploy-preview-42--fokuspace.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTQyLS1mb2t1c3BhY2UubmV0bGlmeS5hcHAifQ.zF_U-UnTtpQIr4yNK2_eaVmMdZN1qjm3PoQJ86E9iHM)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [fokuspace Preview](https://deploy-preview-42--fokuspace.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify project configuration](https://app.netlify.com/projects/fokuspace/configuration/notifications#deploy-notifications)._
author_association: NONE
user: login: AvinashGuleria0
created_at: 2025-05-20T08:36:08Z
body: @CodiumAI-Agent /review
author_association: COLLABORATOR
user: login: qodo-free-for-open-source-projects[bot]
created_at: 2025-05-20T08:36:28Z
body: ## PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

<table>
<tr><td>⏱️&nbsp;<strong>Estimated effort to review</strong>: 3 🔵🔵🔵⚪⚪</td></tr>
<tr><td>🧪&nbsp;<strong>No relevant tests</strong></td></tr>
<tr><td>🔒&nbsp;<strong>Security concerns</strong><br><br>

<strong>Sensitive information exposure:</strong><br> The server logs contain sensitive information such as user IDs (req.user.id) and authentication events like password validation failures in the delete account endpoint. For example, lines 539, 550, 555, and 563 in server/routes/route.js log user IDs and authentication attempts. Additionally, line 8 in server/helpers/otp.js logs generated OTP values with a comment indicating it should be removed in production, but it's still present in the code. These logs could expose user activity patterns and authentication details if server logs are compromised.</td></tr>
<tr><td>⚡&nbsp;<strong>Recommended focus areas for review</strong><br><br>

<details><summary><a href='https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-e30fa8978949227725a84b74a09b40fe042af42657a30641a59bf0a80782407eR84-R89'><strong>Inconsistent UI</strong></a>

The password visibility toggle shows different icons in the JSX (🙈/👁️) versus what's imported from react-icons (FaEye/FaEyeSlash) but the imported icons aren't being used.
</summary>

```jsx
<span
  className="password-toggle-icon"
  onClick={() => setShowPassword(!showPassword)}
>
  {showPassword ? '🙈' : '👁️'}
</span>
```

</details>

<details><summary><a href='https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-2451323074e1b7e39e7f2d4e446fba58ed1ba0100f904d330d368b1a49c1a506R539-R568'><strong>Security Concern</strong></a>

The delete account endpoint logs sensitive information including user IDs and password validation failures, which could expose user activity in server logs.
</summary>

```javascript
console.log('Delete account request for user:', req.user.id);
const errors = validationResult(req);
if (!errors.isEmpty()) {
  console.warn('Validation errors:', errors.array());
  return res.status(400).json({ error: { message: errors.array()[0].msg } });
}

try {
  const { password } = req.body;
  const user = await User.findById(req.user.id);
  if (!user) {
    console.warn('User not found:', req.user.id);
    return res.status(404).json({ error: { message: 'User not found.' } });
  }

  if (user.isGoogleAccount) {
    console.warn('Google account deletion attempted:', req.user.id);
    return res
      .status(400)
      .json({ error: { message: 'Google accounts cannot be deleted this way.' } });
  }

  const isMatch = await bcrypt.compare(password, user.password);
  if (!isMatch) {
    console.warn('Incorrect password for:', req.user.id);
    return res.status(400).json({ error: { message: 'Incorrect password.' } });
  }

  await User.deleteOne({ _id: req.user.id });
  console.log('Account deleted for:', req.user.id);
```

</details>

<details><summary><a href='https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-cc28bf7e5a03c8e641f7ee766565804310a2e8718be43f418cac437b8c26dfd4R8-R8'><strong>Security Log</strong></a>

OTP values are being logged to console which is marked as "Remove in production" but remains in the code, potentially exposing sensitive authentication tokens.
</summary>

```javascript
console.log('Generated OTP:', otp); // Remove in production
return otp;
```

</details>

</td></tr>
</table>

author_association: CONTRIBUTOR
user: login: qodo-free-for-open-source-projects[bot]
created_at: 2025-05-20T08:36:50Z
body: ## PR Code Suggestions ✨

<!-- 5f98569 -->

Explore these optional code suggestions:

<table><thead><tr><td><strong>Category</strong></td><td align=left><strong>Suggestion&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </strong></td><td align=center><strong>Impact</strong></td></tr><tbody><tr><td rowspan=1>Security</td>
<td>



<details><summary>✅ 
Improve post-deletion navigation
</summary>

___

<details><summary><b>Suggestion Impact:</b></summary>The commit implemented exactly what was suggested - removing the setTimeout delay and immediately navigating to login after account deletion, addressing the security concern

code diff:

```diff
-      setTimeout(() => navigate('/login'), 2000);
+      setSuccess('Account deleted successfully');
+      localStorage.removeItem('token');
+      localStorage.removeItem('pendingVerificationEmail');
+      navigate('/login');
```

</details>


___


**After account deletion, immediately navigate to login instead of using <br>setTimeout. The current approach creates a security risk by keeping the user on <br>a page they shouldn't access after their account is deleted.**

[client/src/components/Profile.jsx [117]](https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-ec0f9b0e192357c8f217de96db181d439d4a4615b48abc031e235431eb5e2052R117-R117)

```diff
-setTimeout(() => navigate('/login'), 2000);
+setSuccess('Account deleted successfully');
+localStorage.removeItem('token');
+localStorage.removeItem('pendingVerificationEmail');
+navigate('/login');
```

`[Suggestion processed]`

<details><summary>Suggestion importance[1-10]: 8</summary>

__

Why: This suggestion addresses a security concern by ensuring the user is redirected immediately after account deletion, preventing access to protected content and improving the application's security posture.


</details></details></td><td align=center>Medium

</td></tr><tr><td rowspan=1>Possible issue</td>
<td>



<details><summary>Handle related data deletion</summary>

___


**Consider handling related user data before deletion. The current implementation <br>might leave orphaned data in other collections. Implement a more comprehensive <br>deletion strategy or use cascading delete middleware.**

[server/routes/route.js [567]](https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-2451323074e1b7e39e7f2d4e446fba58ed1ba0100f904d330d368b1a49c1a506R567-R567)

```diff
+// Delete user-related data first
+// await UserData.deleteMany({ userId: req.user.id });
+// await UserPosts.deleteMany({ author: req.user.id });
 await User.deleteOne({ _id: req.user.id });
```

- [ ] **Apply / Chat** <!-- /improve --apply_suggestion=1 -->

<details><summary>Suggestion importance[1-10]: 7</summary>

__

Why: The suggestion highlights a potential data integrity issue by recommending the deletion of related user data, which is important for preventing orphaned records but does not address a critical bug in the current code.


</details></details></td><td align=center>Medium

</td></tr><tr><td rowspan=1>General</td>
<td>



<details><summary>✅ 
Use imported icons
</summary>

___

<details><summary><b>Suggestion Impact:</b></summary>The commit directly implemented the suggestion by replacing the emoji characters ('🙈' and '👁️') with the imported React icons (FaEyeSlash and FaEye) exactly as suggested

code diff:

```diff
-            {showPassword ? '🙈' : '👁️'}
+            {showPassword ? <FaEyeSlash /> : <FaEye />}
```

</details>


___


**Replace emoji characters with the imported React icons for better accessibility <br>and consistent rendering across platforms. You've already imported <code>FaEye</code> and <br><code>FaEyeSlash</code> but aren't using them.**

[client/src/components/Login.jsx [84-89]](https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42/files#diff-e30fa8978949227725a84b74a09b40fe042af42657a30641a59bf0a80782407eR84-R89)

```diff
 <span
   className="password-toggle-icon"
   onClick={() => setShowPassword(!showPassword)}
 >
-  {showPassword ? '🙈' : '👁️'}
+  {showPassword ? <FaEyeSlash /> : <FaEye />}
 </span>
```

`[Suggestion processed]`

<details><summary>Suggestion importance[1-10]: 6</summary>

__

Why: This suggestion improves accessibility and visual consistency by using the imported `FaEye` and `FaEyeSlash` icons instead of emoji, which is a minor but meaningful UI/UX enhancement.


</details></details></td><td align=center>Low

</td></tr>
<tr><td align="center" colspan="2">

- [ ] Update <!-- /improve_multi --more_suggestions=true -->

</td><td></td></tr></tbody></table>
author_association: CONTRIBUTOR
user: login: QodoAI-Agent
created_at: 2025-05-20T08:36:52Z
body: **[Persistent review](https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42#issuecomment-2893472619)** updated to latest commit https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/commit/5f9856900f0aab68284d15bd960f80523263cf82
author_association: NONE
user: login: QodoAI-Agent
created_at: 2025-05-20T08:37:21Z
body: **[Persistent review](https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/pull/42#issuecomment-2893472619)** updated to latest commit https://github.com/kalviumcommunity/S84_Avinash_Capstone_FokuSpace/commit/5f9856900f0aab68284d15bd960f80523263cf82
author_association: NONE