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 && (