Compare commits

..

16 Commits

Author SHA1 Message Date
JaiPandey425 f5f94f016b Merge branch 'master' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker into window-build - merge 1-14 12-Dec - B Master 2025-12-04 13:14:46 +05:30
BhagwanSingh 93704a70f6 Merge branch 'window-build' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker - 04-Dec 2025-12-04 11:57:24 +05:30
BhagwanSingh ed0bcb7107 Socket update 2025-12-02 20:02:55 +05:30
BhagwanSingh 3ef615a160 Merge branch 'window-build' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker - 30-11 Merge Window-build 2025-11-30 11:47:21 +05:30
BhagwanSingh b55f9469ad Merge branch 'master' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker 2025-11-30 11:44:00 +05:30
BhagwanSingh d23933c517 30-11 2025-11-30 11:39:41 +05:30
Bhagwan Singh 92e8c15023 Mac Docva Icon Fixed 2025-11-28 17:40:30 +05:30
Bhagwan Singh 35eb073f46 Merge branch 'master' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker - 28-11 2025-11-28 13:25:02 +05:30
apple 94eedff8af Mac Input fields are not viaible fixed 2025-11-28 13:19:01 +05:30
apple ac3ddf4b2b eerge branch 'window-build' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker 2025-11-27 19:40:22 +05:30
apple a55e6ccba4 upd 2025-11-27 19:40:05 +05:30
BhagwanSingh bd4a3656e7 Merge branch 'window-build' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker 2025-11-27 16:41:51 +05:30
BhagwanSingh 345822885f a 2025-11-27 16:34:42 +05:30
BhagwanSingh 0ae8f6185a a 2025-11-27 12:27:52 +05:30
BhagwanSingh 882e8349c9 Merge branch 'window-build' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker into window-build 2025-11-27 12:24:00 +05:30
BhagwanSingh d641e9432d 27-11 merge 2025-11-27 12:21:53 +05:30
10 changed files with 227 additions and 1775 deletions

BIN
build/icon.icns Normal file

Binary file not shown.

1793
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,26 +4,59 @@
<style> <style>
body { body {
margin: 0; margin: 0;
height: 100vh;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background: #ffffff; background: #ffffff;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
} }
.loader {
width: 50px; .loader-container {
height: 50px; position: relative;
border: 5px solid #e0e0e0; width: 100px;
height: 100px;
}
/* Circular spinner */
.loader-ring {
width: 100%;
height: 100%;
border: 6px solid #e0e0e0;
border-top-color: #6a5acd; border-top-color: #6a5acd;
border-radius: 50%; border-radius: 50%;
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
/* Logo in center */
.loader-logo {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
}
.loader-logo img {
width: 45px;
height: 45px;
object-fit: contain;
}
@keyframes spin { @keyframes spin {
to { transform: rotate(360deg); } to { transform: rotate(360deg); }
} }
</style> </style>
</head> </head>
<body> <body>
<div class="loader"></div> <div class="loader-container">
<div class="loader-ring"></div>
<!-- Place your logo here -->
<div class="loader-logo">
<img src="your-logo.png" alt="App Logo">
</div>
</div>
</body> </body>
</html> </html>

View File

@ -12,7 +12,8 @@ const httpsAgent = new https.Agent({
}); });
const api: AxiosInstance = axios.create({ const api: AxiosInstance = axios.create({
baseURL: 'http://localhost:3000/api/v1/va', // 🔁 your backend // https://dreadingly-unfighting-pandora.ngrok-free.dev/
baseURL: 'https://dreadingly-unfighting-pandora.ngrok-free.dev/api/v1/va', // 🔁 your backend
httpsAgent httpsAgent
// timeout: 10000, // timeout: 10000,
}); });

View File

@ -78,10 +78,6 @@ app.on("ready", async () => {
); );
// Create the main window // Create the main window
const win = new BrowserWindow({ const win = new BrowserWindow({
width: 500, width: 500,
@ -91,8 +87,8 @@ app.on("ready", async () => {
minimizable: false, minimizable: false,
maximizable: false, maximizable: false,
closable: true, closable: true,
alwaysOnTop: true, // alwaysOnTop: true,
skipTaskbar: true, // skipTaskbar: true,
autoHideMenuBar: true, autoHideMenuBar: true,
frame: true, frame: true,
show: false, show: false,
@ -105,9 +101,24 @@ app.on("ready", async () => {
}, },
}); });
win.setAlwaysOnTop(true, 'screen-saver');
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
win.setFullScreenable(false); // win.setAlwaysOnTop(true, 'screen-saver');
// win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
// win.setFullScreenable(false);
// Cross-platform safe always-on-top
const isMac = process.platform === "darwin";
if (isMac) {
win.setAlwaysOnTop(true, "floating"); // best for macOS
win.setVisibleOnAllWorkspaces(true); // NO fullscreen override
} else {
win.setAlwaysOnTop(true, "normal"); // safest for Windows + Zoom
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
win.setFullScreenable(false);
}
mainWindow = win; mainWindow = win;
@ -149,7 +160,7 @@ app.on("ready", async () => {
// ------------------------------------ // ------------------------------------
// HANDLE CLOSE EVENTS // HANDLE CLOSE EVENTS
// ------------------------------------ // ------------------------------------
handleCloseEvents(win); // handleCloseEvents(win);
}); });
@ -173,28 +184,28 @@ app.on("ready", async () => {
// --------------------------- // ---------------------------
// CUSTOM CLOSE BEHAVIOR // CUSTOM CLOSE BEHAVIOR
// --------------------------- // ---------------------------
function handleCloseEvents(window: BrowserWindow) { // function handleCloseEvents(window: BrowserWindow) {
let willClose = false; // let willClose = false;
window.on("close", (e) => { // window.on("close", (e) => {
if (willClose) return; // if (willClose) return;
e.preventDefault(); // e.preventDefault();
window.hide(); // window.hide();
if (app.dock) { // if (app.dock) {
app.dock.hide(); // app.dock.hide();
} // }
}); // });
app.on("before-quit", () => { // app.on("before-quit", () => {
willClose = true; // willClose = true;
}); // });
window.on("show", () => { // window.on("show", () => {
willClose = false; // willClose = false;
}); // });
} // }
// --------------------------- // ---------------------------
// GET MAIN WINDOW EXPORT // GET MAIN WINDOW EXPORT

View File

@ -68,7 +68,7 @@ export const handleLogin = async (credentials: { email: string, password: string
try { try {
console.log("➡️ Calling API..."); console.log("➡️ Calling API...");
const response = await axios.post( const response = await axios.post(
'http://localhost:3000/api/v1/va/login', 'https://dreadingly-unfighting-pandora.ngrok-free.dev/api/v1/va/login',
{ userDetails: { ...credentials } }, { userDetails: { ...credentials } },
{ headers: { "ngrok-skip-browser-warning": 69420 }, httpsAgent } { headers: { "ngrok-skip-browser-warning": 69420 }, httpsAgent }
); );

View File

@ -331,6 +331,7 @@ const DashboardLayout = () => {
const socketRef = useRef<Socket | null>(null); const socketRef = useRef<Socket | null>(null);
const intervalRef = useRef<number | null>(null); const intervalRef = useRef<number | null>(null);
const lastAppsRef = useRef<Object | null>(null);
const [isConnected, setIsConnected] = useState(false); const [isConnected, setIsConnected] = useState(false);
useEffect(() => { useEffect(() => {
@ -540,6 +541,7 @@ const DashboardLayout = () => {
} }
}; };
const handleSocketConnect = async () => { const handleSocketConnect = async () => {
const token = await window.electron.getToken("ACCESS_TOKEN"); const token = await window.electron.getToken("ACCESS_TOKEN");
@ -573,12 +575,56 @@ const DashboardLayout = () => {
setIsConnected(true); setIsConnected(true);
// Start sending every 5 seconds // Start sending every 5 seconds
// intervalRef.current = setInterval(async () => {
// const apps = await window.electron.getRunningApps()
// socketRef.current?.emit("getVisibleApps", { token: await token, apps });
// }, 5000);
});
// socketRef.current.on("startSendAppsDetails", async ({ apps }) => {
// socketRef.current?.emit("getVisibleApps", { token: await token, apps });
// });
socketRef.current.on("startSendAppsDetails", async ({projId}) => {
if (projId !== selectedProject?.projectId) return;
console.log("▶️ startSendAppsDetails received");
// avoid multiple intervals
if (intervalRef.current) return;
intervalRef.current = setInterval(async () => { intervalRef.current = setInterval(async () => {
const apps = await window.electron.getRunningApps() const currentApps = await window.electron.getRunningApps();
socketRef.current?.emit("getVisibleApps", { token: await token, apps });
// Compare with last sent data
const hasChanged = JSON.stringify(currentApps) !== JSON.stringify(lastAppsRef.current);
if (hasChanged) {
lastAppsRef.current = currentApps;
socketRef.current?.emit("getVisibleApps", {
token: await token,
apps: currentApps,
});
}
}, 5000); }, 5000);
}); });
socketRef.current.on("stopSendAppsDetails", async ({projId}) => {
if (projId !== selectedProject?.projectId) return;
console.log("⏹ stopSendAppsDetails received");
// clear the interval
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
// Send final stop event to server
// socketRef.current?.emit("stopSendAppsDetails", {
// token: await token,
// });
});
socketRef.current.on("appToCapture", async ({ appTitle }) => { socketRef.current.on("appToCapture", async ({ appTitle }) => {
console.log("📸 Capture requested for:", appTitle); console.log("📸 Capture requested for:", appTitle);

View File

@ -200,7 +200,7 @@ const PtoLeaveTab: React.FC<{
if (result.success) { if (result.success) {
resetForm(); resetForm();
alert("PTO submitted!"); alert("PTO Request submitted!");
navigate('/dashboard/leave-adjustments') navigate('/dashboard/leave-adjustments')
} else { } else {
setServerError(result.message || "Something went wrong"); setServerError(result.message || "Something went wrong");

View File

@ -126,6 +126,33 @@ const SickLeaveTab: React.FC<{
reader.readAsDataURL(file); reader.readAsDataURL(file);
}); });
useEffect(() => {
const editor = quillRef.current?.getEditor();
if (!editor) return;
editor.getModule("clipboard").addMatcher(Node.ELEMENT_NODE, (node: any, delta: any) => {
return delta;
});
editor.root.addEventListener("paste", async (e: any) => {
const items = e.clipboardData?.items;
if (!items) return;
for (const item of items) {
if (item.type.indexOf("image") === 0) {
const file = item.getAsFile();
const base64 = await convertToBase64(file);
const range = editor.getSelection();
editor.insertEmbed(range.index, "image", base64);
}
}
});
}, []);
const validateLeaveForm = (data: LeaveFormData): Partial<LeaveFormData> => { const validateLeaveForm = (data: LeaveFormData): Partial<LeaveFormData> => {
const errors: Partial<LeaveFormData> = {}; const errors: Partial<LeaveFormData> = {};
@ -161,7 +188,6 @@ const SickLeaveTab: React.FC<{
toDate: "", toDate: "",
comment: "" comment: ""
}; };
setSickLeave(emptyForm); setSickLeave(emptyForm);
setSickErrors({}); setSickErrors({});
@ -190,7 +216,7 @@ const SickLeaveTab: React.FC<{
if (result.success) { if (result.success) {
resetForm(); resetForm();
alert("SICK submitted!"); alert("SICK leave applied!");
navigate('/dashboard/leave-adjustments') navigate('/dashboard/leave-adjustments')
} else { } else {
setServerError(result.message || "Something went wrong"); setServerError(result.message || "Something went wrong");

14
types.d.ts vendored
View File

@ -1,3 +1,13 @@
declare module "quill";
declare module "quill-image-resize-module";
declare module "quill-image-drop-module";
declare module "quill-image-resize-module-react" {
const ImageResize: any;
export default ImageResize;
}
type Statistics = { type Statistics = {
cpuUsage: number; cpuUsage: number;
ramUsage: number; ramUsage: number;
@ -144,14 +154,16 @@ interface Window {
vaId: string; vaId: string;
projectId: string; projectId: string;
type: string; type: string;
time:string
}) => Promise<any>; }) => Promise<any>;
stopProjectTracking: (data: { stopProjectTracking: (data: {
vaId: string; vaId: string;
projectId: string; projectId: string;
type: string; type: string;
time:string
}) => Promise<any>; }) => Promise<any>;
trackingTabsOpeningClosing: (data: { trackingTabsOpeningClosing: (data: {
id?: string; // optional, only present if updating id?: string;
logId: string; logId: string;
projectId: string; projectId: string;
title: string; title: string;