fix: embed conversations data inline in chat page HTML
Instead of making a separate fetch to /admin/chat/conversations (which Nginx intercepts), pre-load conversations in the PHP chat() method and embed them as window.INITIAL_CONVS JSON in the page script. renderConvs(INITIAL_CONVS) runs synchronously on page load — no HTTP request needed. setInterval still tries to refresh via fetch every 15s but the initial render no longer depends on it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
5bae03e5a3
commit
0be3d467ff
@@ -1808,7 +1808,37 @@ HTML;
|
||||
SessionAuth::require();
|
||||
$user = SessionAuth::user();
|
||||
$userName = self::h($user['name'] ?? 'Admin');
|
||||
$companies = CompanyRepository::findAll();
|
||||
|
||||
// Pre-load conversations for inline embedding (no extra HTTP round-trip)
|
||||
$companyMap = [];
|
||||
foreach (CompanyRepository::findAll() as $co) {
|
||||
$companyMap[(int)$co['id']] = $co['name'];
|
||||
}
|
||||
$convRows = db()->query("
|
||||
SELECT c.phone_number,
|
||||
MAX(c.contact_name) as contact_name,
|
||||
MAX(c.company_id) as company_id,
|
||||
MAX(c.created_at) as last_time,
|
||||
(SELECT content FROM conversations c2 WHERE c2.phone_number = c.phone_number ORDER BY c2.id DESC LIMIT 1) as last_message,
|
||||
(SELECT COUNT(*) FROM conversations c3 WHERE c3.phone_number = c.phone_number AND c3.direction = 'inbound'
|
||||
AND c3.id > COALESCE((SELECT MAX(c4.id) FROM conversations c4 WHERE c4.phone_number = c.phone_number AND c4.direction = 'outbound'),0)) as unread_count
|
||||
FROM conversations c
|
||||
GROUP BY c.phone_number
|
||||
ORDER BY last_time DESC
|
||||
")->fetchAll();
|
||||
$initialConvs = [];
|
||||
foreach ($convRows as $r) {
|
||||
$cid = (int)$r['company_id'];
|
||||
$initialConvs[] = [
|
||||
'phone' => $r['phone_number'],
|
||||
'contact_name' => $r['contact_name'] ?? '',
|
||||
'company_name' => $companyMap[$cid] ?? '',
|
||||
'last_message' => mb_substr($r['last_message'] ?? '', 0, 80),
|
||||
'last_time' => $r['last_time'],
|
||||
'unread_count' => (int)$r['unread_count'],
|
||||
];
|
||||
}
|
||||
$initialConvsJson = json_encode($initialConvs, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT);
|
||||
|
||||
http_response_code(200);
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
@@ -1917,16 +1947,42 @@ HTML;
|
||||
</div>
|
||||
<script>
|
||||
let activePhone = '';
|
||||
const INITIAL_CONVS = {$initialConvsJson};
|
||||
|
||||
// ─── Render conversations list ───────────────────────────────────────────────
|
||||
function renderConvs(convs) {
|
||||
const list = document.getElementById('convList');
|
||||
if (!convs || convs.length === 0) {
|
||||
list.innerHTML = '<div style="padding:24px 16px;text-align:center;color:#a0a8b8;font-size:13px">Sin conversaciones aún</div>';
|
||||
return;
|
||||
}
|
||||
list.innerHTML = convs.map(c => {
|
||||
const time = formatTime(c.last_time);
|
||||
const name = c.contact_name || c.phone || '';
|
||||
const avatar = name.charAt(0).toUpperCase() || '?';
|
||||
const unread = c.unread_count > 0 ? \`<div class="conv-unread">\${c.unread_count}</div>\` : '';
|
||||
const active = c.phone === activePhone ? ' active' : '';
|
||||
const company = c.company_name ? \`<span class="conv-company">\${esc(c.company_name)}</span>\` : '';
|
||||
return \`<div class="conv-item\${active}" onclick="selectConv('\${esc(c.phone)}','\${esc(c.contact_name||c.phone)}','\${esc(c.company_name||'')}')">
|
||||
<div class="conv-avatar">\${avatar}</div>
|
||||
<div class="conv-info">
|
||||
<div class="conv-name">\${esc(name || 'Desconocido')} \${company}</div>
|
||||
<div class="conv-phone">\${esc(c.phone)}</div>
|
||||
<div class="conv-last">\${esc(c.last_message || '')}</div>
|
||||
</div>
|
||||
<div class="conv-meta">
|
||||
<div class="conv-time">\${time}</div>
|
||||
\${unread}
|
||||
</div>
|
||||
</div>\`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// ─── Load conversations ──────────────────────────────────────────────────────
|
||||
async function loadConvs() {
|
||||
const list = document.getElementById('convList');
|
||||
try {
|
||||
const r = await fetch('/admin/chat?api=convs');
|
||||
if (!r.ok) {
|
||||
list.innerHTML = \`<div style="padding:16px;color:#e53e3e;font-size:13px">Error \${r.status} al cargar conversaciones</div>\`;
|
||||
return;
|
||||
}
|
||||
if (!r.ok) return;
|
||||
const data = await r.json();
|
||||
const convs = data.conversations || [];
|
||||
if (convs.length === 0) {
|
||||
@@ -1934,28 +1990,9 @@ async function loadConvs() {
|
||||
return;
|
||||
}
|
||||
list.innerHTML = convs.map(c => {
|
||||
const time = formatTime(c.last_time);
|
||||
const name = c.contact_name || c.phone || '';
|
||||
const avatar = name.charAt(0).toUpperCase() || '?';
|
||||
const unread = c.unread_count > 0 ? \`<div class="conv-unread">\${c.unread_count}</div>\` : '';
|
||||
const active = c.phone === activePhone ? ' active' : '';
|
||||
const company = c.company_name ? \`<span class="conv-company">\${esc(c.company_name)}</span>\` : '';
|
||||
return \`<div class="conv-item\${active}" onclick="selectConv('\${esc(c.phone)}','\${esc(c.contact_name||c.phone)}','\${esc(c.company_name||'')}')">
|
||||
<div class="conv-avatar">\${avatar}</div>
|
||||
<div class="conv-info">
|
||||
<div class="conv-name">\${esc(name || 'Desconocido')} \${company}</div>
|
||||
<div class="conv-phone">\${esc(c.phone)}</div>
|
||||
<div class="conv-last">\${esc(c.last_message || '')}</div>
|
||||
</div>
|
||||
<div class="conv-meta">
|
||||
<div class="conv-time">\${time}</div>
|
||||
\${unread}
|
||||
</div>
|
||||
</div>\`;
|
||||
}).join('');
|
||||
renderConvs(convs);
|
||||
} catch (e) {
|
||||
console.error('loadConvs error:', e);
|
||||
list.innerHTML = '<div style="padding:16px;color:#e53e3e;font-size:13px">Error al cargar conversaciones. Revisa la consola.</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2123,7 +2160,7 @@ if (msgInput) {
|
||||
});
|
||||
}
|
||||
|
||||
loadConvs();
|
||||
renderConvs(INITIAL_CONVS);
|
||||
setInterval(loadConvs, 15000);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user