this is my code for chat page
and send message works fine
but i can't send media
its so to ask in modal for get input type and ...
same as WhatsApp on hove attachBtn show a small box above on attach and show icon for select type and open file explore or send location
i can't see any file exploere for give file and also send location dosn't works correct, i'll select location but it don't get that lcation and generated link is wrong

only change this file i'll handel other things

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WhatsApp-style Chat</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB3DuJbc-sguk2Ry47XkKqkhIJHDJJNES4&callback=initMap" async defer></script>
    <style>
        .messages-container::-webkit-scrollbar {
            width: 6px;
        }
        .messages-container::-webkit-scrollbar-thumb {
            background-color: rgba(0, 0, 0, 0.2);
        }
    </style>
</head>
<body class="bg-gray-100 h-screen flex items-center justify-center">
    <div class="w-full max-w-3xl h-[600px] bg-white shadow-lg rounded-lg flex flex-col">
        <div class="bg-[#075E54] text-white p-4 rounded-t-lg">
            <h1 class="text-lg font-semibold">Chat with {{ conversation.user.username }}</h1>
        </div>

        <div id="chatMessages" class="flex-1 overflow-y-auto p-4 space-y-4 messages-container">
            <!-- Messages will be inserted here -->
        </div>

        <div class="bg-[#F0F0F0] p-4 rounded-b-lg">
            <div class="flex items-center space-x-2">
                <button id="attachBtn" class="text-[#128C7E] hover:text-[#075E54]">
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" />
                    </svg>
                </button>
                <input type="text" id="messageInput" class="flex-1 rounded-full py-2 px-4 focus:outline-none focus:ring-2 focus:ring-[#25D366]" placeholder="Type a message">
                <button id="sendBtn" class="bg-[#25D366] text-white rounded-full p-2 hover:bg-[#128C7E] focus:outline-none focus:ring-2 focus:ring-[#25D366]">
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/>
                    </svg>
                </button>
            </div>
        </div>
    </div>

    <!-- Hidden file input -->
    <input type="file" id="fileInput" style="display: none;" accept="image/*,video/*,audio/*">

    <!-- Location Modal -->
    <div id="locationModal" class="fixed z-10 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
        <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
            <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
            <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
            <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
                <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
                    <div id="map" style="height: 300px;"></div>
                </div>
                <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
                    <button type="button" id="sendLocationBtn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-[#25D366] text-base font-medium text-white hover:bg-[#128C7E] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#25D366] sm:ml-3 sm:w-auto sm:text-sm">
                        Send Location
                    </button>
                    <button type="button" id="closeLocationBtn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
                        Cancel
                    </button>
                </div>
            </div>
        </div>
    </div>

    <script>
    (function() {
        const conversationId = '{{ conversation.id }}';
        const currentUser = '{{ request.user.username }}';
        const ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
        const chatSocket = new WebSocket(
            ws_scheme + '://' + window.location.host + '/ws/chat/' + conversationId + '/'
        );

        const messageInput = document.getElementById('messageInput');
        const chatMessages = document.getElementById('chatMessages');
        const sendBtn = document.getElementById('sendBtn');
        const attachBtn = document.getElementById('attachBtn');
        const fileInput = document.getElementById('fileInput');
        const locationModal = document.getElementById('locationModal');
        const sendLocationBtn = document.getElementById('sendLocationBtn');
        const closeLocationBtn = document.getElementById('closeLocationBtn');

        let map, marker;

        function appendMessage(sender, content, timestamp, isSent, isFile = false, fileUrl = '', fileType = '') {
            const messageElement = document.createElement('div');
            messageElement.className = `flex ${isSent ? 'justify-end' : 'justify-start'}`;

            const innerDiv = document.createElement('div');
            innerDiv.className = `max-w-xs md:max-w-md lg:max-w-lg xl:max-w-xl rounded-lg p-3 ${isSent ? 'bg-[#DCF8C6]' : 'bg-white'}`;

            let messageContent = '';
            if (isFile && fileUrl) {
                if (fileType.startsWith('image/')) {
                    messageContent = `<img src="${fileUrl}" alt="Image" class="max-w-full h-auto rounded">`;
                } else if (fileType.startsWith('video/')) {
                    messageContent = `<video controls class="max-w-full h-auto rounded"><source src="${fileUrl}" type="${fileType}">Your browser does not support the video tag.</video>`;
                } else if (fileType.startsWith('audio/')) {
                    messageContent = `<audio controls class="w-full"><source src="${fileUrl}" type="${fileType}">Your browser does not support the audio tag.</audio>`;
                } else {
                    messageContent = `<a href="${fileUrl}" target="_blank" class="text-blue-500 hover:underline">Download File</a>`;
                }
            } else if (content.startsWith('Shared a location:')) {
                const [, locationUrl] = content.split(': ');
                messageContent = `Shared a location: <a href="${locationUrl}" target="_blank" class="text-blue-500 hover:underline">View on Google Maps</a>`;
            } else {
                messageContent = content;
            }

            innerDiv.innerHTML = `
                <p class="font-semibold ${isSent ? 'text-[#075E54]' : 'text-[#128C7E]'}">${sender}</p>
                <div class="text-gray-800">${messageContent}</div>
                <p class="text-xs text-gray-500 text-right">${new Date(timestamp).toLocaleTimeString()}</p>
            `;

            messageElement.appendChild(innerDiv);
            chatMessages.appendChild(messageElement);
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }

        function sendMessage(content, isFile = false, fileUrl = '', fileType = '') {
            const data = {
                'action': 'message',
                'message': content,
                'is_file': isFile,
                'file_url': fileUrl,
                'file_type': fileType
            };
            chatSocket.send(JSON.stringify(data));
        }

        sendBtn.addEventListener('click', () => {
            const messageText = messageInput.value.trim();
            if (messageText !== '') {
                sendMessage(messageText);
                messageInput.value = '';
            }
        });

        messageInput.addEventListener('keypress', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendBtn.click();
            }
        });

        attachBtn.addEventListener('click', () => {
            const options = ['Send File', 'Share Location'];
            const choice = prompt(`Choose an option:\n1. ${options[0]}\n2. ${options[1]}\nEnter the number of your choice:`);

            switch(choice) {
                case '1':
                    fileInput.click();
                    break;
                case '2':
                    locationModal.classList.remove('hidden');
                    initMap();
                    break;
                default:
                    alert('Invalid choice. Please try again.');
            }
        });

        fileInput.addEventListener('change', function() {
            const file = this.files[0];
            if (file) {
                const formData = new FormData();
                formData.append('file', file);

                fetch(`/chat/upload_file/${conversationId}/`, {
                    method: 'POST',
                    body: formData,
                    headers: {
                        'X-CSRFToken': '{{ csrf_token }}',
                    },
                })
                .then(response => response.json())
                .then(data => {
                    if (data.status === 'success') {
                        sendMessage(file.name, true, data.file_url, file.type);
                    } else {
                        console.error('File upload failed:', data.message);
                        alert('File upload failed: ' + data.message);
                    }
                })
                .catch(error => {
                    console.error('Error uploading file:', error);
                    alert('Error uploading file.');
                });
            }
        });

        window.initMap = function() {
            const defaultLocation = { lat: -34.397, lng: 150.644 };
            map = new google.maps.Map(document.getElementById('map'), {
                center: defaultLocation,
                zoom: 8
            });
            marker = new google.maps.Marker({
                position: defaultLocation,
                map: map,
                draggable: true
            });
        };

        sendLocationBtn.addEventListener('click', () => {
            if (marker) {
                const position = marker.getPosition();
                const messageText = `Shared a location: https://www.google.com/maps/search/?api=AIzaSyB3DuJbc-sguk2Ry47XkKqkhIJHDJJNES4&query=${position.lat()},${position.lng()}`;
                sendMessage(messageText);
                locationModal.classList.add('hidden');
            } else {
                alert('Please select a location on the map.');
            }
        });

        closeLocationBtn.addEventListener('click', () => {
            locationModal.classList.add('hidden');
        });

        chatSocket.onopen = function(e) {
            console.log('WebSocket connection established.');
        };

        chatSocket.onmessage = function(e) {
            const data = JSON.parse(e.data);
            if (data.action === 'message') {
                const isSent = data.sender === currentUser;
                appendMessage(data.sender, data.message, data.timestamp, isSent, data.is_file, data.file_url, data.file_type);
            }
        };

        chatSocket.onerror = function(e) {
            console.error('WebSocket error:', e);
        };

        chatSocket.onclose = function(e) {
            console.warn('WebSocket connection closed.');
        };

        // Load old messages
        {% for message in messages %}
            appendMessage(
                '{{ message.sender.username }}',
                '{{ message.content|escapejs }}',
                '{{ message.timestamp|date:"c" }}',
                '{{ message.sender.username }}' === currentUser,
                {{ message.is_file|yesno:"true,false" }},
                '{{ message.file_url|default:"" }}',
                '{{ message.file_type|default:"" }}'
            );
        {% endfor %}
    })();
    </script>
</body>
</html>

user_passes_test(is_operator)
@csrf_exempt
def upload_file(request, conversation_id):
    ALLOWED_CONTENT_TYPES = ['image/jpeg', 'image/png', 'application/pdf', 'text/plain', 'video/mp4', 'audio/mpeg']
    MAX_FILE_SIZE = 20 * 1024 * 1024  # 20 MB

    if request.method == 'POST' and request.FILES.get('file'):
        uploaded_file = request.FILES['file']

        # Validate file type
        if uploaded_file.content_type not in ALLOWED_CONTENT_TYPES:
            return JsonResponse({'status': 'error', 'message': 'Unsupported file type.'}, status=400)

        # Validate file size
        if uploaded_file.size > MAX_FILE_SIZE:
            return JsonResponse({'status': 'error', 'message': 'File size exceeds limit.'}, status=400)

        conversation = get_object_or_404(Conversation, id=conversation_id)

        if not request.user.is_superuser and conversation.operator != request.user:
            return HttpResponseForbidden("You do not have permission to upload a file to this conversation.")

        # Save the message
        message = Message.objects.create(
            conversation=conversation,
            sender=request.user,
            is_file=True
        )

        # Save the attachment
        attachment = Attachment.objects.create(
            message=message,
            file=uploaded_file
        )

        # Notify via WebSocket
        from asgiref.sync import async_to_sync
        from channels.layers import get_channel_layer
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            f'chat_{conversation_id}',
            {
                'type': 'chat_message',
                'message': '',
                'sender': request.user.username,
                'file_url': attachment.file.url,
                'file_type': uploaded_file.content_type,
                'message_id': message.id,
            }
        )

        return JsonResponse({
            'status': 'success',
            'file_url': attachment.file.url,
            'file_type': uploaded_file.content_type,
            'message_id': message.id,
            'message': f"File '{uploaded_file.name}' uploaded successfully."
        })
    return HttpResponseForbidden()