From 8bf3343ba3f5bd1b03f4b3f4c5e42e6c65c0c27b Mon Sep 17 00:00:00 2001 From: JaiPandey425 Date: Fri, 14 Nov 2025 19:12:12 +0530 Subject: [PATCH] time --- package-lock.json | 18 + package.json | 2 + .../LeaveAndAdjustments.tsx | 408 +++++------------- 3 files changed, 126 insertions(+), 302 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3f1177..c2dfdfc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "electron-store": "^11.0.2", "get-windows": "^9.2.3", "lucide-react": "^0.552.0", + "luxon": "^3.7.2", "os-utils": "^0.0.14", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -26,6 +27,7 @@ }, "devDependencies": { "@playwright/test": "^1.47.2", + "@types/luxon": "^3.7.1", "@types/node": "^22.5.5", "@types/os-utils": "^0.0.4", "@types/react": "^18.3.8", @@ -2746,6 +2748,13 @@ "@types/node": "*" } }, + "node_modules/@types/luxon": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz", + "integrity": "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", @@ -7656,6 +7665,15 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", diff --git a/package.json b/package.json index 885d119..f3da710 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "electron-store": "^11.0.2", "get-windows": "^9.2.3", "lucide-react": "^0.552.0", + "luxon": "^3.7.2", "os-utils": "^0.0.14", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -36,6 +37,7 @@ }, "devDependencies": { "@playwright/test": "^1.47.2", + "@types/luxon": "^3.7.1", "@types/node": "^22.5.5", "@types/os-utils": "^0.0.4", "@types/react": "^18.3.8", diff --git a/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx b/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx index c20b869..5a1bcc6 100644 --- a/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx +++ b/src/ui/pages/LeaveAndAdjustments/LeaveAndAdjustments.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; import AdjustmentModal from './AdjustmentModal'; import { RootState } from '../../store'; import { useSelector } from 'react-redux'; +import { DateTime } from 'luxon'; interface LeaveFormData { fromDate: string; @@ -22,6 +23,17 @@ interface LogEntry { status: "Completed" | "In Progress" | "Pending"; } +interface ProjectSummaryResponse { + totalWorkedHours: string; + totalWorkedHoursDetailed: string; + totalWorkedHoursDecimal: string; + totalWorkedMinutes: string; + dedicatedHours: number; + pendingHours: string; + firstLoginTime: string; + lastLogoutTime: string; +} + const data: LogEntry[] = [ { id: 1, date: "2025-11-01", hours: 8, task: "Frontend Development", status: "Completed" }, { id: 2, date: "2025-11-02", hours: 6, task: "API Integration", status: "In Progress" }, @@ -42,7 +54,6 @@ const LeaveAndAdjustments: React.FC = () => { const [ptoLeave, setPtoLeave] = useState({ fromDate: '', toDate: '', - // description:"" }); const [ptoErrors, setPtoErrors] = useState>({}); @@ -50,12 +61,16 @@ const LeaveAndAdjustments: React.FC = () => { const [sickLeave, setSickLeave] = useState({ fromDate: '', toDate: '', - }); const [sickErrors, setSickErrors] = useState>({}); const [selectedProjectId, setSelectedProjectId] = useState("") const [selectedDate, setSelectedDate] = useState("") + // Project Summary State + const [projectSummary, setProjectSummary] = useState(null); + const [startTime, setStartTime] = useState(""); + const [endTime, setEndTime] = useState(""); + // Adjustment State const [selectedPeriod, setSelectedPeriod] = useState('week'); const [adjustmentData, setAdjustmentData] = useState([ @@ -82,10 +97,24 @@ const LeaveAndAdjustments: React.FC = () => { errors.toDate = 'To date must be after from date'; } - return errors; }; + // Function to convert UTC time to local time in HH:mm format + const convertToLocalTime = (utcTimeString: string): string => { + if (!utcTimeString) return ''; + + try { + // Parse the UTC time and convert to local timezone + const localTime = DateTime.fromISO(utcTimeString, { zone: 'utc' }).toLocal(); + + // Format to HH:mm (24-hour format) + return localTime.toFormat('HH:mm'); + } catch (error) { + console.error('Error converting time:', error); + return ''; + } + }; const handlePtoSubmit = async () => { const errors = validateLeaveForm(ptoLeave); @@ -164,42 +193,72 @@ const LeaveAndAdjustments: React.FC = () => { } const handleSelectedDate = (value: string) => { - // Ensure value stays as "YYYY-MM-DD" - setSelectedDate(value); -}; + setSelectedDate(value); + }; + const debugTimezoneInfo = (utcTimeString: string , check : string) => { + const utcTime = DateTime.fromISO(utcTimeString, { zone: 'utc' }); + const localTime = utcTime.toLocal(); + console.log(`-------------------------Timezone Debug Info: ${check}----------------------`); + console.log('UTC Time:', utcTime.toString()); + console.log('Local Time:', localTime.toString()); + console.log('System Timezone:', localTime.zoneName); + console.log('Formatted Local Time:', localTime.toFormat('HH:mm')); + // return localTime.toFormat('HH:mm'); + }; const fetchLogs = async () => { - try { - console.log("Sending =>", selectedProjectId, selectedDate); + try { + console.log("Sending =>", selectedProjectId, selectedDate); - const res = await window.electron.getProjectSummary( - selectedProjectId, - selectedDate - ); + const res = await window.electron.getProjectSummary( + selectedProjectId, + selectedDate + ); - console.log("📥 Summary Response:", res); + console.log("📥 Summary Response:", res); - // if (res.success) { - // // setProjectLogs(res.data); // <-- store logs in state - // } else { - // console.warn("⚠️ Summary API failed:", res.message); - // } - } catch (err) { - console.error("❌ Error fetching project summary:", err); - } -}; + if (res.success) { + setProjectSummary(res?.data?.summary); + // Convert UTC times to local timezone and set them + if (res?.data?.summary?.firstLoginTime) { + const localStartTime = convertToLocalTime(res?.data?.summary?.firstLoginTime); + debugTimezoneInfo(localStartTime ,"start"); + setStartTime(localStartTime); + } + + if (res?.data?.summary?.lastLogoutTime) { + const localEndTime = convertToLocalTime(res?.data?.summary?.lastLogoutTime); + debugTimezoneInfo(localEndTime , "end"); + setEndTime(localEndTime); + } + } else { + console.warn("⚠️ Summary API failed:", res.message); + setProjectSummary(null); + setStartTime(""); + setEndTime(""); + } + } catch (err) { + console.error("❌ Error fetching project summary:", err); + setProjectSummary(null); + setStartTime(""); + setEndTime(""); + } + }; useEffect(() => { if (selectedProjectId && selectedDate) { - fetchLogs() + fetchLogs(); + } else { + setProjectSummary(null); + setStartTime(""); + setEndTime(""); } - }, [selectedProjectId, selectedDate]) - + }, [selectedProjectId, selectedDate]); return (
@@ -228,21 +287,6 @@ const LeaveAndAdjustments: React.FC = () => { Create or Adjust Timesheet - - {/* */}
{/* Tab Content */} @@ -251,10 +295,6 @@ const LeaveAndAdjustments: React.FC = () => { {activeTab === 'create_and_adjust_timesheet' && (
- {/*
-

Paid Time Off Request

-
*/} -
@@ -277,7 +317,6 @@ const LeaveAndAdjustments: React.FC = () => { ))} - {ptoErrors.fromDate && (
- -
handlePtoChange('fromDate', e.target.value)} - className={`input input-bordered input-sm w-full focus:input-primary transition-all ${ptoErrors.fromDate ? 'input-error' : ''}`} + type="text" + value={projectSummary ? `${projectSummary.totalWorkedHoursDecimal} hrs` : "0 hrs"} + readOnly + className="input input-bordered input-sm w-full bg-base-200" /> - {ptoErrors.fromDate && ( - - )}
@@ -320,15 +353,11 @@ const LeaveAndAdjustments: React.FC = () => { Current pending time handlePtoChange('toDate', e.target.value)} - className={`input input-bordered input-sm w-full focus:input-primary transition-all ${ptoErrors.toDate ? 'input-error' : ''}`} + type="text" + value={projectSummary ? `${projectSummary.pendingHours} hrs` : "0 hrs"} + readOnly + className="input input-bordered input-sm w-full bg-base-200" /> - {ptoErrors.toDate && ( - - )}
@@ -337,11 +366,9 @@ const LeaveAndAdjustments: React.FC = () => { - setPtoLeave((prev) => ({ ...prev, fromDate: e.target.value })) - } - className={`input input-bordered input-sm w-full focus:input-primary transition-all ${ptoErrors.fromDate ? 'input-error' : ''}`} + value={startTime} + onChange={(e) => setStartTime(e.target.value)} + className="input input-bordered input-sm w-full focus:input-primary transition-all" />
@@ -351,30 +378,22 @@ const LeaveAndAdjustments: React.FC = () => { - setPtoLeave((prev) => ({ ...prev, toDate: e.target.value })) - } - className={`input input-bordered input-sm w-full focus:input-primary transition-all ${ptoErrors.toDate ? 'input-error' : ''}`} + value={endTime} + onChange={(e) => setEndTime(e.target.value)} + className="input input-bordered input-sm w-full focus:input-primary transition-all" />
-
handlePtoChange('toDate', e.target.value)} - className={`input input-bordered input-sm w-full focus:input-primary transition-all ${ptoErrors.toDate ? 'input-error' : ''}`} + type="text" + placeholder="Calculated automatically" + readOnly + className="input input-bordered input-sm w-full bg-base-200" /> - {ptoErrors.toDate && ( - - )}
@@ -383,10 +402,7 @@ const LeaveAndAdjustments: React.FC = () => { Description / Reason