Skip to content

Conversation

@LuckyNawale
Copy link

@LuckyNawale LuckyNawale commented Sep 3, 2025

πŸ› Bug Fixes & UI Improvements

Issues Fixed:

  • βœ… Contributors "See More" button not working
  • βœ… Missing terms & conditions acceptance in signup form
  • βœ… Help page layout and display issues
  • βœ… GitHub link pointing to profile instead of repository
  • βœ… Rating display mismatch in Fashion & Accessories products

Changes Made:

1. Contributors Page (src/User/pages/Contributors/Contributors.jsx)

  • Added proper state management for visible contributors
  • Fixed "See More" button functionality with useState
  • Improved button styling and text

2. User Authentication (src/User/pages/UserAuth/UserAuth.jsx)

  • Added required terms & conditions checkbox in signup form
  • Added hyperlinks to Terms & Conditions and Privacy Policy
  • Links open in new tabs for better UX

3. Help Page (src/User/pages/Help/Help.jsx)

  • Improved page structure with proper container
  • Added background gradient styling
  • Fixed layout to prevent footer-only display

4. Footer (src/User/components/Footer/Footer.jsx)

  • Added GitHub repository link to social media section
  • Imported and added GitHub icon
  • Link points to actual VigyBag repository

5. Product Rating Display (src/User/components/Popular_Categories/ProductGrid.jsx)

  • Fixed star count and rating number mismatch
  • Both now use rounded whole numbers for consistency
  • Rating 3.6 shows 4 stars and displays (4)

Testing:

  • All modified components render correctly
  • "See More" button works as expected
  • Terms checkbox is required for signup
  • Help page displays full content
  • GitHub link navigates to repository
  • Product ratings show matching star count and number

Type of Change:

  • Bug fix (non-breaking change which fixes an issue)
  • UI/UX improvement
  • New feature
  • Breaking change
Screenshot 2025-09-03 185323 Screenshot 2025-09-03 191144 Screenshot 2025-09-03 191334

Summary by CodeRabbit

  • New Features

    • Several new UI components and a UI Showcase page (hero, animated buttons, animated navbar, smart search, enhanced product cards, loaders, skeletons).
    • Login state exposed; logout available; actions (buy/add-to-cart/wishlist) now require login and prompt for authentication.
    • Signup now includes a required terms acceptance checkbox.
    • Footer gains a GitHub link.
  • Bug Fixes

    • Fixed Help page layout/nesting and adjusted separator styling.
  • Style

    • Added global enhanced UI styles (glassmorphism, gradients, animations, eco color tokens) and imported globally.
  • Documentation

    • README typo corrected.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Sep 3, 2025

Someone is attempting to deploy a commit to the Vivek Prajapati's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 3, 2025

Walkthrough

Adds multiple new UI components (animated button, hero, product card, smart search, navbar, loaders, skeletons), a UI showcase page, global enhanced UI styles, and AuthContext login state; integrates login-gating into product actions and small UI/layout tweaks (Help, Contributors, Footer) plus a README typo fix.

Changes

Cohort / File(s) Summary
Enhanced UI Components
src/User/components/EnhancedButtons/AnimatedButton.jsx, src/User/components/EnhancedHero/EnhancedHero.jsx, src/User/components/EnhancedProductCard/EnhancedProductCard.jsx, src/User/components/EnhancedSearch/SmartSearchBar.jsx
New React components providing animated button, full-screen hero, advanced product card, and interactive smart search β€” Framer Motion, Tailwind-like classes, state/props, and UI interactions.
Loading / Skeletons
src/User/components/LoadingComponents/PageLoader.jsx, src/User/components/LoadingComponents/ProductCardSkeleton.jsx
New full-screen loader and product card skeleton components with looping animations and shimmer effects.
Navigation
src/User/components/ModernNavbar/ModernNavbar.jsx
New responsive, animated navbar with desktop/mobile layouts, expanding search, active item tracking, and mobile drawer.
Auth Context & Gating
src/context/AuthContext.jsx, src/User/components/Popular_Categories/ProductGrid.jsx, src/User/components/ProductCard/ProductCard.jsx, src/User/pages/UserAuth/UserAuth.jsx
AuthContext now exposes isLoggedIn, user, logout; loginAsUser accepts userData. ProductGrid and ProductCard now gate buy/add-to-cart/wishlist actions by login and navigate to /auth when unauthenticated. Signup form adds required terms checkbox (UI only).
UI Showcase Page
src/User/pages/UIShowcase/UIShowcase.jsx
New page assembling the new components with toggles for loader/skeletons and sample product data.
Styling / Globals
src/index.css, src/styles/enhanced-ui.css
New global import and enhanced-ui.css adding eco color variables, glass/gradient utilities, animations, buttons, cards, and skeleton helpers.
Layout & Content Tweaks
src/User/pages/Help/Help.jsx, src/User/pages/Contributors/Contributors.jsx, src/User/components/Footer/Footer.jsx
Help: new gradient wrapper and adjusted border color; Contributors: replaced boolean toggle with visible count + See More/View Less; Footer: added GitHub social link.
Docs
README.md
Typo fix: "accpet" β†’ "accept".

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UI as ProductGrid/ProductCard
  participant Auth as AuthContext
  participant Router

  User->>UI: Click "Add to Cart"/"Buy Now"/"Wishlist"
  UI->>Auth: read isLoggedIn
  alt isLoggedIn = false
    UI-->>User: show "Please login..." toast/alert
    UI->>Router: navigate("/auth")
  else isLoggedIn = true
    UI-->>User: perform action (add to cart / proceed to checkout / toggle wishlist)
  end
Loading
sequenceDiagram
  participant User
  participant Search as SmartSearchBar
  participant LS as localStorage
  participant Parent as onSearch callback

  User->>Search: focus / type query
  Search-->>Search: filter mockSuggestions, update dropdown
  User->>Search: press Enter or click suggestion
  Search->>LS: update recentSearches (dedupe, cap 5)
  Search->>Parent: invoke onSearch(query)
  Search-->>User: close dropdown, update input
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Notes for review:

  • AuthContext API changes (new state and logout) and callers that now depend on isLoggedIn.
  • New components with Framer Motion β€” check animation variants and performance implications.
  • Global CSS import ordering (src/index.css) and potential cascade impacts.
  • ProductGrid/ProductCard gating logic and navigation side effects.

Possibly related PRs

Suggested labels

FrontEnd, level2, OSCI, 2⭐⭐

Poem

I nibble code beneath the green,
Buttons shimmer, heroes preen.
Search leaves twinkle, cards take flight,
Login gates hold carts polite.
I hop β€” "Accept the terms!" β€” then bound into the light. πŸ‡βœ¨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive Title is vague and overly generic, using non-descriptive terms that do not convey specific information about the changeset. Revise the title to be more specific about the primary changes, e.g., 'Fix Contributors pagination, add terms checkbox, and improve Help page layout' or focus on the most impactful change.
βœ… Passed checks (2 passed)
Check name Status Explanation
Description check βœ… Passed Description is comprehensive and well-structured with clear sections detailing bug fixes, changes, testing, and type of change, exceeding template requirements.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • πŸ“ Generate docstrings
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/context/AuthContext.jsx (1)

1-42: Synchronize AuthContext with existing localStorage auth usage
– Update loginAsAdmin, loginAsUser, and logout in AuthContext.jsx to read/write the same keys used elsewhere (isLoggedIn, isAdmin, and a unified user key), rather than only in state.
– Replace or remove all direct localStorage.getItem("isLoggedIn"), getItem("isAdmin"), getItem("username")/"email" calls (e.g. in src/components/Navbar/UserNavbar.jsx, src/User/pages/Dashboard/*, src/PrivateRoute.jsx, src/Admin/components/AdminNavbar/AdminNavbar.jsx) to use useAuth or the standardized keys.

src/User/components/ProductCard/ProductCard.jsx (1)

31-37: Harden star rendering for fractional/out-of-range ratings

Using Array(rating) will break on non-integers and allow >5 stars.

Apply:

-          <div className="flex gap-1 text-yellow-500">
-            {[...Array(rating)].map((_, i) => (
+          <div className="flex gap-1 text-yellow-500">
+            {[...Array(Math.max(0, Math.min(5, Math.round(Number(rating) || 0))))].map((_, i) => (
               <FaStar key={i} />
             ))}
           </div>
src/User/components/Popular_Categories/ProductGrid.jsx (2)

129-136: Rating text shows count, not the rounded rating

PR objective says β€œrating 3.6 shows 4 stars and displays β€˜(4)’.” This prints rating.count (likely number of reviews).

-          <span className="text-gray-500 ml-1">({product.rating.count})</span>
+          <span className="text-gray-500 ml-1">({Math.round(product.rating.rate)})</span>

150-156: β€œBuy Now” is disabled if item is already in cart

This blocks checkout for items already in cart. Remove the disabled state; gating is already handled in handleBuyNow.

-          <button
+          <button
             onClick={() => {
               onAddToCart(product); // First, add the product to the cart
               handleBuyNow(); // Then, navigate to the payment page
             }}
             className="mt-1 bg-orange-600 text-white px-4 py-2 rounded text-sm w-full hover:bg-orange-700 transition-colors disabled:opacity-45 disabled:pointer-events-none"
-            disabled={cartItems.find((item) => item.id === product.id)}>
-            {cartItems.find((item) => item.id === product.id)
-              ? "⚑Buy Now"
-              : "⚑Buy Now"}
+          >
+            ⚑Buy Now
           </button>
🧹 Nitpick comments (50)
README.md (1)

94-94: Typo fix looks good; unify link style and phrasing (nit).

Use consistent links to repo files and slightly clearer wording.

-We accept contributions to our project pertaining to the [Code of Conduct](https://github.com/codervivek5/VigyBag?tab=coc-ov-file) and [Contributing Guidelines](https://github.com/codervivek5/VigyBag/blob/main/CONTRIBUTING.md) stated below.
+We accept contributions to our project in accordance with the [Code of Conduct](https://github.com/codervivek5/VigyBag/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/codervivek5/VigyBag/blob/main/CONTRIBUTING.md) stated below.
src/User/components/Footer/Footer.jsx (1)

156-156: Good addition; consider rel="nofollow" (nit).

External social links often use nofollow.

-<a href="https://github.com/codervivek5/VigyBag" target="_blank" rel="noopener noreferrer" aria-label="GitHub Repository" className="social-link"><FaGithub className="social-icon" /></a>
+<a href="https://github.com/codervivek5/VigyBag" target="_blank" rel="noopener noreferrer nofollow" aria-label="GitHub Repository" className="social-link"><FaGithub className="social-icon" /></a>
src/User/pages/UserAuth/UserAuth.jsx (1)

461-486: Required checkbox works; add rel on new-tab Links and consider tracking acceptance server-side.

HTML5 required blocks submissionβ€”nice. Add rel to Links opened in new tabs. Also, for compliance/audit, consider persisting terms acceptance (boolean/timestamp/version) via API.

-                        <Link
+                        <Link
                           to="/terms-and-condition"
-                          className="text-[#4caf50] hover:underline"
+                          className="text-[#4caf50] hover:underline"
                           target="_blank"
+                          rel="noopener noreferrer"
                         >
...
-                        <Link
+                        <Link
                           to="/privacy-policy"
-                          className="text-[#4caf50] hover:underline"
+                          className="text-[#4caf50] hover:underline"
                           target="_blank"
+                          rel="noopener noreferrer"
                         >

If you want, I can propose a minimal state + payload change to record acceptance.

src/User/pages/Help/Help.jsx (1)

43-58: Layout fix looks good; move inline styles to CSS and drop stray {" "} (nit).

Keeps styles consistent with your enhanced UI.

-        />{" "}
+        />

Optional: extract the color/border styles on the heading and divider into a CSS class or Tailwind utility for consistency.

src/User/pages/Contributors/Contributors.jsx (3)

21-29: Avoid magic number duplication for initial count (nit).

Define a constant to keep 6 in one place.

-  const [visibleContributors, setVisibleContributors] = useState(6);
+  const INITIAL_VISIBLE = 6;
+  const [visibleContributors, setVisibleContributors] = useState(INITIAL_VISIBLE);
...
-    setVisibleContributors(6);
+    setVisibleContributors(INITIAL_VISIBLE);

367-373: Prefer stable keys over index for mapped list.

Using a stable unique key prevents unnecessary re-renders on reorder.

-            {contributorsData.slice(0, visibleContributors).map((contributor, index) => (
+            {contributorsData.slice(0, visibleContributors).map((contributor) => (
               <ContributorCard
-                key={index}
+                key={contributor.name}
                 {...contributor}
                 roleColor="text-green-600"
               />
             ))}

375-386: Minor color token cleanup (nit).

8-digit hex with ff is equivalent to opaque; use Tailwind token for consistency.

-                className="px-6 py-3 bg-[#15a349ff] text-white rounded-lg hover:bg-green-600 focus:outline-none transition duration-300 font-semibold">
+                className="px-6 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 focus:outline-none transition duration-300 font-semibold">
src/styles/enhanced-ui.css (3)

5-16: Backdrops need graceful fallback and GPU hint

Not all browsers/devices support backdrop-filter; add a @supports gate with a safe fallback and consider will-change to reduce repaints on hover-heavy UIs.

 .glass-effect {
   background: rgba(255, 255, 255, 0.25);
   backdrop-filter: blur(10px);
   -webkit-backdrop-filter: blur(10px);
   border: 1px solid rgba(255, 255, 255, 0.18);
+  will-change: backdrop-filter;
 }
+
+@supports not ((backdrop-filter: blur(10px)) or (-webkit-backdrop-filter: blur(10px))) {
+  .glass-effect {
+    background: rgba(255, 255, 255, 0.6);
+  }
+  .glass-dark {
+    background: rgba(0, 0, 0, 0.6);
+  }
+}

86-104: Add visible focus styles for keyboard users on .btn-eco

Improve accessibility and compliance by styling focus-visible.

 .btn-eco {
   background: linear-gradient(135deg, #10b981 0%, #059669 100%);
@@
   cursor: pointer;
 }
 
 .btn-eco:hover {
   transform: translateY(-2px);
   box-shadow: 0 8px 25px rgba(16, 185, 129, 0.3);
 }
+
+.btn-eco:focus-visible {
+  outline: 3px solid rgba(34, 197, 94, 0.7);
+  outline-offset: 2px;
+}

124-133: Tokenize shadows/spacing via CSS variables for consistency

Optional: promote shadow and radius tokens to :root to keep design consistent with --eco-* palette.

src/index.css (2)

2-6: Import order may cause unintended overrides with Tailwind

Custom CSS before Tailwind can be overridden by Tailwind’s layers. Either (1) move the import after @tailwind utilities or (2) wrap classes in enhanced-ui.css with @layer components/utilities. Option (1) shown below.

 @import url('https://fonts.googleapis.com/css2?family=Baloo+2:wght@400..800&display=swap');
-@import './styles/enhanced-ui.css';
 
 @tailwind base;
 @tailwind components;
 @tailwind utilities;
 
+@import './styles/enhanced-ui.css';

To confirm no regressions due to cascade, inspect a few elements using .btn-eco or .card-modern after this change.


9-29: Scrollbar styling: add Firefox support and eco tokens

Broaden compatibility and align to theme variables.

+/* Firefox */
+* {
+  scrollbar-width: thin;
+  scrollbar-color: var(--eco-primary, #10b981) transparent;
+}
 /* WebKit */
 ::-webkit-scrollbar {
   width: 8px;
 }
@@
 ::-webkit-scrollbar-thumb {
-  background: linear-gradient(rgb(20, 83, 45), #d6a075);
+  background: linear-gradient(var(--eco-text, rgb(20, 83, 45)), #d6a075);
src/User/components/LoadingComponents/ProductCardSkeleton.jsx (2)

1-14: Prefer CSS shimmer and reduce motion-aware behavior

Using framer-motion for N skeleton blocks is heavier than a pure-CSS shimmer, and it ignores prefers-reduced-motion. Either swap to the global .skeleton class or gate animations via useReducedMotion.

-import { motion } from 'framer-motion';
+import { motion, useReducedMotion } from 'framer-motion';
@@
 const ProductCardSkeleton = () => {
-  const shimmerVariants = {
+  const prefersReducedMotion = useReducedMotion();
+  const shimmerVariants = {
     animate: {
-      x: [-100, 100],
+      x: prefersReducedMotion ? 0 : [-100, 100],
       transition: {
-        repeat: Infinity,
-        duration: 1.5,
+        repeat: prefersReducedMotion ? 0 : Infinity,
+        duration: prefersReducedMotion ? 0 : 1.5,
         ease: "easeInOut"
       }
     }
   };

30-36: Mark all decorative shimmer layers and dots as aria-hidden

Prevents noisy announcements in screen readers.

-          <motion.div
+          <motion.div
             variants={shimmerVariants}
             animate="animate"
-            className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
+            aria-hidden="true"
+            className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
           />
@@
-            <motion.div
+            <motion.div
               variants={shimmerVariants}
               animate="animate"
-              className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
+              aria-hidden="true"
+              className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
             />
@@
-            <div key={i} className="w-3 h-3 bg-gray-200 rounded" />
+            <div key={i} className="w-3 h-3 bg-gray-200 rounded" aria-hidden="true" />
@@
-          <motion.div
+          <motion.div
             variants={shimmerVariants}
             animate="animate"
-            className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
+            aria-hidden="true"
+            className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
           />
@@
-          <motion.div
+          <motion.div
             variants={shimmerVariants}
             animate="animate"
-            className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
+            aria-hidden="true"
+            className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
           />

Also applies to: 40-53, 65-78

src/context/AuthContext.jsx (3)

1-1: Import useEffect for persistence sync

-import React, { createContext, useState, useContext } from 'react';
+import React, { createContext, useState, useContext, useEffect } from 'react';

27-35: Optional: add a single effect to keep storage in sync

If you prefer centralization over handler writes, add this effect and drop per-handler storage writes.

+  useEffect(() => {
+    localStorage.setItem('isAdmin', String(isAdmin));
+    localStorage.setItem('isLoggedIn', String(isLoggedIn));
+    if (user) localStorage.setItem('user', JSON.stringify(user));
+    else localStorage.removeItem('user');
+  }, [isAdmin, isLoggedIn, user]);

27-35: Expose a stable context value to reduce re-renders

Optional: memoize the context value to avoid unnecessary subtree renders on stable refs.

-  return (
-    <AuthContext.Provider value={{ 
-      isAdmin, 
-      isLoggedIn, 
-      user, 
-      loginAsAdmin, 
-      loginAsUser, 
-      logout 
-    }}>
+  const value = React.useMemo(() => ({
+    isAdmin, isLoggedIn, user, loginAsAdmin, loginAsUser, logout
+  }), [isAdmin, isLoggedIn, user]);
+  return (
+    <AuthContext.Provider value={value}>
       {children}
     </AuthContext.Provider>
   );
src/User/components/LoadingComponents/PageLoader.jsx (1)

65-75: Brand copy nit: consider using app name via config

If the project name changes, β€œLoading VigyBag” hard-codes a string. Pull from a config/env for reuse.

src/User/components/EnhancedHero/EnhancedHero.jsx (3)

6-6: β€œLearn More” is inert. Expose a handler prop to wire navigation.

-const EnhancedHero = ({ onShopNowClick }) => {
+const EnhancedHero = ({ onShopNowClick, onLearnMoreClick }) => {
-            <motion.button
+            <motion.button
+              onClick={onLearnMoreClick}
               className="border-2 border-green-600 text-green-700 px-8 py-4 rounded-full text-lg font-semibold hover:bg-green-50"
               whileHover={{ scale: 1.05 }}
               whileTap={{ scale: 0.95 }}
               transition={{ type: "spring", stiffness: 300 }}
             >
               Learn More
             </motion.button>

Also applies to: 151-158


22-51: Minor: Hoist static variants/constants outside the component to avoid re-creation on every render.


161-198: Hard-coded stats could mislead; consider props or CMS-driven values.

Would you like a quick refactor to accept stats via props with sensible defaults?

src/User/components/EnhancedButtons/AnimatedButton.jsx (4)

43-51: Remove unused rippleVariants.

-  const rippleVariants = {
-    initial: { scale: 0, opacity: 0.5 },
-    animate: {
-      scale: 4,
-      opacity: 0,
-      transition: { duration: 0.6, ease: 'easeOut' }
-    }
-  };

109-116: Avoid Next.js-specific <style jsx>; use a plain style tag or move keyframes to CSS.

-      <style jsx>{`
+      <style>{`
         @keyframes ripple {
           to {
             transform: scale(4);
             opacity: 0;
           }
         }
       `}</style>

If the project uses styled-jsx, ignore; otherwise this prevents an odd jsx attribute on <style>.


84-87: Guard against unknown variant keys.

-      className={`${baseClasses} ${variants[variant]} ${sizes[size]} ${className} ${
+      className={`${baseClasses} ${(variants[variant] || variants.primary)} ${sizes[size]} ${className} ${
         disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
       }`}

24-31: Optional: expose semantic variants via data-attributes for theming; current strings are fine but hard to override.

src/User/components/ModernNavbar/ModernNavbar.jsx (4)

81-105: Active tab check is strict equality; nested routes won’t highlight.

-            {navItems.map((item) => (
+            {navItems.map((item) => {
+              const isActive = location.pathname === item.path || location.pathname.startsWith(item.path + '/');
+              return (
               <Link
                 key={item.name}
                 to={item.path}
                 className="relative group"
               >
                 <motion.span
                   className={`text-gray-700 hover:text-green-600 font-medium transition-colors ${
-                    location.pathname === item.path ? 'text-green-600' : ''
+                    isActive ? 'text-green-600' : ''
                   }`}
                   whileHover={{ y: -2 }}
                   transition={{ type: 'spring', stiffness: 300 }}
                 >
                   {item.name}
                 </motion.span>
-                {location.pathname === item.path && (
+                {isActive && (
                   <motion.div
                     className="absolute -bottom-1 left-0 right-0 h-0.5 bg-green-600"
                     layoutId="activeTab"
                     transition={{ type: 'spring', stiffness: 300, damping: 30 }}
                   />
                 )}
               </Link>
-            ))}
+            )})}

128-173: Wishlist/Cart/Login actions don’t navigate; wire to routes.

-            <motion.button
+            <motion.button
               className="relative p-2 text-gray-600 hover:text-green-600 transition-colors"
               whileHover={{ scale: 1.1 }}
               whileTap={{ scale: 0.9 }}
+              onClick={() => (window.location.href = '/wishlist')}
             >
...
-            <motion.button
+            <motion.button
               className="relative p-2 text-gray-600 hover:text-green-600 transition-colors"
               whileHover={{ scale: 1.1 }}
               whileTap={{ scale: 0.9 }}
+              onClick={() => (window.location.href = '/cart')}
             >
...
-            <motion.button
+            <motion.button
               className="hidden md:flex items-center space-x-2 bg-green-600 text-white px-4 py-2 rounded-full hover:bg-green-700 transition-colors"
               whileHover={{ scale: 1.05 }}
               whileTap={{ scale: 0.95 }}
+              onClick={() => (window.location.href = '/auth')}
             >

Prefer using useNavigate, or convert to motion(Link) for better SPA navigation.


116-125: Add basic a11y: label the search and annotate the menu toggle.

-              <input
+              <input
                 type="text"
                 placeholder="Search eco-friendly products..."
                 value={searchQuery}
                 onChange={(e) => setSearchQuery(e.target.value)}
                 onFocus={() => setIsSearchFocused(true)}
                 onBlur={() => setIsSearchFocused(false)}
+                aria-label="Search products"
                 className="w-full pl-10 pr-4 py-2 border border-gray-200 rounded-full focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent bg-white/80 backdrop-blur-sm"
               />
-            <motion.button
+            <motion.button
               className="lg:hidden p-2 text-gray-600"
               onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
               whileTap={{ scale: 0.9 }}
+              aria-label="Toggle menu"
+              aria-expanded={isMobileMenuOpen}
+              aria-controls="mobile-menu"
             >

Also add id="mobile-menu" to the drawer container if desired.

Also applies to: 164-171


14-20: Minor: throttle scroll handler or use passive listener to reduce main-thread work on scroll-heavy pages.

src/User/components/ProductCard/ProductCard.jsx (2)

10-15: Use consistent notifications (toast) instead of blocking alerts

The rest of the app uses react-hot-toast; align for consistency and better UX.

Proposed change:

-import { useNavigate } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
+import toast from "react-hot-toast";
...
-    if (!isLoggedIn) {
-      alert("Please login to add items to your cart!");
+    if (!isLoggedIn) {
+      toast.error("Please login to add items to your cart!");
       navigate("/auth");
       return;
     }
-    // Add to cart logic here
-    alert(`${title} added to cart!`);
+    // Add to cart logic here
+    toast.success(`${title} added to cart!`);

41-58: Accessibility: add an aria-label to the button

Improves screen-reader clarity.

-        <button
+        <button
+          aria-label="Add to bag"
           onClick={handleAddToCart}
src/User/components/Popular_Categories/ProductGrid.jsx (3)

139-148: Minor: avoid repeated lookups for cart membership

Compute once for readability and tiny perf win.

-          <button
+          {(() => { const inCart = !!cartItems.find((item) => item.id === product.id); return (
+          <button
             className="mt-1 bg-[#166635ff] text-white px-4 py-2 rounded text-sm w-full hover:bg-[#3d9970ff] transition-colors disabled:opacity-45 disabled:pointer-events-none"
             onClick={() => {
               onAddToCart(product);
             }}
-            disabled={cartItems.find((item) => item.id === product.id)}>
-            {cartItems.find((item) => item.id === product.id)
+            disabled={inCart}>
+            {inCart
               ? "Added"
               : "Add to Cart"}
           </button>
+          )})()}

77-105: DRY up auth gating for wishlist actions

The login checks are duplicated in both branches. Extract a guard to reduce repetition.

+  const requireLogin = (fn) => {
+    if (!isLoggedIn) {
+      toast.error("Please login to manage wishlist!");
+      navigate("/auth");
+      return;
+    }
+    fn();
+  };
...
-          onClick={() => {
-            if (!isLoggedIn) {
-              toast.error("Please login to manage wishlist!");
-              navigate("/auth");
-              return;
-            }
-            onAddToWishlist(product);
-            toast.success("Item removed from wishlist!");
-          }}>
+          onClick={() =>
+            requireLogin(() => {
+              onAddToWishlist(product);
+              toast.success("Item removed from wishlist!");
+            })
+          }>
...
-          onClick={() => {
-            if (!isLoggedIn) {
-              toast.error("Please login to add items to wishlist!");
-              navigate("/auth");
-              return;
-            }
-            onAddToWishlist(product);
-            toast.success("Item added to wishlist!");
-          }}>
+          onClick={() =>
+            requireLogin(() => {
+              onAddToWishlist(product);
+              toast.success("Item added to wishlist!");
+            })
+          }>

8-9: Unused import PaymentPage

Remove to keep things tidy.

-import PaymentPage from "../../pages/Payment/Payment";
src/User/components/EnhancedProductCard/EnhancedProductCard.jsx (4)

147-153: No add-to-cart handler wired

Button does nothing. Either accept an onAddToCart(product) prop or integrate with Redux to dispatch manageCartItem.

Example (prop-driven, non-breaking for current Home usage):

-const EnhancedProductCard = ({ product }) => {
+const EnhancedProductCard = ({ product, onAddToCart }) => {
...
-          <motion.button
+          <motion.button
             className="bg-green-600 text-white px-4 py-2 rounded-full text-sm font-semibold hover:bg-green-700"
             whileHover={{ scale: 1.05 }}
             whileTap={{ scale: 0.95 }}
+            onClick={() => onAddToCart?.(product)}
           >
             Add to Cart
           </motion.button>

I can also provide a Redux-wired variant if you prefer.


128-138: Static rating; derive from data or provide sensible fallback

Hardcoded β€œ(4.2)” and 4 filled stars may mislead.

-          {[...Array(5)].map((_, i) => (
+          {(() => {
+            const rating = Number(product?.rating ?? 4.2);
+            const stars = Math.max(0, Math.min(5, Math.round(rating)));
+            return [...Array(5)].map((_, i) => (
             <FaStar
               key={i}
               size={12}
-              className={i < 4 ? 'text-yellow-400' : 'text-gray-300'}
+              className={i < stars ? 'text-yellow-400' : 'text-gray-300'}
             />
-          ))}
-          <span className="text-xs text-gray-500 ml-1">(4.2)</span>
+          )})()}
+          <span className="text-xs text-gray-500 ml-1">({Math.round(Number(product?.rating ?? 4.2))})</span>

141-145: Static price; read from product with graceful default

Avoid showing β‚Ή299/β‚Ή399 for all items.

-            <span className="text-lg font-bold text-green-600">β‚Ή299</span>
-            <span className="text-sm text-gray-400 line-through">β‚Ή399</span>
+            <span className="text-lg font-bold text-green-600">β‚Ή{product?.price ?? 299}</span>
+            <span className="text-sm text-gray-400 line-through">β‚Ή{product?.originalPrice ?? product?.mrp ?? 399}</span>

54-63: Add aria-pressed and aria-label to wishlist toggle

Improves accessibility.

-      <motion.button
+      <motion.button
         className={`absolute top-3 right-3 z-20 p-2 rounded-full ${
           isWishlisted ? 'bg-red-500 text-white' : 'bg-white/80 text-gray-600'
         } shadow-md`}
         whileHover={{ scale: 1.1 }}
         whileTap={{ scale: 0.9 }}
         onClick={() => setIsWishlisted(!isWishlisted)}
+        aria-pressed={isWishlisted}
+        aria-label={isWishlisted ? "Remove from wishlist" : "Add to wishlist"}
       >
src/User/pages/Home/Home.jsx (4)

6-8: Remove unused import LatestInMarketCard

It’s no longer used after switching to EnhancedProductCard.

-import LatestInMarketCard from "../../components/HomPageCard/LatestInMarketCard";

264-281: Consider passing handlers into EnhancedProductCard

Right now cards render purely visual UI. If you adopt the onAddToCart/onView props as suggested, wire them here.

Example:

-                    <EnhancedProductCard product={product} />
+                    <EnhancedProductCard
+                      product={product}
+                      onAddToCart={() => {/* dispatch/manageCartItem here */}}
+                    />

I can wire this to Redux with a small helper.


15-23: Optional: move static data to a config module

popularCategories/latestProducts can live in a constants file to keep Home lean.


30-31: DownArrow import appears unused

Remove if not used later.

-import DownArrow from "../../components/DownArrow/downArrow";
src/User/components/EnhancedSearch/SmartSearchBar.jsx (6)

25-35: Initialize recent searches from localStorage on mount.

You persist recent searches but never hydrate them, so the dropdown’s β€œRecent Searches” starts empty on reload.

Apply this diff above the filtering useEffect:

+  // Load recent searches from localStorage
+  useEffect(() => {
+    try {
+      const saved = JSON.parse(localStorage.getItem('recentSearches') || '[]');
+      if (Array.isArray(saved)) setRecentSearches(saved.slice(0, 5));
+    } catch {
+      // ignore storage read errors (private mode/quota)
+    }
+  }, []);

61-65: Use onKeyDown instead of deprecated onKeyPress.

onKeyPress is deprecated; switch to onKeyDown for reliability across React versions.

-  const handleKeyPress = (e) => {
+  const handleKeyDown = (e) => {
     if (e.key === 'Enter') {
       handleSearch(query);
     }
   };
@@
-          onKeyPress={handleKeyPress}
+          onKeyDown={handleKeyDown}

Also applies to: 111-121


111-121: Lightweight a11y: add combobox semantics.

Expose dropdown state to assistive tech and label options.

         <input
           ref={inputRef}
           type="text"
           value={query}
           onChange={(e) => setQuery(e.target.value)}
           onFocus={() => setIsActive(true)}
-          onKeyPress={handleKeyPress}
+          onKeyDown={handleKeyDown}
           placeholder={placeholder}
-          className="w-full pl-12 pr-12 py-4 text-gray-800 placeholder-gray-500 focus:outline-none bg-transparent"
+          className="w-full pl-12 pr-12 py-4 text-gray-800 placeholder-gray-500 focus:outline-none bg-transparent"
+          role="combobox"
+          aria-expanded={isActive}
+          aria-controls="smart-search-dropdown"
+          aria-autocomplete="list"
         />
@@
-          <motion.div
+          <motion.div
+            id="smart-search-dropdown"
             variants={dropdownVariants}
             initial="hidden"
             animate="visible"
             exit="hidden"
             className="absolute top-full left-0 right-0 mt-2 bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden z-50"
           >
@@
-                  {suggestions.map((item) => (
+                  {suggestions.map((item) => (
                     <motion.div
                       key={item.id}
-                      className="flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 cursor-pointer group"
+                      className="flex items-center justify-between p-3 rounded-lg hover:bg-gray-50 cursor-pointer group"
+                      role="option"
+                      tabIndex={0}
                       whileHover={{ x: 4 }}
                       onClick={() => handleSearch(item.name)}
                     >

Also applies to: 149-158, 167-173


48-56: Guard localStorage writes.

localStorage.setItem can throw (private mode/quota). Wrap in try/catch.

-      localStorage.setItem('recentSearches', JSON.stringify(newRecentSearches));
+      try {
+        localStorage.setItem('recentSearches', JSON.stringify(newRecentSearches));
+      } catch {}

138-146: Remove or wire the spinner; currently dead code.

The spinner is always display:none. Either control it with a loading flag or remove it.

-        {/* Loading Indicator */}
-        <div className="absolute right-4 top-1/2 transform -translate-y-1/2">
-          <motion.div
-            className="w-5 h-5 border-2 border-green-500 border-t-transparent rounded-full"
-            animate={{ rotate: 360 }}
-            transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
-            style={{ display: 'none' }} // Show when loading
-          />
-        </div>

1-24: Consolidate search bars to reduce duplication.

There are multiple search components in the repo (Dashboard/SearchBar.jsx, components/SearchBar.jsx, pages/Home/SearchBar.jsx). Consider a headless useSearch hook (debounce, persistence, suggestions) and a single shared SmartSearchBar to standardize UX and logic.

src/User/pages/UIShowcase/UIShowcase.jsx (2)

1-1: Avoid dangling timeouts for the loader.

setTimeout in onMouseLeave can stack and survive unmount. Keep a ref and clear on reuse/unmount.

-import React, { useState } from 'react';
+import React, { useState, useRef, useEffect } from 'react';
@@
-  const [showLoader, setShowLoader] = useState(false);
+  const [showLoader, setShowLoader] = useState(false);
+  const loaderTimerRef = useRef(null);
+  useEffect(() => {
+    return () => {
+      if (loaderTimerRef.current) clearTimeout(loaderTimerRef.current);
+    };
+  }, []);
@@
-                <AnimatedButton 
-                  variant="danger" 
-                  onClick={() => setShowLoader(true)}
-                  onMouseLeave={() => setTimeout(() => setShowLoader(false), 2000)}
-                >
+                <AnimatedButton 
+                  variant="danger" 
+                  onClick={() => setShowLoader(true)}
+                  onMouseLeave={() => {
+                    if (loaderTimerRef.current) clearTimeout(loaderTimerRef.current);
+                    loaderTimerRef.current = setTimeout(() => setShowLoader(false), 2000);
+                  }}
+                >

Also applies to: 12-14, 209-215


286-288: Wire β€œBack to Home” to navigation (optional).

Hook this to routing so the CTA does something in the showcase.

Example with react-router:

-          <AnimatedButton variant="secondary" size="lg">
-            Back to Home
-          </AnimatedButton>
+          <AnimatedButton variant="secondary" size="lg" onClick={() => window.location.assign('/')}>
+            Back to Home
+          </AnimatedButton>

(Or use useNavigate if react-router is available.)

πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ’‘ Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 36ca86e and b0bf960.

πŸ“’ Files selected for processing (19)
  • README.md (1 hunks)
  • src/User/components/EnhancedButtons/AnimatedButton.jsx (1 hunks)
  • src/User/components/EnhancedHero/EnhancedHero.jsx (1 hunks)
  • src/User/components/EnhancedProductCard/EnhancedProductCard.jsx (1 hunks)
  • src/User/components/EnhancedSearch/SmartSearchBar.jsx (1 hunks)
  • src/User/components/Footer/Footer.jsx (2 hunks)
  • src/User/components/LoadingComponents/PageLoader.jsx (1 hunks)
  • src/User/components/LoadingComponents/ProductCardSkeleton.jsx (1 hunks)
  • src/User/components/ModernNavbar/ModernNavbar.jsx (1 hunks)
  • src/User/components/Popular_Categories/ProductGrid.jsx (5 hunks)
  • src/User/components/ProductCard/ProductCard.jsx (2 hunks)
  • src/User/pages/Contributors/Contributors.jsx (3 hunks)
  • src/User/pages/Help/Help.jsx (2 hunks)
  • src/User/pages/Home/Home.jsx (3 hunks)
  • src/User/pages/UIShowcase/UIShowcase.jsx (1 hunks)
  • src/User/pages/UserAuth/UserAuth.jsx (1 hunks)
  • src/context/AuthContext.jsx (1 hunks)
  • src/index.css (1 hunks)
  • src/styles/enhanced-ui.css (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
src/User/components/Popular_Categories/ProductGrid.jsx (3)
src/User/components/Navbar/UserNavbar.jsx (1)
  • isLoggedIn (22-22)
src/User/pages/Dashboard/dashboard-cart.jsx (1)
  • isLoggedIn (168-168)
src/AdminRoute.jsx (1)
  • isLoggedIn (5-17)
src/User/components/LoadingComponents/ProductCardSkeleton.jsx (1)
src/User/components/HomPageCard/LatestInMarketCard.jsx (1)
  • LatestInMarketCard (4-110)
src/User/components/EnhancedHero/EnhancedHero.jsx (2)
src/User/components/About/Header.jsx (1)
  • Header (4-28)
src/User/components/About/ServiceHeader.jsx (1)
  • Header (4-25)
src/User/components/ModernNavbar/ModernNavbar.jsx (2)
src/User/components/Navbar/MobileMenu.jsx (1)
  • div (6-104)
src/User/components/Navbar/UserNavbar.jsx (1)
  • isOpen (12-264)
src/User/pages/UserAuth/UserAuth.jsx (2)
src/User/pages/TermsAndCondition/TermsAndCondition.jsx (1)
  • useEffect (4-173)
src/User/pages/Privacy-Policy/Privacy.jsx (1)
  • useEffect (7-384)
src/User/components/LoadingComponents/PageLoader.jsx (1)
src/User/components/progressbar/Loader.jsx (1)
  • TopLoader (4-14)
src/User/pages/Contributors/Contributors.jsx (2)
src/User/components/Team/Team.jsx (1)
  • contributor (323-341)
src/User/pages/MeetTheMakers/MeetTheMakers.jsx (1)
  • MeetTheMakers (236-457)
src/User/components/ProductCard/ProductCard.jsx (2)
src/User/components/HomPageCard/LatestInMarketCard.jsx (1)
  • LatestInMarketCard (4-110)
src/User/components/Products/ProductDetails.jsx (1)
  • dispatch (113-157)
src/User/components/EnhancedProductCard/EnhancedProductCard.jsx (1)
src/User/components/HomPageCard/LatestInMarketCard.jsx (1)
  • LatestInMarketCard (4-110)
src/User/components/EnhancedSearch/SmartSearchBar.jsx (4)
src/User/components/Dashboard/SearchBar.jsx (1)
  • div (4-15)
src/User/components/SearchBar/SearchBar.jsx (1)
  • div (4-31)
src/User/pages/Home/SearchBar.jsx (1)
  • div (4-28)
src/Admin/Pages/AdminPanel.jsx (1)
  • searchTerm (11-93)
src/context/AuthContext.jsx (3)
src/AdminRoute.jsx (1)
  • isLoggedIn (5-17)
src/User/components/Navbar/AuthButton.jsx (1)
  • isLoggedIn (6-25)
src/User/components/Buttons/Logout.jsx (1)
  • Logout (4-32)
src/User/pages/Help/Help.jsx (1)
src/User/pages/FAQ/Faq.jsx (1)
  • App (99-134)
src/User/pages/Home/Home.jsx (1)
src/User/components/HomPageCard/LatestInMarketCard.jsx (1)
  • LatestInMarketCard (4-110)
πŸ”‡ Additional comments (9)
src/User/components/Footer/Footer.jsx (1)

9-9: Adding GitHub icon import: LGTM.

src/User/pages/Help/Help.jsx (1)

178-178: Closing wrapper fixes prior layout bleed: LGTM.

src/User/pages/Contributors/Contributors.jsx (1)

1-1: Importing useState: LGTM.

src/User/components/ModernNavbar/ModernNavbar.jsx (2)

137-151: Hard-coded badge counts (β€œ3”, β€œ2”).

Bind to real wishlist/cart counts (context/store) and hide when zero.


59-67: Scope alignment check.

This component overlaps with existing Navbar components. Confirm intended replacement vs. coexistence and update routes/tests accordingly to avoid duplicate navs or inconsistent menus.

src/User/components/ProductCard/ProductCard.jsx (1)

7-9: AuthProvider wrapper confirmed
AuthProvider in src/App.jsx (lines 88–261) wraps the entire app, including ProductCard, so useAuth is safely provided.

src/User/components/EnhancedProductCard/EnhancedProductCard.jsx (1)

1-4: No action required: β€˜framer-motion’ is listed in dependencies (version ^12.0.5).

src/User/pages/Home/Home.jsx (2)

140-149: Loading simulation is fine; ensure no leakage on unmount

You’ve already cleared the timer in cleanup. LGTM.


9-10: framer-motion dependency confirmed
package.json lists "framer-motion": "^12.0.5".

Comment on lines 6 to 9
const [isAdmin, setIsAdmin] = useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [user, setUser] = useState(null);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Initialize from localStorage to avoid auth desyncs

Other parts of the app read isLoggedIn/isAdmin from localStorage. Without initializing from it, routes may mis-gate users after refresh.

-  const [isAdmin, setIsAdmin] = useState(false);
-  const [isLoggedIn, setIsLoggedIn] = useState(false);
-  const [user, setUser] = useState(null);
+  const [isAdmin, setIsAdmin] = useState(() => localStorage.getItem('isAdmin') === 'true');
+  const [isLoggedIn, setIsLoggedIn] = useState(() => localStorage.getItem('isLoggedIn') === 'true');
+  const [user, setUser] = useState(() => {
+    try {
+      const raw = localStorage.getItem('user');
+      return raw ? JSON.parse(raw) : null;
+    } catch {
+      return null;
+    }
+  });
πŸ“ Committable suggestion

‼️ 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.

Suggested change
const [isAdmin, setIsAdmin] = useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [user, setUser] = useState(null);
const [isAdmin, setIsAdmin] = useState(() => localStorage.getItem('isAdmin') === 'true');
const [isLoggedIn, setIsLoggedIn] = useState(() => localStorage.getItem('isLoggedIn') === 'true');
const [user, setUser] = useState(() => {
try {
const raw = localStorage.getItem('user');
return raw ? JSON.parse(raw) : null;
} catch {
return null;
}
});
πŸ€– Prompt for AI Agents
In src/context/AuthContext.jsx around lines 6 to 9, the isAdmin/isLoggedIn/user
state variables are initialized to static defaults which can desync from values
stored in localStorage; change the useState initializers to read existing values
from localStorage (using lazy initializer functions) β€” parse booleans and JSON
safely, provide sensible fallbacks (false/null) if keys are missing or parsing
fails, and ensure any updates to these states also write back to localStorage to
keep them in sync.

Comment on lines +10 to +25
const loginAsAdmin = () => {
setIsAdmin(true);
setIsLoggedIn(true);
};

const loginAsUser = (userData = null) => {
setIsAdmin(false);
setIsLoggedIn(true);
setUser(userData);
};

const logout = () => {
setIsAdmin(false);
setIsLoggedIn(false);
setUser(null);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Persist changes to localStorage in login/logout handlers

Keeps AdminRoute, Navbar, and other consumers consistent across refreshes.

-  const loginAsAdmin = () => {
-    setIsAdmin(true);
-    setIsLoggedIn(true);
-  };
+  const loginAsAdmin = () => {
+    setIsAdmin(true);
+    setIsLoggedIn(true);
+    localStorage.setItem('isAdmin', 'true');
+    localStorage.setItem('isLoggedIn', 'true');
+  };
@@
-  const loginAsUser = (userData = null) => {
-    setIsAdmin(false);
-    setIsLoggedIn(true);
-    setUser(userData);
-  };
+  const loginAsUser = (userData = null) => {
+    setIsAdmin(false);
+    setIsLoggedIn(true);
+    setUser(userData);
+    localStorage.setItem('isAdmin', 'false');
+    localStorage.setItem('isLoggedIn', 'true');
+    if (userData) localStorage.setItem('user', JSON.stringify(userData));
+  };
@@
-  const logout = () => {
-    setIsAdmin(false);
-    setIsLoggedIn(false);
-    setUser(null);
-  };
+  const logout = () => {
+    setIsAdmin(false);
+    setIsLoggedIn(false);
+    setUser(null);
+    localStorage.setItem('isAdmin', 'false');
+    localStorage.setItem('isLoggedIn', 'false');
+    localStorage.removeItem('user');
+  };
πŸ“ Committable suggestion

‼️ 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.

Suggested change
const loginAsAdmin = () => {
setIsAdmin(true);
setIsLoggedIn(true);
};
const loginAsUser = (userData = null) => {
setIsAdmin(false);
setIsLoggedIn(true);
setUser(userData);
};
const logout = () => {
setIsAdmin(false);
setIsLoggedIn(false);
setUser(null);
};
const loginAsAdmin = () => {
setIsAdmin(true);
setIsLoggedIn(true);
localStorage.setItem('isAdmin', 'true');
localStorage.setItem('isLoggedIn', 'true');
};
const loginAsUser = (userData = null) => {
setIsAdmin(false);
setIsLoggedIn(true);
setUser(userData);
localStorage.setItem('isAdmin', 'false');
localStorage.setItem('isLoggedIn', 'true');
if (userData) localStorage.setItem('user', JSON.stringify(userData));
};
const logout = () => {
setIsAdmin(false);
setIsLoggedIn(false);
setUser(null);
localStorage.setItem('isAdmin', 'false');
localStorage.setItem('isLoggedIn', 'false');
localStorage.removeItem('user');
};
πŸ€– Prompt for AI Agents
In src/context/AuthContext.jsx around lines 10 to 25, the loginAsAdmin,
loginAsUser, and logout handlers update state but do not persist those changes
to localStorage; update each handler to write the relevant keys to localStorage
(e.g., set "isAdmin" and "isLoggedIn" as strings and "user" as a JSON string in
loginAsAdmin/loginAsUser) and ensure logout clears or removes those keys
(removeItem or set to null) so state survives page refreshes and consumers stay
consistent.

Comment on lines +37 to +71
/* Animations */
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-20px); }
}

@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}

@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

/* Utility Classes */
.animate-float {
animation: float 3s ease-in-out infinite;
}

.animate-shimmer {
animation: shimmer 2s infinite;
}

.animate-fade-in-up {
animation: fadeInUp 0.6s ease-out;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Honor prefers-reduced-motion for animations and skeletons

Provide a motion-reduced experience to avoid accessibility issues.

 @keyframes float {
   0%, 100% { transform: translateY(0px); }
   50% { transform: translateY(-20px); }
 }
@@
 .animate-float {
   animation: float 3s ease-in-out infinite;
 }
@@
 .animate-shimmer {
   animation: shimmer 2s infinite;
 }
@@
 .animate-fade-in-up {
   animation: fadeInUp 0.6s ease-out;
 }
@@
 .skeleton {
   background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
   background-size: 200% 100%;
   animation: shimmer 1.5s infinite;
 }
+
+@media (prefers-reduced-motion: reduce) {
+  .animate-float,
+  .animate-shimmer,
+  .animate-fade-in-up,
+  .skeleton {
+    animation: none !important;
+  }
+}

Also applies to: 105-110

πŸ€– Prompt for AI Agents
In src/styles/enhanced-ui.css around lines 37-71 (also apply same change for
lines ~105-110), the CSS animations don’t respect users’ prefers-reduced-motion
setting; add a media query @media (prefers-reduced-motion: reduce) that targets
the animated key classes (.animate-float, .animate-shimmer, .animate-fade-in-up
and any skeleton/shimmer classes used at 105-110) and override their animations
by setting animation: none !important; transform: none !important; and any
animated background-position to a static value so motion is removed while
preserving layout and accessibility.

Comment on lines +52 to +80
const handleClick = (e) => {
if (disabled) return;

// Create ripple effect
const button = e.currentTarget;
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;

const ripple = document.createElement('span');
ripple.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
width: ${size}px;
height: ${size}px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
`;

button.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);

if (onClick) onClick(e);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Center ripple for keyboard-initiated β€œclicks”; current math uses clientX/Y which are 0.

   const handleClick = (e) => {
     if (disabled) return;
     
     // Create ripple effect
     const button = e.currentTarget;
     const rect = button.getBoundingClientRect();
     const size = Math.max(rect.width, rect.height);
-    const x = e.clientX - rect.left - size / 2;
-    const y = e.clientY - rect.top - size / 2;
+    const isKeyboard = e.clientX === 0 && e.clientY === 0;
+    const x = isKeyboard ? rect.width / 2 - size / 2 : e.clientX - rect.left - size / 2;
+    const y = isKeyboard ? rect.height / 2 - size / 2 : e.clientY - rect.top - size / 2;
πŸ“ Committable suggestion

‼️ 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.

Suggested change
const handleClick = (e) => {
if (disabled) return;
// Create ripple effect
const button = e.currentTarget;
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
const ripple = document.createElement('span');
ripple.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
width: ${size}px;
height: ${size}px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
`;
button.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
if (onClick) onClick(e);
};
const handleClick = (e) => {
if (disabled) return;
// Create ripple effect
const button = e.currentTarget;
const rect = button.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const isKeyboard = e.clientX === 0 && e.clientY === 0;
- const x = e.clientX - rect.left - size / 2;
const x = isKeyboard
? rect.width / 2 - size / 2
: e.clientX - rect.left - size / 2;
const y = isKeyboard
? rect.height / 2 - size / 2
: e.clientY - rect.top - size / 2;
const ripple = document.createElement('span');
ripple.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
width: ${size}px;
height: ${size}px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
`;
button.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
if (onClick) onClick(e);
};
πŸ€– Prompt for AI Agents
In src/User/components/EnhancedButtons/AnimatedButton.jsx around lines 52 to 80,
the ripple position calculation uses e.clientX/Y which are 0 for
keyboard-initiated clicks so the ripple appears off-center; detect when
clientX/clientY are 0 (or not present) and fall back to centering the ripple by
using (rect.width - size)/2 and (rect.height - size)/2 for x and y respectively
before creating the span, leaving the rest of the ripple creation/removal and
onClick call unchanged.

Comment on lines +82 to +94
return (
<motion.button
className={`${baseClasses} ${variants[variant]} ${sizes[size]} ${className} ${
disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
}`}
variants={buttonVariants}
initial="initial"
whileHover={!disabled ? "hover" : "initial"}
whileTap={!disabled ? "tap" : "initial"}
onClick={handleClick}
disabled={disabled}
{...props}
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Default button type should be β€œbutton” to prevent accidental form submits.

-    <motion.button
+    <motion.button
+      type="button"
       className={`${baseClasses} ${variants[variant]} ${sizes[size]} ${className} ${
         disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
       }`}
πŸ“ Committable suggestion

‼️ 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.

Suggested change
return (
<motion.button
className={`${baseClasses} ${variants[variant]} ${sizes[size]} ${className} ${
disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
}`}
variants={buttonVariants}
initial="initial"
whileHover={!disabled ? "hover" : "initial"}
whileTap={!disabled ? "tap" : "initial"}
onClick={handleClick}
disabled={disabled}
{...props}
>
return (
<motion.button
type="button"
className={`${baseClasses} ${variants[variant]} ${sizes[size]} ${className} ${
disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
}`}
variants={buttonVariants}
initial="initial"
whileHover={!disabled ? "hover" : "initial"}
whileTap={!disabled ? "tap" : "initial"}
onClick={handleClick}
disabled={disabled}
{...props}
>
πŸ€– Prompt for AI Agents
In src/User/components/EnhancedButtons/AnimatedButton.jsx around lines 82 to 94,
the rendered motion.button lacks an explicit type which can cause accidental
form submissions; set a default type of "button" on the element (e.g., pass
type={type || 'button'} or ensure props.type is respected while defaulting to
'button') so the button doesn't submit forms unless explicitly specified.

Comment on lines +37 to +44
return (
<div className="fixed inset-0 bg-white/90 backdrop-blur-sm flex items-center justify-center z-50">
<motion.div
variants={containerVariants}
animate="animate"
className="text-center"
>
{/* Animated Leaves */}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

A11y: announce loading, hide decoratives, and add reduced motion

Add role/aria attributes, remove ineffective style-based animationDelay, and respect prefers-reduced-motion.

-import React from 'react';
-import { motion } from 'framer-motion';
+import React from 'react';
+import { motion, useReducedMotion } from 'framer-motion';
@@
-const PageLoader = () => {
+const PageLoader = () => {
+  const prefersReducedMotion = useReducedMotion();
   const containerVariants = {
     animate: {
       transition: {
         staggerChildren: 0.2
       }
     }
   };
@@
-  const leafVariants = {
-    animate: {
-      y: [0, -20, 0],
-      rotate: [0, 10, -10, 0],
-      transition: {
-        duration: 2,
-        repeat: Infinity,
-        ease: "easeInOut"
-      }
-    }
-  };
+  const leafVariants = {
+    animate: (i = 0) => ({
+      y: prefersReducedMotion ? 0 : [0, -20, 0],
+      rotate: prefersReducedMotion ? 0 : [0, 10, -10, 0],
+      transition: {
+        duration: prefersReducedMotion ? 0 : 2,
+        repeat: prefersReducedMotion ? 0 : Infinity,
+        ease: "easeInOut",
+        delay: i * 0.2
+      }
+    })
+  };
@@
   return (
-    <div className="fixed inset-0 bg-white/90 backdrop-blur-sm flex items-center justify-center z-50">
+    <div
+      className="fixed inset-0 bg-white/90 backdrop-blur-sm flex items-center justify-center z-50"
+      role="status"
+      aria-live="polite"
+      aria-label="Loading"
+      aria-busy="true"
+    >
@@
-        <div className="flex justify-center space-x-2 mb-6">
+        <div className="flex justify-center space-x-2 mb-6" aria-hidden="true">
           {[...Array(3)].map((_, i) => (
             <motion.div
               key={i}
-              variants={leafVariants}
-              animate="animate"
-              style={{ animationDelay: `${i * 0.2}s` }}
+              variants={leafVariants}
+              custom={i}
+              animate="animate"
               className="text-green-600"
             >
               <FaLeaf size={24} />
             </motion.div>
           ))}
         </div>
@@
-        <div className="w-64 h-2 bg-gray-200 rounded-full mt-6 overflow-hidden">
+        <div className="w-64 h-2 bg-gray-200 rounded-full mt-6 overflow-hidden" aria-hidden="true">
           <motion.div
             className="h-full bg-gradient-to-r from-green-400 to-green-600 rounded-full"
             animate={{
-              x: [-256, 256],
+              x: prefersReducedMotion ? 0 : [-256, 256],
               transition: {
-                duration: 2,
-                repeat: Infinity,
+                duration: prefersReducedMotion ? 0 : 2,
+                repeat: prefersReducedMotion ? 0 : Infinity,
                 ease: "easeInOut"
               }
             }}
           />
         </div>

Also applies to: 59-76, 77-90

πŸ€– Prompt for AI Agents
In src/User/components/LoadingComponents/PageLoader.jsx around lines 37-44 (and
similarly for 59-76 and 77-90), the loader lacks accessibility attributes, uses
inline style-based animationDelay on decorative elements, and doesn't respect
reduced-motion preferences; update the top wrapper to include role="status",
aria-live="polite" and aria-busy="true", mark purely decorative elements
(animated leaves) with aria-hidden="true" and remove the ineffective style-based
animationDelay from JSX, implement staggering via motion variants or CSS classes
instead, and integrate prefers-reduced-motion handling (e.g., use
framer-motion's useReducedMotion or
window.matchMedia("(prefers-reduced-motion)") to disable/short-circuit
animations and fall back to a static display). Ensure the same changes are
applied to the other referenced blocks (lines 59-76 and 77-90).

Comment on lines +16 to +25
return (
<div className="bg-white rounded-2xl shadow-lg overflow-hidden max-w-[280px] mx-auto">
{/* Image Skeleton */}
<div className="relative h-48 bg-gray-200 overflow-hidden">
<motion.div
variants={shimmerVariants}
animate="animate"
className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
/>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Add role and aria-live to announce loading state

Expose a single live region and hide decorative shimmers from AT.

-  return (
-    <div className="bg-white rounded-2xl shadow-lg overflow-hidden max-w-[280px] mx-auto">
+  return (
+    <div
+      className="bg-white rounded-2xl shadow-lg overflow-hidden max-w-[280px] mx-auto"
+      role="status"
+      aria-live="polite"
+      aria-label="Loading product"
+    >
@@
-        <motion.div
+        <motion.div
           variants={shimmerVariants}
           animate="animate"
-          className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
+          aria-hidden="true"
+          className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
         />
πŸ“ Committable suggestion

‼️ 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.

Suggested change
return (
<div className="bg-white rounded-2xl shadow-lg overflow-hidden max-w-[280px] mx-auto">
{/* Image Skeleton */}
<div className="relative h-48 bg-gray-200 overflow-hidden">
<motion.div
variants={shimmerVariants}
animate="animate"
className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
/>
</div>
return (
<div
className="bg-white rounded-2xl shadow-lg overflow-hidden max-w-[280px] mx-auto"
role="status"
aria-live="polite"
aria-label="Loading product"
>
{/* Image Skeleton */}
<div className="relative h-48 bg-gray-200 overflow-hidden">
<motion.div
variants={shimmerVariants}
animate="animate"
aria-hidden="true"
className="absolute inset-0 bg-gradient-to-r from-transparent via-white/60 to-transparent"
/>
</div>
πŸ€– Prompt for AI Agents
In src/User/components/LoadingComponents/ProductCardSkeleton.jsx around lines 16
to 25, the loading shimmers are currently exposed to assistive tech; add an
accessible live region and hide decorative elements: add a single visually
hidden element (e.g. a span with className="sr-only") at the top of the card
with role="status" aria-live="polite" aria-atomic="true" containing a short
message like "Loading product…" to announce the loading state, and mark the
decorative shimmer elements and the image skeleton container with
aria-hidden="true" so they are ignored by AT.

Comment on lines +22 to +28
const navItems = [
{ name: 'Home', path: '/' },
{ name: 'Categories', path: '/categories' },
{ name: 'Products', path: '/products' },
{ name: 'About', path: '/about-us' },
{ name: 'Contact', path: '/contact' }
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Nav routes likely don’t exist in this app; align with existing UserNavbar/MobileMenu routes to avoid 404s.

Based on existing components, consider updating defaults:

-  const navItems = [
-    { name: 'Home', path: '/' },
-    { name: 'Categories', path: '/categories' },
-    { name: 'Products', path: '/products' },
-    { name: 'About', path: '/about-us' },
-    { name: 'Contact', path: '/contact' }
-  ];
+  const navItems = [
+    { name: 'Home', path: '/' },
+    { name: 'Fashion', path: '/popularCategories/fashionAccessories' },
+    { name: 'Gifts', path: '/popularCategories/customizedGifts' },
+    { name: 'Furniture', path: '/popularCategories/furnitureDecor' },
+    { name: 'Stationary', path: '/popularCategories/printingStationery' },
+    { name: 'Body-Care', path: '/popularCategories/bodyCare' }
+  ];

Also consider startsWith matching for nested routes (see next comment).

πŸ“ Committable suggestion

‼️ 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.

Suggested change
const navItems = [
{ name: 'Home', path: '/' },
{ name: 'Categories', path: '/categories' },
{ name: 'Products', path: '/products' },
{ name: 'About', path: '/about-us' },
{ name: 'Contact', path: '/contact' }
];
const navItems = [
{ name: 'Home', path: '/' },
{ name: 'Fashion', path: '/popularCategories/fashionAccessories' },
{ name: 'Gifts', path: '/popularCategories/customizedGifts' },
{ name: 'Furniture', path: '/popularCategories/furnitureDecor' },
{ name: 'Stationary', path: '/popularCategories/printingStationery' },
{ name: 'Body-Care', path: '/popularCategories/bodyCare' }
];
πŸ€– Prompt for AI Agents
In src/User/components/ModernNavbar/ModernNavbar.jsx around lines 22–28, the
hardcoded navItems use routes (/, /categories, /products, /about-us, /contact)
that likely don’t exist in this app and will cause 404s; replace this array with
the exact route objects used by the existing UserNavbar and MobileMenu
components (open those files and copy their names/paths), and update any
active-link logic to use path.startsWith(route.path) for nested-route matching
so parent items stay active on child pages.

Comment on lines +39 to 40
const { isLoggedIn } = useAuth();
const cartItems = useSelector((state) => state.cart.items);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Verification agent

🧩 Analysis chain

Confirm AuthContext is available app-wide

Ensure isLoggedIn here is consistent with other places still using localStorage.


🏁 Script executed:

#!/bin/bash
# Find context provider and mixed sources of truth
rg -nP -C2 'AuthProvider|useAuth\(|localStorage\.getItem\(["\']isLoggedIn["\']\)' --type=tsx,ts,jsx,js

Length of output: 116


🏁 Script executed:

#!/bin/bash
# Search for AuthProvider definitions and usage
rg -n "AuthProvider" -C2 --type js,jsx,ts,tsx

# Search for useAuth() hook usage
rg -n "useAuth\s*\(" -C2 --type js,jsx,ts,tsx

# Search for localStorage.getItem/setItem for isLoggedIn
rg -n "localStorage\s*\.\s*(getItem|setItem)\(['\"]isLoggedIn['\"]\)" -C2 --type js,jsx,ts,tsx

Length of output: 308


🏁 Script executed:

#!/bin/bash
# Search for AuthProvider references
rg -n "AuthProvider" -C2 .

# Search for AuthContext definitions
rg -n "AuthContext" -C2 .

# Search for any createContext calls (React context)
rg -n "createContext" -C2 .

# Search for useAuth hook implementation
rg -n "useAuth" -C2 .

# Search for direct localStorage getItem/setItem of 'isLoggedIn'
rg -n "localStorage.*isLoggedIn" -C2 .

Length of output: 19886


Unify isLoggedIn state between Context and localStorage

  • AuthProvider in App.jsx wraps the entire app, so useAuth() is available app-wide.
  • AuthContext’s isLoggedIn isn’t initialized from or persisted to localStorage, yet numerous components (Navbar, PrivateRoute, UserAuth, Dashboard, etc.) still read directly from localStorage. Refactor AuthContext (e.g. in src/context/AuthContext.jsx) to load initial isLoggedIn from localStorage and write back on changes, then replace all direct localStorage.getItem/setItem("isLoggedIn") calls with useAuth().

Comment on lines +10 to +19
const handleAddToCart = () => {
if (!isLoggedIn) {
alert("Please login to add items to your cart!");
navigate("/auth");
return;
}

// Add to cart logic here
alert(`${title} added to cart!`);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Verification agent

🧩 Analysis chain

Misleading β€œadded to cart” UX: no cart state update happens

The handler only shows alerts and navigates; it never updates the Redux cart, so users get a success message without any effect.

Two safe pathsβ€”pick one and I can help wire it:

  • Option A (preferred): Accept an onAddToCart(product) prop and invoke it here.
  • Option B: Integrate Redux directly (import useDispatch and manageCartItem, dispatch with a proper product object).

If you choose Option B, confirm the expected product shape (id/title/image/price) before I propose a concrete diff.

Run to locate call sites and see how ProductCard is used:


🏁 Script executed:

#!/bin/bash
rg -nP --type=tsx,ts,jsx,js -C2 '\b<ProductCard\b'

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Locate the ProductCard component path
find . -type f -name "ProductCard.jsx"
# Search for any JSX usage of ProductCard in the codebase
rg -nC2 '<ProductCard' .

Length of output: 3736


🏁 Script executed:

#!/bin/bash
# Display the first 200 lines of the ProductCard component
sed -n '1,200p' src/User/components/ProductCard/ProductCard.jsx

# Check for Redux dispatch usage
rg -nC2 'useDispatch' src/User/components/ProductCard/ProductCard.jsx
rg -nC2 'dispatch' src/User/components/ProductCard/ProductCard.jsx

Length of output: 2032


Misleading β€œAdd to Bag” UX: no cart state update

File: src/User/components/ProductCard/ProductCard.jsx Lines 10–19

const handleAddToCart = () => {
  if (!isLoggedIn) {
    alert("Please login to add items to your cart!");
    navigate("/auth");
    return;
  }
  
  // Add to cart logic here
  alert(`${title} added to cart!`);
};

handleAddToCart only shows alerts and navigationβ€”it never updates any cart state. Fix by choosing one:

  • Preferred: accept an onAddToCart(product) prop and invoke it here.
  • Or: import useDispatch from react-redux and dispatch a manageCartItem action with the product (id/title/image/price).

Confirm your preferred path and I’ll draft the diff.

πŸ€– Prompt for AI Agents
In src/User/components/ProductCard/ProductCard.jsx around lines 10 to 19,
handleAddToCart currently only shows alerts and navigates but does not update
cart state; change it to call an onAddToCart(product) prop (preferred) β€” accept
onAddToCart in the component props, construct a product object (id, title,
image, price) or use the existing product prop, and invoke onAddToCart(product)
after the isLoggedIn check (keep the login alert/navigation behavior intact);
ensure you guard the call with typeof onAddToCart === 'function' before invoking
and remove or replace the temporary alert with a brief confirmation if desired.

@vercel
Copy link

vercel bot commented Dec 6, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
vigybag Ready Ready Preview Comment Dec 6, 2025 10:55am

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/User/pages/UserAuth/UserAuth.jsx (2)

43-43: Phone validation function is unused.

The isPhoneValid function is defined but never called in handleSignup. Consider validating the phone number before submitting the form to provide immediate feedback.

Apply this diff to add phone validation in the signup handler:

 const handleSignup = async (e) => {
   // Signup ka logic waise hi rahega
   e.preventDefault();
   setLoading(true);
   if (signupPassword !== confirmPassword) {
     await Swal.fire({ title: "Passwords do not match", icon: "error" });
     setLoading(false);
     return;
   }
+  if (!isPhoneValid(phone)) {
+    await Swal.fire({ title: "Invalid phone number", text: "Please enter a valid 10-digit phone number", icon: "error" });
+    setLoading(false);
+    return;
+  }
   // ... baaki validation ...

167-172: Hardcoded localhost URL will break in production.

The Google auth redirect uses a hardcoded localhost:3000 URL instead of the environment variable pattern used elsewhere (lines 89, 120). This will fail in non-local environments.

Apply this diff to use the environment variable:

     } else if (provider === "google") {
-      const apiUrl =
-        "http://localhost:3000";
+      const apiUrl = import.meta.env.VITE_API_URL || "http://localhost:3000";
       // Google ke liye backend par redirect karein
       window.location.href = `${apiUrl}/auth/google`;
     }
🧹 Nitpick comments (1)
src/User/pages/UserAuth/UserAuth.jsx (1)

458-483: Consider managing checkbox state for consistency.

While the checkbox relies on HTML5 validation (which works), all other form inputs use controlled component patterns with state. Adding state management would improve consistency and enable programmatic control.

If you'd like to add state management, apply these diffs:

  1. Add state near the other signup state declarations (after line 41):
   const [showConfirmPassword, setShowConfirmPassword] = useState(false);
   const [passwordStrength, setPasswordStrength] = useState(0);
+  const [termsAccepted, setTermsAccepted] = useState(false);
  1. Update the checkbox to be a controlled component:
                       <input
                         type="checkbox"
                         id="termsAccepted"
+                        checked={termsAccepted}
+                        onChange={(e) => setTermsAccepted(e.target.checked)}
                         required
                         className="mt-1 h-4 w-4 rounded border-gray-300 text-emerald-600 focus:ring-emerald-500"
                       />
πŸ“œ Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between c430bf2 and 682a9db.

πŸ“’ Files selected for processing (4)
  • README.md (1 hunks)
  • src/User/components/Footer/Footer.jsx (2 hunks)
  • src/User/components/Popular_Categories/ProductGrid.jsx (6 hunks)
  • src/User/pages/UserAuth/UserAuth.jsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/User/components/Popular_Categories/ProductGrid.jsx
  • README.md
  • src/User/components/Footer/Footer.jsx

Comment on lines +467 to +481
<Link
to="/terms-and-condition"
className="text-[#4caf50] hover:underline"
target="_blank"
>
Terms and Conditions
</Link>{" "}
and{" "}
<Link
to="/privacy-policy"
className="text-[#4caf50] hover:underline"
target="_blank"
>
Privacy Policy
</Link>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add rel="noopener noreferrer" to external links.

The Links with target="_blank" are missing rel="noopener noreferrer", creating a security risk where the opened page can access window.opener and potentially redirect the parent page.

Apply this diff to secure the links:

                         <Link
                           to="/terms-and-condition"
                           className="text-[#4caf50] hover:underline"
                           target="_blank"
+                          rel="noopener noreferrer"
                         >
                           Terms and Conditions
                         </Link>{" "}
                         and{" "}
                         <Link
                           to="/privacy-policy"
                           className="text-[#4caf50] hover:underline"
                           target="_blank"
+                          rel="noopener noreferrer"
                         >
                           Privacy Policy
                         </Link>
πŸ“ Committable suggestion

‼️ 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.

Suggested change
<Link
to="/terms-and-condition"
className="text-[#4caf50] hover:underline"
target="_blank"
>
Terms and Conditions
</Link>{" "}
and{" "}
<Link
to="/privacy-policy"
className="text-[#4caf50] hover:underline"
target="_blank"
>
Privacy Policy
</Link>
<Link
to="/terms-and-condition"
className="text-[#4caf50] hover:underline"
target="_blank"
rel="noopener noreferrer"
>
Terms and Conditions
</Link>{" "}
and{" "}
<Link
to="/privacy-policy"
className="text-[#4caf50] hover:underline"
target="_blank"
rel="noopener noreferrer"
>
Privacy Policy
</Link>
πŸ€– Prompt for AI Agents
In src/User/pages/UserAuth/UserAuth.jsx around lines 467 to 481, the Link
components that use target="_blank" lack rel="noopener noreferrer"; update both
external Link elements (Terms and Conditions and Privacy Policy) to include
rel="noopener noreferrer" so the new tabs cannot access window.opener and to
mitigate reverse tabnabbing risks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants