Naver Works Calculator

Calculate total work remain time

// ==UserScript==
// @name         Naver Works Calculator
// @namespace    http://tampermonkey.net/
// @version      0.0.12
// @description  Calculate total work remain time
// @author       K
// @match        *://*.ncpworkplace.com/v/home/
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// @license      MIT
// @run-at       document-end
// ==/UserScript==

(async function() {
    'use strict';

    const getWorkUrl = (userId, fromDate, toDate) => 
        `https://cowave.ncpworkplace.com/user/work-statistics/list?fromDate=${fromDate}&toDate=${toDate}&empId=${userId}&chkWorkingDay=N&_=${Date.now()}`;


    const parseWorkTimes = (data) => 
        data.data.list
            .filter(item => item.sumWorkTime && item.sumWorkTime !== '0000' && item.checkYmd !== 'TOTAL')
            .map(item => {
                const [hours, minutes] = [parseInt(item.sumWorkTime.substring(0, 2), 10), parseInt(item.sumWorkTime.substring(2, 4), 10)];
                const totalMinutes = hours * 60 + minutes;
                return {
                    checkYmd: new Date(item.checkYmd.replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3')),
                    sumWorkTime: totalMinutes,
                    diff: totalMinutes - 480
                };
            });

    const calculateTotalRemainWork = (workTimes) => workTimes.reduce((acc, item) => acc + item.diff, 0);

    const updateDOM = (workTimes, totalDiffWithFriday, totalDiffWithoutFriday) => {
        const cardLinkTime = findCardLinkTime();
        const cell = cardLinkTime?.querySelector('.cell');
        const timeBoxes = cell?.querySelectorAll('.time-box');
        const firstTimeBox = timeBoxes?.[0];
        const secondTimeBox = timeBoxes?.[1];

        const totalTimeBox = createTotalTimeBox(totalDiffWithFriday, totalDiffWithoutFriday);
        firstTimeBox?.appendChild(totalTimeBox);
        const button = createDownloadButton(workTimes);
        secondTimeBox?.appendChild(button);
    };

    const findCardLinkTime = () => 
        Array.from(document.querySelectorAll('.card-link')).find(cardLink => 
            cardLink.querySelector('.title.ellipsis')?.textContent.trim() === '나의 근로 시간'
        );

    const createTotalTimeBox = (totalDiffWithFriday, totalDiffWithoutFriday) => {
        const totalTimeBox = document.createElement('div');
        totalTimeBox.className = 'time-box-data-sub';
        totalTimeBox.innerHTML = `
            총 추가 근로 시간 
            <br>
            금요일 포함: ${formatTime(totalDiffWithFriday)}
            <br>
            금요일 미포함: ${formatTime(totalDiffWithoutFriday)}
        `;
        return totalTimeBox;
    };

    const formatTime = (totalDiff) => {
        const sign = totalDiff < 0 ? '-' : '+';
        const hours = Math.floor(Math.abs(totalDiff) / 60);
        const minutes = Math.abs(totalDiff) % 60;
        return `${sign}${hours}시간 ${minutes}분`;
    };
    const createDownloadButton = (workTimes) => {
        const button = document.createElement('button');
        button.className = 'btn btn-md flat';
        button.textContent = 'csv 다운로드';
        button.addEventListener('click', () => {
            const now = new Date();
            const yearMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
            const csvHeader = "날짜,총 근로 시간(분),차이(분)\n";
            const csvContent = "\uFEFF" + csvHeader + 
                workTimes.map(e => `${e.checkYmd.toISOString().split('T')[0]},${e.sumWorkTime},${e.diff}`).join('\n');
            const encodedUri = encodeURI("data:text/csv;charset=utf-8," + csvContent);
            const link = document.createElement('a');
            link.setAttribute('href', encodedUri);
            link.setAttribute('download', `work_times_${yearMonth}.csv`);
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        });
        return button;
    };

    const getUserId = async () => {
        const htmlText = await fetch("https://cowave.ncpworkplace.com/user/work-statistics").then(response => response.text());
        const empIdRegex = /empId:\s*'([^']+)'/;
        const match = htmlText.match(empIdRegex);
        return match[1];
    };

    const userId = await getUserId();
    const now = new Date();
    const fromDate = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}01`;
    const toDate = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate()}`;
    const url = getWorkUrl(userId, fromDate, toDate);
    console.log(userId);

    let workTimes = await fetch(url)
        .then(response => response.json())
        .then(data => parseWorkTimes(data))
        .catch(error => console.error('Error fetching data:', error));
    
    const workTimesWithFriday = workTimes;
    const workTimesWithoutFriday = workTimes.filter(item => item.checkYmd.getDay() !== 5);

    const totalDiffWithFriday = calculateTotalRemainWork(workTimesWithFriday);
    const totalDiffWithoutFriday = calculateTotalRemainWork(workTimesWithoutFriday);

    console.log('Work times including Friday:', workTimesWithFriday);
    console.log('Total difference in minutes including Friday:', totalDiffWithFriday);
    console.log('Work times excluding Friday:', workTimesWithoutFriday);
    console.log('Total difference in minutes excluding Friday:', totalDiffWithoutFriday);

    updateDOM(workTimes, totalDiffWithFriday, totalDiffWithoutFriday);


})();