PurelyImaginary / Timecamp Timeleft

// ==UserScript==
// @name         Timecamp Timeleft
// @version      0.8.5
// @updateURL    https://openuserjs.org/meta/PurelyImaginary/Timecamp_Timeleft.meta.js
// @downloadURL  https://openuserjs.org/src/scripts/PurelyImaginary/Timecamp_Timeleft.user.js
// @author       Purely Imaginary
// @match        https://www.timecamp.com/attendance
// @grant        none
// ==/UserScript==

(function() {
    function appendToUl(header,body){
        var insertString = '<li class="pull-right"><div class="panel panel-success" style="margin:0">';
        insertString += '<div class="panel-heading" style="padding: 5px;text-align: center;font-size: 0.8em;">';
        insertString += header;
        insertString += '</div><div class="panel-body" style="padding: 5px;text-align: center;font-size: 0.8em;">';
        insertString += body;
        insertString += '</div></div></li>';
        $("ul.tt-report-nav").eq(0).append(insertString);
    }

    function stringToMinutes(string){
        var data = string.split(" ");
        var returnVal = 0;
        if (data[0].includes(":")) {
            var split = data[0].split(":");
            returnVal += parseInt(split[0])*60;
            if (string[0] == "-") split[1] = "-" + split[1];
            returnVal += parseInt(split[1]);
            return parseInt(returnVal);
        }
        for (var i=0; i<data.length; i++){
            var unit = data[i].substring(data[i].length-1,data[i].length);
            var amount = data[i].substring(0,data[i].length-1);
            if (unit == "h"){
                returnVal += parseInt(amount*60);
            } else if (unit == "m"){
                returnVal += parseInt(amount);
            }
        }
        if (string[0] == "-") returnVal = "-" + returnVal;
        return parseInt(returnVal);
    }
    function minutesToString(minutes){
        var prefix = (minutes < 0) ? "-" : "";
        var hours = Math.trunc(parseInt(minutes)/60);
        var remainingMinutes = Math.abs(parseInt(minutes) - (hours*60));
        if (remainingMinutes < 10) remainingMinutes = "0" + remainingMinutes.toString();
        return prefix + Math.abs(hours) + ":" + remainingMinutes;
    }
    function minutesToTCString(minutes){
        var prefix = (minutes < 0) ? "-" : "";
        var hours = Math.trunc(parseInt(minutes)/60);
        var remainingMinutes = Math.abs(parseInt(minutes) - (hours*60));
        if (remainingMinutes < 10) remainingMinutes = "0" + remainingMinutes.toString();
        return prefix + Math.abs(hours) + "h " + remainingMinutes + "m";
    }
    $('.sub-list > li:first').before("<li id='breakdown' style='cursor:pointer; color:#dddddd'><strong>Breakdown</strong></li>");
    $('#breakdown').on('click', function () {
        if ($("div:contains('Break now / all time')").length > 0 && ($("div:contains('Time Left')").length === 0)){
            return;
        }
        var sumRow = $("tr:contains('%')");
        sumRow = sumRow[sumRow.length-1];
        var timeReq = 0;
        var enough = false;
        $("tr").each(function(data){
            if ($(this).children()[3] !== undefined){
                if ($(this).children()[3].innerHTML.indexOf("h") !== -1 &&
                    $(this).children()[3].innerHTML.indexOf("href") === -1 &&
                    $(this).children()[3].innerHTML.indexOf("Should") === -1 &&
                    $(this).children()[3].innerHTML.indexOf("%") === -1 &&
                    !enough){
                    timeReq += stringToMinutes($(this).children()[3].innerHTML);
                    if ($(this).children()[6].innerHTML.indexOf("working") !== -1 )
                    {
                        enough = true;
                    }
                }
            }
        });
        var paidSum = sumRow.children[9].innerHTML;
        paidSum = stringToMinutes(paidSum.substring(0,paidSum.indexOf("<")));
        var activeRow = $("tr:contains('still')")[0];
        if (activeRow !== undefined){
            var widgetData = "";
            var children = activeRow.children;
            var startTime = stringToMinutes(children[5].innerHTML);
            var timeAlreadyWorkedToday = stringToMinutes(children[9].children[0].innerHTML);
            var now = new Date();
            var timeBehind = (startTime + timeAlreadyWorkedToday) - (stringToMinutes(now.toISOString().slice(11,16))+119);

            if ($("div:contains('Time Left')").length === 0){
                var todayShouldBe = stringToMinutes(children[3].innerHTML);

                var workedWithoutToday = paidSum - timeAlreadyWorkedToday;

                var timeLeft = timeReq - workedWithoutToday;
                var todayTimeLeft = todayShouldBe - timeAlreadyWorkedToday;
                appendToUl("Work to do today",minutesToString(timeLeft) + " (" + minutesToString(timeLeft - todayShouldBe) + ")");

                var leaveTime = startTime + timeLeft;
                var todayLeaveTime = startTime + todayShouldBe;
                if (todayLeaveTime < leaveTime){
                    appendToUl("Leave Between",minutesToString(todayLeaveTime) + " - " + minutesToString(leaveTime));
                    document.title = minutesToString(todayLeaveTime) + " - " + minutesToString(leaveTime);
                } else {
                    appendToUl("Leave Between",minutesToString(leaveTime) + " - " + minutesToString(todayLeaveTime));
                    document.title = minutesToString(leaveTime) + " - " + minutesToString(todayLeaveTime);
                }

                var leaveDate = new Date();
                var leaveDateSplit = minutesToString(leaveTime).split(":");
                leaveDate.setHours(leaveDateSplit[0],leaveDateSplit[1],0,0);
                var timeleftInWork = leaveDate - now;
                var mLeft = Math.floor((timeleftInWork / 60000));

                var leaveDateToday = new Date();
                var leaveDateTodaySplit = minutesToString(todayLeaveTime).split(":");
                leaveDateToday.setHours(leaveDateTodaySplit[0],leaveDateTodaySplit[1],0,0);
                var timeleftInWorkToday = leaveDateToday - now;
                var mLeftToday = Math.floor((timeleftInWorkToday / 60000));
                if (mLeft < mLeftToday){
                    appendToUl("Time Left ("+timeBehind+"m)",minutesToString(mLeft) + " - " + minutesToString(mLeftToday));
                } else {
                    appendToUl("Time Left ("+timeBehind+"m)",minutesToString(mLeftToday) + " - " + minutesToString(mLeft));
                }
            } else {
                //update Timeleft header
                $("div:contains('Time Left')")[4].innerHTML = "Time Left ("+timeBehind+"m)";
                console.log("updated");
                return;
            }
        }
        var rows = $("tr:contains(':'),tr:contains('am')");
        var targetEff = 0.85;
        for (i=0;i<rows.length;i++){
            var effectiveCell = rows[i].children[8].children[0];
            var paidCell = rows[i].children[9].children[0];
            var privCell = rows[i].children[10];
            var effectiveTime = stringToMinutes(effectiveCell.innerHTML);
            var paidTime = stringToMinutes(paidCell.innerHTML);
            var effPercent = Math.round((effectiveTime/paidTime)*10000)/100;
            var maxPaidTime = effectiveTime / targetEff;
            var freeTimeLeft = maxPaidTime - paidTime;
            if (freeTimeLeft < 0) {
                var diff = paidTime - effectiveTime;
                freeTimeLeft = paidTime - (diff / (1 - targetEff));
            }
            freeTimeLeft = minutesToString(freeTimeLeft);
            privCell.innerHTML = "<small>(" + effPercent + "%) " + freeTimeLeft + "</small>";
        }

        if ($("th:contains('Private leave')")[0]){
            $("th:contains('Private leave')")[0].innerHTML = "Efficiency (" + targetEff*100 + "%)";
        }
        var effSum = sumRow.children[8].innerHTML;
        effSum = stringToMinutes(effSum.substring(0,effSum.indexOf("<")));
        var maxPaidTimeSum = effSum / targetEff;
        var freeTimeLeftSum = maxPaidTimeSum - paidSum;
        if (freeTimeLeftSum < 0) {
            var diff = paidSum - effSum;
            freeTimeLeftSum = paidSum - (diff / (1 - targetEff));
        }

        appendToUl("Break now / all time",freeTimeLeft + " / " + minutesToString(freeTimeLeftSum));

        sumRow.children[10].innerHTML = minutesToTCString(freeTimeLeftSum) + "<br><small>" + Math.round((effSum/paidSum)*10000)/100 + "%</small>";
        if ($("div.row") === undefined) {
            return;
        }
        $("div.row")[0].outerHTML = "";
        for (i=0;i<8;i++){
            $("div#reportContent")[0].children[0].outerHTML = "";
        }
        $("ul.tt-report-nav")[0].children[2].outerHTML = "";

        var temp = $("li:contains('Break now')")[0].outerHTML;
        $("li:contains('Break now')")[0].outerHTML = "";
        $("li.filter-people").after(temp);

        $("h1:contains('Attendance')").eq(0).css("margin","0");
        $("h1:contains('Attendance')").eq(0).css("margin-top","10px");
	$('.bulk-dates').parent().parent().children().each(function(){$(this).css('line-height','0.5');})
	$('.bulk-dates').each(function(){$(this).remove();})
    });
})();