ph-fin / iTpLACEstHEbAMBOOiNtHEbASKET

// ==UserScript==
// @name         iTpLACEstHEbAMBOOiNtHEbASKET
// @namespace    http://tampermonkey.net/
// @license      MIT
// @version      2.2024.02.27a
// @description  it places the bamboo in the basket
// @author       bubacar
// @updateURL    https://openuserjs.org/meta/ph-fin/iTpLACEstHEbAMBOOiNtHEbASKET.meta.js
// @downloadURL  https://openuserjs.org/install/ph-fin/iTpLACEstHEbAMBOOiNtHEbASKET.user.js
// @match        https://finsolutia.bamboohr.com/employees/timesheet/?id=*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bamboohr.com
// @match        https://finsolutia.bamboohr.com/employees/timesheet/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const _version = '2.2024.02.27a';
     console.log(`👻 ghosty: ALL YOUR BASE ARE BELONG TO US. - v${_version}`);

    /////////////////
    ////// HTML /////
    /////////////////
     const _html = {
         _btnDay: '🧙',
         _btnDayLoading: '⏳',
         _btnDayError: '⚠️',
         _btnDaySuccess: '✔️',
     };

    /////////////////
    //// PAYLOADS ///
    /////////////////
    const _payloads = {
        logDay : {
            entries: [
                {
                    id: null,
                    trackingId: 1,
                    employeeId: 69,
                    date: "1999-02-31",
                    start: "09:00",
                    end: "13:00",
                    note: "",
                    projectId: null,
                    taskId: null
                },
                {
                    id: null,
                    trackingId: 1,
                    employeeId: 69,
                    date: "1999-02-31",
                    start: "14:00",
                    end: "18:00",
                    note: "",
                    projectId: null,
                    taskId: null
                },
            ]
        },
    };

    /////////////////
    //// CONFIGS ////
    /////////////////
    function _configDefault() {
        return {
            faggy : false,
            log : {
                showDebug : true,
                showTimers : false,
                showEngine : false
            }
        };
    };
    // clone default config
    let _configUser = {..._configDefault()};

    /////////////////
    ///// PAGE //////
    /////////////////
    const _page = {
        pathname: document.location.pathname.toLowerCase(),
        queryStringParams: new URLSearchParams(document.location.search),
    };

    /////////////////
    /// CURRENT /////
    /////////////////
    const _current = {
        userId: _page.queryStringParams.get('id'),
    };

    /////////////////
    /// FUNCTIONS ///
    /////////////////
    function savelogDay(dateStr, btnElem) {
        _logDebug('savelogDay');
        _logDebug(`initButtonsLogDay - dateStr:${dateStr}`);
        btnElem.innerText = _html._btnDayLoading;

        // set payload info
        _payloads.logDay.entries[0].employeeId = _current.userId;
        _payloads.logDay.entries[0].date = dateStr;
        _payloads.logDay.entries[0].start = getFunkyDateStr(8, 20, 0, 50);
        _payloads.logDay.entries[0].end = getFunkyDateStr(12, 0, 0, 30);
        _payloads.logDay.entries[1].employeeId = _current.userId;
        _payloads.logDay.entries[1].date = dateStr;
        _payloads.logDay.entries[1].start = getFunkyDateStr(13, 20, 0, 15);
        _payloads.logDay.entries[1].end = getFunkyDateStr(18, 25, 0, 30);

        // request settings
        const url = "https://finsolutia.bamboohr.com/timesheet/clock/entries";
        const payloadJson = JSON.stringify(_payloads.logDay);
        const headers = new Headers({
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': CSRF_TOKEN,
            'Accept': 'application/json, text/plain, */*'
        });
        const options = {
            method: 'POST',
            headers: headers,
            body: payloadJson
        };

        _logDebug(`savelogDay - 🎃 fetch:${url}`);

        // fetch
        fetch(url, options)
            .then(response => {
                if (response.ok) {
                    btnElem.innerText = _html._btnDaySuccess;
                    btnElem.onclick = null;
                } else {
                    btnElem.innerText = _html._btnDayError;
                    throw new Error(`HTTP error! Status: ${response.status}`);
                }
            })
            .catch(error => {
               _logError(error);
            });
    }

    function getFunkyDateStr(startingHours, startingMinutes, randomMinutesMin, randomMinutesMax) {
        var date = new Date();
        date.setHours(startingHours);
        date.setMinutes(startingMinutes);
        date = addMinutes(date, getRandomInt(randomMinutesMin, randomMinutesMax));
        date.setMilliseconds(getRandomInt(1,999));

        var hoursStr = date.getHours().toString().padStart(2, '0');
        var minutesStr = date.getMinutes().toString().padStart(2, '0');

        return `${hoursStr}:${minutesStr}`;
    }

    function addMinutes(date, minutes) {
        return new Date(date.getTime() + minutes*60000);
    }

    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    /////////////////
    ///// LOGS //////
    /////////////////
    function _logDebug(msg) {
        if(_configUser.log.showDebug) {
            console.log('🌻iTpLACEstHEbAMBOOiNtHEbASKET🌻 - ' + msg);
        }
    }

    function _logError(message, exception) {
        let errorMsg = '☠️iTpLACEstHEbAMBOOiNtHEbASKET☠️ - ' + message;
        if(exception) {
            errorMsg += '\r\n EXCEPTION \r\n MESSAGE:' + exception.message + ' \r\n STACK:' + exception.stack;
        }
        console.error(errorMsg);
    }

    /////////////////
    ///// INIT //////
    /////////////////
    function initButtonsLogDay() {
        _logDebug('initButtonsLogDay');

        // extract month
        let daysRangeLabel = document.querySelector('.TimesheetSecondHeader__dates h4').innerText;
        let monthNumber = daysRangeLabel.substr(0, 3);

        const currentYear = new Date().getFullYear();

        // get day rows
        let rowElems = document.querySelectorAll('.TimesheetSlat--clock');
        rowElems.forEach(rowElem => {
            let dayOfWeekElem = rowElem.querySelector('.TimesheetSlat__dayOfWeek');
            let dayOfWeek = dayOfWeekElem.innerText;
            let dayDate = rowElem.querySelector('.TimesheetSlat__dayDate').innerText;
            let dayTotal = rowElem.querySelector('.TimesheetSlat__dayTotal').innerText;
            let extraInfoElem = rowElem.querySelector('.TimesheetSlat__extraInfoItem');

            _logDebug(`initButtonsLogDay - dayDate:${dayDate}`);

            // no reported hours
            if(dayTotal === '0h 00m')
            {
                // week day
                if(dayOfWeek !== 'Sat' && dayOfWeek !== 'Sun' && extraInfoElem === null)
                {
                    // create button
                    let logDate = new Date(`${dayDate}, ${currentYear}`);
                    let logDateStr = `${logDate.getFullYear()}-${(logDate.getMonth() + 1).toString().padStart(2, '0')}-${logDate.getDate().toString().padStart(2, '0')}`;
                    _logDebug(`initButtonsLogDay - logDateStr:${logDateStr}`);
                    let btnElem = document.createElement('div');
                    btnElem.className = 'xkBamboo logDay';
                    btnElem.style.marginRight = '-.5em';
                    btnElem.style.cursor = 'pointer';
                    btnElem.innerText = _html._btnDay;
                    btnElem.title = `log day ${logDateStr}`;
                    btnElem.dataset.xkLogDayDate = logDateStr;
                    // event click button
                    btnElem.addEventListener('click', () => {
                        _logDebug('logDay click');

                        savelogDay(logDateStr, btnElem);
                    });

                    // append button
                    dayOfWeekElem.appendChild(btnElem);
                }
            }
        });
    }

    /////////////////
    ///// MAIN //////
    /////////////////
    function main() {
        try {
            initButtonsLogDay();
        }
        catch(e) {
            _logError('main: ', e);
        }
    }
    main();

})();