File size: 3,214 Bytes
bdabf98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
document.addEventListener('DOMContentLoaded', () => {
    initRealTimeData();
    initInteractions();
});

// --------------------------------------------------------
// REAL-TIME API DATA (CoinGecko for Market Simulation)
// --------------------------------------------------------
async function initRealTimeData() {
    const btcEl = document.getElementById('btc-price');
    const ethEl = document.getElementById('eth-price');
    const volEl = document.getElementById('total-vol');

    try {
        // Fetching data from public API
        const response = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd&include_24hr_vol=true');
        const data = await response.json();

        if (data.bitcoin) {
            animateValue(btcEl, 0, data.bitcoin.usd, 1000, '$');
        }
        if (data.ethereum) {
            animateValue(ethEl, 0, data.ethereum.usd, 1000, '$');
        }
        
        // Just a mockup for volume as it requires a different endpoint, utilizing the API response structure
        volEl.innerText = '$84.2B'; 
        
    } catch (error) {
        console.error('API Connection Failed:', error);
        btcEl.innerText = 'OFFLINE';
        ethEl.innerText = 'OFFLINE';
        volEl.innerText = 'UNKNOWN';
    }
}

// Number Counter Animation
function animateValue(obj, start, end, duration, prefix = '') {
    let startTimestamp = null;
    const step = (timestamp) => {
        if (!startTimestamp) startTimestamp = timestamp;
        const progress = Math.min((timestamp - startTimestamp) / duration, 1);
        const value = Math.floor(progress * (end - start) + start);
        obj.innerHTML = prefix + value.toLocaleString();
        if (progress < 1) {
            window.requestAnimationFrame(step);
        } else {
            // Format to 2 decimals at the end for crypto
            obj.innerHTML = prefix + end.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
        }
    };
    window.requestAnimationFrame(step);
}

// --------------------------------------------------------
// INTERACTIONS
// --------------------------------------------------------
function initInteractions() {
    // Smooth scroll for anchor links
    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
        anchor.addEventListener('click', function (e) {
            e.preventDefault();
            const target = document.querySelector(this.getAttribute('href'));
            if (target) {
                target.scrollIntoView({
                    behavior: 'smooth'
                });
            }
        });
    });

    // Randomly update "Status" in agent cards to simulate "Alive" system
    setInterval(() => {
        const cards = document.querySelectorAll('custom-agent-card');
        const randomCard = cards[Math.floor(Math.random() * cards.length)];
        // We would need to expose a method in the component to do this cleanly,
        // but for now we can trigger a visual glitch on the container
        randomCard.classList.add('animate-pulse');
        setTimeout(() => {
            randomCard.classList.remove('animate-pulse');
        }, 500);
    }, 3000);
}