Tuesday 22 August 2023

How to dynamically display Last Refreshed ago message on webpage that updates based on the elapsed time since the last API call

I am new to web development, and I am trying to display "Last Refreshed ago" on the webpage. Something like this website. I am making API call every 5 minutes, what I would like to achieve is I would like to display text for time 0sec-59 sec as "Last Refreshed 1 sec ago" and so forth. Next for minutes it should display text as "Last refreshed 1 minute ago" , and so on until 5 minutes.As soon API call is made again, then it should display "Last refreshed 0 sec" and continues until 5 minutes ago. Below code has 2 issues

  1. As soon as Browser is refreshed it starts the time again from 0 sec, in my case I would like to display continuous time.In provided website link, even if refresh button is pressed on browser you will notice that it display "Trends last updated 1 min ago"
  2. After end of 5 minutes in below code, time continues for 6 minutes, 7 minutes etc. Even though data for Fetch API is refreshed.

Index.html

<!DOCTYPE html>
<html>
<head>
    <title>Trending Hashtags</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <h1>Trending Hashtags</h1>
    <div id="hashtags-container">
        <!-- Trending hashtags will be dynamically added here -->
    </div>
    <div id="timestamp-container">
        <span class="timestamp">Last Refreshed: -</span>
    </div>

    <script>
        let startTime = 0;

        function startTimer() {
            fetch('/start-time') // Fetch initial start time from server
                .then(response => response.json())
                .then(data => {
                    startTime = data.startTime;
                    setInterval(updateTimer, 1000); // Update every second
                })
                .catch(error => console.error('Error fetching start time:', error));
        }

        function updateTimer() {
            const currentTime = Math.floor(Date.now() / 1000); // Get current Unix timestamp in seconds
            const elapsedSeconds = currentTime - startTime;

            updateTimestamp(elapsedSeconds);
        }

        function updateTimestamp(elapsedSeconds) {
            const timestampElement = document.querySelector('#timestamp-container .timestamp');
            if (timestampElement) {
                const timeAgo = formatTime(elapsedSeconds);
                timestampElement.textContent = `Last Refreshed: ${timeAgo} ago`;
            }
        }

        function formatTime(seconds) {
            const mins = Math.floor(seconds / 60);
            const secs = seconds % 60;
            return mins > 0 ? `${mins} min` : `${secs} sec`;
        }

        function fetchAndUpdateHashtags(containerId) {
            fetch('/trends')
                .then(response => response.json())
                .then(data => {
                    updateHashtagsContainer(containerId, data.data);
                })
                .catch(error => console.error('Error fetching trends:', error));
        }

        function updateHashtagsContainer(containerId, data) {
            const hashtagsContainer = document.getElementById(containerId);
            hashtagsContainer.innerHTML = '';

            data.forEach((item, index) => {
                const trendItem = document.createElement('div');
                trendItem.className = 'trend-item';
                trendItem.innerHTML = `
                    <span>${index + 1}.</span>
                    <span><span>${item.hashtag}</span></span>
                    <span class="text-secondary">${formatTweetVolume(item.tweetCount)}</span>
                `;
                hashtagsContainer.appendChild(trendItem);
            });
        }

        function formatTweetVolume(volume) {
            if (volume >= 1000) {
                return (volume / 1000).toFixed(1) + 'k';
            }
            return volume;
        }

        fetchAndUpdateHashtags('hashtags-container'); // Initial fetch
        startTimer(); // Start the timer

        setInterval(() => {
            fetchAndUpdateHashtags('hashtags-container');
        }, 300 * 1000); // Fetch every 5 minutes (300 seconds)
    </script>

    <style>
        .trending-card {
            border: 1px solid #ccc;
            padding: 10px;
            margin: 10px;
            background-color: #f5f5f5;
        }
    </style>
</body>
</html>

server.js

const express = require('express');
const path = require('path');
const Twit = require('twit');

const app = express();

const apikey = '';
const apisecretkey = '';
const accesstoken = '';
const accesstokensecret = '';

const T = new Twit({
  consumer_key: apikey,
  consumer_secret: apisecretkey,
  access_token: accesstoken,
  access_token_secret: accesstokensecret,
  timeout_ms: 60 * 1000,
});

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.get('/start-time', (req, res) => {
  const startTime = Math.floor(Date.now() / 1000);
  res.json({ startTime });
});

app.get('/trends', (req, res) => {
  const timeAgo = req.query.time || '5min'; // Default to 5 minutes
  const params = { id: '23424977' };

  fetchTrendingHashtags(params)
    .then((data) => {
      res.json({ data, timeAgo });
    })
    .catch((error) => {
      res.status(500).send(error);
    });
});

function fetchTrendingHashtags(params) {
  return new Promise((resolve, reject) => {
    T.get('trends/place', params)
      .then((result) => {
        const trends = result.data[0].trends;

        const validTrends = trends.filter((trend) => trend.tweet_volume !== null);

        const sortedTrends = validTrends.sort((a, b) => b.tweet_volume - a.tweet_volume);

        const topTrends = sortedTrends.slice(0, 10);

        const simplifiedTrends = topTrends.map((trend) => {
          return {
            hashtag: trend.name,
            tweetCount: trend.tweet_volume,
          };
        });

        resolve(simplifiedTrends);
      })
      .catch((error) => {
        console.error('Error fetching trends:', error);
        reject('Error fetching trends');
      });
  });
}

const timeIntervals = [
  { minutes: 5, containerId: 'hashtags-container' }, // Fetch every 5 minutes
  // Add other time intervals here if needed
];

timeIntervals.forEach((interval) => {
  setInterval(() => {
    const newParams = { id: '23424977' };
    fetchTrendingHashtags(newParams)
      .then((data) => {
        updateHashtagsContainer(interval.containerId, data.data);
        console.log(`Fetched trends for ${interval.minutes} ago`);
      })
      .catch((error) => {
        console.error(`Error fetching trends for ${interval.minutes} ago:`, error);
      });
  }, interval.minutes * 60 * 1000);
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});


from How to dynamically display Last Refreshed

No comments:

Post a Comment