Keka Log Duration by Jp

try to take over the world

目前為 2024-02-28 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Keka Log Duration by Jp
// @namespace    http://tampermonkey.net/
// @version      2023-12-27
// @description  try to take over the world
// @author       You
// @match        https://ezeetechnosys.keka.com/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=keka.com
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';
    const channel = new BroadcastChannel('keka-duration');
    let fistDuration;
    let secondDuration;
    function parseTime(timeStr) {
        const parts = timeStr.split(':');
        return parseInt(parts[0]) * 3600000 + parseInt(parts[1]) * 60000 + parseInt(parts[2]) * 1000;
    }
    function calculateTotalDuration(duration1Str, duration2Str) {
        // Extract hours and minutes from each duration string
        const [hours1, minutes1] = duration1Str.match(/\d+/g);
        const [hours2, minutes2] = duration2Str.match(/\d+/g);

        // Convert hours and minutes to numbers
        const hours1Num = parseInt(hours1);
        const minutes1Num = parseInt(minutes1);
        const hours2Num = parseInt(hours2);
        const minutes2Num = parseInt(minutes2);
        console.log("IIIIIIIIIIIIIIIIII",hours1Num,minutes1Num,hours2Num,minutes2Num)
        // Add hours and minutes separately
        const totalMinutes = minutes1Num + minutes2Num;
        const totalHours = hours1Num + hours2Num + Math.floor(totalMinutes / 60);
        const remainingMinutes = totalMinutes % 60;

        // Format the total duration string
        const totalDurationStr = `${totalHours} Hr ${remainingMinutes} Min`;

        return totalDurationStr;
       }

    function calculateDuration(startTimeSpan, endTimeSpan) {
        const startTimeStr = startTimeSpan.textContent.trim();
        const endTimeStr = endTimeSpan.textContent.trim();

        // If end time is empty, use current time
        const endTime = endTimeStr !="MISSING" ? endTimeStr : new Date().toLocaleTimeString('en-US', { hour12: true });
        console.log("TIMES",startTimeStr,endTime);
        // Parse time strings into Date objects
        const startTime = new Date(`2023-12-27 ${startTimeStr}`); // Assuming today's date
        const endTimeDate = new Date(`2023-12-27 ${endTime}`);

        // Calculate duration in milliseconds
        const durationMillis = endTimeDate.getTime() - startTime.getTime();

        // Convert milliseconds to hours and minutes
        const durationHours = Math.floor(durationMillis / (3600 * 1000));
        const durationMinutes = Math.floor((durationMillis % (3600 * 1000)) / (60 * 1000));

        // Formatted duration string
        const durationStr = `${durationHours} Hr ${durationMinutes} Min`;

        return durationStr;
    }

    function watchForModals() {
        const modals = document.querySelectorAll('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div');
        console.log("Modals",modals)

        modals.forEach(modal => {

        const modalsArray = Array.from(modals);
        const dayIndex = modalsArray.indexOf(modal) + 1; // Determine the day index (1, 2, or 3)

        const displaySpanXPath = `/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div/div[1]/span[1]`;
        const displaySpan = document.evaluate(
            displaySpanXPath,
            modal,
            null,
            XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
            null
        ).snapshotItem(0);

            const startTimeSpan = document.evaluate(
                '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[1]/div[1]/div[2]/span[2]',
                modal,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;

            const endTimeSpan = document.evaluate(
                '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[1]/div[1]/div[3]/span[2]',
                modal,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;

             const startTimeSpan1 = document.evaluate(
                '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[2]/div[1]/div[2]/span[2]',
                modal,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;

            const endTimeSpan1 = document.evaluate(
                '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[2]/div[1]/div[3]/span[2]',
                modal,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;

 if (startTimeSpan && endTimeSpan) {
    const durationStr = calculateDuration(startTimeSpan, endTimeSpan);
    fistDuration = durationStr
    const durationDisplaySpan = document.querySelector('.d-flex.align-items-center.ml-10');
    
    window.postMessage({ type: 'duration', value: durationStr }, '*');
    console.log("POSTED-DURATION")
    // Check for existing duration span:
    const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-1');
    if (!existingDurationSpan) {
        // Create span only if it doesn't exist
        const durationSpan = document.createElement('span');
        durationSpan.classList.add('duration-span-1'); // Add class for identification
        durationSpan.textContent = durationStr;
        durationSpan.style.fontWeight = 'bold';
        durationSpan.style.paddingLeft = '17px';
        durationSpan.style.color = 'darkred';
        durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
    } else {
        console.log("Duration span already exists, skipping creation.");
    }
}

if (startTimeSpan1 && endTimeSpan1) {
    console.log("11111111--11111", startTimeSpan1, endTimeSpan1)
    const durationStr = calculateDuration(startTimeSpan1, endTimeSpan1);
    secondDuration = durationStr;
    const durationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(2) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid > div.d-flex.align-items-center.ml-10');
    console.log("durationDisplaySpan", durationDisplaySpan)

    // Check for existing duration span:
    const existingDurationSpan = durationDisplaySpan.querySelector('.duration-span-2');
    if (!existingDurationSpan) {
        // Create span only if it doesn't exist
        const durationSpan = document.createElement('span');
        durationSpan.classList.add('duration-span-2'); // Add class for identification
        durationSpan.textContent = durationStr;
        durationSpan.style.fontWeight = 'bold';
        durationSpan.style.paddingLeft = '17px';
        durationSpan.style.color = 'darkred';
        durationDisplaySpan.insertAdjacentElement('afterend', durationSpan);
    } else {
        console.log("Duration span already exists, skipping creation.");
    }

    const totaldurationDisplaySpan = document.querySelector('body > modal-container > div.modal-dialog.small-modal > div > attendance-adjustment-request > div.modal-body > form > div.mt-20 > div > div:nth-child(2) > div > div > div:nth-child(2) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid');
    console.log(fistDuration, secondDuration, "#################")
    const total = calculateTotalDuration(fistDuration, secondDuration);
    console.log("total" , total)

    // Check for existing total duration span:
    const existingTotalDurationSpan = totaldurationDisplaySpan.querySelector('.total-duration-span');
    if (!existingTotalDurationSpan) {
        // Create span only if it doesn't exist
        const TotaldurationSpan = document.createElement('span'); // Added closing parenthesis
        TotaldurationSpan.classList.add('total-duration-span'); // Add class for identification
        TotaldurationSpan.textContent = total;
        TotaldurationSpan.style.fontWeight = 'bold';
        // TotaldurationSpan.style.paddingLeft = '17px';
        TotaldurationSpan.style.color = '#0600ff';
        TotaldurationSpan.style.float = 'right';
        TotaldurationSpan.style.padding = '5px';
        TotaldurationSpan.style.background = 'lightblue';
        TotaldurationSpan.style.marginRight = '150px';
        TotaldurationSpan.style.borderRadius = '5px';
        TotaldurationSpan.style.borderTop = '3px solid #888'
        totaldurationDisplaySpan.insertAdjacentElement('afterend', TotaldurationSpan);

        }
    }

        })
    };


     const observer = new MutationObserver(mutations => {
     console.log("Observing.....")
    const modalTriggerElements = document.querySelectorAll('employee-attendance-list-view .attendance-logs-row');
    modalTriggerElements.forEach(element => {
        element.addEventListener('click', watchForModals);
      });
    });

    observer.observe(document.body, { childList: true, subtree: false });

})(); // Closed parenthesis for the immediately invoked function expression