Skip to content

Conversation

@sage-turing
Copy link

Fixes Issue

My PR closes #issue_number_here

πŸ‘¨β€πŸ’» Changes proposed(What did you do ?)

βœ”οΈ Check List (Check all the applicable boxes)

  • [] My code follows the code style of this project.
  • [] This PR does not contain plagiarized content.
  • [] The title and description of the PR is clear and explains the approach.

Note to reviewers

πŸ“· Screenshots

hammads-turing and others added 30 commits October 6, 2025 16:38
…and Zustand (#6)

* feat: Setup e-commerce frontend with React, TypeScript, Material-UI, and Zustand

- Initialize React + TypeScript + Vite project structure
- Implement feature-based architecture with isolated modules
- Add Material-UI for UI components with custom theme
- Setup Zustand state management with 4 stores (auth, cart, products, UI)
- Create API service layer with Axios client and interceptors
- Implement path aliases for clean imports (@components, @features, @store, etc.)
- Add comprehensive folder structure for scalability
- Create placeholder pages for all major features
- Setup authentication flow with token management
- Implement shopping cart with persistence
- Add common utilities (formatters, validators) and hooks
- Configure TypeScript with strict mode and path mapping
- Add ESLint configuration for code quality
- Create comprehensive documentation (README, STRUCTURE, ZUSTAND_GUIDE)
- Setup development environment with hot reload

Features implemented:
- Authentication (login, register, forgot-password)
- Products (list, detail, search)
- Shopping cart with item management
- Checkout flow
- Order management (list, detail)
- User profile (profile, wishlist, addresses)

Tech stack:
- React 18
- TypeScript 5.2
- Vite 5.0
- Material-UI 5.14
- Zustand 5.0
- React Router 6.20
- Axios 1.6

* intentionally a typo

* fixed minor typo in the import

* added suggestion of replacing href with router link

* added the suggestion to replace href with component

* fixed issues mentioned by the bot

* added prettier on the client side

* fixed the issue of possible undefined config headers

* added changes for the refresh token

* fix: Critical bug fixes for API client authentication and interceptors

Fixed 3 critical issues in the API client:

1. Headers Runtime Error (Medium Severity)
   - Added defensive initialization of config.headers before assignment
   - Prevents runtime error when headers object is undefined
   - Fixed in both request and response interceptors

2. Infinite Loop on Token Refresh (CRITICAL)
   - Prevented infinite recursion when refresh endpoint returns 401
   - Added endpoint check to skip retry logic for refresh calls
   - Use separate axios instance without interceptors for refresh
   - Prevents browser freeze/crash from stack overflow

3. Auth Store Synchronization (CRITICAL)
   - Fixed mismatch between Zustand store and API client token storage
   - API client now reads tokens from Zustand store instead of localStorage
   - Ensures authentication headers are properly added to all requests
   - Token refresh now updates Zustand store correctly
   - Logout properly clears all auth state

Technical Details:
- Import useAuthStore in API client
- Use useAuthStore.getState() to access tokens outside React components
- Single source of truth for authentication state
- Zustand persist middleware handles localStorage automatically

Impact:
- Authentication now works correctly
- No infinite loops or browser crashes
- Proper token refresh handling
- Clean logout functionality
- All protected API requests include auth headers

Documentation:
- Added BUGFIX_AUTH_SYNC.md for auth synchronization fix
- Updated CRITICAL_BUGFIX_SUMMARY.md with all fixes
- Updated PRETTIER_SETUP.md with formatting info
- Applied Prettier formatting to all documentation files

* fix: Ensure auth service uses Zustand store for logout to prevent state drift

Fixed state synchronization issue in auth service:

Problem:
- authService.logout() was directly manipulating localStorage
- This bypassed the Zustand store, causing state drift
- Zustand store would still show user as authenticated
- Inconsistent state between localStorage and Zustand

Solution:
- Import useAuthStore in authService.ts
- Use useAuthStore.getState().logout() instead of direct localStorage manipulation
- Ensures single source of truth for authentication state
- Zustand persist middleware automatically syncs to localStorage

Impact:
- Consistent logout behavior across the application
- No state drift between Zustand and localStorage
- Single source of truth maintained
- All auth state properly cleared on logout

Files Modified:
- src/services/api/auth/authService.ts (logout function)
- BUGFIX_AUTH_SYNC.md (added authService fix documentation)
- CRITICAL_BUGFIX_SUMMARY.md (updated with new fix)

This completes the auth synchronization fixes across the entire codebase.

* feat: Add info pages to prevent dead links in footer

Added 5 new informational pages to align with footer links:

Pages Created:
1. About Page (/about) - Company information and mission
2. Contact Page (/contact) - Contact form and business information
3. Help Page (/help) - FAQ with 10 common questions
4. Returns Page (/returns) - Return policy and refund information
5. Shipping Page (/shipping) - Shipping rates and delivery information

Features:
- All pages use Material-UI components for consistency
- Responsive design with proper spacing
- Professional content with placeholder information
- Contact page includes interactive form (ready for backend integration)
- Help page uses accordion components for FAQs
- Shipping/Returns pages include detailed tables and policies

Routes Added:
- /about β†’ AboutPage
- /contact β†’ ContactPage
- /help β†’ HelpPage
- /returns β†’ ReturnsPage
- /shipping β†’ ShippingPage

Impact:
- No more dead links in footer
- All footer links now navigate to proper pages
- Improved user experience
- Professional appearance
- Ready for content updates

Files Created:
- src/features/info/about/components/AboutPage.tsx
- src/features/info/contact/components/ContactPage.tsx
- src/features/info/help/components/HelpPage.tsx
- src/features/info/returns/components/ReturnsPage.tsx
- src/features/info/shipping/components/ShippingPage.tsx

Files Modified:
- src/routes/AppRoutes.tsx (added 5 new routes)

---------

Co-authored-by: Shehryar Raza <[email protected]>
…d a minor PEP8 fix in settings.py

- Improved the docstring for the asgi.py module.
- Fixed the line length violation within the settings.py file, involving the 'AUTH_PASSWORD_VALIDATORS' constant by the use of parentheses for line breaking.
#21)

* feat: Add beautifully animated sidebar with categories and burger menu

Created a stunning animated sidebar with the following features:

Sidebar Component:
- Beautiful gradient background (purple to violet)
- Smooth slide-in/slide-out animations
- 7 main categories with icons:
  * Electronics (Devices icon)
  * Fashion (Checkroom icon)
  * Home & Garden (Home icon)
  * Sports & Outdoors (Fitness icon)
  * Gaming (Gaming icon)
  * Books & Media (Book icon)
  * Pet Supplies (Pets icon)
- Each category has 5 subcategories
- Expandable/collapsible subcategories with smooth animations
- Click outside to close functionality
- Close button in header
- Professional styling with Material-UI

Features:
βœ… Burger menu button in header (left side)
βœ… Smooth drawer animation from left
βœ… Click outside sidebar to close
βœ… Expandable categories with subcategories
βœ… Beautiful gradient background
βœ… Icon for each category
βœ… Navigation to products with category filters
βœ… Responsive design
βœ… Professional shadows and spacing

UI Store Updates:
- Added openSidebar() method
- Added closeSidebar() method
- Existing toggleSidebar() method

Header Updates:
- Added burger menu icon button
- Integrated with UI store
- Positioned on left side of header

Layout Updates:
- Integrated Sidebar component in MainLayout
- Sidebar available on all pages

Technical Details:
- Uses Material-UI Drawer component
- Zustand for state management
- React Router for navigation
- Click-outside detection with useEffect
- Smooth collapse animations for subcategories
- Gradient background with rgba overlays

Files Created:
- src/components/Sidebar.tsx (300+ lines)

Files Modified:
- src/components/Header.tsx (added burger menu)
- src/components/index.ts (export Sidebar)
- src/layouts/MainLayout.tsx (integrated Sidebar)
- src/store/uiStore.ts (added open/close methods)

* refactor: Remove unnecessary click-outside logic, rely on Drawer's built-in backdrop

Fixed implementation issue in Sidebar component:

Problem:
- Custom click-outside detection using ref and useEffect was incorrect
- SlideProps ref doesn't reference the drawer paper DOM element
- Custom implementation was redundant and wouldn't work as intended

Solution:
- Removed useRef and useEffect for click-outside detection
- Removed SlideProps with ref prop
- Rely on Material-UI Drawer's built-in backdrop behavior
- The onClose prop already handles click-outside via backdrop

Benefits:
βœ… Simpler, cleaner code
βœ… Relies on Material-UI's tested implementation
βœ… Removes unnecessary imports (useEffect, useRef)
βœ… Better performance (no custom event listeners)
βœ… More maintainable
βœ… Follows Material-UI best practices

The Drawer component's backdrop already provides:
- Click outside to close functionality
- Proper event handling
- Accessibility features
- Tested and reliable behavior

Changes:
- Removed: import useEffect, useRef
- Removed: sidebarRef variable
- Removed: useEffect hook with click-outside logic
- Removed: SlideProps prop from Drawer
- Kept: onClose prop (handles backdrop clicks)

Impact:
- Functionality remains the same
- Code is cleaner and more maintainable
- Follows Material-UI conventions
- No breaking changes

---------

Co-authored-by: Shehryar Raza <[email protected]>
AS-2 - implement authentication endpoint register and login
…ment_and_pep8_fix

Improved the top-level docstring for the asgi.py module and introduced a minor PEP8 fix in settings.py
feat: AS-3 - implement github workflow and user role permissions
* feat: Implement centralized color system with Colors class

Created a comprehensive, centralized color system to replace all hardcoded colors
throughout the application. This provides a single source of truth for all colors,
ensuring consistency and making it easy to update the color scheme.

Colors Class Features:
βœ… Primary colors (main, light, dark, contrastText)
βœ… Secondary colors (main, light, dark, contrastText)
βœ… Semantic colors (error, warning, info, success)
βœ… Neutral colors (white, black, gray50-gray900)
βœ… Background colors (default, paper, light, dark)
βœ… Text colors (primary, secondary, disabled, hint, white)
βœ… Gradient colors (6 pre-defined gradients)
βœ… Overlay colors (light/dark with various opacity levels)
βœ… Shadow colors (light, medium, heavy, card)
βœ… Border colors (light, medium, dark, white)
βœ… Brand colors (sidebar, header, footer specific colors)

Utility Methods:
βœ… rgba() - Create custom rgba colors
βœ… hexWithAlpha() - Add transparency to hex colors
βœ… linearGradient() - Create custom gradients
βœ… boxShadow() - Create custom box shadows

Benefits:
βœ… Single source of truth for all colors
βœ… Type-safe with TypeScript
βœ… Easy to update color scheme globally
βœ… Consistent color usage across the app
βœ… Better maintainability
βœ… Autocomplete support in IDEs
βœ… No hardcoded colors in components

Integration:
βœ… Integrated with Material-UI theme
βœ… All theme colors now use Colors class
βœ… Footer component updated to use Colors class
βœ… Ready for use in all components

Documentation:
βœ… Comprehensive COLOR_SYSTEM.md guide
βœ… Usage examples for all color categories
βœ… Best practices and migration guide
βœ… Type exports for TypeScript

Files Created:
- src/config/colors.ts (280+ lines)
- COLOR_SYSTEM.md (comprehensive documentation)

Files Modified:
- src/config/theme.ts (integrated Colors class)
- src/components/Footer.tsx (replaced hardcoded color)

Impact:
- All future components should use Colors class
- Easy to implement dark mode in the future
- Consistent branding across the application
- Simplified color management

* fix: Correct duplicate gradient and add input validation to hexWithAlpha

Fixed two issues in the Colors class:

1. Duplicate Gradient Values:
   Problem: gradient.blueIndigo had the same value as gradient.purpleViolet
   - Old: linear-gradient(135deg, #667eea 0%, #764ba2 100%)
   - New: linear-gradient(135deg, #4e54c8 0%, #8f94fb 100%)
   Impact: Now provides a distinct blue-indigo gradient

2. Input Validation for hexWithAlpha():
   Problem: No validation for hex format or alpha range
   - Invalid hex values (3-digit, 8-digit, malformed) would produce NaN
   - Invalid alpha values could be passed without error

   Solution: Added comprehensive validation
   - Validates hex format (must be exactly 6 hex digits)
   - Validates alpha range (must be 0-1)
   - Throws descriptive errors for invalid inputs
   - Supports both '#RRGGBB' and 'RRGGBB' formats

Changes:
βœ… Fixed gradient.blueIndigo to use distinct colors
βœ… Added regex validation for hex format: /^[0-9A-Fa-f]{6}$/
βœ… Added alpha range validation (0-1)
βœ… Added descriptive error messages
βœ… Updated documentation with validation details
βœ… Added usage examples for both hex formats

Files Modified:
- src/config/colors.ts (fixed gradient, added validation)
- COLOR_SYSTEM.md (updated gradient docs, added validation notes)

Benefits:
βœ… Prevents runtime errors from invalid hex values
βœ… Clear error messages for debugging
βœ… Type-safe with proper validation
βœ… Distinct gradients for better variety
βœ… Better developer experience

---------

Co-authored-by: Shehryar Raza <[email protected]>
feat: AS-3 - implement API for products category and brands
…ecovery flow (#27)

* feat: Implement modern, animated login and register forms

Created professional, modern authentication forms with the latest design standards
and smooth animations. Both forms support email/password authentication with
comprehensive validation and social login placeholders.

Login Page Features:
βœ… Modern gradient background (purple-violet)
βœ… Slide-up animation on page load
βœ… Email and password fields with icons
βœ… Show/hide password toggle
βœ… Real-time form validation
βœ… Email format validation
βœ… Password length validation (min 6 characters)
βœ… Error messages with fade-in animation
βœ… Loading state with spinner
βœ… Forgot password link
βœ… Social login buttons (Google, Facebook, GitHub)
βœ… Sign up link for new users
βœ… Responsive design
βœ… Gradient button with hover effect

Register Page Features:
βœ… Modern gradient background (blue-indigo)
βœ… Slide-up animation on page load
βœ… First name and last name fields (2-column grid)
βœ… Email field with validation
βœ… Password field with strength requirements
βœ… Confirm password field with match validation
βœ… Show/hide password toggles for both fields
βœ… Terms and conditions checkbox
βœ… Comprehensive validation:
  - First/last name: min 2 characters
  - Email: valid format
  - Password: min 8 chars, uppercase, lowercase, number
  - Confirm password: must match
  - Terms: must be accepted
βœ… Real-time error clearing on input
βœ… Loading state with spinner
βœ… Social signup buttons (Google, Facebook, GitHub)
βœ… Sign in link for existing users
βœ… Responsive design with grid layout
βœ… Gradient button with hover effect

Design Standards:
βœ… Material-UI components throughout
βœ… Centralized Colors class for consistency
βœ… Gradient backgrounds for visual appeal
βœ… Icon-enhanced input fields
βœ… Smooth animations (Slide, Fade)
βœ… High elevation paper for depth
βœ… Rounded corners (borderRadius: 3)
βœ… Proper spacing and padding
βœ… Accessible form labels
βœ… Error states with color coding
βœ… Disabled states during submission

Validation Features:
βœ… Client-side validation before API call
βœ… Real-time error clearing on input
βœ… Field-specific error messages
βœ… API error handling with user-friendly messages
βœ… Form submission prevention when invalid
βœ… Visual feedback for all states

User Experience:
βœ… Smooth page transitions
βœ… Instant feedback on errors
βœ… Clear call-to-action buttons
βœ… Easy navigation between login/register
βœ… Social login options for convenience
βœ… Password visibility toggle
βœ… Loading indicators during submission
βœ… Dismissible error alerts

Integration:
βœ… Connected to authService API
βœ… Integrated with Zustand auth store
βœ… Automatic navigation after success
βœ… Token storage via Zustand persist
βœ… Error state management
βœ… Loading state management

Technical Implementation:
βœ… TypeScript for type safety
βœ… React hooks (useState)
βœ… Form validation logic
βœ… Error handling with try-catch
βœ… Async/await for API calls
βœ… Proper cleanup in finally blocks
βœ… ESLint compliant (0 errors, 0 warnings)
βœ… Prettier formatted

Social Login:
βœ… Google login button
βœ… Facebook login button
βœ… GitHub login button
βœ… Placeholder implementation (TODO)
βœ… Consistent styling across providers

Files Modified:
- src/features/auth/login/components/LoginPage.tsx (335 lines)
- src/features/auth/register/components/RegisterPage.tsx (470 lines)

Impact:
- Professional, modern authentication UI
- Improved user experience
- Better form validation
- Ready for production use
- Easy to extend with social auth
- Consistent with design system

* refactor: Remove social login options from auth forms

Removed Google, Facebook, and GitHub social login buttons from both login
and register pages as requested. The forms now only support email/password
authentication.

Changes:
- Removed social login buttons from LoginPage
- Removed social login buttons from RegisterPage
- Removed unused icon imports (Google, Facebook, GitHub)
- Removed unused Divider import
- Removed handleSocialLogin and handleSocialSignup functions
- Cleaned up imports

The forms now have a cleaner, simpler interface focused on email/password
authentication only. Social login can be added back in the future if needed.

* feat: Implement forgot password and reset password pages

Created comprehensive password recovery flow with modern, animated UI matching
the design standards of the login and register pages.

Forgot Password Page Features:
βœ… Modern gradient background (purple-violet)
βœ… Slide-up animation on page load
βœ… Email input field with validation
βœ… Email format validation
βœ… Success message after submission
βœ… Error handling with user-friendly messages
βœ… Loading state with spinner
βœ… Back to login link with arrow icon
βœ… Responsive design
βœ… Gradient button with hover effect
βœ… Dismissible alerts (success/error)

Reset Password Page Features:
βœ… Modern gradient background (blue-indigo)
βœ… Slide-up animation on page load
βœ… Token validation from URL query params
βœ… New password field with show/hide toggle
βœ… Confirm password field with show/hide toggle
βœ… Password strength requirements:
  - Minimum 8 characters
  - Uppercase letter
  - Lowercase letter
  - Number
βœ… Password match validation
βœ… Visual password requirements display
βœ… Success message with auto-redirect to login
βœ… Error handling for invalid/expired tokens
βœ… Loading state with spinner
βœ… Responsive design
βœ… Gradient button with hover effect
βœ… Dismissible alerts (success/error)

User Flow:
1. User clicks "Forgot Password" on login page
2. User enters email on forgot password page
3. System sends reset instructions to email
4. User clicks reset link in email (with token)
5. User enters new password on reset password page
6. Password is reset successfully
7. User is redirected to login page

Integration:
βœ… Connected to authService API
βœ… Uses forgotPassword() method
βœ… Uses resetPassword() method
βœ… Token passed via URL query params
βœ… Automatic redirect after success
βœ… Error state management
βœ… Loading state management

Routes Added:
βœ… /forgot-password - Forgot password page
βœ… /reset-password?token=xxx - Reset password page

Design Standards:
βœ… Material-UI components throughout
βœ… Centralized Colors class for consistency
βœ… Gradient backgrounds for visual appeal
βœ… Icon-enhanced input fields
βœ… Smooth animations (Slide, Fade)
βœ… High elevation paper for depth
βœ… Rounded corners (borderRadius: 3)
βœ… Proper spacing and padding
βœ… Accessible form labels
βœ… Error states with color coding
βœ… Disabled states during submission

Validation Features:
βœ… Client-side validation before API call
βœ… Real-time error clearing on input
βœ… Field-specific error messages
βœ… API error handling with user-friendly messages
βœ… Form submission prevention when invalid
βœ… Visual feedback for all states
βœ… Token validation on page load

Files Created:
- src/features/auth/forgot-password/components/ForgotPasswordPage.tsx (213 lines)
- src/features/auth/forgot-password/components/ResetPasswordPage.tsx (293 lines)

Files Modified:
- src/routes/AppRoutes.tsx (added 2 routes)

Technical Implementation:
βœ… TypeScript for type safety
βœ… React hooks (useState, useEffect)
βœ… React Router (useNavigate, useSearchParams)
βœ… Form validation logic
βœ… Error handling with try-catch
βœ… Async/await for API calls
βœ… Proper cleanup in finally blocks
βœ… ESLint compliant (0 errors, 0 warnings)
βœ… Prettier formatted

Impact:
- Complete password recovery flow
- Professional, modern UI
- Improved user experience
- Better security with token validation
- Ready for production use
- Consistent with design system

* feat: Add password requirements display to login and register pages

Added visible password requirements at the bottom of both login and register
forms to inform users upfront about password constraints before they attempt
to submit the form.

Login Page:
βœ… Added password requirements box below submit button
βœ… Single line format: "Password must contain uppercase, lowercase, and number"
βœ… Light gray background box for visibility
βœ… Positioned above sign-up link

Register Page:
βœ… Added detailed password requirements box below submit button
βœ… Multi-line format with bullet points:
   β€’ At least 8 characters
   β€’ One uppercase letter
   β€’ One lowercase letter
   β€’ One number
βœ… Light gray background box for visibility
βœ… Positioned above sign-in link

Design:
βœ… Uses Colors.background.light for subtle background
βœ… Typography variant="caption" for smaller text
βœ… Text color: text.secondary for reduced emphasis
βœ… Rounded corners (borderRadius: 1)
βœ… Proper padding (p: 2)
βœ… Consistent spacing (mt: 3)

Benefits:
βœ… Users know password requirements before typing
βœ… Reduces form submission errors
βœ… Better user experience
βœ… Clearer expectations
βœ… Matches reset password page design

Files Modified:
- src/features/auth/login/components/LoginPage.tsx
- src/features/auth/register/components/RegisterPage.tsx

* refactor: Reduce height of text input fields across all auth pages

Reduced the height of all text input fields by adding size="small" prop to
TextField components across all authentication pages for a more compact and
modern appearance.

Changes Applied:
βœ… Login Page - Email and Password fields
βœ… Register Page - First Name, Last Name, Email, Password, Confirm Password fields
βœ… Forgot Password Page - Email field
βœ… Reset Password Page - New Password and Confirm Password fields

Technical Details:
- Added size="small" prop to all TextField components
- Reduces default height from 56px to 40px
- Maintains all functionality (icons, validation, error messages)
- Consistent across all auth pages
- Better visual density
- More modern, compact appearance

Benefits:
βœ… More compact form layout
βœ… Better use of vertical space
βœ… Modern, streamlined appearance
βœ… Consistent sizing across all pages
βœ… Improved visual hierarchy
βœ… Better mobile experience

Files Modified:
- src/features/auth/login/components/LoginPage.tsx (2 fields)
- src/features/auth/register/components/RegisterPage.tsx (5 fields)
- src/features/auth/forgot-password/components/ForgotPasswordPage.tsx (1 field)
- src/features/auth/forgot-password/components/ResetPasswordPage.tsx (2 fields)

Total: 10 text fields updated across 4 files

* refactor: Reduce size of input icons across all auth pages

Reduced the size of all input field icons to match the smaller TextField
components by adding fontSize="small" to all icons and size="small" to
all IconButtons.

Icons Updated:
βœ… Email icons - All email input fields
βœ… Lock icons - All password input fields
βœ… Person icons - First name and last name fields
βœ… Visibility/VisibilityOff icons - Password toggle buttons
βœ… IconButtons - All password visibility toggle buttons

Changes by Page:

Login Page (3 icons):
- Email icon (fontSize="small")
- Lock icon (fontSize="small")
- Visibility/VisibilityOff icons (fontSize="small")
- IconButton (size="small")

Register Page (9 icons):
- Person icon x2 (firstName, lastName) (fontSize="small")
- Email icon (fontSize="small")
- Lock icon x2 (password, confirmPassword) (fontSize="small")
- Visibility/VisibilityOff icons x2 (fontSize="small")
- IconButton x2 (size="small")

Forgot Password Page (1 icon):
- Email icon (fontSize="small")

Reset Password Page (6 icons):
- Lock icon x2 (newPassword, confirmPassword) (fontSize="small")
- Visibility/VisibilityOff icons x2 (fontSize="small")
- IconButton x2 (size="small")

Technical Details:
- fontSize="small" reduces icon size from 24px to 20px
- size="small" reduces IconButton padding
- Better visual proportion with size="small" TextFields
- Maintains all functionality and accessibility
- Consistent sizing across all auth pages

Benefits:
βœ… Better visual balance with smaller input fields
βœ… More compact, modern appearance
βœ… Consistent icon sizing across all pages
βœ… Improved visual hierarchy
βœ… Better proportions overall
βœ… Professional, polished look

Total Icons Updated: 19 icons across 4 files

* fix: Remove password strength validation from login and cleanup setTimeout

Fixed two critical issues in authentication pages:

1. Login Page - Removed Password Strength Requirements:
   - Removed minimum length validation (was blocking valid credentials)
   - Login should only check if password is provided, not enforce strength
   - Removed password requirements text box from UI
   - Users can now login with any valid password they previously set

   Problem: validateForm was enforcing 6-character minimum on login, which:
   - Can block legitimate logins if user's password doesn't meet criteria
   - Is inconsistent with the requirements text shown (uppercase, lowercase, number)
   - Should only be enforced during registration, not login

   Solution: Only check if password field is not empty during login validation

2. Reset Password Page - Fixed setTimeout Cleanup:
   - Moved setTimeout to useEffect with proper cleanup
   - Prevents navigation after component unmounts
   - Avoids unexpected navigation if user navigates away before timeout

   Problem: setTimeout in handleSubmit had no cleanup, so if component
   unmounts before 2 seconds (e.g., user navigates away), it would still
   navigate unexpectedly.

   Solution: Use useEffect with cleanup function to clear timeout on unmount

Technical Details:

Login Page Changes:
- validateForm(): Removed password.length < 6 check
- Removed password requirements Box from UI (lines 237-242)
- Only validates that password field is not empty
- Comment added explaining no strength requirements on login

Reset Password Page Changes:
- Added new useEffect hook to handle redirect with cleanup
- useEffect triggers when successMessage is set
- Returns cleanup function: () => clearTimeout(timeoutId)
- Removed setTimeout from handleSubmit
- Added comment: "Redirect handled by useEffect with cleanup"

Benefits:
βœ… Users can login with any password (no false rejections)
βœ… No unexpected navigation after unmount
βœ… Proper React lifecycle management
βœ… Better user experience
βœ… Consistent validation logic

Files Modified:
- src/features/auth/login/components/LoginPage.tsx
- src/features/auth/forgot-password/components/ResetPasswordPage.tsx

* feat: Add Terms and Privacy pages with proper routing

Fixed broken links in RegisterPage by creating proper Terms and Privacy pages
and adding corresponding routes to AppRoutes.

Problem:
- RegisterPage had links to /terms and /privacy routes that didn't exist
- These undefined routes would redirect users to / (home page)
- Users couldn't view terms or privacy policy before agreeing
- Links used href instead of React Router navigation

Solution:
1. Created TermsPage component with comprehensive terms and conditions
2. Created PrivacyPage component with detailed privacy policy
3. Added /terms and /privacy routes to AppRoutes
4. Updated RegisterPage links to use RouterLink for proper navigation

New Pages Created:

1. TermsPage (src/features/info/terms/components/TermsPage.tsx):
   - Comprehensive terms and conditions (12 sections)
   - Covers: Acceptance, License, Account Terms, Products, Pricing,
     Shipping, Returns, Liability, Privacy, Modifications, Governing Law
   - Professional layout with Material-UI Paper and Typography
   - Uses Colors class for consistent styling
   - Responsive container with proper spacing
   - Last updated date displayed

2. PrivacyPage (src/features/info/privacy/components/PrivacyPage.tsx):
   - Detailed privacy policy (11 sections)
   - Covers: Introduction, Data Collection, Usage, Security, Retention,
     Legal Rights, Cookies, Third-Party Links, Children's Privacy, Changes
   - Lists all types of data collected (Identity, Contact, Financial, etc.)
   - Explains user rights under data protection laws
   - Professional layout matching TermsPage design
   - Uses Colors class for consistent styling
   - Last updated date displayed

Routes Added to AppRoutes.tsx:
- /terms -> TermsPage (public route with MainLayout)
- /privacy -> PrivacyPage (public route with MainLayout)

RegisterPage Changes:
- Updated Terms link: href="/terms" -> component={RouterLink} to="/terms"
- Updated Privacy link: href="/privacy" -> component={RouterLink} to="/privacy"
- Both links open in new tab (target="_blank")
- Proper React Router navigation instead of full page reload

Benefits:
βœ… Users can now view terms and privacy policy
βœ… Links work correctly without redirecting to home
βœ… Proper React Router navigation (no page reload)
βœ… Professional, comprehensive legal pages
βœ… Consistent styling with design system
βœ… Opens in new tab for better UX
βœ… SEO-friendly routes
βœ… Compliant with legal requirements

Technical Details:
- Both pages use Material-UI Container, Paper, Typography, Box
- Responsive layout (maxWidth: lg, padding: 6)
- Paper elevation: 2 for subtle shadow
- Colors.text.primary for headings
- Colors.text.secondary for body text
- Proper semantic HTML (h1, ul, li)
- Last updated date auto-generated with new Date()

Files Created:
- src/features/info/terms/components/TermsPage.tsx (179 lines)
- src/features/info/privacy/components/PrivacyPage.tsx (189 lines)

Files Modified:
- src/routes/AppRoutes.tsx (added 2 imports, 2 routes)
- src/features/auth/register/components/RegisterPage.tsx (updated links)

---------

Co-authored-by: Shehryar Raza <[email protected]>
feat: AS-4 - implement file model and aws s3 config
* feat: Add product search bar to header with debounced search

- Created SearchBar common component with debounced search functionality
- Integrated SearchBar into Header component
- Installed lodash and @types/lodash for debouncing
- Search displays product results with image, title, and price
- Includes loading states, error handling, and empty states
- Responsive design (hidden on mobile, visible on desktop)
- Click on result navigates to product detail page
- Auto-closes on click away or result selection

Files changed:
- src/components/common/SearchBar.tsx (new)
- src/components/Header.tsx (updated)
- package.json (added lodash dependencies)

* fix: Optimize SearchBar to prevent icon re-renders on every keystroke

- Memoized SearchIcon, ClearButton, and LoadingSpinner components
- Optimized endAdornment to only render when needed (searchQuery || isLoading)
- Memoized handleClear function to prevent re-creation on every render
- Added IconButton wrapper for better UX on clear button

Performance improvements:
- Icons no longer re-render on every keystroke
- Reduced unnecessary component re-renders
- Better React performance with memo and useMemo
- Cleaner conditional rendering logic

Files changed:
- src/components/common/SearchBar.tsx

* docs: Add dummy product data and testing guide for SearchBar

- Added dummyProducts.json with 15 electronic products
- Products include smartphones, laptops, headphones, cameras, and accessories
- All products have Unsplash images for realistic testing
- Created comprehensive TESTING_SEARCHBAR.md guide
- Guide includes 3 testing options: mock service, DevTools, backend integration
- Instructions for performance testing and troubleshooting

Files added:
- src/data/dummyProducts.json (15 products with images)
- TESTING_SEARCHBAR.md (comprehensive testing guide)

* fix: Completely eliminate close icon flickering in SearchBar

The previous fix didn't fully resolve the issue because the endAdornment
was being recreated on every keystroke due to the changing condition.

Solution:
- Created memoized EndAdornment component that wraps the entire end section
- Component only re-renders when isLoading or hasQuery props actually change
- Used useCallback for handleClear to ensure stable reference
- EndAdornment component handles conditional rendering internally

This ensures that:
- The close icon never flickers or re-renders on keystroke
- Only the TextField value updates, not the adornments
- Better performance with proper React.memo usage

Files changed:
- src/components/common/SearchBar.tsx

* fix: Properly prevent close icon re-rendering with hasQuery state

The previous attempts still had the issue because useMemo was depending
on searchQuery (string) which changes on every keystroke.

Solution:
- Added hasQuery boolean state that only changes when going empty <-> non-empty
- Memoized entire InputProps object with useMemo
- InputProps only re-creates when hasQuery, isLoading, or handleClear changes
- Separated ClearButtonAdornment and LoadingAdornment as distinct memoized components

This ensures:
- Close icon only appears/disappears when needed
- No re-rendering while typing (hasQuery stays true)
- Stable component references throughout typing
- handleClear has stable reference via useCallback

Files changed:
- src/components/common/SearchBar.tsx

* feat: Add mock product service and fix icon re-rendering completely

Added mock product service:
- Created mockProductService.ts with searchProducts, getProducts, etc.
- Uses dummyProducts.json data with 300ms simulated network delay
- SearchBar now uses mock service instead of real API
- No more network errors when backend is not running

Fixed icon re-rendering (final solution):
- Renamed hasQuery to showClearButton for clarity
- Only update showClearButton when transitioning empty <-> non-empty
- Added conditional check to prevent unnecessary state updates
- Memoized endAdornment with useMemo depending on stable values
- Simplified component structure, removed unnecessary wrapper components

The close icon now truly only renders when:
- Appearing (first character typed)
- Disappearing (all text cleared)
- Loading state changes

It does NOT re-render on every keystroke while typing.

Files changed:
- src/services/api/products/mockProductService.ts (new)
- src/components/common/SearchBar.tsx (optimized)

* fix: Add @DaTa path alias for JSON imports

- Added @DaTa alias to vite.config.ts
- Added @DaTa alias to tsconfig.json paths
- Updated mockProductService to use @data/dummyProducts.json
- Fixes 'Failed to resolve import' error

Files changed:
- vite.config.ts (added @DaTa alias)
- tsconfig.json (added @DaTa path mapping)
- mockProductService.ts (updated import path)

* fix: Add gap between product image and text in search results

- Added gap: 2 (16px) to ListItemButton for spacing
- Added px: 2 for better horizontal padding
- Set ListItemAvatar minWidth to 'auto' to remove default spacing
- Improves visual spacing and readability of search results

Files changed:
- src/components/common/SearchBar.tsx

* fix: Prevent stale search results race condition

Added latestQueryRef to track the most recent search query and prevent
stale results from overwriting current results.

Race condition scenario (BEFORE):
1. User types 'iphone' -> Request A starts (slow)
2. User types 'mac' -> Request B starts (fast)
3. Request B completes -> Shows MacBook results βœ…
4. Request A completes -> Overwrites with iPhone results ❌ (WRONG!)

Solution (AFTER):
- Track latest query in latestQueryRef
- Before updating state, check if response matches latest query
- Discard stale responses that don't match current query
- Prevents dropdown from reopening with outdated results

Benefits:
- No stale results shown
- No dropdown reopening after clearing
- Consistent UI state
- Better UX when typing quickly

Files changed:
- src/components/common/SearchBar.tsx

* fix: Keep dropdown open to show 'No products found' message

Previously, the dropdown would close when searchResults.length === 0,
preventing users from seeing the 'No products found' feedback.

Changes:
- Always set isOpen to true after search completes (success or error)
- Dropdown now shows 'No products found' when query returns 0 results
- Dropdown shows error message when search fails
- Only closes when user explicitly clears or clicks away

User feedback improvements:
- βœ… Search 'xyz123' -> Shows 'No products found'
- βœ… Network error -> Shows error message
- βœ… Clear button -> Closes dropdown
- βœ… Click away -> Closes dropdown

This aligns with the testing guide expectations and provides
better UX with explicit feedback for all search states.

Files changed:
- src/components/common/SearchBar.tsx

* feat: Add accessibility improvements and prevent setState on unmounted component

Accessibility improvements (WCAG compliance):
- Added aria-label='Search products' to input for screen readers
- Added aria-describedby with hidden description text
- Added aria-autocomplete='list' to indicate autocomplete behavior
- Added aria-controls and aria-expanded for dropdown state
- Added role='listbox' to results list
- Added role='option' to each result item
- Added descriptive aria-label to each product button

Cleanup improvements:
- Added isMountedRef to track component mount state
- Guard all setState calls with isMountedRef.current check
- Prevents 'Can't perform a React state update on an unmounted component' warnings
- Set isMountedRef.current = false in cleanup effect
- Prevents memory leaks from in-flight requests

Benefits:
- βœ… Screen readers announce 'Search products' instead of just placeholder
- βœ… Screen readers announce dropdown state (expanded/collapsed)
- βœ… Screen readers can navigate results with arrow keys
- βœ… Each product is properly announced with name and price
- βœ… No setState warnings when component unmounts during search
- βœ… No memory leaks from async operations

Files changed:
- src/components/common/SearchBar.tsx

* fix: Separate mount tracking from debounce cleanup and use visually-hidden for aria-describedby

Issue 1: isMountedRef incorrectly set to false on dependency changes
---------------------------------------------------------------------
Problem:
- Previous cleanup ran when debouncedSearch changed (debounceDelay/maxResults)
- Set isMountedRef.current = false while component still mounted
- Blocked all future state updates even though component was mounted

Solution:
- Separated mount/unmount tracking into dedicated useEffect with empty deps []
- Only sets isMountedRef.current = true on mount
- Only sets isMountedRef.current = false on unmount
- Debounce cleanup in separate useEffect that only cancels pending calls

Before (BROKEN):
useEffect(() => {
  return () => {
    isMountedRef.current = false  // ❌ Runs on dependency change!
    debouncedSearch.cancel()
  }
}, [debouncedSearch])  // ❌ Runs when debounceDelay/maxResults change

After (FIXED):
useEffect(() => {
  isMountedRef.current = true
  return () => {
    isMountedRef.current = false  // βœ… Only on unmount
  }
}, [])  // βœ… Empty deps - only mount/unmount

useEffect(() => {
  return () => {
    debouncedSearch.cancel()  // βœ… Cancel debounce separately
  }
}, [debouncedSearch])

Issue 2: aria-describedby element hidden from screen readers
-------------------------------------------------------------
Problem:
- Used style={{ display: 'none' }}
- CSS display:none hides from screen readers AND visual users
- aria-describedby description was never announced

Solution:
- Used visually-hidden technique (sr-only pattern)
- Positions element off-screen but keeps it in accessibility tree
- Screen readers can read it, but visual users don't see it

Before (BROKEN):
<span style={{ display: 'none' }}>  {/* ❌ Hidden from screen readers */}
  Description text
</span>

After (FIXED):
<Box sx={{
  position: 'absolute',
  width: '1px',
  height: '1px',
  padding: 0,
  margin: '-1px',
  overflow: 'hidden',
  clip: 'rect(0, 0, 0, 0)',
  whiteSpace: 'nowrap',
  border: 0,
}}>  {/* βœ… Visually hidden but accessible */}
  Description text
</Box>

Benefits:
- βœ… isMountedRef only changes on actual mount/unmount
- βœ… State updates work correctly when props change
- βœ… Debounce still properly cleaned up
- βœ… Screen readers announce the description
- βœ… WCAG 2.1 compliant visually-hidden technique
- βœ… No visual clutter for sighted users

Files changed:
- src/components/common/SearchBar.tsx

* Fix: Cancel pending debounced search when clearing search input

- Add debouncedSearch.cancel() call in handleClear to prevent stale results
- Prevents queued search requests from repopulating dropdown after clear
- Fixes race condition when user clicks clear within debounce window

* Fix: Only set aria-controls when search results list is rendered

- Change aria-controls condition from isOpen to isOpen && searchResults.length > 0
- Prevents invalid ARIA reference when dropdown shows error or empty states
- Ensures aria-controls only references search-results-list when it exists in DOM

* Fix: Prevent dropdown from reopening after click-away and remove non-existent placeholder

- Add userDismissedRef to track when user explicitly dismisses dropdown
- Only call setIsOpen(true) in search handlers if user hasn't dismissed
- Reset userDismissedRef when user types or clears search
- Remove '/placeholder-product.png' fallback that may not exist
- Let MUI Avatar handle missing images with built-in fallback
- Prevents unexpected dropdown reopening when search completes after click-away

* Docs: Update TESTING_SEARCHBAR.md to reflect current mock service setup

- Clarify that SearchBar already uses mock service by default
- Remove outdated instructions about 'temporarily replacing the import'
- Add clear section on how to switch to real backend service when ready
- Reorganize sections to reflect current implementation
- Make testing instructions more accurate and easier to follow

* Fix: Cancel debounced search on result click and add return type to getCategories

SearchBar changes:
- Add debouncedSearch.cancel() in handleResultClick to cancel pending searches
- Reset latestQueryRef.current to prevent in-flight requests from updating state
- Prevents dropdown from reopening after navigation when search completes

mockProductService changes:
- Add Promise<Category[]> return type to getCategories method
- Add Category to imports from @features/products/types
- Add type parameter to Map<string, Category> for type safety
- Ensures mock service matches real service contract for interchangeability

* Fix: Use unique IDs per SearchBar instance to avoid duplicate-id accessibility issues

- Import and use React's useId hook to generate unique IDs per instance
- Replace hard-coded 'search-products-description' with descriptionId
- Replace hard-coded 'search-results-list' with resultsListId
- Prevents duplicate ID collisions when multiple SearchBar components are mounted
- Ensures valid ARIA references for aria-describedby and aria-controls
- Improves accessibility compliance for screen readers

---------

Co-authored-by: Shehryar Raza <[email protected]>
* feat: Add shop page with filters and sorting

- Add ProductFilters and SortBy types to product types
- Create 20 mock products across 5 categories (Electronics, Clothing, Home & Kitchen, Sports, Books)
- Implement PriceRangeFilter component with two-way slider (adjustable min/max)
- Implement RatingFilter component with two-way slider (0-5 stars range)
- Create ProductCard component with:
  - Product image, name, category, rating, price
  - Discount badge and out-of-stock indicator
  - Low stock warning
  - Hover effects and navigation
- Create SortDropdown component with options:
  - Newest First
  - Price: Low to High
  - Price: High to Low
  - Highest Rated
- Implement ShopPage with:
  - Left sidebar with filters (desktop) / drawer (mobile)
  - Center product grid (responsive 3-column on desktop, 2 on tablet, 1 on mobile)
  - Top bar with product count and sort dropdown
  - Filter and sort logic applied to products
  - Empty state with reset filters option
- Add /shop route to AppRoutes and ROUTES constants
- All components fully responsive with mobile support

* fix: Add @DaTa path alias to tsconfig and vite config

- Add @data/* path alias to tsconfig.json
- Add @DaTa alias to vite.config.ts
- Fixes import resolution for mockProducts in ShopPage

* feat: Improve slider responsiveness with drag support

- Add local state to both PriceRangeFilter and RatingFilter for smooth dragging
- Use onChangeCommitted to only update filters when drag is complete (better performance)
- Add step={1} for price slider and step={0.5} for rating slider
- Add disableSwap to prevent thumbs from crossing
- Enhance visual feedback with hover and active states
- Increase track and rail height for better touch/mouse interaction
- Add visual feedback with shadow effects on hover and drag
- Display values update in real-time while dragging
- Filters only apply when user releases the slider (prevents lag)

* fix: Improve slider drag support and add product animations

Slider improvements:
- Fix trackpad dragging by using useEffect instead of direct state comparison
- Properly sync local state with prop changes
- Ensure smooth dragging on all input devices (mouse, trackpad, touch)

Routing changes:
- Replace /shop route with /products route
- Use ShopPage component for /products instead of ProductListPage
- Remove SHOP constant from routes

Animation improvements:
- Add Fade animation to ProductCard components
- Stagger animation timing based on card index (30ms delay per card)
- 300ms base fade-in duration for smooth appearance
- Products now fade in sequentially when loaded or filtered

* renamed file

* removed unused import

* fix: Use sx prop for warning color in Typography

- Change color='warning.main' to sx={{ color: 'warning.main' }}
- Fixes TypeScript error as Typography color prop only accepts specific string values
- Maintains the same visual appearance with proper type safety

* fix: Import React for SyntheticEvent type annotation

- Add React import to PriceRangeFilter.tsx
- Add React import to RatingFilter.tsx
- Fixes TypeScript error where React.SyntheticEvent was referenced without importing React
- Maintains proper type safety for event handlers

* refactor: Import SyntheticEvent directly instead of React namespace

- Import SyntheticEvent directly from 'react' in PriceRangeFilter
- Import SyntheticEvent directly from 'react' in RatingFilter
- Cleaner imports without needing React namespace
- Improved code formatting and consistency

* fix: Use nullish coalescing for numeric filter defaults

- Replace || with ?? for minPrice, maxPrice, minRating, maxRating
- Prevents 0 values from being incorrectly treated as falsy
- Allows users to filter with 0 as a valid bound (e.g., /opt/homebrew/bin/bash price, 0 rating)
- Also fix discountPrice fallback to use ?? instead of ||
- Only defaults to fallback value when undefined/null, not when 0

* revert: Restore color prop for Typography warning text

- Revert back to using color='warning.main' prop
- Previous change to sx={{ color: 'warning.main' }} was unnecessary
- MUI Typography does support theme color paths in color prop

* revert: Restore || operator for filter defaults

- Revert nullish coalescing (??) back to logical OR (||)
- Restore original behavior for minPrice, maxPrice, minRating, maxRating
- Restore discountPrice fallback using ||

---------

Co-authored-by: Shehryar Raza <[email protected]>
feat: AS-5 - add image field to product, brand and category. Also implement…
feat: AS-5 - implement account endpoint and test cases
shehryar-turing and others added 27 commits October 23, 2025 19:12
* feat: Implement comprehensive cart page with full functionality

Cart Store Enhancements:
- Added removeItems() method to remove multiple items at once
- Supports bulk deletion for selected items

Cart Page Features:
- Product display with image, title, description, and price
- Quantity controls (increase/decrease with +/- buttons)
- Direct quantity input with stock validation
- Checkbox selection for individual items
- Select all checkbox for bulk operations
- Remove selected items functionality
- Clear entire cart functionality
- Stock warnings when quantity exceeds available stock
- Empty cart state with call-to-action

Order Summary:
- Subtotal calculation
- Tax calculation (10%)
- Shipping cost (free over $50)
- Total amount
- Free shipping progress indicator
- Proceed to Checkout button
- Continue Shopping button

UI/UX:
- Responsive layout (mobile and desktop)
- Sticky order summary on desktop
- Table layout for cart items
- Product images with proper sizing
- Hover effects on table rows
- Selected row highlighting
- Disabled states for buttons and controls
- Stock validation for quantity changes
- Professional styling with MUI components

All features integrated with Zustand cart store for state management

* debug: Add console logging to cart page for debugging

- Added console logs to see cart state
- Logs cart object, items array, and item count
- This will help identify why items aren't showing

* debug: Add more detailed console logging

- Added check for cart.items existence
- Added items length log
- Added empty check boolean log
- Added log when showing empty state
- Added log when rendering items
- This will help identify exact issue

* feat: Implement full CartDrawer with product display and management

CartDrawer Features:
- Display all cart items with product images (80x80 avatars)
- Product name, price per unit, and subtotal
- Quantity controls (increase/decrease with +/- buttons)
- Direct quantity input with stock validation
- Remove item button for each product
- Stock limit warnings
- Empty cart state with icon and message

Order Summary in Drawer:
- Subtotal display
- Tax calculation (10%)
- Shipping cost (free over $50)
- Total amount with prominent styling

Action Buttons:
- Proceed to Checkout (navigates to /checkout)
- View Full Cart (navigates to /cart page)
- Continue Shopping (closes drawer)

UI/UX:
- Scrollable list for cart items
- Sticky header and footer
- Responsive width (100% mobile, 420px desktop)
- Clean dividers between items
- Professional MUI styling
- Proper spacing and typography

All features integrated with Zustand cart store

* debug: Add console logging to addItem in cart store

- Log item being added with quantity
- Log existing vs new quantity when updating
- Log final quantity after stock validation
- This will help identify quantity mismatch issue

* fix: Replace cart item quantity instead of adding to it

Changed behavior:
- When adding a product that's already in cart, the quantity is now REPLACED instead of ADDED
- Example: If cart has 5 items, and you add 3 from product page, cart will show 3 (not 8)
- This matches expected UX where the product page quantity selector sets the desired quantity

Technical changes:
- Modified addItem() in cartStore to replace existing item quantity
- Removed quantity addition logic (existingItem.quantity + item.quantity)
- Now directly uses item.quantity for existing items
- Stock validation still applies
- Removed debug console logs

* debug: Add detailed logging to addItem function

- Log item being added and its product ID
- Log current cart items and their product IDs
- Log whether replacing or adding new item
- Log old vs new quantity
- Log final updated items
- This will help identify why quantity isn't updating in CartDrawer

* feat: Change product page to show Update Cart button when item in cart

UX Changes:
- When product is NOT in cart: Shows 'Add to Cart' button
- When product IS in cart: Shows 'Update Cart' button + 'Remove' button
- Both buttons are displayed side by side when product is in cart
- Clicking 'Update Cart' calls addItem() which replaces the quantity
- Clicking 'Remove' removes the product from cart

This allows users to:
- Add product to cart initially
- Change quantity on product page and click 'Update Cart' to update
- Remove product from cart with separate 'Remove' button

Fixes the issue where users couldn't update quantity from product page

* feat: Add confirmation dialogs for remove and clear cart actions

Product Detail Page:
- Added confirmation dialog when clicking 'Remove' button
- Dialog asks 'Remove from Cart?' with Cancel/Remove options
- Prevents accidental removal of products from cart

Cart Page:
- Added confirmation dialog when clicking 'Clear Cart' button
- Dialog asks 'Clear Cart?' with warning about irreversible action
- Prevents accidental clearing of entire cart

Implementation:
- Used MUI Dialog, DialogTitle, DialogContent, DialogActions components
- Added state management for dialog open/close
- Split handlers into click/confirm/cancel functions
- Consistent UX across both dialogs
- Auto-focus on confirm button for keyboard accessibility

UX Improvements:
- Users must confirm before destructive actions
- Clear messaging about what will happen
- Easy to cancel if clicked by mistake

* feat: Add confirmation dialog for removing items in CartDrawer

CartDrawer Changes:
- Added confirmation dialog when clicking delete icon on cart items
- Dialog shows product name being removed
- Prevents accidental removal of items from cart drawer

Implementation:
- Added useState for dialog state and item to remove
- Created handleRemoveClick to open dialog with item details
- Created handleRemoveConfirm to actually remove the item
- Created handleRemoveCancel to close dialog without removing
- Updated delete IconButton to call handleRemoveClick
- Added Dialog component at end of CartDrawer

Dialog Features:
- Title: 'Remove Item?'
- Message: Shows product name in bold
- Cancel button (primary color)
- Remove button (error/red, auto-focused)
- Keyboard accessible (Enter/Escape)
- ARIA labels for accessibility

UX Consistency:
- Matches confirmation dialogs in ProductDetailPage and CartPage
- Same visual style and interaction pattern
- Prevents accidental deletions across all cart interfaces

* feat: Add confirmation dialog for individual item deletion in CartPage

CartPage Changes:
- Added confirmation dialog when clicking delete icon on cart items in table
- Dialog shows product name being removed
- Prevents accidental removal of individual items from cart page

Implementation:
- Added state for removeItemDialogOpen and itemToRemove
- Created handleRemoveItemClick to open dialog with item details
- Created handleRemoveItemConfirm to remove item and update selected items
- Created handleRemoveItemCancel to close dialog without removing
- Updated delete IconButton onClick to call handleRemoveItemClick
- Added second Dialog component for individual item removal

Dialog Features:
- Title: 'Remove Item?'
- Message: Shows product name in bold
- Cancel button (primary color)
- Remove button (error/red, auto-focused)
- Keyboard accessible (Enter/Escape)
- ARIA labels for accessibility
- Also removes item from selectedItems array if it was selected

Complete Coverage:
- All four deletion points now have confirmation dialogs:
  1. Product Detail Page - Remove button
  2. Cart Page - Clear Cart button
  3. Cart Page - Individual delete icons (NEW!)
  4. Cart Drawer - Individual delete icons
- Consistent UX across entire cart system
- No accidental deletions possible anywhere

* refactor: Remove debug logs and fix quantity initialization

Removed Debug Logs:
- Removed all console.log statements from CartPage
- Removed all debug logging from cartStore addItem function
- Cleaner production code without noise in logs

Fixed Quantity Initialization:
- Product detail page now initializes quantity from existing cart item
- When product is already in cart, quantity selector shows current cart quantity
- Prevents accidental quantity reduction when clicking 'Update Cart'
- Added useEffect to sync quantity state with cartItem changes
- Resets to 1 when product is removed from cart

Benefits:
- No more unintentional quantity changes
- Better UX - users see their current cart quantity
- Cleaner console logs in production
- More predictable behavior when updating cart from product page

* feat: Add confirmation dialog for bulk deletion (Remove Selected)

CartPage Changes:
- Added confirmation dialog for 'Remove Selected' button
- Prevents accidental bulk deletion of multiple cart items
- Completes the goal of confirmations for ALL destructive actions

Implementation:
- Added removeSelectedDialogOpen state
- Renamed handleRemoveSelected to handleRemoveSelectedClick
- Created handleRemoveSelectedConfirm to execute bulk deletion
- Created handleRemoveSelectedCancel to close dialog
- Updated 'Remove Selected' button onClick handler
- Added Dialog component with dynamic item count

Dialog Features:
- Title: 'Remove Selected Items?'
- Message: Shows count of selected items (e.g., '3 selected items')
- Proper singular/plural handling ('1 item' vs '3 items')
- Cancel button (primary color)
- Remove button shows count (e.g., 'Remove 3 Items')
- Error color for destructive action
- Auto-focused confirm button
- Keyboard accessible (Enter/Escape)
- ARIA labels for accessibility

Complete Coverage - All 5 Destructive Actions Now Protected:
1. Product Detail Page - Remove button βœ…
2. Cart Page - Clear Cart button βœ…
3. Cart Page - Individual delete icons βœ…
4. Cart Page - Remove Selected (bulk) βœ… NEW!
5. Cart Drawer - Individual delete icons βœ…

No accidental deletions possible anywhere in the cart system!

* feat: Improve quantity TextField with type=number and inputMode=numeric

CartPage and CartDrawer Changes:
- Added type="number" to quantity TextField inputs
- Added inputMode="numeric" to inputProps
- Browsers now enforce numeric input validation
- Min/max constraints are properly honored by browser

Benefits:
- Prevents entering non-numeric characters (letters, symbols)
- Mobile devices show numeric keyboard instead of full keyboard
- Better UX - users can't accidentally enter invalid values
- Browser-native validation for min/max values
- Improved accessibility with proper input type
- Consistent behavior across both cart page and drawer

Technical Details:
- type="number" enables browser numeric validation
- inputMode="numeric" optimizes mobile keyboard layout
- Works with existing min/max inputProps (1 to stock)
- Maintains existing onChange validation as fallback

* refactor: Disable quantity TextField to rely on +/- buttons only

CartPage and CartDrawer Changes:
- Added disabled attribute to quantity TextField inputs
- Removed onChange handlers (no longer needed)
- Users must now use +/- IconButtons to change quantity
- Quantity field is now read-only display

Rationale:
- Prepares for real-time stock API integration
- Prevents manual input validation issues
- Ensures quantity changes go through controlled +/- buttons
- Better UX - clear, predictable interaction pattern
- Stock validation happens only in +/- button handlers
- Avoids edge cases with direct text input

Benefits:
- Simpler validation logic (only in increment/decrement)
- Prevents users from typing invalid values
- Consistent with common e-commerce UX patterns
- Ready for API service integration for real-time stock
- Cleaner code - no onChange validation needed
- Better mobile experience - no keyboard popup

Future-Ready:
- When API service is implemented, stock updates will be real-time
- +/- buttons will check live stock availability
- Disabled field prevents race conditions with API updates
- Clear visual indication that quantity is controlled

---------

Co-authored-by: Shehryar Raza <[email protected]>
feat: SCRUM-30 - implement product search and ordering
feat: SCRUM-32 - implement cart and cart item model
feat: SRUM-18 - implement logout endpoint
* feat: API base setup with Django backend integration

- Integrate Django authentication APIs (login, register, token refresh)
- Add email verification flow after registration
- Configure CORS for frontend-backend communication
- Implement token-based authentication with JWT
- Add user profile API integration
- Setup API client with automatic token refresh interceptors
- Configure Zustand store for auth state management
- Add success/error banners for auth pages
- Update API endpoints to match Django URL patterns
- Transform data between camelCase (frontend) and snake_case (backend)

Auth Flow:
- Registration: User registers β†’ Email verification page β†’ Verify email β†’ Login
- Login: Fetch tokens β†’ Fetch user profile β†’ Store in Zustand β†’ Redirect
- Token Refresh: Auto-refresh expired tokens via interceptor
- Logout: Clear tokens and user data from store

Backend Changes:
- Add django-cors-headers for CORS support
- Configure CORS allowed origins for local development
- Update RegisterSerializer to return user data only (no tokens)

Frontend Changes:
- Create VerifyEmailPage component for email verification
- Update LoginPage with enhanced error handling
- Update RegisterPage to redirect to email verification
- Add LoginResponseAPI and RegisterResponseAPI types
- Update authService to handle Django response formats
- Update API client token refresh logic
- Update auth store authentication logic based on accessToken presence

* fix: add support for 'details' error key in auth error handling

- Add handling for 'details' key to match Django NON_FIELD_ERRORS_KEY config
- Update LoginPage and RegisterPage error handling
- Maintain backward compatibility with non_field_errors and detail keys
- Handle both array and string formats for details field

* fix: prevent duplicate form submissions during redirect delay

- Remove finally block that resets isSubmitting state
- Only reset isSubmitting on error to re-enable form
- Keep form disabled during success redirect to prevent duplicate submissions
- Affects LoginPage and RegisterPage with 1.5s redirect delays

* fix: ensure client auth state clears even when logout API fails

- Wrap logout API call in try-catch-finally block
- Always clear Zustand auth state in finally block
- Prevents users from being stuck logged in if /auth/logout/ returns 404
- Update Header component to use authService.logout() instead of direct store access
- Ensures reliable logout even when backend endpoint is not implemented

---------

Co-authored-by: Shehryar Raza <[email protected]>
…trol

feat: Scrum 18 email verification control
feat: SCRUM-33 - implement cart endpoints
…ess (#47)

* feat: API base setup with Django backend integration

- Integrate Django authentication APIs (login, register, token refresh)
- Add email verification flow after registration
- Configure CORS for frontend-backend communication
- Implement token-based authentication with JWT
- Add user profile API integration
- Setup API client with automatic token refresh interceptors
- Configure Zustand store for auth state management
- Add success/error banners for auth pages
- Update API endpoints to match Django URL patterns
- Transform data between camelCase (frontend) and snake_case (backend)

Auth Flow:
- Registration: User registers β†’ Email verification page β†’ Verify email β†’ Login
- Login: Fetch tokens β†’ Fetch user profile β†’ Store in Zustand β†’ Redirect
- Token Refresh: Auto-refresh expired tokens via interceptor
- Logout: Clear tokens and user data from store

Backend Changes:
- Add django-cors-headers for CORS support
- Configure CORS allowed origins for local development
- Update RegisterSerializer to return user data only (no tokens)

Frontend Changes:
- Create VerifyEmailPage component for email verification
- Update LoginPage with enhanced error handling
- Update RegisterPage to redirect to email verification
- Add LoginResponseAPI and RegisterResponseAPI types
- Update authService to handle Django response formats
- Update API client token refresh logic
- Update auth store authentication logic based on accessToken presence

* feat: implement login flow with route protection and guest access

- Add ProtectedRoute component to guard authenticated routes
- Add PublicRoute component to prevent logged-in users from accessing auth pages
- Update AppRoutes with route protection for auth and protected routes
- Add 'Continue as Guest' button on login page for unauthenticated browsing
- Login redirects to home page (/) after successful authentication
- Protected routes (/checkout, /orders, /profile, /wishlist) require authentication
- Auth routes (/login, /register) redirect to home if already logged in
- Guest users can browse products but must login for protected features

* fix: add support for 'details' error key in auth error handling

- Add handling for 'details' key to match Django NON_FIELD_ERRORS_KEY config
- Update LoginPage and RegisterPage error handling
- Maintain backward compatibility with non_field_errors and detail keys
- Handle both array and string formats for details field

* fix: prevent duplicate form submissions during redirect delay

- Remove finally block that resets isSubmitting state
- Only reset isSubmitting on error to re-enable form
- Keep form disabled during success redirect to prevent duplicate submissions
- Affects LoginPage and RegisterPage with 1.5s redirect delays

* fix: ensure client auth state clears even when logout API fails

- Wrap logout API call in try-catch-finally block
- Always clear Zustand auth state in finally block
- Prevents users from being stuck logged in if /auth/logout/ returns 404
- Update Header component to use authService.logout() instead of direct store access
- Ensures reliable logout even when backend endpoint is not implemented

* added change

* added protected gate

* fix: prevent premature route redirects before auth state hydration

- Add hasHydrated flag to authStore to track persist rehydration status
- Update ProtectedRoute to wait for hydration before checking auth state
- Update PublicRoute to wait for hydration before redirecting
- Prevents authenticated users from being redirected to /login on initial page load
- Fixes race condition where routing decisions were made before localStorage state loaded
- Uses Zustand persist onRehydrateStorage callback to set hydration flag

---------

Co-authored-by: Shehryar Raza <[email protected]>
* feat: API base setup with Django backend integration

- Integrate Django authentication APIs (login, register, token refresh)
- Add email verification flow after registration
- Configure CORS for frontend-backend communication
- Implement token-based authentication with JWT
- Add user profile API integration
- Setup API client with automatic token refresh interceptors
- Configure Zustand store for auth state management
- Add success/error banners for auth pages
- Update API endpoints to match Django URL patterns
- Transform data between camelCase (frontend) and snake_case (backend)

Auth Flow:
- Registration: User registers β†’ Email verification page β†’ Verify email β†’ Login
- Login: Fetch tokens β†’ Fetch user profile β†’ Store in Zustand β†’ Redirect
- Token Refresh: Auto-refresh expired tokens via interceptor
- Logout: Clear tokens and user data from store

Backend Changes:
- Add django-cors-headers for CORS support
- Configure CORS allowed origins for local development
- Update RegisterSerializer to return user data only (no tokens)

Frontend Changes:
- Create VerifyEmailPage component for email verification
- Update LoginPage with enhanced error handling
- Update RegisterPage to redirect to email verification
- Add LoginResponseAPI and RegisterResponseAPI types
- Update authService to handle Django response formats
- Update API client token refresh logic
- Update auth store authentication logic based on accessToken presence

* feat: implement login flow with route protection and guest access

- Add ProtectedRoute component to guard authenticated routes
- Add PublicRoute component to prevent logged-in users from accessing auth pages
- Update AppRoutes with route protection for auth and protected routes
- Add 'Continue as Guest' button on login page for unauthenticated browsing
- Login redirects to home page (/) after successful authentication
- Protected routes (/checkout, /orders, /profile, /wishlist) require authentication
- Auth routes (/login, /register) redirect to home if already logged in
- Guest users can browse products but must login for protected features

* fix: add support for 'details' error key in auth error handling

- Add handling for 'details' key to match Django NON_FIELD_ERRORS_KEY config
- Update LoginPage and RegisterPage error handling
- Maintain backward compatibility with non_field_errors and detail keys
- Handle both array and string formats for details field

* fix: prevent duplicate form submissions during redirect delay

- Remove finally block that resets isSubmitting state
- Only reset isSubmitting on error to re-enable form
- Keep form disabled during success redirect to prevent duplicate submissions
- Affects LoginPage and RegisterPage with 1.5s redirect delays

* fix: ensure client auth state clears even when logout API fails

- Wrap logout API call in try-catch-finally block
- Always clear Zustand auth state in finally block
- Prevents users from being stuck logged in if /auth/logout/ returns 404
- Update Header component to use authService.logout() instead of direct store access
- Ensures reliable logout even when backend endpoint is not implemented

* added change

* added protected gate

* fix: prevent premature route redirects before auth state hydration

- Add hasHydrated flag to authStore to track persist rehydration status
- Update ProtectedRoute to wait for hydration before checking auth state
- Update PublicRoute to wait for hydration before redirecting
- Prevents authenticated users from being redirected to /login on initial page load
- Fixes race condition where routing decisions were made before localStorage state loaded
- Uses Zustand persist onRehydrateStorage callback to set hydration flag

* feat: implement user profile page with API integration

- Add comprehensive ProfilePage component with view/edit modes
- Implement GET /accounts/profile/ API integration
- Implement PATCH /accounts/profile/ API integration for updates
- Add UserProfileAPI and UpdateProfileRequestAPI types matching backend
- Add API response/request format conversion (snake_case <-> camelCase)
- Support all profile fields: username, firstName, lastName, mobile, gender
- Add profile header with avatar showing user initials
- Add inline editing with Edit/Save/Cancel buttons
- Add loading states and error handling
- Add success message with auto-hide after 3 seconds
- Display read-only fields: email, role, account status, member since date
- Use MUI Grid layout for responsive form fields
- Apply consistent styling with Colors config

* fix: use PUT instead of PATCH for profile update API call

- Change updateProfile to use apiClient.put instead of apiClient.patch
- Matches backend API endpoint that accepts PUT method

* fix: use PATCH and only send changed fields in profile update

- Change back to PATCH method for profile updates
- Only send fields that have actually changed (not empty and different from current)
- Add validation to check if there are any changes before sending request
- Show 'No changes to save' error if user tries to save without modifications
- Prevents sending empty username field that causes backend errors
- Ensures PATCH semantics: only modified fields are sent

* refactor: consolidate UserProfile to use backend API format (snake_case)

- Remove duplicate UserProfileAPI and UpdateProfileRequestAPI interfaces
- Use single UserProfile interface matching backend format with snake_case
- Remove conversion helper functions (convertProfileFromAPI, convertProfileToAPI)
- Update ProfilePage to use snake_case field names (first_name, last_name, etc.)
- Simplify userService by removing format conversion layer
- Direct API response/request mapping without transformation
- Benefits: simpler code, fewer conversions, single source of truth

* feat: integrate Mantine form with validation for ProfilePage

- Install @mantine/core, @mantine/hooks, @mantine/form packages
- Add MantineProvider to App.tsx wrapping MUI ThemeProvider
- Replace manual form state management with Mantine's useForm hook
- Add comprehensive validation rules:
  - Username: required, min 3 chars, max 150 chars
  - First name: required, min 2 chars, max 150 chars
  - Last name: required, min 2 chars, max 150 chars
  - Mobile: optional, max 20 chars
- Keep all UI components as MUI (TextField, Button, Grid, etc.)
- Use Mantine form's getInputProps() for field binding
- Display validation errors inline with MUI TextField error/helperText
- Form validates on submit, prevents submission if invalid
- Validation only shows when in edit mode
- Remove manual formData state and handleInputChange
- Use form.onSubmit() for handleSave with automatic validation

* refactor: move 'changed fields' validation logic into useForm hook

- Convert validate from object to function for access to all form values
- Add validation to check if any field has actually changed from profile
- Prevent form submission if no changes detected
- Show error message 'No changes detected' on username field if nothing changed
- Remove redundant 'No changes to save' check from handleSave
- Validation now handles both field-level and form-level validation
- API will only be called if at least one field has been modified
- Cleaner handleSave function with validation logic centralized in useForm

* refactor: modularize ProfilePage validation logic

- Create profileValidation.ts utility module with:
  - VALIDATION_MESSAGES: centralized error messages
  - VALIDATION_CONSTRAINTS: validation rules (min/max lengths)
  - validateUsername, validateFirstName, validateLastName, validateMobile: individual field validators
  - hasProfileChanges: check if any field changed from original
  - getChangedFields: extract only modified fields for API call
  - validateProfileForm: main validation function combining all validators

- Create useProfileForm custom hook:
  - Encapsulates Mantine form initialization
  - Integrates validateProfileForm for validation
  - Provides setProfileValues and resetToProfile helper methods
  - Cleaner separation of form logic from component

- Update ProfilePage component:
  - Replace inline validation with useProfileForm hook
  - Use setProfileValues in fetchProfile
  - Use resetToProfile in handleCancel
  - Use getChangedFields in handleSave
  - Reduced component from ~200 lines to ~100 lines
  - Much cleaner and more maintainable code

Benefits:
- Reusable validation functions
- Testable validation logic in isolation
- Centralized validation messages and constraints
- Easier to maintain and extend
- Better separation of concerns
- Type-safe validation utilities

* refactor: implement Zod for profile validation

- Install zod package for schema-based validation
- Replace manual validation functions with Zod schema (profileUpdateSchema)
- Create zodResolver helper to convert Zod errors to Mantine form format
- Export ProfileUpdateFormValues type inferred from Zod schema
- Update validateProfileForm to use zodResolver
- Maintain custom business logic (change detection) alongside Zod validation

Benefits of Zod:
- Type-safe validation with automatic TypeScript inference
- Declarative schema definition (easier to read and maintain)
- Built-in error messages with custom overrides
- Composable schemas for complex validation
- Runtime type checking aligned with TypeScript types
- Better error handling and reporting
- Industry standard for schema validation
- Reduces boilerplate code significantly

Schema features:
- Username: required, trimmed, 3-150 chars
- First name: required, trimmed, 2-150 chars
- Last name: required, trimmed, 2-150 chars
- Mobile: optional, max 20 chars
- Gender: enum (Male, Female, Other), optional
- Custom validation: no changes detection

* refactor: remove @mantine/core and @mantine/hooks packages

- Uninstall @mantine/core and @mantine/hooks
- Keep only @mantine/form for form management
- Remove MantineProvider from App.tsx
- Remove @mantine/core/styles.css import
- Use MUI exclusively for UI components
- Use @mantine/form only for form state and validation logic

Benefits:
- Smaller bundle size (removed 22 packages)
- No UI library conflicts
- Cleaner dependency tree
- MUI for all UI components (consistent design)
- Mantine form for validation logic only
- Best of both worlds: MUI UI + Mantine form management

* fix: allow clearing optional fields and support 'Not specified' gender

Issue 1: getChangedFields used truthy checks preventing cleared values
- Changed from truthy checks (values.mobile &&) to !== undefined
- Now allows sending empty string to clear mobile field
- Consistent with hasProfileChanges which uses !== undefined
- Prevents skipping updates when intended value is empty

Issue 2: Gender schema didn't allow empty string for 'Not specified'
- Updated gender schema to accept empty string: .or(z.literal(''))
- Aligns with MenuItem value='' for 'Not specified' option
- Prevents validation error when user selects 'Not specified'
- Allows clearing gender field

Before:
- if (values.mobile && values.mobile !== ...) // Truthy check
- gender: z.enum(['Male', 'Female', 'Other']).optional()

After:
- if (values.mobile !== undefined && values.mobile !== ...) // Explicit check
- gender: z.enum(['Male', 'Female', 'Other']).optional().or(z.literal(''))

Benefits:
- Users can now clear optional fields (mobile, gender)
- 'Not specified' gender option works without validation errors
- Consistent validation logic across all fields
- Empty strings are properly sent to API for clearing values

* fix: add in-flight guard to prevent concurrent save submissions

Issue: Double-clicking Save button causes multiple PATCH requests
- Multiple API calls can create race conditions
- Duplicate updates sent to backend
- No visual feedback during save operation
- Cancel button remains clickable during save

Solution: Add isSaving state to track save operation
- Early return if already saving: if (isSaving) return
- Set isSaving=true at start of save operation
- Set isSaving=false in finally block (always executes)
- Disable both Save and Cancel buttons while saving
- Show loading spinner in Save button during save
- Change button text to 'Saving...' for visual feedback

Implementation:
1. Added isSaving state: useState(false)
2. Guard clause in handleSave: if (isSaving) return
3. Set isSaving in try/finally blocks
4. Disabled buttons: disabled={isSaving}
5. Loading indicator: startIcon={isSaving ? <CircularProgress /> : <Save />}
6. Dynamic text: {isSaving ? 'Saving...' : 'Save Changes'}

Benefits:
- βœ… Prevents duplicate API requests
- βœ… Prevents race conditions
- βœ… Clear visual feedback (spinner + text)
- βœ… Buttons disabled during save
- βœ… Better UX with loading state
- βœ… Guaranteed cleanup with finally block

* fix: align gender field types with backend contract

Issue: Type mismatch between UI, validation, and backend
- UI allowed empty string '' for 'Not specified' option
- Zod schema allowed empty string: .or(z.literal(''))
- TypeScript types only allowed: 'Male' | 'Female' | 'Other'
- Backend gender field is NOT nullable (no null=True)
- Backend has default value of 'Other'
- Backend ALWAYS returns one of: 'Male' | 'Female' | 'Other'

Problem:
- If user selects 'Not specified' (empty string), backend rejects it
- Backend never returns empty string, so 'Not specified' state is impossible
- Type inconsistency between frontend and backend contract
- Potential runtime errors when backend returns non-empty gender

Solution: Align frontend with backend contract
1. Removed 'Not specified' option from UI
2. Updated Zod schema to require gender (removed .or(z.literal('')))
3. Updated form initial value: gender: 'Other' (matches backend default)
4. Updated setProfileValues: gender: profileData.gender (no fallback to undefined)
5. Gender is now always one of: 'Male' | 'Female' | 'Other'

Changes:
- ProfilePage.tsx: Removed <MenuItem value=""> for 'Not specified'
- profileValidation.ts: Changed gender schema from .optional().or(z.literal('')) to required enum
- useProfileForm.ts: Changed initial gender from undefined to 'Other'
- useProfileForm.ts: Removed fallback in setProfileValues (backend always returns value)

Backend Contract (Django):

Benefits:
- βœ… Frontend types match backend contract
- βœ… No type inconsistencies
- βœ… No runtime errors from unexpected empty strings
- βœ… Validation aligns with backend constraints
- βœ… Default value matches backend default ('Other')
- βœ… Simpler UI - no ambiguous 'Not specified' state

* fix: prevent memory leak from success message timeout on unmount

Issue: Success message timeout not cleared on unmount
- setTimeout creates a timeout that triggers setSuccessMessage after 3 seconds
- If user navigates away within 3 seconds, timeout still fires
- Causes 'setState on unmounted component' warning
- Minor memory leak from uncancelled timeout

Problem:
1. No cleanup function to clear timeout on unmount
2. Using setTimeout instead of lodash delay
3. No reference to timeout ID for cleanup

Solution: Add cleanup effect and use lodash delay
1. Import useRef from React
2. Import delay from lodash/delay
3. Add successTimeoutRef to store timeout ID
4. Clear existing timeout before setting new one in handleSave
5. Use lodash delay instead of setTimeout
6. Add cleanup useEffect to clear timeout on unmount

Changes:
- Added import: useRef from 'react'
- Added import: delay from 'lodash/delay'
- Added ref: successTimeoutRef = useRef<number | null>(null)
- Added cleanup effect: clears timeout on unmount
- Updated handleSave: clears existing timeout before setting new one
- Replaced setTimeout with lodash delay
- Store timeout ID in successTimeoutRef.current

Benefits:
- βœ… No setState on unmounted component warnings
- βœ… No memory leaks from uncancelled timeouts
- βœ… Proper cleanup on component unmount
- βœ… Using lodash delay (consistent with project patterns)
- βœ… Prevents multiple timeouts if user saves multiple times quickly

Code Flow:
1. User saves profile β†’ setSuccessMessage('...')
2. Store timeout ID: successTimeoutRef.current = delay(...)
3. If user saves again before 3s β†’ clear old timeout, set new one
4. If user navigates away β†’ cleanup effect clears timeout
5. No setState on unmounted component βœ…

---------

Co-authored-by: Shehryar Raza <[email protected]>
feat: SCRUM-34 - add default pagination
@vercel
Copy link

vercel bot commented Oct 29, 2025

@sageliteoff is attempting to deploy a commit to the dunsin's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

PR Compliance Checks

Thank you for your Pull Request! We have run several checks on this pull request in order to make sure it's suitable for merging into this project. The results are listed in the following section.

Issue Reference In order to be considered for merging, the pull request description must refer to a specific issue number. This is described in our Contributing Guide. This check is looking for a phrase similar to: "Fixes #XYZ" or "Resolves #XYZ" where XYZ is the issue number that this PR is meant to address.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants