fixed issue if no project assign
This commit is contained in:
parent
e3692467e3
commit
b4403c2cd5
|
|
@ -1,12 +1,11 @@
|
||||||
|
|
||||||
[Interface]
|
[Interface]
|
||||||
PrivateKey = EA2j6mOQB17w497cZS4B91m/xDzEcGz9lU3jKtc1wU8=
|
PrivateKey = yHrWqSi5ZV4YV1cVVPBt2NbmTHd/mDWtZGVWGQe5I3s=
|
||||||
Address = 10.0.0.27/32
|
Address = 10.0.0.91/32
|
||||||
DNS = 1.1.1.1
|
DNS = 1.1.1.1
|
||||||
|
|
||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = jG+7H5thEiNjxY1XqI1R9oyMAMTIegLwE3tZkS1Rj2U=
|
PublicKey = jG+7H5thEiNjxY1XqI1R9oyMAMTIegLwE3tZkS1Rj2U=
|
||||||
AllowedIPs = 10.0.0.0/24
|
|
||||||
Endpoint = 35.95.209.161:51820
|
Endpoint = 35.95.209.161:51820
|
||||||
AllowedIPs = 10.0.0.0/24
|
AllowedIPs = 10.0.0.0/24
|
||||||
PersistentKeepalive = 25
|
PersistentKeepalive = 25
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// electron/api/axiosClient.ts
|
// electron/api/axiosClient.ts
|
||||||
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||||
import { getToken } from '../utils/tokenHelper.js';
|
import { getToken } from '../utils/tokenHelper.js';
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { sendTokenExpired } from '../ipc/ipcHandler.js';
|
import { sendTokenExpired } from '../ipc/ipcHandler.js';
|
||||||
|
|
@ -8,40 +8,61 @@ import { getBaseURL } from './baseURL.js';
|
||||||
|
|
||||||
const TOKEN_KEY = 'ACCESS_TOKEN';
|
const TOKEN_KEY = 'ACCESS_TOKEN';
|
||||||
|
|
||||||
const Base_URL = await getBaseURL()
|
// const Base_URL = await getBaseURL()
|
||||||
|
|
||||||
const httpsAgent = new https.Agent({
|
const httpsAgent = new https.Agent({
|
||||||
rejectUnauthorized: false
|
rejectUnauthorized: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
console.log('Base_URL$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$' ,Base_URL)
|
// console.log('Base_URL$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$' ,Base_URL)
|
||||||
|
|
||||||
const api: AxiosInstance = axios.create({
|
const api: AxiosInstance = axios.create({
|
||||||
// baseURL: 'https://portal-sf.docva.com/api/v1/va', // 🔁 your backend
|
// baseURL: 'https://portal-sf.docva.com/api/v1/va', // 🔁 your backend
|
||||||
baseURL: `${Base_URL}/api/v1/va`,
|
// baseURL: `${Base_URL}/api/v1/va`,
|
||||||
httpsAgent
|
httpsAgent
|
||||||
// timeout: 10000,
|
// timeout: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export function syncAxiosBaseURL() {
|
||||||
|
const baseURL = getBaseURL();
|
||||||
|
api.defaults.baseURL = `${baseURL}/api/v1/va`;
|
||||||
|
|
||||||
|
console.log('✅ Axios baseURL synced →', api.defaults.baseURL);
|
||||||
|
}
|
||||||
|
|
||||||
// console.log("Creating Axios Instance", axios.VERSION);
|
// console.log("Creating Axios Instance", axios.VERSION);
|
||||||
// console.log("Axios .get reference:", api.get);
|
// console.log("Axios .get reference:", api.get);
|
||||||
// console.log("Axios .request reference:", api.request);
|
// console.log("Axios .request reference:", api.request);
|
||||||
|
|
||||||
// --- Request Interceptor ---
|
// --- Request Interceptor ---
|
||||||
|
// api.interceptors.request.use(
|
||||||
|
// async (config: AxiosRequestConfig): Promise<any> => {
|
||||||
|
// const token = await getToken(TOKEN_KEY);
|
||||||
|
// config.headers = config.headers || {}
|
||||||
|
|
||||||
|
// if (token) {
|
||||||
|
// config.headers['token'] = token;
|
||||||
|
// config.headers['ngrok-skip-browser-warning'] = 'true';
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return config;
|
||||||
|
// },
|
||||||
|
// (error) => Promise.reject(error)
|
||||||
|
// );
|
||||||
|
|
||||||
api.interceptors.request.use(
|
api.interceptors.request.use(
|
||||||
async (config: AxiosRequestConfig): Promise<any> => {
|
async (config: InternalAxiosRequestConfig) => {
|
||||||
const token = await getToken(TOKEN_KEY);
|
const token = await getToken(TOKEN_KEY);
|
||||||
config.headers = config.headers || {}
|
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
config.headers['token'] = token;
|
config.headers.token = token;
|
||||||
config.headers['ngrok-skip-browser-warning'] = 'true';
|
config.headers['ngrok-skip-browser-warning'] = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
},
|
}
|
||||||
(error) => Promise.reject(error)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- Response Interceptor ---
|
// --- Response Interceptor ---
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
import { syncAxiosBaseURL } from "./axiosClient.js";
|
||||||
|
|
||||||
// let CURRENT_BASE_URL = "https://portal-sf.docva.com/api/v1/va";
|
// let CURRENT_BASE_URL = "https://portal-sf.docva.com/api/v1/va";
|
||||||
let CURRENT_BASE_URL = "https://portal-sf.docva.com";
|
let CURRENT_BASE_URL = "https://portal-sf.docva.com";
|
||||||
|
|
||||||
export const getBaseURL = () => CURRENT_BASE_URL;
|
export const getBaseURL = () => CURRENT_BASE_URL;
|
||||||
export const setBaseURL = (url: string) => {
|
export const setBaseURL = (url: string) => {
|
||||||
CURRENT_BASE_URL = url;
|
CURRENT_BASE_URL = url;
|
||||||
|
syncAxiosBaseURL();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ const finalizeAndSendLogs = useCallback(
|
||||||
// } : null,
|
// } : null,
|
||||||
// });
|
// });
|
||||||
|
|
||||||
let res = window.electron.trackingTabsOpeningClosing(payload);
|
let res = await window.electron.trackingTabsOpeningClosing(payload);
|
||||||
console.log("Tracking response:", res);
|
console.log("Tracking response:", res);
|
||||||
|
|
||||||
dispatch(clearProjectLogs({ projectId }));
|
dispatch(clearProjectLogs({ projectId }));
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,14 @@ const Dashboard: React.FC = () => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// FIX: Check if we have any projects
|
||||||
|
if (res.data.length === 0) {
|
||||||
|
// No projects available, clear selected project
|
||||||
|
dispatch(setSelectedProjectSlice(null));
|
||||||
|
// fetchProfile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we already have a selected project that's being tracked
|
// Check if we already have a selected project that's being tracked
|
||||||
const currentlySelected = selectedProject;
|
const currentlySelected = selectedProject;
|
||||||
const currentlyTracking = isTracking;
|
const currentlyTracking = isTracking;
|
||||||
|
|
@ -208,9 +216,13 @@ const Dashboard: React.FC = () => {
|
||||||
fetchProfile();
|
fetchProfile();
|
||||||
} else {
|
} else {
|
||||||
console.warn("⚠️ Unexpected response:", res);
|
console.warn("⚠️ Unexpected response:", res);
|
||||||
|
// FIX: Also clear selected project on unexpected response
|
||||||
|
dispatch(setSelectedProjectSlice(null));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("❌ Error fetching projects:", err);
|
console.error("❌ Error fetching projects:", err);
|
||||||
|
// FIX: Clear selected project on error
|
||||||
|
dispatch(setSelectedProjectSlice(null));
|
||||||
} finally {
|
} finally {
|
||||||
setIsRefreshing(false);
|
setIsRefreshing(false);
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +230,7 @@ const Dashboard: React.FC = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchProjects();
|
fetchProjects();
|
||||||
|
fetchProfile()
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleRefresh = async () => {
|
const handleRefresh = async () => {
|
||||||
|
|
@ -285,6 +298,7 @@ const Dashboard: React.FC = () => {
|
||||||
<h1 className="text-md font-bold">Dashboard</h1>
|
<h1 className="text-md font-bold">Dashboard</h1>
|
||||||
</div>
|
</div>
|
||||||
{/* Tracking Section */}
|
{/* Tracking Section */}
|
||||||
|
{/* Tracking Section */}
|
||||||
<div className="w-full mb-4">
|
<div className="w-full mb-4">
|
||||||
<div className="card bg-base-100 border border-base-200 shadow-sm card-sm">
|
<div className="card bg-base-100 border border-base-200 shadow-sm card-sm">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
|
|
@ -305,11 +319,6 @@ const Dashboard: React.FC = () => {
|
||||||
<p className="text-lg font-extrabold text-success">
|
<p className="text-lg font-extrabold text-success">
|
||||||
{formatTime(displayTime)}
|
{formatTime(displayTime)}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* <p className={`text-lg font-extrabold ${isLimitReached ? 'text-error' : 'text-success'}`}>
|
|
||||||
{formatTime(displayTime)}
|
|
||||||
{isLimitReached && " ⚠️"}
|
|
||||||
</p> */}
|
|
||||||
<div>
|
<div>
|
||||||
<span className="text-base-content/70">Project:</span>{" "}
|
<span className="text-base-content/70">Project:</span>{" "}
|
||||||
<span className="font-semibold">
|
<span className="font-semibold">
|
||||||
|
|
@ -356,7 +365,9 @@ const Dashboard: React.FC = () => {
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-sm text-base-content/60 text-center">
|
<p className="text-sm text-base-content/60 text-center">
|
||||||
Select a project below to start tracking.
|
{projectsData.length === 0
|
||||||
|
? "No projects available."
|
||||||
|
: "Select a project below to start tracking."}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -369,15 +380,15 @@ const Dashboard: React.FC = () => {
|
||||||
<div className="sticky top-0 z-20 bg-base-100 border-b border-base-content/10 p-3 flex justify-between items-center">
|
<div className="sticky top-0 z-20 bg-base-100 border-b border-base-content/10 p-3 flex justify-between items-center">
|
||||||
<p className="text-md font-bold">Projects</p>
|
<p className="text-md font-bold">Projects</p>
|
||||||
{!selectedData?.isTracking &&
|
{!selectedData?.isTracking &&
|
||||||
<button
|
<button
|
||||||
onClick={handleRefresh}
|
onClick={handleRefresh}
|
||||||
disabled={isRefreshing }
|
disabled={isRefreshing}
|
||||||
className="btn btn-xs btn-ghost gap-1 text-warning"
|
className="btn btn-xs btn-ghost gap-1 text-warning"
|
||||||
title="Refresh projects"
|
title="Refresh projects"
|
||||||
>
|
>
|
||||||
<RefreshCw className={`w-3 h-3 text-warning ${isRefreshing ? 'animate-spin' : ''}`} />
|
<RefreshCw className={`w-3 h-3 text-warning ${isRefreshing ? 'animate-spin' : ''}`} />
|
||||||
Refresh
|
Refresh
|
||||||
</button>}
|
</button>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 🔹 Table or Empty State or Skeleton */}
|
{/* 🔹 Table or Empty State or Skeleton */}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ const PaysSlips = () => {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [rows, setRows] = useState<any[]>([]);
|
const [rows, setRows] = useState<any[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!projectSummary?.vaId) return;
|
if (!projectSummary?.vaId) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,13 +64,11 @@ const Timesheets: React.FC = () => {
|
||||||
const [lastRefreshed, setLastRefreshed] = useState<Date | null>(null);
|
const [lastRefreshed, setLastRefreshed] = useState<Date | null>(null);
|
||||||
const [initialLoading, setInitialLoading] = useState(true);
|
const [initialLoading, setInitialLoading] = useState(true);
|
||||||
const [tick, setTick] = useState(0);
|
const [tick, setTick] = useState(0);
|
||||||
const { selectedProject } =
|
const { selectedProject } = useSelector((state: any) => state.projects);
|
||||||
useSelector((state: any) => state.projects);
|
const selectedProjectId = selectedProject?.projectId ?? null;
|
||||||
|
|
||||||
const activeProjects = projectsData.filter(p => p.status === "ACTIVE");
|
const activeProjects = projectsData.filter(p => p.status === "ACTIVE");
|
||||||
|
|
||||||
console.log("selectedProject", selectedProject.projectId)
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
|
|
@ -225,13 +223,13 @@ const Timesheets: React.FC = () => {
|
||||||
<td>{formatWorkTime(entry.totalWorkTime)}</td>
|
<td>{formatWorkTime(entry.totalWorkTime)}</td>
|
||||||
<td>
|
<td>
|
||||||
<button
|
<button
|
||||||
disabled={(formatWorkTime(entry.totalWorkTime) === "0h 0m" || (isTracking && entry.projectId === selectedProject.projectId))}
|
disabled={(formatWorkTime(entry.totalWorkTime) === "0h 0m" || (isTracking && entry.projectId === selectedProjectId))}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
handleViewLogs(entry.projectId, entry.projectName)
|
handleViewLogs(entry.projectId, entry.projectName)
|
||||||
}
|
}
|
||||||
className="btn btn-ghost btn-xs"
|
className="btn btn-ghost btn-xs"
|
||||||
>
|
>
|
||||||
{(formatWorkTime(entry.totalWorkTime) === "0h 0m" || (isTracking && entry.projectId === selectedProject.projectId)) ? (
|
{(formatWorkTime(entry.totalWorkTime) === "0h 0m" || (isTracking && entry.projectId === selectedProjectId)) ? (
|
||||||
<EyeOff size={16} />
|
<EyeOff size={16} />
|
||||||
) : (
|
) : (
|
||||||
<Eye size={16} />
|
<Eye size={16} />
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ interface Props {
|
||||||
|
|
||||||
const VpnGuard: React.FC<Props> = ({ children }) => {
|
const VpnGuard: React.FC<Props> = ({ children }) => {
|
||||||
|
|
||||||
const VPN_API = "http://10.0.0.1:3000";
|
const VPN_API = "http://10.0.0.1";
|
||||||
const DEFAULT_API = "https://portal-sf.docva.com"
|
const DEFAULT_API = "https://portal-sf.docva.com"
|
||||||
|
|
||||||
const [checking, setChecking] = useState(true);
|
const [checking, setChecking] = useState(true);
|
||||||
|
|
@ -66,6 +66,7 @@ const VpnGuard: React.FC<Props> = ({ children }) => {
|
||||||
console.log("vpnRes", vpnRes);
|
console.log("vpnRes", vpnRes);
|
||||||
|
|
||||||
if (vpnRes) {
|
if (vpnRes) {
|
||||||
|
|
||||||
// Run VPN check again AFTER URL changes
|
// Run VPN check again AFTER URL changes
|
||||||
await checkVPN();
|
await checkVPN();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue