La mia app

Questa è la web app in html, css e js.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>MyTabs</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="/test/silver.css">

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
    <script src="/test/silver.js"></script>
</head>

<body>
    <div id="container" class="container">
        <ul class="nav nav-tabs">
            <li class="nav-item">
                <a class="nav-link active" data-toggle="tab" href="#tab1">Silver</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" data-toggle="tab" href="#tab2">ADA</a>
            </li>
        </ul>

        <div class="tab-content">
            <div id="tab1" class="tab-pane fade show active">
                <div id="tab1" class="tab-pane fade show active">

                    <h1>Exchange Rates</h1>
                    <div id="exchange-rates"></div>

                </div>
            </div>
            <div id="tab2" class="tab-pane fade">

                <h1>Exchange Rates</h1>
                <div id="price"></div>

            </div>
        </div>
    </div>
    <script>
        $('.nav-tabs a').on('click', function (e) {
            e.preventDefault()
            $(this).tab('show')
        })
    </script>
</body>

</html>
/* Stile degli elementi con classe "flag" */
.flag {
    display: inline-block;
    width: 64px;
    height: 48px;
    background-size: auto;
    /* Centra in verticale */
    vertical-align: middle;
    margin: 5px;
}

/* Stile delle valute che utilizzano il colore argento */
.flag.CNY {
    background-image: url('/test/img/cn.svg');
}

.flag.EUR {
    background-image: url('/test/img/eu.svg');
}

.flag.RUB {
    background-image: url('/test/img/ru.svg');
}

.flag.USD {
    background-image: url('/test/img/us.svg');
}

/* Stile della tabella dei tassi di cambio */
#exchange-rates, #price {
    margin-top: 20px;
    padding: 10px;
    background-color: #808080;
    /* un colore grigio chiaro */
    border-radius: 5px;
}

#exchange-rates div, #price div {
    margin-bottom: 5px;
    padding: 5px;
    background-color: #c0c0c0;
    border-radius: 5px;
    font-size: xx-large;
}

#exchange-rates div span, #price div span {
    display: inline-block;
    margin-right: 10px;
}

body {
    zoom: 200%;
    background-color: lightgray;
}

/* Riduce la distanza tra la scritta "Exchange Rates" e la tabella */
#exchange-rates-header {
    margin-bottom: 0;
}

/* Aggiunge uno sfondo grigio chiaro alla tabella */
#exchange-rates-table {
    background-color: lightgray;
}

/* Rende le righe della tabella più leggibili */
#exchange-rates-table tr:nth-child(even) {
    background-color: lightgray;
}

/* Rende il testo delle intestazioni di colonna in grassetto */
#exchange-rates-table th {
    font-weight: bold;
}

/* Rende il testo delle celle della tabella centrato verticalmente e in grassetto */
#exchange-rates-table td {
    text-align: center;
    font-weight: bold;
}

#container {
    background-color: lightgray;
}

#time {
    color: lightgray;
}
// Definiamo i valori di default
const defaultData = {
    success: true,
    base: 'XAG',
    timestamp: 0,
    rates: {
        CNY: 0.0,
        EUR: 0.0,
        RUB: 0.0,
        USD: 0.0
    }
};

// Funzione per visualizzare i dati ricevuti o i valori di default in caso di errore
function displayData(data) {
    const ratesDiv = document.getElementById('exchange-rates');
    const rates = data.rates || defaultData.rates;
    const timestamp = new Date((data.timestamp || defaultData.timestamp) * 1000);
    const options = {
        timeZone: 'Europe/Rome',
        day: '2-digit',
        month: '2-digit',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit'
    };
    const formatter = new Intl.DateTimeFormat('it-IT', options);
    const formattedTimestamp = formatter.format(timestamp);
    const html = Object.entries(rates).map(([currency, rate]) => {
        const flagClass = `flag ${currency}`;
        return `
      <div>
        <span class="${flagClass}"></span>
        <span>${currency}</span>
        <span>${rate.toFixed(2)}</span>
      </div>
    `;
    }).join('');
    const errorMessage = data.message ? `Error: ${data.message}. Using default data.` : '';
    ratesDiv.innerHTML = `
    <p>${errorMessage}</p>
    <p id="time">Last updated: ${formattedTimestamp}</p>
    ${html}
  `;
}

// Interrogazione dell'endpoint
fetch('/silver/ws_values/silver')
    .then(response => {
        if (!response.ok) {
            throw new Error(response.statusText);
        }
        return response.json();
    })
    .then(data => {
        displayData(data);
    })
    .catch(error => {
        displayData({ message: error.message });
    });

// Definiamo i valori di default
const defaultData2 = {
    price: 0.0,
    timestamp: new Date(0)
};

// Funzione per visualizzare i dati ricevuti o i valori di default in caso di errore
function displayData2(data) {
    const priceDiv = document.getElementById('price');
    const price = data.price || defaultData2.price;
    const timestamp = new Date(data.timestamp || defaultData2.timestamp);
    const options = {
        timeZone: 'Europe/Rome',
        day: '2-digit',
        month: '2-digit',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit'
    };
    const formatter = new Intl.DateTimeFormat('it-IT', options);
    const formattedTimestamp = formatter.format(timestamp);

    const currency = 'EUR';

    const html = `
    <div>
        <span class="flag ${currency}"></span>
        <span>${currency}</span>
        <span>${price.toFixed(2)}</span>
    </div>
    `;

    const errorMessage = data.message ? `Error: ${data.message}. Using default data.` : '';
    priceDiv.innerHTML = `
    <p>${errorMessage}</p>
    <p id="time">Last updated: ${formattedTimestamp}</p>
    ${html}
  `;
}

// Interrogazione dell'endpoint
fetch('/silver/ws_values/ada')
    .then(response => {
        if (!response.ok) {
            throw new Error(response.statusText);
        }
        return response.json();
    })
    .then(data => {
        displayData2(data);
    })
    .catch(error => {
        displayData2({ message: error.message });
    });

Per saperne di più sulla mia app, vai alla pagina successiva.