Repository: Learnathon-By-Geeky-Solutions/codeclusters
Pull request #13: refactor code according sonar
Author: login: mhbarshan
Created: 2025-04-04T19:05:48Z | Merged: 2025-04-04T19:11:15Z



Diff:
diff --git a/admin/src/components/Login.jsx b/admin/src/components/Login.jsx
index c8cd0c9d..728db073 100644
--- a/admin/src/components/Login.jsx
+++ b/admin/src/components/Login.jsx
@@ -2,6 +2,7 @@ import axios from "axios";
 import React, { useState } from "react";
 import { backendUrl } from "../App";
 import { toast } from "react-toastify";
+import PropTypes from "prop-types";
 
 const Login = ({ setToken }) => {
   const [email, setEmail] = useState("");
@@ -26,7 +27,9 @@ const Login = ({ setToken }) => {
       toast.error(error.message);
     }
   };
-
+  Login.propTypes = {
+    setToken: PropTypes.string.isRequired,
+  };
   return (
     <div className="min-h-screen flex items-center justify-center w-full">
       <div className="bg-white shadow-md rounded-lg px-8 py-6 max-w-md">
diff --git a/backend/controllers/otpController.js b/backend/controllers/otpController.js
index 82c63cab..207f1c58 100644
--- a/backend/controllers/otpController.js
+++ b/backend/controllers/otpController.js
@@ -81,10 +81,7 @@ const resetPass = async (email, newPassword) => {
         message: "Password should be more than 8 character",
       };
     }
-    // const c = await verifyOTP(email, otp);
 
-    // if (c.valid) {
-    // Hash the new password
     const salt = await bcrypt.genSalt(10);
     const hashedPassword = await bcrypt.hash(newPassword, salt);
 
@@ -99,11 +96,6 @@ const resetPass = async (email, newPassword) => {
       success: true,
       message: "Password reset",
     };
-    // } else {
-    //   return {
-    //     error: c.message,
-    //   };
-    // }
   } catch (error) {
     console.log("Error in reset password function", error.message);
     return {
@@ -282,7 +274,7 @@ const verifyOtp = asyncHandler(async (req, res) => {
 
 //route for resetPass
 const resetPassword = asyncHandler(async (req, res) => {
-  const { email, otp, newPassword } = req.body;
+  const { email, newPassword } = req.body;
 
   //validating email & password
   if (!validator.isEmail(email)) {
@@ -290,10 +282,9 @@ const resetPassword = asyncHandler(async (req, res) => {
   }
   //checking user exist or not
   const User = await user.findOne({ email });
-  //   console.log(User);
+
   try {
     if (User) {
-      //   console.log(email, otp, newPassword);
       const result = await resetPass(email, newPassword);
 
       res.json(result);
diff --git a/backend/controllers/productController.js b/backend/controllers/productController.js
index 6167e448..f8e003ad 100644
--- a/backend/controllers/productController.js
+++ b/backend/controllers/productController.js
@@ -1,4 +1,3 @@
-import { json } from "express";
 import asyncHandler from "express-async-handler";
 import productModel from "../models/productModel.js";
 
@@ -15,10 +14,10 @@ const addProduct = asyncHandler(async (req, res) => {
       bestSeller,
     } = req.body;
 
-    const image1 = req.files.image1 && req.files.image1[0];
-    const image2 = req.files.image2 && req.files.image2[0];
-    const image3 = req.files.image3 && req.files.image3[0];
-    const image4 = req.files.image4 && req.files.image4[0];
+    const image1 = req.files.image1?.[0];
+    const image2 = req.files.image2?.[0];
+    const image3 = req.files.image3?.[0];
+    const image4 = req.files.image4?.[0];
 
     const images = [image1, image2, image3, image4].filter(
       (item) => item !== undefined
@@ -40,14 +39,10 @@ const addProduct = asyncHandler(async (req, res) => {
       date: Date.now(),
     };
 
-    // console.log(productData);
-
     const product = new productModel(productData);
     await product.save();
 
     res.status(200).json({ success: "true", message: "Product added" });
-
-    // console.log(imagesUrl);
   } catch (error) {
     console.log("Error in addProduct controller", error.message);
     res.status(500).json({
@@ -127,7 +122,6 @@ const removeProduct = asyncHandler(async (req, res) => {
     console.log("Error in removeProduct controller", error.message);
     res.status(500).json({
       error: "Internal server error",
-      error: "Internal server error",
     });
   }
 });
diff --git a/backend/controllers/userController.js b/backend/controllers/userController.js
index ffdc529e..b2f7b8ca 100644
--- a/backend/controllers/userController.js
+++ b/backend/controllers/userController.js
@@ -3,7 +3,6 @@ import validator from "validator";
 import bcrypt from "bcrypt";
 import user from "../models/userModel.js";
 import generateToken from "../utils/generateJWT.js";
-import { generateOTP, storeOTP } from "./otpController.js";
 
 //route for login
 const login = asyncHandler(async (req, res) => {
diff --git a/backend/middleware/multer.js b/backend/middleware/multer.js
index faf26ee6..29b18c4e 100644
--- a/backend/middleware/multer.js
+++ b/backend/middleware/multer.js
@@ -1,11 +1,5 @@
 import multer from "multer";
 
-// const storage = multer.diskStorage({
-//   filename: function (req, file, cb) {
-//     cb(null, file.originalname);
-//   },
-// });
-
 const storage = multer.diskStorage({
   destination: (req, file, cb) => {
     cb(null, "uploads/");
@@ -15,7 +9,6 @@ const storage = multer.diskStorage({
   },
 });
 
-// const upload = multer({ storage });
 const upload = multer({
   storage: storage,
   limits: { fileSize: 10 * 1024 * 1024 }, // 10 MB limit
diff --git a/backend/routes/orderRoute.js b/backend/routes/orderRoute.js
index 8bd9c83b..66668ef7 100644
--- a/backend/routes/orderRoute.js
+++ b/backend/routes/orderRoute.js
@@ -19,7 +19,6 @@ orderRouter.post("/status", adminAuth, updateStatus);
 //payment features
 orderRouter.post("/place", userAuth, placeOrder);
 orderRouter.post("/stripe", userAuth, placeOrderStripe);
-// orderRouter.post("/ssl", userAuth, placeOrder);
 
 //user feature
 orderRouter.post("/userorders", userAuth, userOrders);
diff --git a/frontend/src/pages/PlaceOrder.jsx b/frontend/src/pages/PlaceOrder.jsx
index d75ea9a9..fbbbb4f9 100644
--- a/frontend/src/pages/PlaceOrder.jsx
+++ b/frontend/src/pages/PlaceOrder.jsx
@@ -1,9 +1,8 @@
 // eslint-disable-next-line no-unused-vars
-import React, { useEffect, useState } from "react";
+import React, { useEffect, useState, useContext } from "react";
 import Title from "../components/Title";
 import CartTotal from "../components/CartTotal";
 import { assets } from "../assets/assets";
-import { useContext } from "react";
 import { ShopContext } from "../context/ShopContext";
 
 import axios from "axios";
@@ -44,71 +43,67 @@ const PlaceOrder = () => {
     setFormData((data) => ({ ...data, [name]: value }));
   };
 
-  const onSubmitHandler = async (e) => {
-    e.preventDefault();
-    // console.log("SubmitHandler");
-
-    try {
-      let orderItems = [];
-      for (const items in cartItems) {
-        for (const item in cartItems[items]) {
-          if (cartItems[items][item] > 0) {
-            const itemInfo = structuredClone(
-              products.find((product) => product._id === items)
-            );
-            // console.log(itemInfo);
-            if (itemInfo) {
-              itemInfo.size = item;
-
-              itemInfo.quantity = cartItems[items][item];
-
-              orderItems.push(itemInfo);
-            }
+  const buildOrderItems = (cartItems, products) => {
+    const orderItems = [];
+    for (const productId in cartItems) {
+      for (const size in cartItems[productId]) {
+        if (cartItems[productId][size] > 0) {
+          const product = structuredClone(
+            products.find((p) => p._id === productId)
+          );
+          if (product) {
+            product.size = size;
+            product.quantity = cartItems[productId][size];
+            orderItems.push(product);
           }
         }
       }
-      let orderData = {
+    }
+    return orderItems;
+  };
+  const placeCODOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/place", orderData, {
+      headers: { token },
+    });
+    return res.data;
+  };
+
+  const placeStripeOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/stripe", orderData, {
+      headers: { token },
+    });
+    return res.data;
+  };
+  const onSubmitHandler = async (e) => {
+    e.preventDefault();
+    try {
+      const orderItems = buildOrderItems(cartItems, products);
+      const orderData = {
         address: formData,
         items: orderItems,
         amount: getCartAmount() + deliver_fee,
       };
 
-      switch (method) {
-        //api call for cod
-        case "cod": {
-          const res = await axios.post(
-            backendUrl + "/api/order/place",
-            orderData,
-            { headers: { token } }
-          );
-          if (res.data.success) {
-            setCartItems({});
-            navigate("/orders");
-          } else {
-            toast.error(res.data.message);
-          }
-          break;
-        }
+      let response;
+      if (method === "cod") {
+        response = await placeCODOrder(orderData, token);
+      } else if (method === "stripe") {
+        response = await placeStripeOrder(orderData, token);
+      }
 
-        case "stripe": {
-          const res = await axios.post(
-            backendUrl + "/api/order/stripe",
-            orderData,
-            { headers: { token } }
-          );
-          if (res.data.success) {
-            const { session_url } = res.data;
-            window.location.replace(session_url);
-          } else toast.error(res.data.message);
-          break;
+      if (response?.success) {
+        if (method === "stripe") {
+          window.location.replace(response.session_url);
+        } else {
+          setCartItems({});
+          navigate("/orders");
         }
-
-        default:
-          break;
+      } else {
+        toast.error(response?.message || "Unknown error");
       }
     } catch (error) {
-      console.log(error);
-      toast.error(error.message);
+      console.error(error);
+      toast.error(error.message || "Something went wrong");
     }
   };
 
@@ -221,7 +216,7 @@ const PlaceOrder = () => {
         <div className="mt-12">
           <Title text1={"PAYMENT"} text2={"METHOD"} />
           <div className="flex gap-3 flex-col lg:flex-row">
-            <div
+            <button
               onClick={() => setMethod("stripe")}
               className="hover:bg-gray-100 flex items-center gap-3 border p-2 px-3 cursor-pointer"
             >
@@ -236,8 +231,8 @@ const PlaceOrder = () => {
                 src={assets.stripe_logo}
                 alt=""
               />
-            </div>
-            <div
+            </button>
+            <button
               onClick={() => setMethod("ssl")}
               className="hover:bg-gray-100 flex items-center gap-3 border p-2 px-3 cursor-pointer"
             >
@@ -247,8 +242,8 @@ const PlaceOrder = () => {
                 }`}
               ></p>
               <img className="h-8 mx-4" src={assets.ssl_logo} alt="" />
-            </div>
-            <div
+            </button>
+            <button
               onClick={() => setMethod("cod")}
               className="hover:bg-gray-100 flex items-center gap-3 border p-2 px-3 cursor-pointer"
             >
@@ -260,7 +255,7 @@ const PlaceOrder = () => {
               <p className=" text-gray-500 text-sm font-medium mx-4">
                 CASH ON DELIVERY
               </p>
-            </div>
+            </button>
           </div>
 
           <div className="w-full text-end mt-8">


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 5**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>frontend/src/pages/PlaceOrder.jsx (1)</summary><blockquote>

`219-258`: _🧹 Nitpick (assertive)_

**Beeep boop. Add explicit `type="button"` for non-submitting buttons.**  
In a form context, these buttons default to `type="submit"`, which may unintentionally trigger a form submission. Use `type="button"` or whichever type is suitable.  


```diff
-<button
+<button
+  type="button"
   onClick={() => setMethod("stripe")}
   ...
```

```diff
-<button
+<button
+  type="button"
   onClick={() => setMethod("ssl")}
   ...
```

```diff
-<button
+<button
+  type="button"
   onClick={() => setMethod("cod")}
   ...
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 223-227: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead


(lint/style/useSelfClosingElements)

---

[error] 239-243: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead


(lint/style/useSelfClosingElements)

---

[error] 250-254: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing.

Unsafe fix: Use a SelfClosingElement instead


(lint/style/useSelfClosingElements)

---

[error] 219-222: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

---

[error] 235-238: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

---

[error] 246-249: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 20afa15340c51de08775dafcad93cec84afa3749 and 911c34c446a73b509609f7501f5a2db7b6f163d1.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `admin/src/components/Login.jsx` (2 hunks)
* `backend/controllers/otpController.js` (1 hunks)
* `backend/controllers/productController.js` (1 hunks)
* `backend/controllers/userController.js` (0 hunks)
* `backend/middleware/multer.js` (0 hunks)
* `backend/routes/orderRoute.js` (0 hunks)
* `frontend/src/pages/PlaceOrder.jsx` (6 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (3)</summary>

* backend/controllers/userController.js
* backend/routes/orderRoute.js
* backend/middleware/multer.js

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>frontend/src/pages/PlaceOrder.jsx (1)</summary><blockquote>

<details>
<summary>frontend/src/context/ShopContext.jsx (6)</summary>

* `cartItems` (17-17)
* `products` (18-18)
* `token` (19-19)
* `getCartAmount` (130-145)
* `deliver_fee` (13-13)
* `navigate` (35-35)

</details>

</blockquote></details>

</details><details>
<summary>🪛 Biome (1.9.4)</summary>

<details>
<summary>frontend/src/pages/PlaceOrder.jsx</summary>

[error] 65-65: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 72-72: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

---

[error] 219-222: Provide an explicit type prop for the button element.

The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset

(lint/a11y/useButtonType)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>admin/src/components/Login.jsx (1)</summary>

`5-5`: **Beeep boop. PropTypes import recognized.**  
This import statement is good and sets the stage for explicit prop type validations.

</details>
<details>
<summary>backend/controllers/productController.js (1)</summary>

`17-20`: **Beeep boop. Optional chaining usage validated.**  
Safer file access is achieved with `?.[0]`. This prevents runtime errors when `req.files.imageX` is `undefined`.

</details>
<details>
<summary>frontend/src/pages/PlaceOrder.jsx (1)</summary>

`46-63`: **Beeep boop. `buildOrderItems` logic acknowledged.**  
Your loop neatly structures order items. One note: `structuredClone` might have limited support in older environments. Otherwise, beep boop, it’s a neat approach.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-04T19:10:07Z

Review comments:
diff_hunk: @@ -26,7 +27,9 @@ const Login = ({ setToken }) => {
       toast.error(error.message);
     }
   };
-
+  Login.propTypes = {
+    setToken: PropTypes.string.isRequired,
+  };
path: admin/src/components/Login.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Beeep boop. Mismatch in prop-type declaration for `setToken`.**  
You have declared `setToken` as a string, but the code reveals that it's used as a function to set state. Replace `PropTypes.string` with `PropTypes.func`.  


```diff
-Login.propTypes = {
-  setToken: PropTypes.string.isRequired,
-};
+Login.propTypes = {
+  setToken: PropTypes.func.isRequired,
+};
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
  Login.propTypes = {
    setToken: PropTypes.func.isRequired,
  };
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-04T19:10:06Z
author_association: NONE
diff_hunk: @@ -282,18 +274,17 @@ const verifyOtp = asyncHandler(async (req, res) => {
 
 //route for resetPass
 const resetPassword = asyncHandler(async (req, res) => {
-  const { email, otp, newPassword } = req.body;
+  const { email, newPassword } = req.body;
 
   //validating email & password
   if (!validator.isEmail(email)) {
     return res.json({ success: false, message: "Email is not valid" });
   }
   //checking user exist or not
   const User = await user.findOne({ email });
-  //   console.log(User);
+
path: backend/controllers/otpController.js
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beeep boop. OTP removal may weaken security.**  
Removing OTP verification significantly reduces the protection of your password reset flow. It is advisable to replace it with an alternative method (e.g., secure tokens, one-time links) if you want to maintain strong security. I can help design a secure workflow if desired.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-04T19:10:06Z
author_association: NONE
diff_hunk: @@ -44,71 +43,67 @@ const PlaceOrder = () => {
     setFormData((data) => ({ ...data, [name]: value }));
   };
 
-  const onSubmitHandler = async (e) => {
-    e.preventDefault();
-    // console.log("SubmitHandler");
-
-    try {
-      let orderItems = [];
-      for (const items in cartItems) {
-        for (const item in cartItems[items]) {
-          if (cartItems[items][item] > 0) {
-            const itemInfo = structuredClone(
-              products.find((product) => product._id === items)
-            );
-            // console.log(itemInfo);
-            if (itemInfo) {
-              itemInfo.size = item;
-
-              itemInfo.quantity = cartItems[items][item];
-
-              orderItems.push(itemInfo);
-            }
+  const buildOrderItems = (cartItems, products) => {
+    const orderItems = [];
+    for (const productId in cartItems) {
+      for (const size in cartItems[productId]) {
+        if (cartItems[productId][size] > 0) {
+          const product = structuredClone(
+            products.find((p) => p._id === productId)
+          );
+          if (product) {
+            product.size = size;
+            product.quantity = cartItems[productId][size];
+            orderItems.push(product);
           }
         }
       }
-      let orderData = {
+    }
+    return orderItems;
+  };
+  const placeCODOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/place", orderData, {
+      headers: { token },
+    });
+    return res.data;
+  };
+
+  const placeStripeOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/stripe", orderData, {
+      headers: { token },
+    });
+    return res.data;
+  };
+  const onSubmitHandler = async (e) => {
+    e.preventDefault();
+    try {
+      const orderItems = buildOrderItems(cartItems, products);
+      const orderData = {
         address: formData,
         items: orderItems,
         amount: getCartAmount() + deliver_fee,
       };
 
-      switch (method) {
-        //api call for cod
-        case "cod": {
-          const res = await axios.post(
-            backendUrl + "/api/order/place",
-            orderData,
-            { headers: { token } }
-          );
-          if (res.data.success) {
-            setCartItems({});
-            navigate("/orders");
-          } else {
-            toast.error(res.data.message);
-          }
-          break;
-        }
+      let response;
+      if (method === "cod") {
+        response = await placeCODOrder(orderData, token);
+      } else if (method === "stripe") {
+        response = await placeStripeOrder(orderData, token);
+      }
 
-        case "stripe": {
-          const res = await axios.post(
-            backendUrl + "/api/order/stripe",
-            orderData,
-            { headers: { token } }
-          );
-          if (res.data.success) {
-            const { session_url } = res.data;
-            window.location.replace(session_url);
-          } else toast.error(res.data.message);
-          break;
+      if (response?.success) {
+        if (method === "stripe") {
+          window.location.replace(response.session_url);
+        } else {
+          setCartItems({});
+          navigate("/orders");
         }
-
-        default:
-          break;
+      } else {
+        toast.error(response?.message || "Unknown error");
       }
     } catch (error) {
-      console.log(error);
-      toast.error(error.message);
+      console.error(error);
+      toast.error(error.message || "Something went wrong");
     }
   };
path: frontend/src/pages/PlaceOrder.jsx
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Beeep boop. `ssl` method is not handled.**  
You present a button that sets the payment method to `ssl`, but you only handle `cod` or `stripe` in `onSubmitHandler`. This logic mismatch will lead to errors or undefined responses for `ssl`.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-04T19:10:06Z
author_association: NONE
diff_hunk: @@ -44,71 +43,67 @@ const PlaceOrder = () => {
     setFormData((data) => ({ ...data, [name]: value }));
   };
 
-  const onSubmitHandler = async (e) => {
-    e.preventDefault();
-    // console.log("SubmitHandler");
-
-    try {
-      let orderItems = [];
-      for (const items in cartItems) {
-        for (const item in cartItems[items]) {
-          if (cartItems[items][item] > 0) {
-            const itemInfo = structuredClone(
-              products.find((product) => product._id === items)
-            );
-            // console.log(itemInfo);
-            if (itemInfo) {
-              itemInfo.size = item;
-
-              itemInfo.quantity = cartItems[items][item];
-
-              orderItems.push(itemInfo);
-            }
+  const buildOrderItems = (cartItems, products) => {
+    const orderItems = [];
+    for (const productId in cartItems) {
+      for (const size in cartItems[productId]) {
+        if (cartItems[productId][size] > 0) {
+          const product = structuredClone(
+            products.find((p) => p._id === productId)
+          );
+          if (product) {
+            product.size = size;
+            product.quantity = cartItems[productId][size];
+            orderItems.push(product);
           }
         }
       }
-      let orderData = {
+    }
+    return orderItems;
+  };
+  const placeCODOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/place", orderData, {
path: frontend/src/pages/PlaceOrder.jsx
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beeep boop. Use template literal instead of string concatenation.**  
Replace `backendUrl + "/api/order/place"` with a template literal for improved readability.  


```diff
-const res = await axios.post(backendUrl + "/api/order/place", orderData, {
+const res = await axios.post(`${backendUrl}/api/order/place`, orderData, {
   headers: { token },
 });
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    const res = await axios.post(`${backendUrl}/api/order/place`, orderData, {
      headers: { token },
    });
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 65-65: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-04T19:10:06Z
author_association: NONE
diff_hunk: @@ -44,71 +43,67 @@ const PlaceOrder = () => {
     setFormData((data) => ({ ...data, [name]: value }));
   };
 
-  const onSubmitHandler = async (e) => {
-    e.preventDefault();
-    // console.log("SubmitHandler");
-
-    try {
-      let orderItems = [];
-      for (const items in cartItems) {
-        for (const item in cartItems[items]) {
-          if (cartItems[items][item] > 0) {
-            const itemInfo = structuredClone(
-              products.find((product) => product._id === items)
-            );
-            // console.log(itemInfo);
-            if (itemInfo) {
-              itemInfo.size = item;
-
-              itemInfo.quantity = cartItems[items][item];
-
-              orderItems.push(itemInfo);
-            }
+  const buildOrderItems = (cartItems, products) => {
+    const orderItems = [];
+    for (const productId in cartItems) {
+      for (const size in cartItems[productId]) {
+        if (cartItems[productId][size] > 0) {
+          const product = structuredClone(
+            products.find((p) => p._id === productId)
+          );
+          if (product) {
+            product.size = size;
+            product.quantity = cartItems[productId][size];
+            orderItems.push(product);
           }
         }
       }
-      let orderData = {
+    }
+    return orderItems;
+  };
+  const placeCODOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/place", orderData, {
+      headers: { token },
+    });
+    return res.data;
+  };
+
+  const placeStripeOrder = async (orderData, token) => {
+    const res = await axios.post(backendUrl + "/api/order/stripe", orderData, {
path: frontend/src/pages/PlaceOrder.jsx
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beeep boop. Use template literal instead of string concatenation.**  
Similarly, replace `backendUrl + "/api/order/stripe"` with a template literal.  


```diff
-const res = await axios.post(backendUrl + "/api/order/stripe", orderData, {
+const res = await axios.post(`${backendUrl}/api/order/stripe`, orderData, {
   headers: { token },
 });
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    const res = await axios.post(`${backendUrl}/api/order/stripe`, orderData, {
      headers: { token },
    });
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Biome (1.9.4)</summary>

[error] 72-72: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.


(lint/style/useTemplate)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-04T19:10:06Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-04T19:05:56Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

<details>
<summary>📝 Walkthrough</summary>

## Summary by CodeRabbit

- **Refactor**
  - Streamlined the password reset process for a more direct user recovery.
  - Enhanced the order submission flow with accessible, interactive payment options and improved error handling.
  - Optimized file and image handling for smoother uploads and more reliable operations.
  
- **Chores**
  - Removed redundant and outdated code comments to simplify the underlying system.
## Walkthrough
This pull request implements several updates across both backend and frontend components. The changes include adding PropTypes validation in the Login component, removing OTP verification logic and related imports in password resetting, and enhancing image file access with optional chaining in the product controller. Additionally, the multer storage configuration is updated with timestamping for unique filenames, a commented-out order route is removed, and the order submission logic in the PlaceOrder page is refactored using helper functions for cleaner control flow.

## Changes

| File(s) | Change Summary |
| ------- | -------------- |
| `admin/src/components/Login.jsx` | Added PropTypes validation: declared `Login.propTypes` with required `setToken` as a string. |
| `backend/controllers/otpController.js`<br>`backend/controllers/userController.js` | Removed OTP verification in password reset and deleted obsolete OTP imports from user controller. |
| `backend/controllers/productController.js` | Replaced logical AND checks with optional chaining for image access and removed a duplicate error message in `removeProduct`. |
| `backend/middleware/multer.js` | Updated storage configuration to timestamp filenames; removed commented-out storage configuration code. |
| `backend/routes/orderRoute.js` | Removed a commented-out POST route for `/ssl`. |
| `frontend/src/pages/PlaceOrder.jsx` | Refactored order submission: introduced helper functions (`buildOrderItems`, `placeCODOrder`, `placeStripeOrder`), replaced `div` elements with `button` for payment selections, and improved error/response handling. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant U as User
    participant P as PlaceOrder Page
    participant S as Server (COD/Stripe)

    U->>P: Submit order details
    P->>P: Build order items (buildOrderItems)
    alt Payment Method: COD
        P->>S: Execute placeCODOrder(orderData, token)
    else Payment Method: Stripe
        P->>S: Execute placeStripeOrder(orderData, token)
    end
    S-->>P: Return order response
    P-->>U: Redirect on success or display error message
```

## Poem
> In circuits deep, our code refined,  
> PropTypes and helpers neatly aligned.  
> OTPs removed, the flow is clear,  
> Timestamps stamp files far and near.  
> Order logic reformed with a digital cheer!  
> Beep boop—code excellence is here!  
>  


</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Learnathon-By-Geeky-Solutions/codeclusters&utm_content=13):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-04-04T19:06:19Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=Learnathon-By-Geeky-Solutions_codeclusters&pullRequest=13)


author_association: NONE