Fineco MyCards: Show only the credit card transactions

This script adds a button in the page "My Cards" of FinecoBank.com that allows to show the list (and the total amount) of the only credit card transactions.

// ==UserScript==
// @name           Fineco MyCards: Show only the credit card transactions
// @name:it        Fineco MyCards: Mostra soltanto le operazioni della carta di credito
// @description    This script adds a button in the page "My Cards" of FinecoBank.com that allows to show the list (and the total amount) of the only credit card transactions.
// @description:it Questo script aggiunge un bottone nella pagina "My Cards" di FinecoBank.com che consente di visualizzare la lista (e l'ammontare totale) delle sole operazioni con carta di credito.
// @match          https://finecobank.com/conto-e-carte/mycards*
// @grant          none
//// @run-at         document-start
// @version        1.1.5
// @author         Cyrano68
// @license        MIT
// @namespace https://greasyfork.org/users/788550
// ==/UserScript==

(function()
{
    "use strict";

    function console_log(text)
    {
        //let now = new Date().toISOString();
        let now = new Date().toLocaleString();
        console.log(`${now} ${text}`);
    }

    function setInterval2(callback, interval_ms)
    {
        console_log(`==> Fineco_MyCards_ShowOnlyCC: setInterval2 - STARTING TIMER - interval_ms=${interval_ms}`);
        let timerId = setInterval(callback, interval_ms);
        console_log(`==> Fineco_MyCards_ShowOnlyCC: setInterval2 - TIMER STARTED - timerId=${timerId}`);
        callback(timerId);
        return timerId;
    }

    console_log("==> Fineco_MyCards_ShowOnlyCC: HELLO! Loading script...");

    let timerId = 0;
    let interval_ms = 250;

    document.addEventListener("DOMContentLoaded", onDOMContentLoaded);
    window.addEventListener("load", onWindowLoaded);

    function onDOMContentLoaded()
    {
        console_log(`==> Fineco_MyCards_ShowOnlyCC: onDOMContentLoaded - document.readyState=${document.readyState}`);

        let myCSS = document.createElement("style");

        // SEE: https://getcssscan.com/css-buttons-examples
        myCSS.textContent = `
            .button-3 {
                appearance: none;
                background-color: #2ea44f;
                border: 1px solid rgba(27, 31, 35, .15);
                border-radius: 6px;
                box-shadow: rgba(27, 31, 35, .1) 0 1px 0;
                box-sizing: border-box;
                color: #fff;
                cursor: pointer;
                display: inline-block;
                font-family: -apple-system,system-ui,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
                font-size: 14px;
                font-weight: 600;
                line-height: 20px;
                padding: 6px 16px;
                position: relative;
                text-align: center;
                text-decoration: none;
                user-select: none;
                -webkit-user-select: none;
                touch-action: manipulation;
                vertical-align: middle;
                white-space: nowrap;
            }
            .button-3:focus:not(:focus-visible):not(.focus-visible) {
                box-shadow: none;
                outline: none;
            }
            .button-3:hover {
                background-color: #2c974b;
            }
            .button-3:focus {
                box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
                outline: none;
            }
            .button-3:disabled {
                background-color: #94d3a2;
                border-color: rgba(27, 31, 35, .1);
                color: rgba(255, 255, 255, .8);
                cursor: default;
            }
            .button-3:active {
                background-color: #298e46;
                box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
            }
        `;

        document.body.appendChild(myCSS);
        console_log(`==> Fineco_Inbox_DeleteAll: onDOMContentLoaded - myCSS.outerHTML='${myCSS.outerHTML}'`);
    }

    function onWindowLoaded()
    {
        console_log(`==> Fineco_MyCards_ShowOnlyCC: onWindowLoaded - document.readyState=${document.readyState}`);
        addMyButton();
    }

    function addMyButton()
    {
        console_log("==> Fineco_MyCards_ShowOnlyCC: addMyButton");

        let interval_ms = 250;
        let timerId = setInterval2((inputTimerId) =>
        {
            let effectiveTimerId = (inputTimerId === undefined) ? timerId : inputTimerId;
            console_log(`==> Fineco_MyCards_ShowOnlyCC: addMyButton - inputTimerId=${inputTimerId}, effectiveTimerId=${effectiveTimerId}`);

            let divMovimenti = document.querySelector("div.movimenti-container");
            console_log(`==> Fineco_MyCards_ShowOnlyCC: addMyButton - divMovimenti=${divMovimenti}`);
            if (divMovimenti !== null)
            {
                console_log("==> Fineco_MyCards_ShowOnlyCC: addMyButton - data READY");

                clearInterval(effectiveTimerId);
                console_log(`==> Fineco_MyCards_ShowOnlyCC: addMyButton - TIMER STOPPED - effectiveTimerId=${effectiveTimerId}`);

                // Create a new button that will allow to show only the credit card entries.
                let myButton = Object.assign(document.createElement("button"), {id: "myButton", textContent: "SHOW ONLY CREDIT CARD", className: "button-3"});
                myButton.addEventListener("click", showOnlyCC);
                console_log(`==> Fineco_MyCards_ShowOnlyCC: addMyButton - myButton.outerHTML='${myButton.outerHTML}'`);

                // The button is placed before the "divMovimenti".
                divMovimenti.before(myButton);

                console_log(`==> Fineco_MyCards_ShowOnlyCC: addMyButton - DONE`);
            }
            else
            {
                console_log("==> Fineco_MyCards_ShowOnlyCC: addMyButton - data NOT READY... wait");
            }
        }, interval_ms);
    }

    function showOnlyCC()
    {
        console_log("==> Fineco_MyCards_ShowOnlyCC: showOnlyCC");

        // First of all delete the span tag (eventually added in a previous click) that shows the total amount of the credit card transactions.
        let mySpan = document.querySelector("span#mySpan");
        console_log(`==> Fineco_MyCards_ShowOnlyCC: showOnlyCC - mySpan=${mySpan}`);
        if (mySpan !== null)
        {
            mySpan.remove();
        }

        // Then remove the bancomat entries.
        let bancomatEntries = document.querySelectorAll("div.movimenti-container div.text-right > img[src$='Bancomat.svg']");
        console_log(`==> Fineco_MyCards_ShowOnlyCC: showOnlyCC - bancomatEntries.length=${bancomatEntries.length}`);

        // Sometimes there was a problem when the bancomat entries were removed. In details, it happened when in the same day there was a visa entry and a bancomat entry.
        // After the bancomat entry was removed if I tried to expand the visa entry (in order to see the details of the transaction) an error was generated.
        // Therefore I decided to hide the bancomat entries instead of remove them.
        bancomatEntries.forEach((bancomatEntry, i) =>
        {
            // The bancomat entries will be hidden.
            let divAccordionWrapper = bancomatEntry.closest("div.accordionWrapper");
            console_log(`==> Fineco_MyCards_ShowOnlyCC: showOnlyCC - i=${i}, divAccordionWrapper=${divAccordionWrapper}`);
            if (divAccordionWrapper !== null)
            {
                divAccordionWrapper.style.display = "none";  // Hide node.
            }
        });

        // Finally calculate the total amount of the credit card transactions.
        calculateTotalCC();
    }

    function calculateTotalCC()
    {
        console_log(`==> Fineco_MyCards_ShowOnlyCC: calculateTotalCC`);

        let allEntries = document.querySelectorAll("div.accordionWrapper");
        console_log(`==> Fineco_MyCards_ShowOnlyCC: calculateTotalCC - allEntries.length=${allEntries.length}`);

        let ccEntries = Array.from(allEntries).filter((entry) => {return (entry.style.display !== "none");});
        console_log(`==> Fineco_MyCards_ShowOnlyCC: calculateTotalCC - ccEntries.length=${ccEntries.length}`);

        let totalCC = 0;
        ccEntries.forEach((ccEntry, i) =>
        {
            //console_log(`==> Fineco_MyCards_ShowOnlyCC: calculateTotalCC - i=${i}`);
            let spanAmount = ccEntry.querySelector("div.text-right.amountDetail > span.detailAmount");

            let amountText = spanAmount.textContent.slice(0,-4);
            let amountText2;

            // Try to understand the type of decimal point (dot or comma) used in the page (it is supposed that there are always two digits after the decimal point).
            if (amountText.slice(-3,-2) == ",")
            {
                // The decimal point is a comma (",")... therefore remove the "thousand" separators (".") and transform the comma decimal point in dot decimal point.
                amountText2 = amountText.replace(/\./g,"").replace(/\,/g,".");
            }
            else
            {
                // The decimal point is a dot (".")... Therefore only remove the "thousand" separators (",").
                amountText2 = amountText.replace(/\,/g,"");
            }

            // Now the variable "amountText2" is a string that contains numbers and at most the dot decimal point... i.e it can be parsed with "parseFloat".
            let amountValue = parseFloat(amountText2);
            totalCC += amountValue;
        });

        addMySpan(totalCC);
    }

    function addMySpan(totalCC)
    {
        console_log(`==> Fineco_MyCards_ShowOnlyCC: addMySpan - totalCC=${totalCC}`);

        // Add a span (next to the new button) that shows the total amount of the credit card transactions.
        let totalCCText = " TOTAL: " + Number(Math.abs(totalCC)).toLocaleString("it-IT", {style: "currency", currency: "EUR"});
        let mySpan = Object.assign(document.createElement("span"), {id: "mySpan", textContent: totalCCText, style: "color: blue; font-weight: bold; font-size: 16px"});
        console_log(`==> Fineco_MyCards_ShowOnlyCC: addMySpan - mySpan.outerHTML='${mySpan.outerHTML}'`);

        let myButton = document.querySelector("button#myButton");

        // The span is placed after the "myButton".
        myButton.after(mySpan);
    }

    console_log("==> Fineco_MyCards_ShowOnlyCC: Script loaded");
})();