From b0d720c821fa57a3e3cfe80be55afe0ce81d8e98 Mon Sep 17 00:00:00 2001 From: Yashwin Date: Wed, 21 Jan 2026 19:32:18 +0530 Subject: [PATCH] Refactor environment configuration for local development, add Sonner for toast notifications, and enhance user feedback across various components. Update API response handling in authentication and management services to include message properties. Improve form components with password visibility toggle and initial option handling in dropdowns. --- .env | 4 +- package-lock.json | 11 ++ package.json | 1 + src/App.tsx | 2 + src/components/layout/Header.tsx | 10 +- src/components/shared/ActionDropdown.tsx | 8 +- src/components/shared/EditUserModal.tsx | 120 ++++++++++++++++----- src/components/shared/FormField.tsx | 53 ++++++--- src/components/shared/PaginatedSelect.tsx | 5 +- src/components/shared/PrimaryButton.tsx | 2 +- src/components/shared/SecondaryButton.tsx | 2 +- src/pages/AuditLogs.tsx | 2 +- src/pages/Login.tsx | 4 + src/pages/Modules.tsx | 2 +- src/pages/ResetPassword.tsx | 126 +++++++++++++--------- src/pages/Roles.tsx | 13 ++- src/pages/Tenants.tsx | 13 ++- src/pages/Users.tsx | 13 ++- src/services/auth-service.ts | 1 + src/services/tenant-service.ts | 2 + src/store/authSlice.ts | 31 +++--- src/types/role.ts | 2 + src/types/user.ts | 10 ++ src/utils/toast.ts | 31 ++++++ 24 files changed, 344 insertions(+), 124 deletions(-) create mode 100644 src/utils/toast.ts diff --git a/.env b/.env index 75d31ae..ec8b053 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -# VITE_API_BASE_URL=http://localhost:3000/api/v1 -VITE_API_BASE_URL=https://backendqaasure.tech4bizsolutions.com/api/v1 +VITE_API_BASE_URL=http://localhost:3000/api/v1 +# VITE_API_BASE_URL=https://backendqaasure.tech4bizsolutions.com/api/v1 diff --git a/package-lock.json b/package-lock.json index 0173bec..5627a5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "react-router-dom": "^7.12.0", "recharts": "^3.6.0", "redux-persist": "^6.0.0", + "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "zod": "^4.3.5" @@ -4244,6 +4245,16 @@ "node": ">=8" } }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/package.json b/package.json index e52ccac..34a0d1b 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "react-router-dom": "^7.12.0", "recharts": "^3.6.0", "redux-persist": "^6.0.0", + "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "zod": "^4.3.5" diff --git a/src/App.tsx b/src/App.tsx index 16a6bf9..f088c1c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { Toaster } from "sonner"; import Login from "./pages/Login"; import Dashboard from "./pages/Dashboard"; import Tenants from "./pages/Tenants"; @@ -14,6 +15,7 @@ import ResetPassword from "./pages/ResetPassword"; function App() { return ( + } /> } /> diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 17d61df..2d00b56 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -5,6 +5,7 @@ import { Button } from '@/components/ui/button'; import { useAppDispatch, useAppSelector } from '@/hooks/redux-hooks'; import { logoutAsync } from '@/store/authSlice'; import { cn } from '@/lib/utils'; +import { showToast } from '@/utils/toast'; import type { ReactElement } from 'react'; interface HeaderProps { @@ -70,14 +71,21 @@ export const Header = ({ currentPage, onMenuClick }: HeaderProps): ReactElement try { // Call logout API with Bearer token - await dispatch(logoutAsync()).unwrap(); + const result = await dispatch(logoutAsync()).unwrap(); + const message = result.message || 'Logged out successfully'; + const description = result.message ? undefined : 'You have been logged out'; + showToast.success(message, description); // Clear state and redirect navigate('/', { replace: true }); } catch (error: any) { // Even if API call fails, clear local state and redirect to login console.error('Logout error:', error); + // Try to get message from error response + const message = error?.message || 'Logged out successfully'; + const description = error?.message ? undefined : 'You have been logged out'; // Dispatch logout action to clear local state dispatch({ type: 'auth/logout' }); + showToast.success(message, description); navigate('/', { replace: true }); } }; diff --git a/src/components/shared/ActionDropdown.tsx b/src/components/shared/ActionDropdown.tsx index ff0c62b..feff4a5 100644 --- a/src/components/shared/ActionDropdown.tsx +++ b/src/components/shared/ActionDropdown.tsx @@ -48,7 +48,7 @@ export const ActionDropdown = ({ type="button" onClick={() => setIsOpen(!isOpen)} className={cn( - 'flex items-center justify-center w-7 h-7 rounded-full border border-[rgba(0,0,0,0.08)] transition-colors', + 'flex items-center justify-center w-7 h-7 rounded-full border border-[rgba(0,0,0,0.08)] transition-colors cursor-pointer', isOpen ? 'bg-[#084cc8] text-white' : 'bg-white text-[#0f1724] hover:bg-[#084cc8] hover:text-white' @@ -66,7 +66,7 @@ export const ActionDropdown = ({ )} - aria-invalid={hasError} - aria-describedby={error ? `${fieldId}-error` : helperText ? `${fieldId}-helper` : undefined} - {...props} - /> + {error && (