Files
WebGIS-Project/webgis-v3/assets/js/chat.js
T
2026-06-10 19:48:00 +07:00

100 lines
4.2 KiB
JavaScript

const Chat = (() => {
let currentRoom = null, pollTimer = null;
const DEMO_ROOMS = [
{ id:1, nama:'# Koordinasi Umum' },
{ id:2, nama:'# Bantuan Darurat' },
{ id:3, nama:'# Distribusi Sembako' },
];
const DEMO_MSGS = {
null: [
{ id:1, id_user:2, nama_lengkap:'Ahmad Fauzi', pesan:'Salam rekan-rekan semua. Ada keluarga di Gg. Mawar yang sangat butuh bantuan sembako segera.', created_at:'2025-05-13 08:00:00' },
{ id:2, id_user:3, nama_lengkap:'Romo Benediktus',pesan:'Baik. Kami di Katedral juga sedang tangani kasus Ibu Maria yang sakit keras. Mohon dikoordinasikan.', created_at:'2025-05-13 08:05:00' },
{ id:3, id_user:2, nama_lengkap:'Ahmad Fauzi', pesan:'Insya Allah kita distribusi bersama hari Jumat. Tolong daftarkan semua ke sistem ya.', created_at:'2025-05-13 08:10:00' },
{ id:4, id_user:3, nama_lengkap:'Romo Benediktus',pesan:'Setuju. Saya sudah verifikasi laporan Ibu Maria. Status diproses.', created_at:'2025-05-13 08:15:00' },
],
1: [{ id:5, id_user:2, nama_lengkap:'Ahmad Fauzi', pesan:'Koordinasi umum aktif. Silakan gunakan channel ini untuk diskusi lintas RI.', created_at:'2025-05-13 09:00:00' }],
2: [{ id:6, id_user:3, nama_lengkap:'Romo Benediktus', pesan:'Ada kasus darurat di Akcaya — balita gizi buruk. Butuh respons cepat.', created_at:'2025-05-14 07:00:00' }],
3: [{ id:7, id_user:2, nama_lengkap:'Ahmad Fauzi', pesan:'Jadwal distribusi sembako Ramadan: 15 Maret 2025, mulai pukul 08.00 di halaman masjid.', created_at:'2025-05-12 16:00:00' }],
};
async function init() {
// Load rooms
let rooms = [];
try { const d = await Api.get('/chat/rooms'); rooms = d?.length ? d : DEMO_ROOMS; }
catch { rooms = DEMO_ROOMS; }
const container = ge('chat-rooms');
container.innerHTML = `<button class="room-btn active" data-room="" onclick="Chat.loadRoom('',this)"># Umum</button>`;
rooms.forEach(r => {
const btn = document.createElement('button');
btn.className = 'room-btn';
btn.dataset.room = r.id;
btn.textContent = r.nama;
btn.onclick = function() { Chat.loadRoom(r.id, this); };
container.appendChild(btn);
});
await loadRoom(null, container.firstChild);
}
async function loadRoom(roomId, btn) {
currentRoom = roomId || null;
clearInterval(pollTimer);
document.querySelectorAll('.room-btn').forEach(b => b.classList.remove('active'));
if (btn) btn.classList.add('active');
await fetchMessages();
pollTimer = setInterval(fetchMessages, 5000); // poll tiap 5 detik
}
async function fetchMessages() {
let msgs = [];
try {
const url = currentRoom ? `/chat?room=${currentRoom}` : '/chat';
msgs = await Api.get(url);
} catch {
msgs = DEMO_MSGS[currentRoom] || DEMO_MSGS[null];
}
renderMessages(msgs);
}
function renderMessages(msgs) {
const box = ge('chat-messages');
const user = App.currentUser();
if (!msgs?.length) {
box.innerHTML = '<div class="chat-empty">💬 Belum ada pesan di channel ini</div>';
return;
}
const prevScroll = box.scrollHeight - box.scrollTop;
box.innerHTML = msgs.map(m => {
const mine = user && m.id_user == user.id;
return `<div class="chat-bubble ${mine ? 'mine' : 'other'}">
${!mine ? `<div class="chat-sender">${m.nama_lengkap || 'User'}</div>` : ''}
<div class="chat-text">${escHtml(m.pesan)}</div>
<div class="chat-time">${(m.created_at||'').substring(11,16)}</div>
</div>`;
}).join('');
// Scroll ke bawah jika sudah di bawah
if (prevScroll < 200) box.scrollTop = box.scrollHeight;
}
async function send() {
const inp = ge('chat-input');
const pesan = inp.value.trim();
if (!pesan) return;
if (!App.currentUser()) { App.toast('Harus login untuk mengirim pesan','warning'); App.showModal('modal-login'); return; }
inp.value = '';
try {
await Api.post('/chat', { pesan, id_room: currentRoom });
await fetchMessages();
} catch(e) { App.toast(e.message,'error'); }
}
function escHtml(s) {
return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\n/g,'<br>');
}
return { init, loadRoom, send };
})();