va-tracker/src/ui/pages/Vpn/VpnGuard.tsx

202 lines
7.4 KiB
TypeScript

import React, { useEffect, useState } from "react";
import { Shield, ShieldAlert, RefreshCw, Wifi, Power } from "lucide-react";
interface Props {
children: React.ReactNode;
}
const VpnGuard: React.FC<Props> = ({ children }) => {
const VPN_API = "http://10.0.0.1";
const DEFAULT_API = "https://portal-sf.docva.com"
const [checking, setChecking] = useState(true);
const [vpnConnected, setVpnConnected] = useState(true);
const [isRetrying, setIsRetrying] = useState(false);
const checkVPN = async () => {
try {
setChecking(true);
const res = await window.electron?.checkRegion();
console.log("VpnGuard", res);
if (res.status === 200) {
setVpnConnected(true);
} else {
setVpnConnected(false);
return;
}
// setVpnConnected(res?.success === true);
} catch (error) {
console.error("VPN check failed:", error);
setVpnConnected(false);
} finally {
setChecking(false);
setIsRetrying(false);
}
};
useEffect(() => {
checkVPN();
}, []);
const connectVPN = async () => {
setChecking(true);
try {
const res = await window.electron.connectVPN();
console.log("connectVPN result → ", res);
// Only proceed if VPN actually connected
if (res === "Windows VPN connected silently") {
const vpnRes = await window.electron.updateBaseURL(VPN_API);
console.log("vpnRes", vpnRes);
if (vpnRes) {
// Run VPN check again AFTER URL changes
await checkVPN();
} else {
console.warn("Base URL updated but health check failed");
}
}
} catch (error) {
console.log(error);
const vpnRes = await window.electron.updateBaseURL(VPN_API);
console.log("vpnRes", vpnRes);
if (vpnRes) {
// Run VPN check again AFTER URL changes
await checkVPN();
} else {
console.warn("Base URL updated but health check failed");
}
} finally {
setChecking(false);
}
};
const disconnectVPN = async () => {
setChecking(true);
try {
const res = await window.electron.disconnectVPN();;
console.log("disconnectVPN →", res);
// Restore original base URL
const baseRes = await window.electron.updateBaseURL(DEFAULT_API);
console.log("baseRes disconnect →", baseRes);
setVpnConnected(true);
// await checkVPN();
} catch (error) {
console.log("Disconnect Error:", error);
} finally {
setChecking(false);
}
};
// Checking state
if (checking && !isRetrying) {
return (
<div className="min-h-screen flex flex-col justify-center items-center bg-base-200">
<div className="relative">
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-24 h-24 border-4 border-primary opacity-20 rounded-full animate-ping"></div>
</div>
<div className="relative bg-base-100 rounded-full p-6 shadow-xl">
<Shield className="w-12 h-12 text-primary animate-pulse" />
</div>
</div>
<div className="mt-8 text-center">
<h2 className="text-2xl font-semibold mb-2">
Verifying Connection
</h2>
<p className="text-base-content opacity-70">Checking VPN status...</p>
<div className="flex justify-center mt-4 gap-1">
<span className="loading loading-dots loading-md text-primary"></span>
</div>
</div>
</div>
);
}
// VPN not connected state
if (!vpnConnected) {
return (
<div className="min-h-screen flex flex-col justify-center items-center bg-base-200 p-4">
<div className="max-w-md w-full">
<div className="card bg-base-100 shadow-2xl">
<div className="card-body items-center text-center">
{/* Icon */}
<div className="relative mb-4">
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-20 h-20 border-4 border-error opacity-20 rounded-full animate-pulse"></div>
</div>
<div className="relative bg-error bg-opacity-10 rounded-full p-4">
<ShieldAlert className="w-12 h-12" />
</div>
</div>
<h2 className="card-title text-3xl mb-3">VPN Required</h2>
<p className="mb-6 opacity-80">
Please connect to your company VPN to access this application.
</p>
{/* Connect VPN */}
<button
className="btn btn-primary btn-wide gap-2"
onClick={connectVPN}
disabled={isRetrying || vpnConnected} // Disable if retrying OR already connected
>
{isRetrying ? (
<>
<span className="loading loading-spinner loading-sm"></span>
Checking Connection...
</>
) : (
<>
<RefreshCw className="w-5 h-5" />
Connect VPN
</>
)}
</button>
{/* Disconnect VPN (Disabled when NOT connected) */}
<button
className="btn btn-error btn-wide gap-2 mt-3"
onClick={disconnectVPN}
// disabled={!vpnConnected || checking} // Disable if not connected
>
<Power className="w-4 h-4" />
Disconnect VPN
</button>
<div className="divider"></div>
<p className="text-xs opacity-60">
Need help? Contact IT support at{" "}
<a href="mailto:support@docva.com" className="link link-primary">
support@docva.com
</a>
</p>
</div>
</div>
</div>
</div>
);
}
return (
<>
{children}
</>
);
};
export default VpnGuard;