TKK_E32230273/chat.php

227 lines
12 KiB
PHP

<?php
include 'header.php';
include 'koneksi.php';
// Try to create columns if they don't exist yet
try { $pdo->exec("ALTER TABLE chats ADD COLUMN deleted_by_occupant TINYINT DEFAULT 0 AFTER is_read"); } catch(PDOException $e) {}
try { $pdo->exec("ALTER TABLE occupant ADD COLUMN last_active DATETIME NULL"); } catch(PDOException $e) {}
try { $pdo->exec("ALTER TABLE occupant ADD COLUMN telegram_id VARCHAR(100) NULL AFTER no_hp"); } catch(PDOException $e) {}
// For simplicity, account is 1 since Admin views this
$id_account = isset($_SESSION['id_account']) ? $_SESSION['id_account'] : 1;
?>
<div class="main-panel">
<div class="content-wrapper">
<div class="row">
<div class="col-md-12 grid-margin">
<div class="row">
<div class="col-12 col-xl-8 mb-4 mb-xl-0">
<h3 class="font-weight-bold">Chat Management</h3>
<h6 class="font-weight-normal mb-0">Hubungi occupant Anda melalui Integrasi Telegram Bot.</h6>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Contact List -->
<div class="col-md-4 grid-margin stretch-card">
<div class="card" style="border: 1px solid #e2e8f0; border-radius: 10px;">
<div class="card-body p-0">
<div class="p-3 border-bottom bg-light" style="border-radius: 10px 10px 0 0;">
<h6 class="mb-0 font-weight-bold">Daftar Chat</h6>
</div>
<div id="contactList" style="height: 200px; overflow-y: auto;">
<div class="p-4 text-center text-muted"><i class="mdi mdi-loading mdi-spin"></i> Loading...</div>
</div>
</div>
</div>
</div>
<!-- Chat Area -->
<div class="col-md-8 grid-margin stretch-card">
<div class="card" style="border: 1px solid #e2e8f0; border-radius: 10px; display: flex; flex-direction: column;">
<!-- Chat Header -->
<div class="border-bottom p-3 d-flex align-items-center bg-light" id="chatHeader" style="border-radius: 10px 10px 0 0; display: none !important;">
<img src="images/faces/user.jpg" id="activeChatAvatar" style="width:40px;height:40px;border-radius:50%;object-fit:cover;border:2px solid #fff;box-shadow:0 2px 5px rgba(0,0,0,0.1);">
<div class="ml-3">
<h6 class="mb-0 font-weight-bold" id="activeChatName">Pilih Chat</h6>
<small class="text-muted" id="activeChatStatus">Belum ada obrolan</small>
</div>
<input type="hidden" id="activeOccupantId" value="0">
</div>
<!-- Empty State -->
<div id="chatEmptyState" class="d-flex flex-column align-items-center justify-content-center" style="height: 200px; background:#f4f5f7;">
<div style="background:#e0e7ff; width:80px; height:80px; border-radius:50%; display:flex; align-items:center; justify-content:center; margin-bottom:15px;">
<i class="mdi mdi-forum-outline text-primary" style="font-size:40px;"></i>
</div>
<h5 class="text-muted font-weight-bold">Pilih Occupant</h5>
<p class="text-muted" style="font-size:13px;">Klik nama di sebelah kiri untuk melihat pesan otomatis dari Telegram</p>
</div>
<!-- Chat History -->
<div id="chatHistory" style="height: 200px; overflow-y: auto; padding: 20px; background-color: #f8fafc; background-image: url('images/walpaper.jpg'); background-size: cover; background-position: center; display: none; flex-direction: column; gap: 15px;">
<!-- Messages will appear here -->
</div>
<!-- Chat Footer -->
<div id="chatFooter" class="border-top p-3" style="background:#fff; border-radius: 0 0 10px 10px; display: none;">
<form id="formChat" class="d-flex align-items-center" style="gap: 10px;">
<input type="text" id="chatInput" class="form-control" autocomplete="off" placeholder="Ketik pesan untuk dikirim ke Telegram..." style="border-radius: 20px; padding: 10px 20px; flex: 1; border: 1px solid #ced4da;">
<button type="submit" class="btn btn-primary" style="width: 45px; height: 45px; border-radius: 50%; padding: 0; display: flex; align-items: center; justify-content: center; flex-shrink: 0;"><i class="mdi mdi-send"></i></button>
</form>
</div>
</div>
</div>
</div>
</div>
<style>
.contact-item { padding: 15px; border-bottom: 1px solid #f0f0f0; cursor: pointer; transition: background 0.2s; display: flex; align-items: center; }
.contact-item:hover { background: #f8fafc; }
.contact-item.active { background: #eff6ff; border-left: 4px solid #4b49ac; }
.contact-msg-preview { font-size: 12px; color: #6c757d; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 180px; display: block; }
.chat-bubble { padding: 10px 15px; border-radius: 15px; max-width: 75%; font-size: 13.5px; line-height: 1.4; position: relative; }
.chat-left { align-self: flex-start; background: #ffffff; border: 1px solid #e2e8f0; border-bottom-left-radius: 0; box-shadow: 0 2px 4px rgba(0,0,0,0.02); }
.chat-right { align-self: flex-end; background: #4b49ac; color: white; border-bottom-right-radius: 0; box-shadow: 0 2px 6px rgba(75, 73, 172, 0.2); }
.chat-time { font-size: 10px; margin-top: 5px; opacity: 0.7; display: block; }
.chat-right .chat-time { text-align: right; }
.badge-unread { background: #ef4444; color: white; font-size: 10px; border-radius: 10px; padding: 2px 6px; font-weight: bold; }
</style>
<script>
let currentOccupantId = 0;
function fetchContacts() {
$.post('chat_api.php', { action: 'get_contacts' }, function(res) {
if (res.status === 'success') {
let html = '';
res.data.forEach(c => {
let isActive = c.id_occupant == currentOccupantId ? 'active' : '';
let lastMsg = c.last_message ? c.last_message : 'Belum ada pesan';
let unread = c.unread_count > 0 ? `<span class="badge-unread">${c.unread_count}</span>` : '';
let telegramIcon = c.telegram_id ? '<i class="mdi mdi-telegram text-info" title="Telegram Terhubung" style="font-size:16px;"></i>' : '<i class="mdi mdi-cellphone text-muted" title="Belum Terhubung" style="font-size:16px;"></i>';
html += `
<div class="contact-item ${isActive}" onclick="openChat(${c.id_occupant}, '${c.name.replace(/'/g, "\\'")}', '${c.foto}', '${c.status}')">
<div style="position:relative;">
<img src="${c.foto}" style="width:45px;height:45px;border-radius:50%;object-fit:cover;border:1px solid #ddd;">
<div style="position:absolute; bottom:-4px; right:-2px; background:#fff; border-radius:50%; width:18px; height:18px; display:flex; align-items:center; justify-content:center; box-shadow:0 1px 3px rgba(0,0,0,0.2);">${telegramIcon}</div>
</div>
<div class="ml-3" style="flex:1; min-width:0;">
<div class="d-flex justify-content-between align-items-center">
<span class="font-weight-bold text-dark" style="font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${c.name}</span>
${unread}
</div>
<div class="contact-msg-preview mt-1">${lastMsg}</div>
</div>
</div>
`;
});
$('#contactList').html(html || '<div class="p-4 text-center text-muted">Tidak ada kontak.</div>');
}
}, 'json');
}
function openChat(id, name, foto, status) {
currentOccupantId = id;
$('#activeOccupantId').val(id);
$('#activeChatName').text(name);
$('#activeChatAvatar').attr('src', foto);
$('#activeChatStatus').text(status === 'approved' ? 'Terverifikasi' : status);
// Highlight contact
$('.contact-item').removeClass('active');
event.currentTarget.classList.add('active');
// Toggle UI
$('#chatEmptyState').hide();
$('#chatHeader').css('display', 'flex').attr('style', 'border-radius: 10px 10px 0 0; display: flex !important;');
$('#chatHistory').css('display', 'flex');
$('#chatFooter').show();
fetchMessages();
}
function fetchMessages() {
if (currentOccupantId === 0) return;
$.post('chat_api.php', { action: 'get_messages', id_occupant: currentOccupantId, viewer: 'account' }, function(res) {
if (res.status === 'success') {
let container = document.getElementById('chatHistory');
let isScrolledBottom = container.scrollHeight - container.clientHeight <= container.scrollTop + 10;
let html = '';
if (res.data.length === 0) {
html = '<div class="text-center text-muted mt-5" style="font-size:13px;">Belum ada riwayat percakapan. Mulai kirim chat!</div>';
} else {
res.data.forEach(msg => {
let isSelf = msg.sender === 'account';
let cls = isSelf ? 'chat-right' : 'chat-left';
let time = new Date(msg.created_at);
let timeStr = ("0" + time.getHours()).slice(-2) + ":" + ("0" + time.getMinutes()).slice(-2);
let check = '';
if (isSelf) {
let checkColor = msg.is_read == 1 ? '#4ade80' : '#cbd5e1';
check = `<i class="mdi mdi-check-all" style="color:${checkColor}; font-size:14px; margin-right:4px;"></i>`;
}
html += `
<div class="chat-bubble ${cls}">
${msg.message}
<span class="chat-time">${check}${timeStr}</span>
</div>
`;
});
}
if (container.innerHTML !== html) {
container.innerHTML = html;
if (isScrolledBottom || container.scrollTop === 0) {
container.scrollTop = container.scrollHeight;
}
}
}
}, 'json');
}
$('#formChat').on('submit', function(e) {
e.preventDefault();
let text = $('#chatInput').val().trim();
if (!text || currentOccupantId === 0) return;
// Disabled input immediately
$('#chatInput').prop('disabled', true);
let submitBtn = $(this).find('button[type="submit"]');
submitBtn.prop('disabled', true).html('<i class="mdi mdi-loading mdi-spin"></i>');
$.post('chat_api.php', { action: 'send_message', id_occupant: currentOccupantId, message: text, sender: 'account' }, function(res) {
if (res.status === 'success') {
$('#chatInput').val('');
fetchMessages();
fetchContacts();
} else {
showCustomAlert(res.message);
}
$('#chatInput').prop('disabled', false).focus();
submitBtn.prop('disabled', false).html('<i class="mdi mdi-send"></i>');
}, 'json').fail(function() {
showCustomAlert("Gagal terhubung ke API");
$('#chatInput').prop('disabled', false);
submitBtn.prop('disabled', false).html('<i class="mdi mdi-send"></i>');
});
});
$(document).ready(function() {
fetchContacts();
setInterval(fetchContacts, 7000);
setInterval(fetchMessages, 3000);
});
</script>
<?php include 'footer.php'; ?>
<?php include 'copy.php'; ?>