diff --git a/backend/app.js b/backend/app.js index ee695d78..8eb4fa36 100644 --- a/backend/app.js +++ b/backend/app.js @@ -2,6 +2,7 @@ const express = require("express"); const cors = require("cors"); const session = require("express-session"); +const dotenv = require("dotenv"); const passport = require("./middlewares/Passport"); const routes = require("./routes"); const authRoutes = require("./routes/authRoutes"); @@ -11,6 +12,8 @@ const adminRegistrationRoutes = require("./routes/adminRegistrationRoutes"); const app = express(); +dotenv.config(); + // Middleware setup app.use(express.json()); app.use(cors()); @@ -28,7 +31,7 @@ app.use(passport.session()); app.use("/auth", authRoutes); app.use("/api", routes); app.use("/api", passwordResetRoutes); -app.use("/vpi", userRoutes); +app.use("/api/users", userRoutes); app.use("/api/v1", adminRegistrationRoutes); module.exports = app; diff --git a/backend/controllers/userController.js b/backend/controllers/userController.js new file mode 100644 index 00000000..b9c36cee --- /dev/null +++ b/backend/controllers/userController.js @@ -0,0 +1,70 @@ +const mongoose = require("mongoose"); +const User = require("../models/User"); + +exports.getUsers = async (_, res) => { + try { + const users = await User.find().select("-password -__v").lean(); + + return res.status(200).json({ users }); + } catch (error) { + console.error("getUsers error:", error); + return res.status(500).json({ message: "Internal server error" }); + } +}; + +exports.getUserByUsername = async (req, res) => { + try { + const { user_name } = req.params; + + if (!user_name) + return res.status(400).json({ message: "Username is required" }); + + const user = await User.findOne({ username: user_name }) + .select("-password -__v") + .lean(); + + if (!user) return res.status(404).json({ message: "User not found" }); + + return res.status(200).json({ user }); + } catch (error) { + console.error("getUserByUsername error:", error); + return res.status(500).json({ message: "Internal server error" }); + } +}; + +exports.updateUser = async (req, res) => { + try { + const { id } = req.params; + if (!mongoose.Types.ObjectId.isValid(id)) { + return res.status(400).json({ message: "Invalid user id" }); + } + + const { name, email, phone, gender, profile_picture } = req.body; + + if (!name || !email || !phone || !gender || !profile_picture) + return res + .status(400) + .json({ message: "Enter the required fields to update your profile" }); + + const user = await User.findById(id); + + if (!user) return res.status(404).json({ message: "User not found" }); + + const updatedUser = await User.findByIdAndUpdate( + { _id: id }, + { name, email, phone, gender, profile_picture }, + { new: true } + ).select("-password -__v") + .lean(); + + if (updatedUser) + return res + .status(200) + .json({ message: "Profile updated", user: updatedUser }); + + return res.status(500).json({ message: "Failed to your profile" }); + } catch (error) { + console.error("updateUser error:", error); + return res.status(500).json({ message: "Internal server error" }); + } +}; diff --git a/backend/models/User.js b/backend/models/User.js index d56e4d49..e1861e27 100644 --- a/backend/models/User.js +++ b/backend/models/User.js @@ -10,6 +10,10 @@ const userSchema = new Schema({ unique: true, trim: true, }, + name: { + type: String, + default: null + }, email: { type: String, required: false, @@ -29,6 +33,14 @@ const userSchema = new Schema({ trim: true, match: [/^\d{10}$/, "Please enter a 10-digit phone number"], }, + gender: { + type: String, + default: null + }, + profile_picture: { + type: String, + default: null + }, role: { type: Number, default: 0, diff --git a/backend/routes/userRoutes.js b/backend/routes/userRoutes.js index 3e116524..d1dde9cd 100644 --- a/backend/routes/userRoutes.js +++ b/backend/routes/userRoutes.js @@ -1,22 +1,27 @@ const express = require("express"); const router = express.Router(); const User = require("../models/User"); +const userController = require("../controllers/userController") -router.post("/update-details", async (req, res) => { - try { - const { email, phone } = req.body; - const user = await User.findById(req.user.id); - if (user) { - user.email = email; - user.phone = phone; - await user.save(); - res.status(200).send("Details updated successfully"); - } else { - res.status(404).send("User not found"); - } - } catch (error) { - res.status(500).send(error.message); - } -}); +// router.post("/update-details", async (req, res) => { +// try { +// const { email, phone } = req.body; +// const user = await User.findById(req.user.id); +// if (user) { +// user.email = email; +// user.phone = phone; +// await user.save(); +// res.status(200).send("Details updated successfully"); +// } else { +// res.status(404).send("User not found"); +// } +// } catch (error) { +// res.status(500).send(error.message); +// } +// }); + +router.get("/", userController.getUsers) +router.get("/:user_name", userController.getUserByUsername) +router.put("/:id", userController.updateUser); module.exports = router; diff --git a/src/User/components/Navbar/UserNavbar.jsx b/src/User/components/Navbar/UserNavbar.jsx index dda86754..b8f03ddf 100644 --- a/src/User/components/Navbar/UserNavbar.jsx +++ b/src/User/components/Navbar/UserNavbar.jsx @@ -27,13 +27,22 @@ const UserNavbar = ({ isAdmin }) => { const handleSearch = (e) => setSearchTerm(e.target.value); const searchableItems = [ - { name: "Fashion & Accessories", link: "/popularCategories/fashionAccessories" }, - { name: "Printing & Stationery", link: "/popularCategories/printingStationery" }, + { + name: "Fashion & Accessories", + link: "/popularCategories/fashionAccessories", + }, + { + name: "Printing & Stationery", + link: "/popularCategories/printingStationery", + }, { name: "Food & Beverages", link: "/popularCategories/foodBeverages" }, { name: "Beauty & Wellness", link: "/popularCategories/beautyWellness" }, { name: "Furniture & Decor", link: "/popularCategories/furnitureDecor" }, { name: "Body Care", link: "/popularCategories/bodyCare" }, - { name: "Health Supplements", link: "/popularCategories/healthSupplements" }, + { + name: "Health Supplements", + link: "/popularCategories/healthSupplements", + }, { name: "Customized Gifts", link: "/popularCategories/customizedGifts" }, { name: "Handmade Soaps", link: "/latestInMarket/handmadeSoaps" }, { name: "Art Supplies", link: "/latestInMarket/artSupplies" }, @@ -47,7 +56,7 @@ const UserNavbar = ({ isAdmin }) => { useEffect(() => { if (searchTerm) { - const results = searchableItems.filter(item => + const results = searchableItems.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); setSearchResults(results); @@ -114,7 +123,7 @@ const UserNavbar = ({ isAdmin }) => { { to: "/popularCategories/furnitureDecor", text: "Furniture" }, { to: "/popularCategories/printingStationery", text: "Stationary" }, { to: "/popularCategories/bodyCare", text: "Body-Care" }, - // { to: "/meet-the-makers", text: "Meet the Makers" }, + { to: "/meet-the-makers", text: "Meet the Makers" }, ]; const handleResultClick = (link) => { @@ -136,7 +145,8 @@ const UserNavbar = ({ isAdmin }) => { + className="text-green-800 hover:text-green-500 hover:underline block px-4 py-2 font-bold text-base" + > {link.text} ))} @@ -162,46 +172,55 @@ const UserNavbar = ({ isAdmin }) => {
{isLoggedIn ? ( -
- +
- - {username} - + > + + + {username} + +
{showDropdown && (
+ className="absolute top-14 w-48 bg-white rounded-md shadow-lg py-1" + > {isAdminT && ( + className="block px-4 py-2 text-gray-800 hover:bg-gray-200" + > Admin Dashboard )} + className="block px-4 py-2 text-gray-800 hover:bg-gray-200" + > Dashboard - - Meet the Makers - + + Meet the Makers +
@@ -216,12 +235,14 @@ const UserNavbar = ({ isAdmin }) => {
} modal - nested> + nested + > {(close) => (
+ {" "} + {" "} + ×{" "} + {" "}
+ {" "}

- When You Deactivate Your VigyBag Account -

-
+ {" "} + When You Deactivate Your VigyBag Account{" "} + {" "} +
{" "}
    -
  • You are logged out of your VigyBag account.
  • -
    -
  • Your public profile on VigyBag is no longer visible.
  • -
    + {" "} +
  • You are logged out of your VigyBag account.

  • {" "} +
  • Your public profile on VigyBag is no longer visible.
  • {" "} +
    {" "}
  • + {" "} Your reviews/ratings are still visible, but your profile - information is shown as ‘unavailable’ due to deactivation. -
  • -
    + information is shown as ‘unavailable’ due to deactivation.{" "} + {" "} +
    {" "}
  • + {" "} Your wishlist items are no longer accessible through the associated public hyperlink. The wishlist is shown as - ‘unavailable’ due to deactivation. -
  • -
    + ‘unavailable’ due to deactivation.{" "} + {" "} +
    {" "}
  • + {" "} You will be unsubscribed from receiving promotional emails from - VigyBag. -
  • -
    + VigyBag.{" "} + {" "} +
    {" "}
  • + {" "} Your account data is retained and can be restored if you choose - to reactivate your account. -
  • -
-
- + to reactivate your account.{" "} + {" "} + {" "} +
{" "}

- How Do I Reactivate My VigyBag Account? -

-

Reactivation is easy.

-
+ {" "} + How Do I Reactivate My VigyBag Account?{" "} + {" "} +

Reactivation is easy.


{" "}
    + {" "}
  • + {" "} Simply log in with your registered email ID or mobile number and the password used prior to deactivation. Your account data will - be fully restored. -
  • -
    + be fully restored.{" "} + {" "} +
    {" "}
  • + {" "} Default settings will be applied, and you will be subscribed to - receive promotional emails from VigyBag. -
  • -
    -
+ receive promotional emails from VigyBag.{" "} + {" "} +
{" "} + {" "}

+ {" "} VigyBag retains your account data so you can conveniently resume - from where you left off if you decide to reactivate your account. -

+ from where you left off if you decide to reactivate your account.{" "} +

{" "}

+ {" "} Remember: Account reactivation can be done only - on the desktop version. -

-
+ on the desktop version.{" "} +

{" "} +
{" "}
+ {" "} -
+ }} + > + {" "} + CONFIRM DEACTIVATION{" "} + {" "} +
{" "}
)} @@ -114,403 +243,330 @@ const ProfilePage = () => { } modal - nested> + nested + > {(close) => (
+ {" "} + {" "} + ×{" "} + {" "}
+ {" "}

+ {" "} Please note that once you choose to delete your account with VigyBag (“Platform”), your account will no longer be available to you and you will not be able to activate, restore, or - use the account again. -

+ use the account again.{" "} +

{" "}

+ {" "} In case you are not sure about deleting your account, you may - instead deactivate your account. -

+ instead deactivate your account.{" "} +

{" "}

+ {" "} When you deactivate your account, you are logged out of your account, your public profile on the Platform is no longer visible, your wishlist items are no longer accessible through the associated public hyperlink, and you will be unsubscribed from - receiving promotional emails. -

- + receiving promotional emails.{" "} +

{" "}

+ {" "} If you wish to proceed with an account deletion request, please - ensure that you have read and understood the following: -

+ ensure that you have read and understood the following:{" "} + {" "}
    + {" "}
  • + {" "} There are no pending orders, cancellations, returns, refunds, or other requests (“Transactions”). If there are pending Transactions, please raise your account deletion request once - the Transactions are completed. -
  • + the Transactions are completed.{" "} + {" "}
  • + {" "} If you hold any subscription or membership, you will lose all benefits and rewards associated with it immediately upon - deletion of the account. -
  • + deletion of the account.{" "} + {" "}
  • + {" "} You have exhausted or do not intend to use SuperCoins, Gift Cards, or any such reward points or balances associated with your account. Please note that once your account is deleted, you - will not be able to access any such reward points. -
  • + will not be able to access any such reward points.{" "} + {" "}
  • + {" "} You will not be able to access or request to access order history, profile, wishlists, saved addresses, previous orders and invoices, saved or preferred payment methods, content, images, or use any of the products and services offered by the Platform immediately on deletion and will have to create a new - account to use products and services offered by us. -
  • + account to use products and services offered by us.{" "} + {" "}
  • + {" "} The Platform may choose to refuse deletion of your account in case you have any legal dispute, or grievances related to pending payments to your orders, shipments or deliveries, credit - lines, etc. -
  • + lines, etc.{" "} + {" "}
  • + {" "} The Platform may retain certain data for legitimate reasons (towards enforcement of legal rights or regulatory compliance) such as security, fraud prevention, future abuse, and regulatory compliance including the exercise of legal rights or comply with - legal orders under applicable laws. -
  • + legal orders under applicable laws.{" "} + {" "}
  • + {" "} After your account is deleted, if you log into the Platform using the same phone number or email ID, a fresh new account will be created and your old account data will not be - accessible. -
  • + accessible.{" "} + {" "}
  • + {" "} Please uninstall the VigyBag App after your account is deleted to stop receiving any notifications from VigyBag. Notifications are app-level settings and uninstalling the app is required to - stop the notifications. -
  • -
+ stop the notifications.{" "} + {" "} + {" "}

- You acknowledge that you have read our - Terms of Use and - Privacy Policy. -

+ {" "} + You acknowledge that you have read our{" "} + Terms of Use and{" "} + Privacy Policy.{" "} +

{" "}

-
-


-
+ {" "} +


{" "} I have read and - agreed to the Terms and Conditions. -

- -

Please tell us why you’re leaving us

-