Undefined timestamp Issue in frontend with javascript

I have created django consumers.py and a frontend in html and css to disply messages sent by a user, the profile picture of the sender and the username of the sender but anytime i open the browser, the message displays well and the username appears well but the time since always appear as undefined even though i printed the time stamp from the websocket and it shows the actual timp. ususally when i send a message, i see the received timestamp on the developer console but immediately i refresh the page it changes to undefine, i simply want to be able to display the time elapsed since a essage was sent, example X seconds ago, X minutes ago, X hours ago my timestamp field is using timezone.now, Please i want a user to see the timesince a message was sent, the tmplate filere timesince isnt working though

this is my consumers.py


import os
import json
from channels.generic.websocket import AsyncWebsocketConsumer
from django.contrib.auth import get_user_model
from django.conf import settings
from channels.db import database_sync_to_async
from virtualrooms.models import VirtualRoom
from .models import Interaction
from django.templatetags.static import static
from datetime import datetime


User = get_user_model()

class DiscussionRoomConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = f"discussion_room_{self.room_name}"

        # Join room group
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

        # Get or create the VirtualRoom instance based on the provided room_name
        virtual_room = await self.get_virtual_room()

        if virtual_room is not None:
            # Send existing messages and old messages to the new user
            old_messages = await self.get_old_messages(virtual_room)
            for message in old_messages:
                await self.send(text_data=json.dumps({
                    'message': message['content'],
                    'username': await self.get_username(message['user']),
                    'user_picture': await self.get_user_profile_picture(message['user']),
                }))

    async def disconnect(self, close_code):
        # Leave room group
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        user_id = self.scope["user"].id

        # Get the VirtualRoom instance based on the extracted room name asynchronously
        virtual_room = await self.get_virtual_room()

        # Check if the VirtualRoom instance exists
        if virtual_room:
            # Save message to the database with the VirtualRoom instance asynchronously
            await self.save_interaction_to_database(user_id, virtual_room, message)

            # Send message to the room group
            time_stamp = datetime.now().isoformat()
            username = await self.get_username(user_id)
            user_picture = await self.get_user_profile_picture(user_id)


            # Log the entire message data
            print("Sending message data:", {
                'message': message,
                'username': username,
                'user_picture': user_picture,
                'time_stamp': time_stamp,
            })
            await self.channel_layer.group_send(
                self.room_group_name,
                {
                    'type': 'chat.message',
                    'message': message,
                    'username': username,
                    'user_picture': user_picture,
                    'time_stamp': time_stamp,
                }
            )
        else:
            # Handle the case where the VirtualRoom does not exist
            print(f"VirtualRoom with slug '{self.room_name}' does not exist.")

    @database_sync_to_async
    def save_interaction_to_database(self, user_id, virtual_room, message):
        # Save the message to the database with the VirtualRoom instance
        Interaction.objects.create(
            user_id=user_id,
            room_name=virtual_room,
            content=message
        )

    @database_sync_to_async
    def get_old_messages(self, virtual_room):
        # Fetch old messages based on the VirtualRoom
        return list(Interaction.objects.filter(room_name=virtual_room).order_by('time_stamp').values('user', 'content'))

    @database_sync_to_async
    def get_username(self, user_id):
        try:
            user = User.objects.get(id=user_id)
            return user.username
        except User.DoesNotExist:
            return None

    @database_sync_to_async
    def get_user_profile_picture(self, user_id):
        try:
            user = User.objects.get(id=user_id)

            # Check if the user has a profile picture
            if hasattr(user, 'user_picture') and user.user_picture:
                user_picture = user.user_picture
                # Use Django storage to get the correct file path
                image_path = user_picture.path
                if os.path.isfile(image_path):
                    # Return the actual user picture URL if the image file exists
                    return user_picture.url
                else:
                    # Log that the image file doesn't exist and return the default avatar
                    print(f"Image file for user {user_id} does not exist. Using default avatar.")
                    return static('images/avatar.svg')
            else:
                # Log that the user does not have a profile picture and return the default avatar
                print(f"User {user_id} does not have a profile picture. Using default avatar.")
                return static('images/avatar.svg')

        except User.DoesNotExist:
            # Log that the user does not exist and return the default avatar
            print(f"User {user_id} does not exist. Using default avatar.")
            return static('images/avatar.svg')

    @database_sync_to_async
    def get_virtual_room(self):
        try:
            return VirtualRoom.objects.get(slug__iexact=self.room_name)
        except VirtualRoom.DoesNotExist:
            return None

    # Receive message from the room group
    async def chat_message(self, event):
        message = event['message']
        username = event['username']
        user_picture = event['user_picture']
        time_stamp = event['time_stamp']

        print(f"Sending message with timestamp: {time_stamp}")
        # Send the message to WebSocket
        await self.send(text_data=json.dumps({
            'message': message,
            'username': username,
            'user_picture': user_picture,
            'time_stamp': time_stamp,
        }))




and this is my frontend:


<!DOCTYPE html>
{% load static %}
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="{% static 'css/discussionroom.css' %}">
    <title>Discussion Room</title>
</head>
<body>
<div id="discussion-room">
    <div id="chat-box">
    {% for message in messages %}
        <div>
            <img src="{{ message.user_picture.url|default:'/static/images/avatar.svg' }}" alt="User Picture" style="width: 30px; height: 30px;">
            <strong>{{ message.username }}:</strong>
            {{ message.message }}
            <span class="timestamp">{{ message.time_stamp|timesince }}</span>
        </div>
    {% endfor %}
    </div>
    <input type="text" id="message-input" placeholder="Type your message...">
    <button onclick="sendMessage()">Send</button>
</div>

<script>
    // Get the room name from the URL
    const pathArray = window.location.pathname.split('/');
    const roomNameIndex = pathArray.indexOf('discussions') + 1;
    const roomName = pathArray[roomNameIndex].split('@')[1];

    // Log the extracted room name
    console.log('Extracted room name:', roomName);

    // Create a new WebSocket connection
    const socket = new WebSocket(`ws://${window.location.host}/ws/discussions/${roomName}/`);

    socket.onmessage = function(event) {
        const data = JSON.parse(event.data);
        console.log('Received data:', data);
        displayMessage(data.user_picture, data.username, data.message, data.time_stamp);
        // Save timestamp to local storage
    localStorage.setItem('lastTimestamp', data.time_stamp);
};
    

    
    

    function sendMessage() {
        const message = document.getElementById('message-input').value;
        if (message.trim() !== '') {
            socket.send(JSON.stringify({'message': message}));
            document.getElementById('message-input').value = '';
        }
    }

    
    function displayMessage(userPicture, username, message, timestamp) {
        console.log('Received timestamp:', timestamp);
        console.log('Received user picture:', userPicture);
     localStorage.setItem('lastTimestamp', timestamp);

    const messageDiv = document.createElement('div');

    // Set the userPicture URL
    const imageUrl = userPicture || '/static/images/avatar.svg';

    //console.log('Selected image URL:', imageUrl);

    const imgElement = new Image();
    imgElement.src = imageUrl;

    // Add an event listener to handle image load errors
    imgElement.addEventListener('error', function() {
        //console.warn('Error loading image. Using default avatar.');
        messageDiv.innerHTML = `<img src="/static/images/avatar.svg" alt="Default Avatar" style="width: 30px; height: 30px;"> ${message}`;
        document.getElementById('chat-box').appendChild(messageDiv);
    });

    // Add an event listener to handle image load success
    imgElement.addEventListener('load', function() {
        imgElement.className = 'user-profile-img'; // Add this line
        messageDiv.innerHTML = `<img src="${imageUrl}" alt="User Picture" style="width: 30px; height: 30px;  border-radius: 50%; object-fit: cover; "> <strong>${username}:</strong> ${message}`;
        document.getElementById('chat-box').appendChild(messageDiv);
    });
}
const storedTimestamp = localStorage.getItem('lastTimestamp');
if (storedTimestamp) {
    console.log('Retrieved timestamp from local storage:', storedTimestamp);
}
</script>

</body>
</html>

Back to Top