logout error
This commit is contained in:
parent
6783fba264
commit
ec383c109f
|
|
@ -5,34 +5,35 @@ import { getToken } from '../utils/tokenHelper.js';
|
||||||
const TOKEN_KEY = 'auth_token';
|
const TOKEN_KEY = 'auth_token';
|
||||||
|
|
||||||
const api: AxiosInstance = axios.create({
|
const api: AxiosInstance = axios.create({
|
||||||
baseURL: 'https://api.example.com', // 🔁 your backend
|
baseURL: 'https://wired-terminally-muskrat.ngrok-free.app/api/v1', // 🔁 your backend
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Request Interceptor ---
|
// --- Request Interceptor ---
|
||||||
api.interceptors.request.use(
|
api.interceptors.request.use(
|
||||||
async (config: AxiosRequestConfig) : Promise<any> => {
|
async (config: AxiosRequestConfig): Promise<any> => {
|
||||||
const token = await getToken(TOKEN_KEY);
|
const token = await getToken(TOKEN_KEY);
|
||||||
if (token && config.headers) {
|
if (token && config.headers) {
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
config.headers.token = token;
|
||||||
}
|
config.headers['ngrok-skip-browser-warning'] = 98098;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`[Axios] ${config.method?.toUpperCase()} ${config.url}`);
|
console.log(`[Axios] ${config.method?.toUpperCase()} ${config.url}`);
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error) => Promise.reject(error)
|
(error) => Promise.reject(error)
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- Response Interceptor ---
|
// --- Response Interceptor ---
|
||||||
api.interceptors.response.use(
|
api.interceptors.response.use(
|
||||||
(response: AxiosResponse) => response.data,
|
(response: AxiosResponse) => response.data,
|
||||||
async (error) => {
|
async (error) => {
|
||||||
console.error('[Axios Error]', error.message);
|
console.error('[Axios Error]', error.message);
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
console.warn('Token expired — trigger refresh logic if needed');
|
console.warn('Token expired — trigger refresh logic if needed');
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import { ipcMain } from 'electron';
|
import { ipcMain } from 'electron';
|
||||||
import { getToken, saveToken, clearToken } from '../utils/tokenHelper.js';
|
import { getToken, saveToken, clearToken } from '../utils/tokenHelper.js';
|
||||||
import { handleLogin, takeScreenshot } from '../utils/utilityFunctions.js';
|
import { handleLogin, takeScreenshot } from '../utils/utilityFunctions.js';
|
||||||
|
import api from '../api/axiosClient.js';
|
||||||
|
|
||||||
ipcMain.handle('get-token', async (_, TOKEN_KEY: string) => {
|
ipcMain.handle('get-token', async (_, TOKEN_KEY: string) => {
|
||||||
return await getToken(TOKEN_KEY);
|
return await getToken(TOKEN_KEY);
|
||||||
|
|
@ -25,4 +26,11 @@ ipcMain.handle('upload-screenshot', async () => {
|
||||||
// Handle login request from renderer
|
// Handle login request from renderer
|
||||||
ipcMain.handle('login-request', async (event, credentials: { email: string, password: string }) => {
|
ipcMain.handle('login-request', async (event, credentials: { email: string, password: string }) => {
|
||||||
return handleLogin(credentials);
|
return handleLogin(credentials);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('logout-request', async () => {
|
||||||
|
(async () => {
|
||||||
|
console.log("Handle Logout listened")
|
||||||
|
await api.get("/logout");
|
||||||
|
})()
|
||||||
});
|
});
|
||||||
|
|
@ -16,7 +16,11 @@ contextBridge.exposeInMainWorld('electron', {
|
||||||
}),
|
}),
|
||||||
getStaticData: () => ipcInvoke('getStaticData'),
|
getStaticData: () => ipcInvoke('getStaticData'),
|
||||||
sendFrameAction: (payload) => ipcSend('sendFrameAction', payload),
|
sendFrameAction: (payload) => ipcSend('sendFrameAction', payload),
|
||||||
|
|
||||||
login: (credentials: { email: string, password: string }) => ipcRenderer.invoke('login-request', credentials),
|
login: (credentials: { email: string, password: string }) => ipcRenderer.invoke('login-request', credentials),
|
||||||
|
|
||||||
|
logout: () => ipcRenderer.invoke('logout-request'),
|
||||||
|
|
||||||
getToken: (TOKEN_KEY: string) => ipcRenderer.invoke('get-token', TOKEN_KEY),
|
getToken: (TOKEN_KEY: string) => ipcRenderer.invoke('get-token', TOKEN_KEY),
|
||||||
uploadScreenshot: () => ipcRenderer.invoke('upload-screenshot'),
|
uploadScreenshot: () => ipcRenderer.invoke('upload-screenshot'),
|
||||||
} satisfies Window['electron']);
|
} satisfies Window['electron']);
|
||||||
|
|
|
||||||
|
|
@ -68,25 +68,25 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
|
|
||||||
// Tracking states
|
// Tracking states
|
||||||
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
|
const [selectedProject, setSelectedProject] = useState<Project | null>(null);
|
||||||
const [isTracking, setIsTracking] = useState(false);
|
const [isTracking, setIsTracking] = useState(false);
|
||||||
const [isPaused, setIsPaused] = useState(false);
|
const [isPaused, setIsPaused] = useState(false);
|
||||||
const [elapsedTime, setElapsedTime] = useState(0);
|
const [elapsedTime, setElapsedTime] = useState(0);
|
||||||
const [startTime, setStartTime] = useState<Date | null>(null);
|
const [startTime, setStartTime] = useState<Date | null>(null);
|
||||||
const [endTime, setEndTime] = useState<Date | null>(null);
|
const [endTime, setEndTime] = useState<Date | null>(null);
|
||||||
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||||
|
|
||||||
const [projectsData, setProjectsData] = useState<Project[]>([
|
const [projectsData, setProjectsData] = useState<Project[]>([
|
||||||
{ id: 1, projectName: "CRM Redesign", clientName: "Salesforce" },
|
{ id: 1, projectName: "CRM Redesign", clientName: "Salesforce" },
|
||||||
{ id: 2, projectName: "AI Assistant", clientName: "OpenAI" },
|
{ id: 2, projectName: "AI Assistant", clientName: "OpenAI" },
|
||||||
{ id: 3, projectName: "Marketing Dashboard", clientName: "Google" },
|
{ id: 3, projectName: "Marketing Dashboard", clientName: "Google" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const [projectTrackingMap, setProjectTrackingMap] = useState<
|
const [projectTrackingMap, setProjectTrackingMap] = useState<
|
||||||
Map<number, ProjectTrackingData>
|
Map<number, ProjectTrackingData>
|
||||||
>(new Map());
|
>(new Map());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
|
|
@ -100,9 +100,20 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
return () => window.removeEventListener("resize", handleResize);
|
return () => window.removeEventListener("resize", handleResize);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = async () => {
|
||||||
localStorage.removeItem("user");
|
localStorage.removeItem("user");
|
||||||
setUser(null);
|
setUser(null);
|
||||||
|
|
||||||
|
console.log("calling Logout UI")
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await window.electron.logout()
|
||||||
|
console.log(res)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -122,7 +133,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// Sync global states with selected project tracking data
|
// Sync global states with selected project tracking data
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedProject) {
|
if (selectedProject) {
|
||||||
const projectData = projectTrackingMap.get(selectedProject.id);
|
const projectData = projectTrackingMap.get(selectedProject.id);
|
||||||
|
|
@ -159,7 +170,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
current.isTracking = true;
|
current.isTracking = true;
|
||||||
current.isPaused = false;
|
current.isPaused = false;
|
||||||
updated.set(project.id, current);
|
updated.set(project.id, current);
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -173,7 +184,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
setProjectTrackingMap((prev) => {
|
setProjectTrackingMap((prev) => {
|
||||||
const updated = new Map(prev);
|
const updated = new Map(prev);
|
||||||
const current = updated.get(project.id);
|
const current = updated.get(project.id);
|
||||||
|
|
||||||
// Only increment when tracking AND not paused
|
// Only increment when tracking AND not paused
|
||||||
if (current && current.isTracking && !current.isPaused) {
|
if (current && current.isTracking && !current.isPaused) {
|
||||||
current.elapsedTime += 1;
|
current.elapsedTime += 1;
|
||||||
|
|
@ -187,25 +198,25 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
// Pause/Resume tracking
|
// Pause/Resume tracking
|
||||||
const handlePauseResume = () => {
|
const handlePauseResume = () => {
|
||||||
if (!selectedProject) return;
|
if (!selectedProject) return;
|
||||||
|
|
||||||
// Get current state before toggling to avoid double-click issues
|
// Get current state before toggling to avoid double-click issues
|
||||||
const currentProjectData = projectTrackingMap.get(selectedProject.id);
|
const currentProjectData = projectTrackingMap.get(selectedProject.id);
|
||||||
if (!currentProjectData || !currentProjectData.isTracking) return;
|
if (!currentProjectData || !currentProjectData.isTracking) return;
|
||||||
|
|
||||||
const newPausedState = !currentProjectData.isPaused;
|
const newPausedState = !currentProjectData.isPaused;
|
||||||
|
|
||||||
setProjectTrackingMap((prev) => {
|
setProjectTrackingMap((prev) => {
|
||||||
const updated = new Map(prev);
|
const updated = new Map(prev);
|
||||||
const current = updated.get(selectedProject.id);
|
const current = updated.get(selectedProject.id);
|
||||||
if (!current) return updated;
|
if (!current) return updated;
|
||||||
|
|
||||||
// Set the new pause state
|
// Set the new pause state
|
||||||
current.isPaused = newPausedState;
|
current.isPaused = newPausedState;
|
||||||
updated.set(selectedProject.id, { ...current });
|
updated.set(selectedProject.id, { ...current });
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update global isPaused state immediately
|
// Update global isPaused state immediately
|
||||||
setIsPaused(newPausedState);
|
setIsPaused(newPausedState);
|
||||||
};
|
};
|
||||||
|
|
@ -231,7 +242,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
current.isPaused = false;
|
current.isPaused = false;
|
||||||
current.endTime = now;
|
current.endTime = now;
|
||||||
updated.set(selectedProject.id, { ...current });
|
updated.set(selectedProject.id, { ...current });
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -240,7 +251,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
setIsPaused(false);
|
setIsPaused(false);
|
||||||
setEndTime(new Date());
|
setEndTime(new Date());
|
||||||
|
|
||||||
console.log("projectTrackingMap",projectTrackingMap)
|
console.log("projectTrackingMap", projectTrackingMap)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cleanup timer on unmount
|
// Cleanup timer on unmount
|
||||||
|
|
@ -256,11 +267,11 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
const handleProjectSelect = (id: number) => {
|
const handleProjectSelect = (id: number) => {
|
||||||
// Only allow project selection when not tracking
|
// Only allow project selection when not tracking
|
||||||
if (isTracking) return;
|
if (isTracking) return;
|
||||||
|
|
||||||
const project = projectsData.find((p) => p.id === id);
|
const project = projectsData.find((p) => p.id === id);
|
||||||
if (project) {
|
if (project) {
|
||||||
setSelectedProject(project);
|
setSelectedProject(project);
|
||||||
|
|
||||||
// Load existing tracking data if available
|
// Load existing tracking data if available
|
||||||
const projectData = projectTrackingMap.get(id);
|
const projectData = projectTrackingMap.get(id);
|
||||||
if (projectData) {
|
if (projectData) {
|
||||||
|
|
@ -302,12 +313,11 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
className={`
|
className={`
|
||||||
fixed md:relative inset-y-0 left-0 z-40 transform
|
fixed md:relative inset-y-0 left-0 z-40 transform
|
||||||
bg-base-100 border-r border-t border-base-300 transition-all duration-300 ease-in-out
|
bg-base-100 border-r border-t border-base-300 transition-all duration-300 ease-in-out
|
||||||
${
|
${isMobile
|
||||||
isMobile
|
? isSidebarOpen
|
||||||
? isSidebarOpen
|
? "translate-x-0 w-64"
|
||||||
? "translate-x-0 w-64"
|
: "-translate-x-full w-64"
|
||||||
: "-translate-x-full w-64"
|
: isSidebarOpen
|
||||||
: isSidebarOpen
|
|
||||||
? "w-50"
|
? "w-50"
|
||||||
: "w-20"
|
: "w-20"
|
||||||
}
|
}
|
||||||
|
|
@ -339,10 +349,9 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
to={item.path}
|
to={item.path}
|
||||||
end={item.exact}
|
end={item.exact}
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
`flex items-center gap-3 my-1 font-medium transition-all duration-150 ${
|
`flex items-center gap-3 my-1 font-medium transition-all duration-150 ${isActive
|
||||||
isActive
|
? "bg-primary text-primary-content rounded-lg"
|
||||||
? "bg-primary text-primary-content rounded-lg"
|
: "hover:bg-base-300 rounded-lg"
|
||||||
: "hover:bg-base-300 rounded-lg"
|
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onClick={closeSidebarOnMobile}
|
onClick={closeSidebarOnMobile}
|
||||||
|
|
@ -380,8 +389,8 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
{location.pathname.includes("projects")
|
{location.pathname.includes("projects")
|
||||||
? "Projects"
|
? "Projects"
|
||||||
: location.pathname.includes("leave-adjustments")
|
: location.pathname.includes("leave-adjustments")
|
||||||
? "Leave & Adjustments"
|
? "Leave & Adjustments"
|
||||||
: "Dashboard"}
|
: "Dashboard"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -418,7 +427,7 @@ const DashboardLayout: React.FC<DashboardLayoutProps> = ({ setUser }) => {
|
||||||
|
|
||||||
{/* Page Content */}
|
{/* Page Content */}
|
||||||
<main className="flex-1 overflow-y-auto p-4 md:px-6 no-scrollbar">
|
<main className="flex-1 overflow-y-auto p-4 md:px-6 no-scrollbar">
|
||||||
<Outlet context={trackingState}/>
|
<Outlet context={trackingState} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ interface Window {
|
||||||
) => UnsubscribeFunction;
|
) => UnsubscribeFunction;
|
||||||
sendFrameAction: (payload: FrameWindowAction) => void;
|
sendFrameAction: (payload: FrameWindowAction) => void;
|
||||||
login: (credentials: { email: string; password: string }) => Promise<any>;
|
login: (credentials: { email: string; password: string }) => Promise<any>;
|
||||||
|
logout: () => {};
|
||||||
getToken: (tokenKey: string) => Promise<string | null>;
|
getToken: (tokenKey: string) => Promise<string | null>;
|
||||||
uploadScreenshot: () => {};
|
uploadScreenshot: () => {};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue