isLimit end then change the color working but comment
This commit is contained in:
parent
c0a89d3f69
commit
1cc863d3c9
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
import axios from "axios";
|
||||
import https from "https";
|
||||
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
|
||||
export const checkRegion = async () => {
|
||||
const baseURL = "https://daniela-nonprofessed-boastfully.ngrok-free.app";
|
||||
|
||||
try {
|
||||
|
||||
const res = await axios.get(`${baseURL}/health`, {
|
||||
headers: { "ngrok-skip-browser-warning": "true" },
|
||||
httpsAgent
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: res.status,
|
||||
data: res.data
|
||||
};
|
||||
|
||||
} catch (error: any) {
|
||||
const status = error?.response?.status || 500;
|
||||
|
||||
console.log("Region Check Error:", status);
|
||||
|
||||
// 🔁 Auto retry if 403 — server blocked first try
|
||||
if (status === 403) {
|
||||
try {
|
||||
const retry = await axios.get(`${baseURL}/api`, {
|
||||
headers: { "ngrok-skip-browser-warning": "true" },
|
||||
httpsAgent
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: retry.status,
|
||||
data: retry.data,
|
||||
retry: true
|
||||
};
|
||||
} catch (retryErr: any) {
|
||||
return {
|
||||
success: false,
|
||||
status: retryErr?.response?.status || 500,
|
||||
message: "403 Retry failed"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
status,
|
||||
message: "Region check failed"
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -3,6 +3,7 @@ import { getToken, saveToken, clearToken } from "../utils/tokenHelper.js";
|
|||
import { getActiveApp, handleLogin, takeScreenshot, startWindowPolling, getRunningAppsList, captureSpecificApp } from "../utils/utilityFunctions.js";
|
||||
import api from "../api/axiosClient.js";
|
||||
import { getMainWindow } from '../main.js';
|
||||
import { checkRegion } from "../api/regionCheck.js";
|
||||
|
||||
|
||||
|
||||
|
|
@ -10,6 +11,8 @@ import { getMainWindow } from '../main.js';
|
|||
export const registerIPCHandlers = (mainWindow: BrowserWindow) => {
|
||||
console.log("⚙️ Registering IPC Handlers...");
|
||||
|
||||
|
||||
|
||||
ipcMain.handle("get-token", async (_, key: "ACCESS_TOKEN" | "REFRESH_TOKEN") => {
|
||||
return await getToken(key);
|
||||
});
|
||||
|
|
@ -534,6 +537,11 @@ ipcMain.handle("update-payment", async (event, data: Record<string, any>) => {
|
|||
|
||||
|
||||
|
||||
ipcMain.handle("check-region", async () => {
|
||||
return await checkRegion();
|
||||
});
|
||||
|
||||
|
||||
|
||||
export const sendTokenExpired = () => {
|
||||
console.log("⚠️ Sending token-expired event to renderer");
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ contextBridge.exposeInMainWorld('electron', {
|
|||
getLeaveList: () => ipcRenderer.invoke("get-leave-list"),
|
||||
getAdjustmentsList:(vaId: string) => ipcRenderer.invoke("get-adjustments-list",vaId),
|
||||
|
||||
checkRegion: () => ipcRenderer.invoke("check-region")
|
||||
|
||||
} satisfies Window['electron']);
|
||||
|
||||
// function ipcInvoke<Key extends keyof EventPayloadMapping>(
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ import Vpn from "./pages/Vpn/Vpn";
|
|||
import Schedule from "./pages/Schedule/Schedule";
|
||||
import PaysSlips from "./pages/PaySlips/PaysSlips";
|
||||
import ApplyLeaveAndAdjustmentsTime from "./pages/LeaveAndAdjustments/ApplyLeaveAndAdjustmentsTime";
|
||||
import VpnGuard from "./pages/Vpn/VpnGuard";
|
||||
|
||||
|
||||
const App: React.FC = () => {
|
||||
|
|
@ -122,7 +123,9 @@ const App: React.FC = () => {
|
|||
path="/login"
|
||||
element={
|
||||
<PublicRoute user={user}>
|
||||
<Login />
|
||||
<VpnGuard>
|
||||
<Login />
|
||||
</VpnGuard>
|
||||
</PublicRoute>
|
||||
}
|
||||
/>
|
||||
|
|
@ -132,20 +135,22 @@ const App: React.FC = () => {
|
|||
path="/dashboard"
|
||||
element={
|
||||
<ProtectedRoute user={user}>
|
||||
{/* <VpnGuard> */}
|
||||
<DashboardLayout />
|
||||
{/* </VpnGuard> */}
|
||||
</ProtectedRoute>
|
||||
}
|
||||
>
|
||||
<Route index element={<Dashboard />} />
|
||||
<Route path="projects" element={<Projects />} />
|
||||
<Route path="leave-adjustments" element={<LeaveAndAdjustments />} />
|
||||
<Route path="leave-adjustments/apply" element={<ApplyLeaveAndAdjustmentsTime/>} />
|
||||
<Route path="leave-adjustments/apply" element={<ApplyLeaveAndAdjustmentsTime />} />
|
||||
<Route path="timesheet" element={<Timesheets />} />
|
||||
<Route path="settings" element={<Settings />} />
|
||||
<Route path="vpn" element={<Vpn />} />
|
||||
<Route path="help-support" element={<HelpSupport />} />
|
||||
<Route path="schedule" element={<Schedule/>} />
|
||||
<Route path="pays-slips" element={<PaysSlips/>} />
|
||||
<Route path="schedule" element={<Schedule />} />
|
||||
<Route path="pays-slips" element={<PaysSlips />} />
|
||||
</Route>
|
||||
|
||||
{/* Default Redirect */}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,8 @@ const DashboardLayout = () => {
|
|||
`Timer will continue running. Please stop manually when ready.`
|
||||
);
|
||||
|
||||
|
||||
|
||||
console.log("✅ Alert shown, timer continues running");
|
||||
}, [selectedProject]);
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ const Dashboard: React.FC = () => {
|
|||
const projectSummary = useSelector((state: any) => state.projects.projectSummary);
|
||||
const projectTrackingMap = useSelector((state: any) => state.projects.projectTrackingMap);
|
||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||
const isLimitReached = selectedProject ? isProjectLimitReached(selectedProject) : false;
|
||||
|
||||
console.log("Line 111", projectsData, selectedProject, projectTrackingMap)
|
||||
|
||||
|
|
@ -156,7 +157,7 @@ const Dashboard: React.FC = () => {
|
|||
const firstProject = res.data[0];
|
||||
|
||||
|
||||
console.log("Line 158" , firstProject)
|
||||
console.log("Line 158", firstProject)
|
||||
// Select the project
|
||||
dispatch(setSelectedProjectSlice(firstProject));
|
||||
|
||||
|
|
@ -272,6 +273,11 @@ const Dashboard: React.FC = () => {
|
|||
<p className="text-lg font-extrabold text-success">
|
||||
{formatTime(displayTime)}
|
||||
</p>
|
||||
|
||||
{/* <p className={`text-lg font-extrabold ${isLimitReached ? 'text-error' : 'text-success'}`}>
|
||||
{formatTime(displayTime)}
|
||||
{isLimitReached && " ⚠️"}
|
||||
</p> */}
|
||||
<div>
|
||||
<span className="text-base-content/70">Project:</span>{" "}
|
||||
<span className="font-semibold">
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ const AdjustmentTab: React.FC<AdjustmentTabProps> = ({ projects }) => {
|
|||
console.log("Timesheet Created Successfully");
|
||||
resetForm();
|
||||
// Show success toast instead of alert
|
||||
showToast("PTO Request submitted successfully!", "success");
|
||||
showToast("Timesheet Request submitted successfully!", "success");
|
||||
|
||||
// Navigate after a small delay
|
||||
setTimeout(() => {
|
||||
|
|
@ -681,3 +681,4 @@ const AdjustmentTab: React.FC<AdjustmentTabProps> = ({ projects }) => {
|
|||
};
|
||||
|
||||
export default AdjustmentTab;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,54 +1,58 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const VpnGuard: React.FC<Props> = ({ children }) => {
|
||||
const [checking, setChecking] = useState(true);
|
||||
const [vpnConnected, setVpnConnected] = useState(true);
|
||||
const [checking, setChecking] = useState(true);
|
||||
const [vpnConnected, setVpnConnected] = useState(true);
|
||||
|
||||
// const checkVPN = async () => {
|
||||
// try {
|
||||
// const res = await window.electron.checkVpnConnection();
|
||||
// setVpnConnected(res?.success);
|
||||
// } catch {
|
||||
// setVpnConnected(false);
|
||||
// } finally {
|
||||
// setChecking(false);
|
||||
// }
|
||||
// };
|
||||
const checkVPN = async () => {
|
||||
setChecking(true)
|
||||
try {
|
||||
const res = await window.electron.checkRegion();
|
||||
console.log("VpnGuard", res)
|
||||
if (res.success) {
|
||||
setVpnConnected(true);
|
||||
}
|
||||
} catch {
|
||||
setVpnConnected(false);
|
||||
} finally {
|
||||
setChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// checkVPN();
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
checkVPN();
|
||||
}, []);
|
||||
|
||||
if (checking) {
|
||||
return (
|
||||
<div className="min-h-screen flex justify-center items-center">
|
||||
<span className="loading loading-spinner loading-lg"></span>
|
||||
<span className="ml-3">Checking VPN...</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (checking) {
|
||||
return (
|
||||
<div className="min-h-screen flex justify-center items-center">
|
||||
<span className="loading loading-spinner loading-lg"></span>
|
||||
<span className="ml-3">Checking VPN...</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!vpnConnected) {
|
||||
return (
|
||||
<div className="min-h-screen flex justify-center items-center text-center">
|
||||
<div className="card shadow-xl bg-base-100 p-6">
|
||||
<h2 className="text-xl font-bold text-red-600">VPN Required</h2>
|
||||
<p className="mt-2">Please connect to your company VPN to continue.</p>
|
||||
if (!vpnConnected) {
|
||||
return (
|
||||
<div className="min-h-screen flex justify-center items-center text-center">
|
||||
<div className="card shadow-xl bg-base-100 p-6">
|
||||
<h2 className="text-xl font-bold text-red-600">VPN Required</h2>
|
||||
<p className="mt-2">Please connect to your company VPN to continue.</p>
|
||||
|
||||
<button className="btn btn-primary mt-4"
|
||||
onClick={() => window.location.reload()}>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<button className="btn btn-primary mt-4"
|
||||
onClick={checkVPN}>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default VpnGuard;
|
||||
|
|
|
|||
|
|
@ -133,6 +133,15 @@ interface PayslipResponse {
|
|||
}
|
||||
|
||||
|
||||
interface RegionResponse {
|
||||
success: boolean;
|
||||
status: number;
|
||||
data?: any;
|
||||
retry?: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
|
||||
interface Window {
|
||||
electron: {
|
||||
login: (credentials: { email: string; password: string }) => Promise<any>;
|
||||
|
|
@ -241,6 +250,8 @@ interface Window {
|
|||
success: boolean;
|
||||
data?: any;
|
||||
}>;
|
||||
|
||||
checkRegion: () => Promise<RegionResponse>;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue