add Communications section to operations — inbox/sent brief with bounce alerts

This commit is contained in:
Oliver
2026-06-09 18:52:29 -03:00
parent d8d487e5d2
commit d1fac009c3
2 changed files with 165 additions and 0 deletions
+160
View File
@@ -368,8 +368,95 @@
font-weight: 700;
}
/* ── Communications ──────────────────────── */
.comms-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.comms-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-card);
padding: 20px;
}
.comms-card h3 {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--accent);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.comms-card .comms-summary {
display: flex;
gap: 20px;
margin-bottom: 12px;
}
.comms-card .comms-stat {
text-align: center;
}
.comms-card .comms-stat-num {
font-size: 24px;
font-weight: 700;
color: var(--text);
}
.comms-card .comms-stat-label {
font-size: 10px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.comms-list { list-style: none; }
.comms-list li {
font-size: 12px;
padding: 6px 0;
border-bottom: 1px solid rgba(10,48,96,0.3);
display: flex;
align-items: flex-start;
gap: 8px;
line-height: 1.5;
}
.comms-list li:last-child { border-bottom: none; }
.comms-list .comms-time {
color: var(--text-muted);
font-size: 11px;
white-space: nowrap;
flex-shrink: 0;
min-width: 60px;
}
.comms-list .comms-subj {
color: var(--text);
}
.comms-list .comms-detail {
color: var(--text-muted);
font-size: 11px;
}
.comms-list .comms-from {
color: var(--accent);
font-size: 11px;
}
.comms-alert {
background: var(--bg-card);
border: 1px solid rgba(255,59,59,0.3);
border-left: 3px solid var(--danger);
border-radius: var(--radius-card);
padding: 12px 16px;
margin-top: 10px;
font-size: 12px;
display: flex;
align-items: flex-start;
gap: 8px;
}
.comms-alert .alert-icon { color: var(--danger); flex-shrink: 0; font-size: 14px; }
.comms-alert .alert-body { color: var(--text); }
.comms-alert .alert-detail { color: var(--text-muted); font-size: 11px; margin-top: 2px; }
@media (max-width: 900px) {
.campaign-grid { grid-template-columns: 1fr; }
.comms-grid { grid-template-columns: 1fr; }
.goals-grid { grid-template-columns: repeat(2, 1fr); }
.strategy-grid { grid-template-columns: 1fr; }
}
@@ -427,6 +514,17 @@
</div>
</div>
<!-- ═══════════════ COMMUNICATIONS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('comms-section', this)">
<h2><span class="icon"></span> Communications <span class="count">last 35 hours</span></h2>
<span class="section-toggle"></span>
</div>
<div class="section-body" id="comms-section">
<div class="comms-grid" id="comms-grid"></div>
</div>
</div>
<!-- ═══════════════ STRATEGY & RECOMMENDATIONS ═══════════════ -->
<div class="section">
<div class="section-header" onclick="toggleSection('strategy-section', this)">
@@ -512,6 +610,30 @@
}
];
const comms = {
inbox: {
total: 4,
last35h: 2,
items: [
{ time: 'Jun 09 14:44', from: 'Mail Delivery System', subj: 'Undelivered — the@123.de', detail: '421 Downstream server error — cold email bounced', alert: true },
{ time: 'Jun 08 21:04', from: 'Mail Delivery System', subj: 'Undelivered — the@123.de', detail: '421 Downstream server error', alert: false },
],
alerts: [
{ icon: '⚠', body: 'Cold email to the@123.de bouncing (421 Downstream server error)', detail: 'Check recipient email validity or retry later.' }
]
},
sent: {
total: 8,
last35h: 2,
items: [
{ time: 'Jun 09', to: 'o.arnold@projektbox.de', subj: 'setting up an agent for projektbox' },
{ time: 'Jun 08', to: 'oliver@odoo4projects.com', subj: 'managing your agents without SSH' },
],
top_sent: 'Mark — Customer Success Agent'
},
note: '2 bounce alerts need review. Sending from support@derez.ai as Mark.'
};
const recommendations = [
'Prioritise the top 20 YouTube creators from the 60 collected — these are your most winnable influencer channel.',
'Unlock cold email outreach by populating real business emails for those 20 creators. Templates and coupons are ready.',
@@ -586,6 +708,43 @@
).join('');
}
function renderCommunications() {
const c = comms;
const inboxItems = c.inbox.items.map(i =>
`<li><span class="comms-time">${i.time}</span><span><span class="comms-from">${i.from}</span><br><span class="comms-subj">${i.subj}</span> <span class="comms-detail">${i.detail}</span></span></li>`
).join('');
const alerts = c.inbox.alerts.map(a =>
`<div class="comms-alert"><span class="alert-icon">${a.icon}</span><div><div class="alert-body">${a.body}</div><div class="alert-detail">${a.detail}</div></div></div>`
).join('');
const sentItems = c.sent.items.map(i =>
`<li><span class="comms-time">${i.time}</span><span><span class="comms-from">${i.to}</span><br><span class="comms-subj">${i.subj}</span></span></li>`
).join('');
document.getElementById('comms-grid').innerHTML =
`<div class="comms-card">
<h3>📥 Inbox</h3>
<div class="comms-summary">
<div class="comms-stat"><div class="comms-stat-num">${c.inbox.total}</div><div class="comms-stat-label">Total</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.inbox.last35h}</div><div class="comms-stat-label">Last 35h</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.inbox.alerts.length}</div><div class="comms-stat-label">Alerts</div></div>
</div>
<ul class="comms-list">${inboxItems}</ul>
${alerts}
</div>
<div class="comms-card">
<h3>📤 Sent</h3>
<div class="comms-summary">
<div class="comms-stat"><div class="comms-stat-num">${c.sent.total}</div><div class="comms-stat-label">Total Sent</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.sent.last35h}</div><div class="comms-stat-label">Last 35h</div></div>
<div class="comms-stat"><div class="comms-stat-num">${c.sent.items.length}</div><div class="comms-stat-label">Recent</div></div>
</div>
<ul class="comms-list">${sentItems}</ul>
<div style="margin-top:8px;font-size:11px;color:var(--text-muted);">
Sender: ${c.sent.top_sent} &middot; ${c.note}
</div>
</div>`;
}
async function fetchLiveData() {
try {
const res = await fetch('data/operations.json?t=' + Date.now());
@@ -602,6 +761,7 @@
renderGoals();
renderCampaigns();
renderActions();
renderCommunications();
renderStrategy();
fetchLiveData();
</script>