Sindbad~EG File Manager

Current Path : /home/copmadinaarea/thecopmadinaarea.org/portal/includes/
Upload File :
Current File : /home/copmadinaarea/thecopmadinaarea.org/portal/includes/admin-chat-inbox.php

<?php
// Admin Chat Inbox Widget - Shows incoming chats from members/visitors
?>

<style>
#admin-chat-inbox {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 9999;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

#admin-inbox-button {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: linear-gradient(135deg, #10B981 0%, #059669 100%);
    color: white;
    border: none;
    cursor: pointer;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26px;
    transition: all 0.3s ease;
    position: relative;
}

#admin-inbox-button:hover {
    transform: scale(1.1);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
}

#admin-inbox-button.has-unread {
    animation: pulse 2s infinite;
}

@keyframes pulse {
    0% {
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15), 0 0 0 0 rgba(16, 185, 129, 0.7);
    }
    50% {
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15), 0 0 0 10px rgba(16, 185, 129, 0);
    }
    100% {
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15), 0 0 0 0 rgba(16, 185, 129, 0);
    }
}

.unread-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    background: linear-gradient(135deg, #EF4444 0%, #DC2626 100%);
    color: white;
    min-width: 24px;
    height: 24px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: bold;
    border: 2px solid white;
    padding: 0 6px;
}

#admin-inbox-panel {
    display: none;
    position: fixed;
    bottom: 100px;
    right: 20px;
    width: 420px;
    max-width: calc(100vw - 40px);
    height: 600px;
    max-height: 80vh;
    background: white;
    border-radius: 16px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
    flex-direction: column;
    overflow: hidden;
}

#admin-inbox-panel.open {
    display: flex;
    animation: slideUp 0.3s ease;
}

@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.inbox-header {
    background: linear-gradient(135deg, #10B981 0%, #059669 100%);
    color: white;
    padding: 16px 20px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
}

.inbox-header h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
}

.inbox-close {
    background: none;
    border: none;
    color: white;
    font-size: 24px;
    cursor: pointer;
    padding: 0;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: background 0.2s;
}

.inbox-close:hover {
    background: rgba(255, 255, 255, 0.2);
}

.inbox-tabs {
    display: flex;
    background: #f9fafb;
    border-bottom: 1px solid #e5e7eb;
    flex-shrink: 0;
}

.inbox-tab {
    flex: 1;
    padding: 12px;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    color: #6b7280;
    border-bottom: 2px solid transparent;
    transition: all 0.2s;
}

.inbox-tab.active {
    color: #10B981;
    border-bottom-color: #10B981;
    background: white;
}

.inbox-list {
    flex: 1;
    overflow-y: auto;
    background: #f9fafb;
}

.conversation-item {
    padding: 16px;
    background: white;
    border-bottom: 1px solid #e5e7eb;
    cursor: pointer;
    transition: all 0.2s;
    display: flex;
    gap: 12px;
    align-items: start;
}

.conversation-item:hover {
    background: #f0fdf4;
}

.conversation-item.unread {
    background: #ecfdf5;
    border-left: 3px solid #10B981;
}

.conversation-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: linear-gradient(135deg, #1E40AF 0%, #9333EA 100%);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 16px;
    flex-shrink: 0;
}

.conversation-content {
    flex: 1;
    min-width: 0;
}

.conversation-header {
    display: flex;
    justify-content: space-between;
    align-items: start;
    margin-bottom: 4px;
}

.conversation-name {
    font-weight: 600;
    color: #1f2937;
    font-size: 14px;
}

.conversation-time {
    font-size: 12px;
    color: #9ca3af;
}

.conversation-preview {
    font-size: 13px;
    color: #6b7280;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.conversation-item.unread .conversation-preview {
    font-weight: 500;
    color: #1f2937;
}

.empty-state {
    padding: 40px 20px;
    text-align: center;
    color: #9ca3af;
}

.empty-state i {
    font-size: 48px;
    margin-bottom: 16px;
    color: #d1d5db;
}

/* Conversation View */
#conversation-view {
    display: none;
    position: fixed;
    bottom: 100px;
    right: 20px;
    width: 420px;
    max-width: calc(100vw - 40px);
    height: 600px;
    max-height: 80vh;
    background: white;
    border-radius: 16px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
    flex-direction: column;
}

#conversation-view.open {
    display: flex;
    animation: slideUp 0.3s ease;
}

.conversation-header-bar {
    background: linear-gradient(135deg, #10B981 0%, #059669 100%);
    color: white;
    padding: 16px 20px;
    display: flex;
    align-items: center;
    gap: 12px;
}

.back-button {
    background: none;
    border: none;
    color: white;
    font-size: 20px;
    cursor: pointer;
    padding: 0;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: background 0.2s;
}

.back-button:hover {
    background: rgba(255, 255, 255, 0.2);
}

.conversation-messages {
    flex: 1;
    overflow-y: auto;
    padding: 16px;
    background: #f9fafb;
}

.message-item {
    margin-bottom: 16px;
    display: flex;
    gap: 8px;
    align-items: start;
}

.message-item.admin {
    flex-direction: row-reverse;
}

.message-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: linear-gradient(135deg, #1E40AF 0%, #9333EA 100%);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: bold;
    flex-shrink: 0;
}

.message-item.admin .message-avatar {
    background: linear-gradient(135deg, #10B981 0%, #059669 100%);
}

.message-bubble {
    max-width: 70%;
    padding: 10px 14px;
    border-radius: 16px;
    background: white;
    color: #1f2937;
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

.message-item.admin .message-bubble {
    background: linear-gradient(135deg, #10B981 0%, #059669 100%);
    color: white;
}

.message-time {
    font-size: 11px;
    color: #9ca3af;
    margin-top: 4px;
    text-align: right;
}

.message-item.admin .message-time {
    color: rgba(255,255,255,0.8);
}

.conversation-input-area {
    padding: 12px;
    background: white;
    border-top: 1px solid #e5e7eb;
}

.conversation-input-form {
    display: flex;
    gap: 8px;
}

.conversation-input {
    flex: 1;
    padding: 10px 14px;
    border: 1px solid #d1d5db;
    border-radius: 20px;
    font-size: 14px;
    outline: none;
    resize: none;
}

.conversation-input:focus {
    border-color: #10B981;
}

.send-button {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: linear-gradient(135deg, #10B981 0%, #059669 100%);
    color: white;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.2s;
}

.send-button:hover {
    transform: scale(1.1);
}

@media (max-width: 768px) {
    #admin-inbox-panel, #conversation-view {
        width: calc(100% - 40px);
        right: 20px;
        left: 20px;
    }
}
</style>

<div id="admin-chat-inbox">
    <!-- Inbox Button -->
    <button id="admin-inbox-button" onclick="toggleInbox()" aria-label="Chat Inbox">
        <i class="fas fa-inbox"></i>
        <span id="unread-badge" class="unread-badge" style="display: none;">0</span>
    </button>

    <!-- Inbox Panel -->
    <div id="admin-inbox-panel">
        <div class="inbox-header">
            <h3><i class="fas fa-inbox mr-2"></i>Member Chats</h3>
            <button class="inbox-close" onclick="closeInbox()">&times;</button>
        </div>
        
        <div class="inbox-tabs">
            <button class="inbox-tab active" onclick="filterConversations('all')">
                All <span id="count-all">(0)</span>
            </button>
            <button class="inbox-tab" onclick="filterConversations('unread')">
                Unread <span id="count-unread">(0)</span>
            </button>
        </div>
        
        <div id="inbox-list" class="inbox-list">
            <div class="empty-state">
                <i class="fas fa-comments"></i>
                <p>No conversations yet</p>
            </div>
        </div>
    </div>

    <!-- Conversation View -->
    <div id="conversation-view">
        <div class="conversation-header-bar">
            <button class="back-button" onclick="backToInbox()">
                <i class="fas fa-arrow-left"></i>
            </button>
            <div>
                <div class="conversation-name" id="current-conversation-name"></div>
                <div class="conversation-time" id="current-conversation-type" style="font-size: 12px; opacity: 0.9;"></div>
            </div>
        </div>
        
        <div id="conversation-messages" class="conversation-messages"></div>
        
        <div class="conversation-input-area">
            <form id="reply-form" class="conversation-input-form">
                <textarea id="reply-input" class="conversation-input" rows="1" placeholder="Type your reply..."></textarea>
                <button type="submit" class="send-button">
                    <i class="fas fa-paper-plane"></i>
                </button>
            </form>
        </div>
    </div>
</div>

<script>
let inboxOpen = false;
let conversationViewOpen = false;
let currentFilter = 'all';
let currentConversationId = null;
let conversations = [];

// Toggle Inbox
function toggleInbox() {
    inboxOpen = !inboxOpen;
    const panel = document.getElementById('admin-inbox-panel');
    
    if (inboxOpen) {
        panel.classList.add('open');
        closeConversationView();
        loadConversations();
    } else {
        panel.classList.remove('open');
    }
}

function closeInbox() {
    document.getElementById('admin-inbox-panel').classList.remove('open');
    inboxOpen = false;
}

// Load Conversations
async function loadConversations() {
    try {
        const res = await fetch('<?php echo BASE_URL; ?>api/admin_chat_list.php');
        const data = await res.json();
        
        if (data.success) {
            conversations = data.conversations || [];
            updateConversationCounts();
            renderConversations();
        }
    } catch (e) {
        console.error('Failed to load conversations', e);
    }
}

function updateConversationCounts() {
    const all = conversations.length;
    const unread = conversations.filter(c => c.unread_count > 0).length;
    
    document.getElementById('count-all').textContent = `(${all})`;
    document.getElementById('count-unread').textContent = `(${unread})`;
    
    const badge = document.getElementById('unread-badge');
    const button = document.getElementById('admin-inbox-button');
    
    if (unread > 0) {
        badge.textContent = unread > 99 ? '99+' : unread;
        badge.style.display = 'flex';
        button.classList.add('has-unread');
    } else {
        badge.style.display = 'none';
        button.classList.remove('has-unread');
    }
}

function renderConversations() {
    const list = document.getElementById('inbox-list');
    let filtered = conversations;
    
    if (currentFilter === 'unread') {
        filtered = conversations.filter(c => c.unread_count > 0);
    }
    
    if (filtered.length === 0) {
        list.innerHTML = `
            <div class="empty-state">
                <i class="fas fa-comments"></i>
                <p>${currentFilter === 'unread' ? 'No unread chats' : 'No conversations yet'}</p>
            </div>
        `;
        return;
    }
    
    list.innerHTML = filtered.map(conv => `
        <div class="conversation-item ${conv.unread_count > 0 ? 'unread' : ''}" onclick="openConversation(${conv.id})">
            <div class="conversation-avatar">
                ${getInitials(conv.name)}
            </div>
            <div class="conversation-content">
                <div class="conversation-header">
                    <span class="conversation-name">${escapeHtml(conv.name)}</span>
                    <span class="conversation-time">${formatTime(conv.last_message_time)}</span>
                </div>
                <div class="conversation-preview">
                    ${escapeHtml(conv.last_message || 'No messages yet')}
                </div>
            </div>
        </div>
    `).join('');
}

function filterConversations(filter) {
    currentFilter = filter;
    document.querySelectorAll('.inbox-tab').forEach(tab => tab.classList.remove('active'));
    event.target.classList.add('active');
    renderConversations();
}

// Open Conversation
async function openConversation(conversationId) {
    currentConversationId = conversationId;
    const conv = conversations.find(c => c.id === conversationId);
    
    if (!conv) return;
    
    document.getElementById('current-conversation-name').textContent = conv.name;
    document.getElementById('current-conversation-type').textContent = conv.type || 'Member';
    
    closeInbox();
    document.getElementById('conversation-view').classList.add('open');
    conversationViewOpen = true;
    
    await loadMessages(conversationId);
}

function backToInbox() {
    document.getElementById('conversation-view').classList.remove('open');
    conversationViewOpen = false;
    toggleInbox();
}

function closeConversationView() {
    document.getElementById('conversation-view').classList.remove('open');
    conversationViewOpen = false;
}

// Load Messages
async function loadMessages(conversationId) {
    try {
        const params = new URLSearchParams({ conversation_id: conversationId });
        const res = await fetch('<?php echo BASE_URL; ?>api/chat_fetch.php?' + params.toString());
        const data = await res.json();
        
        if (data.success) {
            renderMessages(data.messages || []);
        }
    } catch (e) {
        console.error('Failed to load messages', e);
    }
}

function renderMessages(messages) {
    const container = document.getElementById('conversation-messages');
    container.innerHTML = messages.map(msg => `
        <div class="message-item ${msg.sender_type === 'admin' ? 'admin' : ''}">
            <div class="message-avatar">
                ${msg.sender_type === 'admin' ? 'A' : getInitials(msg.sender_name || 'U')}
            </div>
            <div>
                <div class="message-bubble">
                    ${escapeHtml(msg.message_text || '')}
                </div>
                <div class="message-time">${formatTime(msg.created_at)}</div>
            </div>
        </div>
    `).join('');
    
    container.scrollTop = container.scrollHeight;
}

// Send Reply
document.getElementById('reply-form')?.addEventListener('submit', async (e) => {
    e.preventDefault();
    
    const input = document.getElementById('reply-input');
    const message = input.value.trim();
    
    if (!message || !currentConversationId) return;
    
    try {
        const formData = new FormData();
        formData.append('conversation_id', currentConversationId);
        formData.append('message', message);
        
        const res = await fetch('<?php echo BASE_URL; ?>api/admin_chat_reply.php', {
            method: 'POST',
            body: formData
        });
        
        const data = await res.json();
        
        if (data.success) {
            input.value = '';
            loadMessages(currentConversationId);
            loadConversations(); // Update conversation list
        }
    } catch (e) {
        console.error('Failed to send reply', e);
    }
});

// Utility Functions
function getInitials(name) {
    const parts = name.split(' ');
    if (parts.length >= 2) {
        return (parts[0][0] + parts[1][0]).toUpperCase();
    }
    return name.substring(0, 2).toUpperCase();
}

function formatTime(timestamp) {
    if (!timestamp) return '';
    const date = new Date(timestamp);
    const now = new Date();
    const diff = now - date;
    
    if (diff < 60000) return 'Just now';
    if (diff < 3600000) return Math.floor(diff / 60000) + 'm ago';
    if (diff < 86400000) return Math.floor(diff / 3600000) + 'h ago';
    return date.toLocaleDateString();
}

function escapeHtml(text) {
    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return String(text).replace(/[&<>"']/g, m => map[m]);
}

// Auto-refresh conversations every 10 seconds
setInterval(() => {
    if (inboxOpen) {
        loadConversations();
    }
    if (conversationViewOpen && currentConversationId) {
        loadMessages(currentConversationId);
    }
}, 10000);

// Initial load
loadConversations();
setInterval(loadConversations, 30000); // Check for new messages every 30s
</script>

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists