100 lines
4.2 KiB
JavaScript
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,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\n/g,'<br>');
|
|
}
|
|
|
|
return { init, loadRoom, send };
|
|
})();
|