refactor: Centralize logout logic to a dedicated page, clear local storage, and prevent API requests during the process.
This commit is contained in:
@@ -1,17 +1,33 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { signOut } from 'next-auth/react';
|
import { signOut } from 'next-auth/react';
|
||||||
|
|
||||||
export default function LogoutPage() {
|
export default function LogoutPage() {
|
||||||
|
const hasStarted = useRef(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (hasStarted.current) return;
|
||||||
|
hasStarted.current = true;
|
||||||
|
|
||||||
// Clear localStorage tokens
|
// Clear localStorage tokens
|
||||||
localStorage.removeItem('accessToken');
|
localStorage.removeItem('accessToken');
|
||||||
localStorage.removeItem('refreshToken');
|
localStorage.removeItem('refreshToken');
|
||||||
localStorage.removeItem('user');
|
localStorage.removeItem('user');
|
||||||
|
|
||||||
// Sign out via NextAuth (clears session cookie) and redirect to login
|
// Sign out via NextAuth (clears session cookie), then manually redirect
|
||||||
signOut({ callbackUrl: '/login', redirect: true });
|
signOut({ redirect: false })
|
||||||
|
.then(() => {
|
||||||
|
window.location.href = '/login';
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
window.location.href = '/login';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Safety fallback - if signOut hangs, redirect after 3 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/login';
|
||||||
|
}, 3000);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useState, useEffect, useRef, useCallback } from 'react';
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
|
||||||
import { useSession, signOut } from 'next-auth/react';
|
import { useSession } from 'next-auth/react';
|
||||||
import { agentsService } from '@/services/agents.service';
|
import { agentsService } from '@/services/agents.service';
|
||||||
import { usersService } from '@/services/users.service';
|
import { usersService } from '@/services/users.service';
|
||||||
import { uploadService } from '@/services/upload.service';
|
import { uploadService } from '@/services/upload.service';
|
||||||
@@ -295,7 +295,13 @@ export function CommonHeader() {
|
|||||||
|
|
||||||
{/* Log Out */}
|
{/* Log Out */}
|
||||||
<button
|
<button
|
||||||
onClick={() => signOut({ callbackUrl: '/login' })}
|
onClick={() => {
|
||||||
|
setShowProfileMenu(false);
|
||||||
|
localStorage.removeItem('accessToken');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
|
localStorage.removeItem('user');
|
||||||
|
window.location.href = '/logout';
|
||||||
|
}}
|
||||||
className="w-full flex items-center gap-3 px-4 py-3 hover:bg-black/5 transition-colors"
|
className="w-full flex items-center gap-3 px-4 py-3 hover:bg-black/5 transition-colors"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ const api: AxiosInstance = axios.create({
|
|||||||
// Request interceptor
|
// Request interceptor
|
||||||
api.interceptors.request.use(
|
api.interceptors.request.use(
|
||||||
(config: InternalAxiosRequestConfig) => {
|
(config: InternalAxiosRequestConfig) => {
|
||||||
|
// Skip API calls during logout to prevent refresh loops
|
||||||
|
if (isLoggingOut) {
|
||||||
|
return Promise.reject(new axios.Cancel('Logging out'));
|
||||||
|
}
|
||||||
// Add auth token if available
|
// Add auth token if available
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
const token = localStorage.getItem('accessToken');
|
const token = localStorage.getItem('accessToken');
|
||||||
|
|||||||
Reference in New Issue
Block a user