Sindbad~EG File Manager
<?php
require_once '../../config/config.php';
checkLogin();
$pageTitle = 'Chat - ' . APP_NAME;
$db = Database::getInstance()->getConnection();
$success = '';
$error = '';
$userId = $_SESSION['user_id'] ?? null;
$conversationId = (int)($_GET['id'] ?? 0);
if ($conversationId <= 0) {
redirect('index.php');
}
// Load conversation details
$stmt = $db->prepare("SELECT c.*,
m.first_name, m.last_name, m.email, m.phone
FROM chat_conversations c
LEFT JOIN members m ON c.member_id = m.id
WHERE c.id = :id");
$stmt->execute(['id' => $conversationId]);
$conversation = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$conversation) {
redirect('index.php');
}
// Mark messages as read (from visitor/member perspective)
$db->prepare("UPDATE chat_messages SET is_read = 1
WHERE conversation_id = :id AND sender_type != 'admin'")
->execute(['id' => $conversationId]);
include '../../includes/header.php';
include '../../includes/sidebar.php';
?>
<main class="flex-1 md:ml-64 mt-16">
<div class="container mx-auto px-4 py-8">
<div class="max-w-4xl mx-auto">
<div class="mb-6">
<a href="index.php" class="text-sm text-blue-600 hover:text-blue-800 mb-2 inline-block">
<i class="fas fa-arrow-left mr-1"></i>Back to Conversations
</a>
<div class="flex items-center space-x-3">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-white font-bold" style="background: linear-gradient(135deg, #1E40AF 0%, #F97316 100%);">
<?php if ($conversation['member_id']): ?>
<?php echo strtoupper(substr($conversation['first_name'] ?? 'M', 0, 1)); ?>
<?php else: ?>
<i class="fas fa-user-circle"></i>
<?php endif; ?>
</div>
<div>
<h1 class="text-2xl font-bold text-gray-800">
<?php if ($conversation['member_id']): ?>
<?php echo htmlspecialchars(trim(($conversation['first_name'] ?? '') . ' ' . ($conversation['last_name'] ?? ''))); ?>
<?php else: ?>
Guest Chat
<?php endif; ?>
</h1>
<p class="text-sm text-gray-500">
<?php if ($conversation['member_id'] && $conversation['email']): ?>
<?php echo htmlspecialchars($conversation['email']); ?>
<?php else: ?>
Guest Token: <?php echo htmlspecialchars(substr($conversation['guest_token'] ?? '', 0, 12)); ?>
<?php endif; ?>
</p>
</div>
</div>
</div>
<!-- Chat Container -->
<div class="bg-white rounded-lg shadow-lg overflow-hidden">
<div id="chatMessagesContainer" class="p-6 space-y-3 overflow-y-auto bg-gray-50" style="height: 500px;"></div>
<div class="border-t border-gray-200 p-4 bg-white">
<form id="adminChatForm" class="flex items-end space-x-3">
<textarea id="adminChatInput" rows="2" class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none" placeholder="Type your message..." required></textarea>
<button type="submit" class="px-6 py-2 rounded-lg text-white font-semibold shadow-lg hover:shadow-xl transition" style="background: linear-gradient(135deg, #1E40AF 0%, #F97316 100%);">
<i class="fas fa-paper-plane mr-2"></i>Send
</button>
</form>
</div>
</div>
</div>
</div>
</main>
<script>
const conversationId = <?php echo $conversationId; ?>;
let lastMessageId = 0;
let pollInterval = null;
async function fetchMessages() {
try {
const params = new URLSearchParams();
params.append('conversation_id', conversationId);
params.append('last_message_id', lastMessageId);
const res = await fetch('../../api/chat_fetch.php?' + params.toString());
const data = await res.json();
if (!data.success) return;
const container = document.getElementById('chatMessagesContainer');
if (!container) return;
(data.messages || []).forEach(msg => {
const bubble = document.createElement('div');
const isAdmin = msg.sender_type === 'admin';
const alignment = isAdmin ? 'justify-end' : 'justify-start';
const bgClass = isAdmin ? 'bg-blue-600 text-white' : 'bg-white text-gray-800 border border-gray-200';
const time = msg.created_at ? new Date(msg.created_at).toLocaleTimeString() : '';
bubble.className = 'flex ' + alignment;
bubble.innerHTML = '<div class="max-w-[70%] px-4 py-3 rounded-lg shadow-sm ' + bgClass + '">' +
'<div class="whitespace-pre-line text-sm">' + escapeHtml(msg.message_text || '') + '</div>' +
(time ? '<div class="mt-1 text-xs opacity-70">' + time + '</div>' : '') +
'</div>';
container.appendChild(bubble);
lastMessageId = Math.max(lastMessageId, parseInt(msg.id || 0, 10));
});
if (data.messages && data.messages.length > 0) {
container.scrollTop = container.scrollHeight;
}
} catch (e) {
console.error('Fetch messages failed', e);
}
}
async function sendMessage(messageText) {
const formData = new FormData();
formData.append('conversation_id', conversationId);
formData.append('message', messageText);
try {
const res = await fetch('../../api/chat_send.php', {
method: 'POST',
body: formData
});
const data = await res.json();
if (data.success) {
fetchMessages();
}
} catch (e) {
console.error('Send message failed', e);
}
}
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return String(text).replace(/[&<>"']/g, function(m) { return map[m]; });
}
document.getElementById('adminChatForm').addEventListener('submit', function(e) {
e.preventDefault();
const input = document.getElementById('adminChatInput');
const message = (input.value || '').trim();
if (!message) return;
sendMessage(message);
input.value = '';
});
// Initial load
fetchMessages();
pollInterval = setInterval(fetchMessages, 3000);
</script>
<?php include '../../includes/footer.php'; ?>
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists