Keka Log Duration by Jp

try to take over the world

目前為 2024-11-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Keka Log Duration by Jp
// @namespace    http://tampermonkey.net/
// @version      1.4
// @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;
    let thirdDuration;
    let fourthDuration;
    let fifthDuration;
    function parseTime(timeStr) {
        const parts = timeStr.split(':');
        return parseInt(parts[0]) * 3600000 + parseInt(parts[1]) * 60000 + parseInt(parts[2]) * 1000;
    }
    let lastLogIndex=0;

    function calculateTotalDuration(duration1Str, duration2Str, duration3Str, duration4Str, duration5Str) {
        // Initialize total hours and minutes
        let totalHours = 0;
        let totalMinutes = 0;

        // Array of all duration strings
        const durations = [duration1Str, duration2Str, duration3Str, duration4Str, duration5Str];

        // Loop through each duration string
        durations.forEach(durationStr => {
            if (durationStr) { // Check if the duration string is not empty
                const [hours, minutes] = durationStr.match(/\d+/g).map(Number);
                totalHours += hours;
                totalMinutes += minutes;
            }
        });

        // Add overflow from minutes to hours
        totalHours += Math.floor(totalMinutes / 60);
        totalMinutes = totalMinutes % 60;

        // Format the total duration string
        const totalDurationStr = `${totalHours} Hr ${totalMinutes} 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;

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

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

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

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

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

            const endTimeSpan4 = document.evaluate(
                '/html/body/modal-container/div[2]/div/attendance-adjustment-request/div[2]/form/div[2]/div/div[2]/div/div/div[5]/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.");
                }

                var parentDivs = document.querySelectorAll('div.mb-30.ng-untouched.ng-pristine.ng-valid');
                if (parentDivs.length > 1) {
                    // Targeting the second div as per your requirement
                    var targetDiv = parentDivs[1];
                    var pElement = targetDiv.querySelector('p.text-large'); // Assuming the span is the one you've added
                    var spanElement = document.createElement('span');
                    // Texts array for the morphing effect
                    const texts = ["Log Duration", "    By @Jaydeep😶"];
                    let textIndex = 0;

                    // Function to update the text with a morphing effect
                    function updateText() {
                        const nextText = texts[textIndex % texts.length];
                        textIndex++;

                        // Applying a fade-out effect
                        spanElement.style.opacity = '0';
                        spanElement.style.transition = 'opacity 0.5s ease-out';

                        // After fade-out, change the text and fade it back in
                        setTimeout(() => {
                            spanElement.textContent = nextText;

                            // Applying blur during transition
                            spanElement.style.filter = 'blur(2px)';
                            spanElement.style.opacity = '1';
                            spanElement.style.transition = 'opacity 0.5s ease-in, filter 0.5s ease';

                            // Removing blur after a moment
                            setTimeout(() => {
                                spanElement.style.filter = 'none';
                            }, 500); // Match the transition time
                        }, 500); // Wait for the fade-out to complete
                    }

                    // Starting the text update process
                    spanElement.style.fontWeight = 'bold';
                    spanElement.style.color = 'rgb(0, 123, 255)';
                    spanElement.style.padding = '5px';
                    spanElement.style.borderRadius = '5px';
                    spanElement.style.fontSize = '16px';
                    spanElement.style.marginLeft = '262px';
                    spanElement.textContent = texts[textIndex % texts.length];
                    textIndex++;
                    pElement.appendChild(spanElement);
                    setInterval(updateText, 2000);
                }
            }

            if (startTimeSpan1 && endTimeSpan1) {
                lastLogIndex = 1;
                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.");
                }

            }
            if (startTimeSpan2 && endTimeSpan2) {
                lastLogIndex = 2;
                console.log("11111111--11111", startTimeSpan2, endTimeSpan2)
                const durationStr = calculateDuration(startTimeSpan2, endTimeSpan2);
                thirdDuration = 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(3) > 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-3');
                if (!existingDurationSpan) {
                    // Create span only if it doesn't exist
                    const durationSpan = document.createElement('span');
                    durationSpan.classList.add('duration-span-3'); // 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 (startTimeSpan3 && endTimeSpan3) {
                lastLogIndex = 3;
                console.log("11111111--11111", startTimeSpan3, endTimeSpan3)
                const durationStr = calculateDuration(startTimeSpan3, endTimeSpan3);
                fourthDuration = 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(3) > 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-3');
                if (!existingDurationSpan) {
                    // Create span only if it doesn't exist
                    const durationSpan = document.createElement('span');
                    durationSpan.classList.add('duration-span-3'); // 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 (startTimeSpan4 && endTimeSpan4) {
                lastLogIndex = 4;
                console.log("11111111--11111", startTimeSpan4, endTimeSpan4)
                const durationStr = calculateDuration(startTimeSpan4, endTimeSpan4);
                fifthDuration = 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(4) > 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-4');
                if (!existingDurationSpan) {
                    // Create span only if it doesn't exist
                    const durationSpan = document.createElement('span');
                    durationSpan.classList.add('duration-span-4'); // 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(lastLogIndex) {

            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(${lastLogIndex+1}) > div.d-flex.align-items-center.ng-untouched.ng-pristine.ng-valid`);
            console.log(fistDuration, secondDuration,"3",thirdDuration,'4',fourthDuration,'5',fifthDuration, "#################111")
            const total = calculateTotalDuration(
                fistDuration,
                startTimeSpan1 ? secondDuration : 0,
                startTimeSpan2 ? thirdDuration : 0,
                startTimeSpan3 ? fourthDuration : 0,
                startTimeSpan4 ? fifthDuration : 0
              );           
               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