From 7bfd1728c09a92a2904b13249767897af31d913d Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Mon, 12 May 2025 11:33:04 +0530 Subject: [PATCH 1/2] updated regularization logic based on 48-hour checkout threshold for attendanceLogs. --- src/components/Activities/AttendLogs.jsx | 66 ++++++++++++++++++------ 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/src/components/Activities/AttendLogs.jsx b/src/components/Activities/AttendLogs.jsx index b246768b..0ae97b8f 100644 --- a/src/components/Activities/AttendLogs.jsx +++ b/src/components/Activities/AttendLogs.jsx @@ -2,12 +2,27 @@ import React, { useEffect, useState } from "react"; import { useEmployeeAttendacesLog } from "../../hooks/useAttendance"; import { convertShortTime } from "../../utils/dateUtils"; import { useNavigate } from "react-router-dom"; +import {THRESH_HOLD} from "../../utils/constants"; const AttendLogs = ({ Id }) => { const { logs, loading } = useEmployeeAttendacesLog(Id); const navigate = useNavigate(); - const whichActivityPerform = (actvity) => { + const isCheckoutRegularized = ( + activityTimeStr, + checkoutTimeStr, + threshHours + )=> { + if (!activityTimeStr || !checkoutTimeStr) return false; + + const activityTime = new Date(activityTimeStr); + const checkoutTime = new Date(checkoutTimeStr); + const threshTimeMs = threshHours * 60 * 60 * 1000; + + return checkoutTime - activityTime > threshTimeMs; + } + + const whichActivityPerform = (actvity,checkOutTime) => { switch (actvity) { case 1: return ( @@ -24,12 +39,12 @@ const AttendLogs = ({ Id }) => { case 2: return ( ); break; @@ -41,27 +56,43 @@ const AttendLogs = ({ Id }) => { data-bs-offset="0,8" data-bs-placement="top" data-bs-custom-class="tooltip" - title="Regularized" + title="Request Deleted!" > ); break; case 4: - return ( - - ); + if ( + checkOutTime && + isCheckoutRegularized(logs[0]?.activityTime, checkOutTime, THRESH_HOLD) + ) { + return ( + + ); + } else { + return ( + + ); + } break; case 5: return ( { const url = `https://www.google.com/maps?q=${lat},${lng}`; window.open(url, "_blank"); // Open in new tab }; + useEffect(() => { const tooltipTriggerList = Array.from( document.querySelectorAll('[data-bs-toggle="tooltip"]') @@ -122,11 +154,11 @@ const AttendLogs = ({ Id }) => { {log.activityTime.slice(0, 10)} {convertShortTime(log.activityTime)} - {whichActivityPerform(log.activity)} + {whichActivityPerform(log.activity,log.activityTime)} {log?.latitude != 0 ? ( Date: Sat, 31 May 2025 23:34:55 +0530 Subject: [PATCH 2/2] fixed attendance status & logs logic with proper activity handling --- src/components/Activities/AttendLogs.jsx | 24 ++-- src/hooks/useAttendanceStatus.js | 168 +++++++++-------------- 2 files changed, 83 insertions(+), 109 deletions(-) diff --git a/src/components/Activities/AttendLogs.jsx b/src/components/Activities/AttendLogs.jsx index 0ae97b8f..b94c80c6 100644 --- a/src/components/Activities/AttendLogs.jsx +++ b/src/components/Activities/AttendLogs.jsx @@ -2,17 +2,17 @@ import React, { useEffect, useState } from "react"; import { useEmployeeAttendacesLog } from "../../hooks/useAttendance"; import { convertShortTime } from "../../utils/dateUtils"; import { useNavigate } from "react-router-dom"; -import {THRESH_HOLD} from "../../utils/constants"; +import { THRESH_HOLD } from "../../utils/constants"; const AttendLogs = ({ Id }) => { const { logs, loading } = useEmployeeAttendacesLog(Id); const navigate = useNavigate(); - const isCheckoutRegularized = ( + const isCheckoutRegularized = ( activityTimeStr, checkoutTimeStr, threshHours - )=> { + ) => { if (!activityTimeStr || !checkoutTimeStr) return false; const activityTime = new Date(activityTimeStr); @@ -20,9 +20,9 @@ const AttendLogs = ({ Id }) => { const threshTimeMs = threshHours * 60 * 60 * 1000; return checkoutTime - activityTime > threshTimeMs; - } + }; - const whichActivityPerform = (actvity,checkOutTime) => { + const whichActivityPerform = (actvity, checkOutTime) => { switch (actvity) { case 1: return ( @@ -63,7 +63,11 @@ const AttendLogs = ({ Id }) => { case 4: if ( checkOutTime && - isCheckoutRegularized(logs[0]?.activityTime, checkOutTime, THRESH_HOLD) + isCheckoutRegularized( + logs[0]?.activityTime, + checkOutTime, + THRESH_HOLD + ) ) { return ( { {log.activityTime.slice(0, 10)} {convertShortTime(log.activityTime)} - {whichActivityPerform(log.activity,log.activityTime)} + + {whichActivityPerform(log.activity, log.activityTime)} + {log?.latitude != 0 ? ( { }`} - {log?.comment || "--"} + {log?.comment?.length > 50 + ? `${log.comment.slice(0, 50)}...` + : log.comment || "--"} ))} diff --git a/src/hooks/useAttendanceStatus.js b/src/hooks/useAttendanceStatus.js index b1b6180b..4085fba2 100644 --- a/src/hooks/useAttendanceStatus.js +++ b/src/hooks/useAttendanceStatus.js @@ -1,17 +1,16 @@ -import { useEffect, useState } from "react"; -import { timeElapsed } from "../utils/dateUtils"; -import { useSelector } from "react-redux"; -import { THRESH_HOLD } from "../utils/constants"; +import { useEffect, useState } from 'react'; +import { timeElapsed } from '../utils/dateUtils'; // Make sure it calculates in hours +import { THRESH_HOLD } from '../utils/constants'; +// THRESH_HOLD in hours (e.g., 12, 48, or 60) export const ACTIONS = { CHECK_IN: 0, CHECK_OUT: 1, REGULARIZATION: 2, REQUESTED: 3, APPROVED: 4, - REJECTED: 5, + REJECTED: 5 }; -const now = new Date(); const useAttendanceStatus = (attendanceData) => { const [status, setStatus] = useState({ @@ -19,133 +18,100 @@ const useAttendanceStatus = (attendanceData) => { action: null, disabled: true, text: "Unknown", - color: "btn-secondary", + color: 'btn-secondary', }); useEffect(() => { const { checkInTime, checkOutTime, activity } = attendanceData; + const now = new Date(); - if (activity === 0 && checkInTime === null && checkOutTime === null) { - setStatus({ + const isSameDay = (date1, date2) => + new Date(date1).toDateString() === new Date(date2).toDateString(); + + // 1. No check-in/check-out yet → Allow Check-In + if (activity === 0 && !checkInTime && !checkOutTime) { + return setStatus({ status: "Check-In", action: ACTIONS.CHECK_IN, disabled: false, text: "Check In", - color: "btn-primary", + color: 'btn-primary', }); - } else if (activity === 4 && new Date(checkOutTime) < now) { - setStatus({ - status: "Approved", - action: ACTIONS.APPROVED, - disabled: true, - text: "Approved", - color: "btn-success", - }); - } else if ( - activity === 0 && - checkInTime === null && - checkOutTime === null && - !timeElapsed(checkInTime, THRESH_HOLD) - ) { - setStatus({ - status: "Check-In", - action: ACTIONS.CHECK_IN, - disabled: false, - text: "Check In", - color: "btn-primary", - }); - } else if ( - activity === 0 && - checkInTime !== null && - checkOutTime === null && - timeElapsed(checkInTime, THRESH_HOLD) - ) { - setStatus({ - status: "Request Regularize", - action: ACTIONS.REGULARIZATION, - disabled: false, - text: "Regularizes", - color: "btn-warning", - }); - } else if ( - activity === 1 && - checkInTime !== null && - checkOutTime === null && - !timeElapsed(checkInTime, THRESH_HOLD) - ) { - setStatus({ - status: "Check-Out", - action: ACTIONS.CHECK_OUT, - disabled: false, - text: "Check Out", - color: "btn-primary", - }); - } else if ( - activity === 1 && - checkInTime !== null && - checkOutTime === null && - timeElapsed(checkInTime, THRESH_HOLD) - ) { - setStatus({ - status: "Request Regularize", - action: ACTIONS.REGULARIZATION, - disabled: false, - text: "Regularize", - color: "btn-warning", - }); - } else if ( - activity === 4 && - checkInTime !== null && - checkOutTime !== null && - !timeElapsed(checkInTime, THRESH_HOLD) - ) { - if ( - activity === 4 && - checkInTime !== null && - checkOutTime !== null && - new Date(checkOutTime).toDateString() !== new Date().toDateString() - ) { - setStatus({ + } + + // 2. Checked in, no checkout yet + if (checkInTime && !checkOutTime) { + if (timeElapsed(checkInTime, THRESH_HOLD)) { + return setStatus({ + status: "Request Regularize", + action: ACTIONS.REGULARIZATION, + disabled: false, + text: "Regularize", + color: 'btn-warning', + }); + } else { + return setStatus({ + status: "Check-Out", + action: ACTIONS.CHECK_OUT, + disabled: false, + text: "Check Out", + color: 'btn-primary', + }); + } + } + + // 3. Already checked in and out → Handle activity === 4 (Approved) + if (checkInTime && checkOutTime && activity === 4) { + if (!isSameDay(checkOutTime, now) && !timeElapsed(checkOutTime, THRESH_HOLD)) { + return setStatus({ status: "Approved", action: ACTIONS.APPROVED, disabled: true, text: "Approved", - color: "btn-success", + color: 'btn-success', }); - } else { - setStatus({ + } else if (isSameDay(checkOutTime, now)) { + return setStatus({ status: "Check-In", action: ACTIONS.CHECK_IN, disabled: false, text: "Check In", - color: "btn-primary", + color: 'btn-primary', }); } - } else if (activity === 2 && checkInTime !== null) { - setStatus({ + } + + // 4. Regularization Requested + if (activity === 2) { + return setStatus({ status: "Requested", action: ACTIONS.REQUESTED, disabled: true, text: "Requested", - color: "btn-info", + color: 'btn-info', }); - } else if (activity === 5 && checkInTime !== null) { - setStatus({ + } + + // 5. Rejected Regularization + if (activity === 5) { + return setStatus({ status: "Rejected", action: ACTIONS.REJECTED, disabled: true, text: "Rejected", - color: "btn-danger", - }); - } else { - setStatus({ - status: "Approved", - action: ACTIONS.APPROVED, - disabled: true, - text: "Approved", - color: "btn-success", + color: 'btn-danger', }); } + + // Default to Approved if none of the above apply + return setStatus({ + status: "Approved", + action: ACTIONS.APPROVED, + disabled: true, + text: "Approved", + color: 'btn-success', + }); + }, [attendanceData]); return status; -- 2.43.0