Merge branch 'window-build' of http://git.hicglobalsolutions.in/BhawanSingh/va-tracker - 30-11 Merge Window-build
This commit is contained in:
commit
3ef615a160
|
|
@ -183,19 +183,6 @@ ipcMain.handle("tracking-tabs-opening-and-closing", async (event, payload) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// ipcMain.handle("get-project-logs", async (event, projectID) => {
|
|
||||||
// try {
|
|
||||||
// console.log("get-project-logs",projectID)
|
|
||||||
// const response = await api.get(`/report/project/${projectID}`);
|
|
||||||
// console.log("response-logs 164" , response)
|
|
||||||
|
|
||||||
// return response;
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Error fetching project logs:", error);
|
|
||||||
// throw error;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
ipcMain.handle("get-project-logs", async (event, { projectID, fromDate, toDate }) => {
|
ipcMain.handle("get-project-logs", async (event, { projectID, fromDate, toDate }) => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -378,6 +365,75 @@ ipcMain.handle("create-leave-request", async (event, payload) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ipcMain.handle("get-schedules", async () => {
|
||||||
|
try {
|
||||||
|
console.log(" Fetching schedules...");
|
||||||
|
|
||||||
|
const response = await api.get("/payrollSchedule"); // Backend API call
|
||||||
|
|
||||||
|
console.log("✅ Schedule Data:", response.data);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
result: response.data
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("❌ Fetch Schedules Failed:");
|
||||||
|
|
||||||
|
let message = "Unknown error occurred";
|
||||||
|
|
||||||
|
if (error.response) {
|
||||||
|
console.log("Status:", error.response.status);
|
||||||
|
console.log("Message:", error.response.statusText);
|
||||||
|
console.log("Server Response:", error.response.data);
|
||||||
|
|
||||||
|
message = error.response.data?.message || error.response.statusText;
|
||||||
|
} else {
|
||||||
|
message = error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
ipcMain.handle("get-payslips", async (event, vaId: string) => {
|
||||||
|
console.log("get-payslips",vaId)
|
||||||
|
try {
|
||||||
|
const response = await api.get(`/paySlip/${vaId}`);
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: response.data?.data || [],
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
let message = "Unknown error occurred";
|
||||||
|
|
||||||
|
if (error.response) {
|
||||||
|
console.log("Status:", error.response.status);
|
||||||
|
console.log("Message:", error.response.statusText);
|
||||||
|
console.log("Server Response:", error.response.data);
|
||||||
|
|
||||||
|
message = error.response.data?.message || error.response.statusText;
|
||||||
|
} else {
|
||||||
|
message = error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const sendTokenExpired = () => {
|
export const sendTokenExpired = () => {
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@ contextBridge.exposeInMainWorld('electron', {
|
||||||
createPTOAndSickLeaveRequest: (data) =>
|
createPTOAndSickLeaveRequest: (data) =>
|
||||||
ipcRenderer.invoke("create-leave-request", data),
|
ipcRenderer.invoke("create-leave-request", data),
|
||||||
|
|
||||||
|
getSchedules: () => ipcRenderer.invoke("get-schedules"),
|
||||||
|
|
||||||
|
getPayslips: (vaId: string) => ipcRenderer.invoke("get-payslips", vaId),
|
||||||
|
|
||||||
} satisfies Window['electron']);
|
} satisfies Window['electron']);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ import Settings from "./pages/Settings/Settings";
|
||||||
import HelpSupport from "./pages/HelpSupport/HelpSupport";
|
import HelpSupport from "./pages/HelpSupport/HelpSupport";
|
||||||
import Vpn from "./pages/Vpn/Vpn";
|
import Vpn from "./pages/Vpn/Vpn";
|
||||||
import Schedule from "./pages/Schedule/Schedule";
|
import Schedule from "./pages/Schedule/Schedule";
|
||||||
|
import PaysSlips from "./pages/PaySlips/PaysSlips";
|
||||||
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
@ -142,6 +143,7 @@ const App: React.FC = () => {
|
||||||
<Route path="vpn" element={<Vpn />} />
|
<Route path="vpn" element={<Vpn />} />
|
||||||
<Route path="help-support" element={<HelpSupport />} />
|
<Route path="help-support" element={<HelpSupport />} />
|
||||||
<Route path="schedule" element={<Schedule/>} />
|
<Route path="schedule" element={<Schedule/>} />
|
||||||
|
<Route path="pays-slips" element={<PaysSlips/>} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
{/* Default Redirect */}
|
{/* Default Redirect */}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import {
|
||||||
ChevronUp,
|
ChevronUp,
|
||||||
GlobeLock,
|
GlobeLock,
|
||||||
ClipboardClock,
|
ClipboardClock,
|
||||||
|
CircleDollarSign,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useActiveAppTracker } from "../hooks/useActiveAppTracker";
|
import { useActiveAppTracker } from "../hooks/useActiveAppTracker";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
@ -113,6 +114,7 @@ const DashboardLayout = () => {
|
||||||
{ label: "Timesheet", path: "/dashboard/timesheet", icon: <TimerIcon size={18} /> },
|
{ label: "Timesheet", path: "/dashboard/timesheet", icon: <TimerIcon size={18} /> },
|
||||||
{ label: "Leave & Adjust", path: "/dashboard/leave-adjustments", icon: <CalendarDays size={18} /> },
|
{ label: "Leave & Adjust", path: "/dashboard/leave-adjustments", icon: <CalendarDays size={18} /> },
|
||||||
{ label: "Schedule", path: "/dashboard/schedule", icon: <ClipboardClock size={18} />},
|
{ label: "Schedule", path: "/dashboard/schedule", icon: <ClipboardClock size={18} />},
|
||||||
|
{ label: "Pays Slips", path: "/dashboard/pays-slips", icon: <CircleDollarSign size={18} />},
|
||||||
{ label: "Settings", path: "/dashboard/settings", icon: <SettingsIcon size={18} /> },
|
{ label: "Settings", path: "/dashboard/settings", icon: <SettingsIcon size={18} /> },
|
||||||
{ label: "VPN", path: "/dashboard/vpn", icon: <GlobeLock size={18} /> },
|
{ label: "VPN", path: "/dashboard/vpn", icon: <GlobeLock size={18} /> },
|
||||||
{ label: "Help & Support", path: "/dashboard/help-support", icon: <HelpCircleIcon size={18} /> },
|
{ label: "Help & Support", path: "/dashboard/help-support", icon: <HelpCircleIcon size={18} /> },
|
||||||
|
|
@ -297,7 +299,7 @@ const DashboardLayout = () => {
|
||||||
);
|
);
|
||||||
console.log("Alert Message 2")
|
console.log("Alert Message 2")
|
||||||
// Stop tracking
|
// Stop tracking
|
||||||
await handleStopTracking();
|
// await handleStopTracking();
|
||||||
}, [selectedProject, handleStopTracking]);
|
}, [selectedProject, handleStopTracking]);
|
||||||
|
|
||||||
// Initialize useActiveAppTracker and store finalizeTracking in ref
|
// Initialize useActiveAppTracker and store finalizeTracking in ref
|
||||||
|
|
@ -743,7 +745,7 @@ const DashboardLayout = () => {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="absolute bottom-13 ">
|
<div className={`bsolute ${!isTracking ? "bottom-13" : "bottom-5"} `}>
|
||||||
<label className="swap swap-rotate p-2.5">
|
<label className="swap swap-rotate p-2.5">
|
||||||
{/* this hidden checkbox controls the state */}
|
{/* this hidden checkbox controls the state */}
|
||||||
<input type="checkbox" className="theme-controller" onChange={toggleTheme}
|
<input type="checkbox" className="theme-controller" onChange={toggleTheme}
|
||||||
|
|
|
||||||
|
|
@ -258,8 +258,8 @@ const PtoLeaveTab: React.FC<{
|
||||||
onChange={(val) => handleChange('comment', val)}
|
onChange={(val) => handleChange('comment', val)}
|
||||||
className="h-60"
|
className="h-60"
|
||||||
/>
|
/>
|
||||||
{errors.comment && <p className="text-error text-xs">{errors.comment}</p>}
|
|
||||||
</div>
|
</div>
|
||||||
|
{errors.comment && <p className="text-error text-xs">{errors.comment}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{serverError && (
|
{serverError && (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { RootState } from "../../store";
|
||||||
|
|
||||||
|
const PaysSlips = () => {
|
||||||
|
const { projectSummary } =
|
||||||
|
useSelector((state: any) => state.projects);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [rows, setRows] = useState<any[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!projectSummary?.vaId) return;
|
||||||
|
|
||||||
|
fetchPayslips(projectSummary?.vaId);
|
||||||
|
|
||||||
|
}, [projectSummary?.vaId]);
|
||||||
|
|
||||||
|
const fetchPayslips = async (vaId: string) => {
|
||||||
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log("getPayslips" , vaId)
|
||||||
|
const result = await window.electron.getPayslips(vaId);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
setError(result.message || "Failed to load payslips");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = result.data;
|
||||||
|
|
||||||
|
if (!response || response.length === 0) {
|
||||||
|
setRows([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract payrolls array from first index
|
||||||
|
const payrolls = response[0]?.payrolls || [];
|
||||||
|
|
||||||
|
setRows(payrolls);
|
||||||
|
} catch (err: any) {
|
||||||
|
setError("An unexpected error occurred");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col gap-2 max-h-screen">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<h2 className="text-md font-bold">Payslips</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="overflow-y-auto rounded-box border border-base-content/10 bg-base-100 shadow-md max-h-[80vh] min-h-[83vh] no-scrollbar">
|
||||||
|
|
||||||
|
{loading && (
|
||||||
|
<div className="flex justify-center py-10">
|
||||||
|
<span className="loading loading-spinner loading-md"></span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<div className="text-center text-red-500 py-5">{error}</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && !error && rows.length === 0 && (
|
||||||
|
<div className="text-center py-10 text-gray-500">
|
||||||
|
No payslip data available.
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!loading && !error && rows.length > 0 && (
|
||||||
|
<div className="overflow-x-auto w-full no-scrollbar">
|
||||||
|
<table className="table table-zebra w-full text-[12px] min-w-[650px]">
|
||||||
|
<thead className="sticky top-0 bg-base-200 z-10">
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Total Hours</th>
|
||||||
|
<th>Total Pay</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{rows.map((row, index) => (
|
||||||
|
<tr key={row.id}>
|
||||||
|
<td>{index + 1}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
className={`badge ${
|
||||||
|
row.status === "Paid"
|
||||||
|
? "badge-success"
|
||||||
|
: "badge-warning"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{row.status}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>{row.payrollSchedule}</td>
|
||||||
|
|
||||||
|
<td>{row.totalHoursFormatted}</td>
|
||||||
|
|
||||||
|
<td>${row.totalPayAmount.toFixed(2)}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-primary"
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PaysSlips;
|
||||||
|
|
@ -1,70 +1,115 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
|
interface ScheduleItem {
|
||||||
|
id: string;
|
||||||
|
isActive: boolean;
|
||||||
|
status: string | null;
|
||||||
|
ScheduleDate: string;
|
||||||
|
cutOffTime: string | null;
|
||||||
|
periodEnd: string | null;
|
||||||
|
periodStart: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
const Schedule = () => {
|
const Schedule = () => {
|
||||||
const rows = [
|
const [rows, setRows] = useState<ScheduleItem[]>([]);
|
||||||
{
|
const [loading, setLoading] = useState(true);
|
||||||
period: "Oct 25, 2025 to Nov 07, 2025",
|
const [error, setError] = useState<string | null>(null);
|
||||||
cutoff: "Nov 11, 2025 05:29:59 AM",
|
|
||||||
payDate: "Nov 14, 2025"
|
// Format helpers using Luxon
|
||||||
},
|
const formatDateTime = (input: string | null) => {
|
||||||
{
|
if (!input) return "-";
|
||||||
period: "Nov 08, 2025 to Nov 21, 2025",
|
return DateTime.fromISO(input)
|
||||||
cutoff: "Nov 25, 2025 05:29:59 AM",
|
.setZone("local")
|
||||||
payDate: "Nov 28, 2025"
|
.toLocaleString(DateTime.DATETIME_MED);
|
||||||
},
|
};
|
||||||
{
|
|
||||||
period: "Nov 22, 2025 to Dec 05, 2025",
|
const formatOnlyDate = (input: string | null) => {
|
||||||
cutoff: "Dec 09, 2025 05:29:59 AM",
|
if (!input) return "-";
|
||||||
payDate: "Dec 12, 2025"
|
return DateTime.fromISO(input)
|
||||||
},
|
.setZone("local")
|
||||||
{
|
.toLocaleString(DateTime.DATE_MED);
|
||||||
period: "Dec 06, 2025 to Dec 19, 2025",
|
};
|
||||||
cutoff: "Dec 23, 2025 05:29:59 AM",
|
|
||||||
payDate: "Dec 26, 2025"
|
// Fetch schedules
|
||||||
},
|
useEffect(() => {
|
||||||
{
|
const loadSchedules = async () => {
|
||||||
period: "Dec 20, 2025 to Jan 02, 2026",
|
try {
|
||||||
cutoff: "Jan 06, 2026 05:29:59 AM",
|
const res = await window.electron.getSchedules();
|
||||||
payDate: "Jan 09, 2026"
|
console.log(res.result);
|
||||||
},
|
|
||||||
{
|
if (!res.success) {
|
||||||
period: "Jan 03, 2026 to Jan 16, 2026",
|
setError(res.message || "Failed to load schedules");
|
||||||
cutoff: "Jan 20, 2026 05:29:59 AM",
|
return;
|
||||||
payDate: "Jan 23, 2026"
|
}
|
||||||
},
|
|
||||||
{
|
const list = res.result || []; // Use data array
|
||||||
period: "Jan 17, 2026 to Jan 30, 2026",
|
setRows(list);
|
||||||
cutoff: "Feb 03, 2026 05:29:59 AM",
|
} catch (err: any) {
|
||||||
payDate: "Feb 06, 2026"
|
setError(err.message || "Unexpected error");
|
||||||
},
|
} finally {
|
||||||
{
|
setLoading(false);
|
||||||
period: "Jan 31, 2026 to Feb 13, 2026",
|
}
|
||||||
cutoff: "Feb 17, 2026 05:29:59 AM",
|
};
|
||||||
payDate: "Feb 20, 2026"
|
|
||||||
},
|
loadSchedules();
|
||||||
{
|
}, []);
|
||||||
period: "Feb 14, 2026 to Feb 27, 2026",
|
|
||||||
cutoff: "Mar 03, 2026 05:29:59 AM",
|
// Determine if current date is within the schedule period
|
||||||
payDate: "Mar 06, 2026"
|
const isActiveRow = (row: ScheduleItem) => {
|
||||||
},
|
if (!row.periodStart || !row.periodEnd) return false;
|
||||||
{
|
|
||||||
period: "Feb 28, 2026 to Mar 13, 2026",
|
const now = DateTime.local();
|
||||||
cutoff: "Mar 17, 2026 05:29:59 AM",
|
const start = DateTime.fromISO(row.periodStart).startOf("day");
|
||||||
payDate: "Mar 20, 2026"
|
const end = DateTime.fromISO(row.periodEnd).endOf("day");
|
||||||
}
|
|
||||||
];
|
return now >= start && now <= end;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get Active Schedule (only one)
|
||||||
|
const activeSchedule = rows.find((r) => isActiveRow(r));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex flex-col gap-2 max-h-screen">
|
||||||
<div className="flex flex-col gap-2 max-h-screen">
|
{/* Header */}
|
||||||
{/* Header */}
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center justify-between">
|
<h2 className="text-md font-bold">Schedules</h2>
|
||||||
<h2 className="text-md font-bold">Schedules</h2>
|
{activeSchedule && (
|
||||||
</div>
|
<div className="p-1 bg-secondary text-secondary-content rounded-lg">
|
||||||
|
<p className="text-xs">
|
||||||
|
Pay Date: <span className="font-semibold">
|
||||||
|
{formatOnlyDate(activeSchedule.ScheduleDate)}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="overflow-y-auto rounded-box border border-base-content/10 bg-base-100 shadow-md max-h-[80vh] min-h-[83vh] no-scrollbar">
|
<div className="overflow-y-auto rounded-box border border-base-content/10 bg-base-100 shadow-md max-h-[80vh] min-h-[83vh] no-scrollbar">
|
||||||
|
{/* Loader */}
|
||||||
|
{loading && (
|
||||||
|
<div className="flex justify-center items-center h-full">
|
||||||
|
<span className="loading loading-spinner text-primary"></span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* ⭐ FIXED: Horizontal scroll wrapper */}
|
{/* Error */}
|
||||||
|
{!loading && error && (
|
||||||
|
<div className="text-center text-red-500 py-10">❌ {error}</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* No Data */}
|
||||||
|
{!loading && !error && rows.length === 0 && (
|
||||||
|
<div className="text-center text-gray-500 py-10">No schedules found.</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* Table */}
|
||||||
|
{!loading && !error && rows.length > 0 && (
|
||||||
<div className="overflow-x-auto w-full no-scrollbar">
|
<div className="overflow-x-auto w-full no-scrollbar">
|
||||||
<table className="table table-zebra w-full text-[12px] min-w-[600px]">
|
<table className="table w-full text-[12px] min-w-[600px]">
|
||||||
<thead className="sticky top-0 bg-base-200 z-10">
|
<thead className="sticky top-0 bg-base-200 z-10">
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
|
|
@ -76,24 +121,24 @@ const Schedule = () => {
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
{rows.map((row, index) => (
|
{rows.map((row, index) => (
|
||||||
<tr key={index}>
|
<tr
|
||||||
|
key={row.id}
|
||||||
|
className={isActiveRow(row) ? "bg-secondary font-semibold" : ""}
|
||||||
|
>
|
||||||
<td>{index + 1}</td>
|
<td>{index + 1}</td>
|
||||||
<td>{row.period}</td>
|
|
||||||
<td>
|
<td>
|
||||||
{row.cutoff}
|
{formatOnlyDate(row.periodStart)} → {formatOnlyDate(row.periodEnd)}
|
||||||
<br />
|
|
||||||
<span className="text-gray-500 text-[11px]">(Asia/Calcutta)</span>
|
|
||||||
</td>
|
</td>
|
||||||
<td>{row.payDate}</td>
|
<td>{formatDateTime(row.cutOffTime)}</td>
|
||||||
|
<td>{formatOnlyDate(row.ScheduleDate)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,36 @@ type LeaveRequestResponse = {
|
||||||
message?: string;
|
message?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface ScheduleItem {
|
||||||
|
id: string;
|
||||||
|
isActive: boolean;
|
||||||
|
status: string | null;
|
||||||
|
ScheduleDate: string;
|
||||||
|
cutOffTime: string | null;
|
||||||
|
periodEnd: string | null;
|
||||||
|
periodStart: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface PayslipItem {
|
||||||
|
totalHoursFormatted: string;
|
||||||
|
payrollSchedule: string;
|
||||||
|
totalPayAmount: number;
|
||||||
|
status: string;
|
||||||
|
date: string | null;
|
||||||
|
createdDate: string;
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PayslipResponse {
|
||||||
|
payrolls: PayslipItem[];
|
||||||
|
vaPortalId: string;
|
||||||
|
vaName: string;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
electron: {
|
electron: {
|
||||||
login: (credentials: { email: string; password: string }) => Promise<any>;
|
login: (credentials: { email: string; password: string }) => Promise<any>;
|
||||||
|
|
@ -174,7 +204,13 @@ interface Window {
|
||||||
payload: LeaveRequestPayload
|
payload: LeaveRequestPayload
|
||||||
) => Promise<LeaveRequestResponse>;
|
) => Promise<LeaveRequestResponse>;
|
||||||
|
|
||||||
|
getSchedules: () => Promise<any>;
|
||||||
|
|
||||||
|
getPayslips: (vaId: string) => Promise<{
|
||||||
|
success: boolean;
|
||||||
|
data?: PayslipResponse[];
|
||||||
|
message?: string;
|
||||||
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue