/** * ========================================================================= * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0 * Interface Client - Onglet : Messagerie (Vue en liste) * ========================================================================= */ // ========================================================================= // 1. LOGIQUE MÉTIER : COMPILATION DES FILS DE DISCUSSION CLIENT // ========================================================================= window.pano_buildClientChatThreads = (interactions, myClientData, visiblePanels, pendingInvites) => { const supportThreadId = `SUPPORT_${myClientData.id}`; const threadsMap = { [supportThreadId]: { id: supportThreadId, title: "Support technique", targetEmail: 'Admin', messages: [], unread: 0, type: 'support' } }; [...visiblePanels, ...pendingInvites].forEach(p => { const groupId = `GROUP_${p.id}`; threadsMap[groupId] = { id: groupId, panneauId: p.id, title: `Équipe du panneau : ${p.name || 'Brouillon'}`, targetEmail: 'Groupe', messages: [], unread: 0, type: 'group', panneauData: p }; }); interactions.forEach(m => { if (m.panneauId === supportThreadId) { threadsMap[supportThreadId].messages.push(m); if (!m.resolved && m.author !== 'Client' && m.author !== myClientData.email && m.author !== myClientData.full_name && m.author !== myClientData.name) { threadsMap[supportThreadId].unread++; } } else if (m.panneauId.startsWith('GROUP_')) { if (threadsMap[m.panneauId]) { threadsMap[m.panneauId].messages.push(m); if (!m.resolved && m.author !== 'Client' && m.author !== myClientData.email && m.author !== myClientData.full_name && m.author !== myClientData.name) { threadsMap[m.panneauId].unread++; } } } else { const isInternalMsg = m.authorType === 'Client' || m.authorType === 'Admin'; const riverainEmail = (!isInternalMsg && m.author !== myClientData.email && m.author !== myClientData.full_name && m.author !== myClientData.name) ? m.author : m.target; if (riverainEmail && riverainEmail !== 'Groupe') { const threadId = `${m.panneauId}_${riverainEmail}`; const panneauObj = visiblePanels.find(c => c.id === m.panneauId); if (panneauObj) { if (!threadsMap[threadId]) { threadsMap[threadId] = { id: threadId, panneauId: m.panneauId, title: `Riverain : ${panneauObj.name} - ${riverainEmail}`, targetEmail: riverainEmail, messages: [], unread: 0, type: 'riverain' }; } threadsMap[threadId].messages.push(m); if (!isInternalMsg && !m.resolved) threadsMap[threadId].unread++; } } } }); return Object.values(threadsMap) .filter(t => t.type === 'support' || t.messages.length > 0 || t.type === 'group') .sort((a,b) => { const dateA = a.messages.length > 0 ? new Date(String(a.messages[a.messages.length - 1].created_at || '').replace(' ', 'T')).getTime() : 0; const dateB = b.messages.length > 0 ? new Date(String(b.messages[b.messages.length - 1].created_at || '').replace(' ', 'T')).getTime() : 0; return dateB - dateA; }); }; // ========================================================================= // 2. COMPOSANT : ONGLET MESSAGERIE (LISTE DES CONVERSATIONS) // ========================================================================= window.pano_ClientMessagesTab = ({ data, myClientData, refreshData }) => { const { useState, useEffect } = React; const [forceRender, setForceRender] = useState(0); useEffect(() => { const handlePop = () => setForceRender(f => f + 1); window.addEventListener('popstate', handlePop); return () => window.removeEventListener('popstate', handlePop); }, []); const { UsersIcon, MessageSquareIcon, MessageCircleIcon } = window.pano_getIcons(); const IconBadge = window.pano_IconBadge || (() => null); const { pendingInvites, visiblePanels } = window.pano_getPanelAccessRights ? window.pano_getPanelAccessRights(data.panneaux || [], myClientData.id) : { pendingInvites:[], visiblePanels:[] }; const threads = window.pano_buildClientChatThreads ? window.pano_buildClientChatThreads(data.interactions || [], myClientData, visiblePanels, pendingInvites) : []; const openChat = (id) => { const u = new URL(window.location); u.searchParams.set('chat_id', id); window.history.pushState({ chat_id: id }, '', u); window.dispatchEvent(new Event('popstate')); refreshData(); }; const getThreadTitleClass = (type) => { if (type === 'support') return 'font-black text-emerald-700'; if (type === 'group') return 'font-black text-blue-700'; return 'font-bold text-slate-800'; }; return (

Messagerie

Échanges avec les riverains, votre équipe et le support.

{threads.map(t => { const lastMsg = t.messages.length > 0 ? t.messages[t.messages.length - 1] : null; return (
openChat(t.id)} className="bg-white border border-slate-200 rounded-3xl p-5 cursor-pointer hover:border-emerald-300 hover:shadow-md transition flex flex-col gap-3 relative overflow-hidden group" > {t.unread > 0 && ( {t.unread} )}
{IconBadge && ( )}

{t.title}

{t.targetEmail}

0 ? 'text-slate-800 font-bold' : 'text-slate-600'}`}> {lastMsg ? lastMsg.detail.replace(/\[ATTACHMENT:[^\]]+\]/g, '[Pièce jointe]').replace(/<[^>]*>?/gm, '') : Nouvelle conversation...}

{lastMsg ? new Date(String(lastMsg.created_at || '').replace(' ', 'T')).toLocaleString('fr-FR') : ''}
); })} {threads.length === 0 && (

Aucune conversation pour le moment.

)}
); }; /* EOF ========== [_react/_clients_messages.jsx] */