105 lines
3.2 KiB
TypeScript
105 lines
3.2 KiB
TypeScript
|
|
import React, { useState } from 'react';
|
|
import { useSelector } from 'react-redux';
|
|
import { RootState } from '../../store';
|
|
import PtoLeaveTab from './tabs/PtoLeaveTab';
|
|
import SickLeaveTab from './tabs/SickLeaveTab';
|
|
import AdjustmentTab from './tabs/AdjustmentTab';
|
|
|
|
type TabType = 'pto' | 'sick' | 'adjustment';
|
|
|
|
const LeaveAndAdjustments: React.FC = () => {
|
|
const [activeTab, setActiveTab] = useState<TabType>('pto');
|
|
const [isSubmitting, setIsSubmitting] = useState(false); // 🚀 NEW
|
|
const projects = useSelector((state: RootState) => state.projects.projectsData);
|
|
|
|
// ------- COMMON API CALL FOR BOTH TABS -------
|
|
const submitLeave = async (payload: {
|
|
dateFrom: string;
|
|
dateTo: string;
|
|
leaveType: "PTO" | "SICK";
|
|
comment: string;
|
|
}) => {
|
|
try {
|
|
setIsSubmitting(true);
|
|
|
|
console.log("Leave /sick Payload:", payload);
|
|
|
|
const response = await window.electron.createPTOAndSickLeaveRequest(payload)
|
|
console.log("Leave Payload:", response)
|
|
if (response.success) {
|
|
return { success: true };
|
|
}
|
|
|
|
return {
|
|
success: false,
|
|
message: response.message
|
|
};
|
|
} catch (err) {
|
|
console.error(err);
|
|
return { success: false, message: "Request failed" };
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="max-h-screen">
|
|
<div className="w-full mx-auto">
|
|
<h1 className="text-mb font-bold mb-2">Leave & Adjust Timesheet</h1>
|
|
|
|
{/* Tabs — Disabled while submitting */}
|
|
<div role="tablist" className="tabs tabs-border w-full mb-1 opacity-100">
|
|
<a
|
|
role="tab"
|
|
className={`tab text-xs font-semibold ${activeTab === "pto" ? "tab-active text-primary" : ""
|
|
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
|
onClick={() => setActiveTab("pto")}
|
|
>
|
|
PTO Leave
|
|
</a>
|
|
|
|
<a
|
|
role="tab"
|
|
className={`tab text-xs font-semibold ${activeTab === "sick" ? "tab-active text-primary" : ""
|
|
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
|
onClick={() => setActiveTab("sick")}
|
|
>
|
|
Sick Leave
|
|
</a>
|
|
|
|
<a
|
|
role="tab"
|
|
className={`tab text-xs font-semibold ${activeTab === "adjustment" ? "tab-active text-primary" : ""
|
|
} ${isSubmitting ? "pointer-events-none opacity-50" : ""}`}
|
|
onClick={() => setActiveTab("adjustment")}
|
|
>
|
|
Adjustment Submission
|
|
</a>
|
|
</div>
|
|
|
|
{/* Main Container */}
|
|
<div className="rounded-lg bg-base-100 overflow-hidden">
|
|
<div className="px-8 py-4 overflow-y-auto no-scrollbar max-h-[81vh]">
|
|
|
|
{activeTab === "pto" && (
|
|
<PtoLeaveTab submitLeave={submitLeave} isSubmitting={isSubmitting} />
|
|
)}
|
|
|
|
{activeTab === "sick" && (
|
|
<SickLeaveTab submitLeave={submitLeave} isSubmitting={isSubmitting} />
|
|
)}
|
|
|
|
{activeTab === "adjustment" && (
|
|
<AdjustmentTab projects={projects} />
|
|
)}
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LeaveAndAdjustments;
|