/* AAU CRM — Conversation Intelligence (Enablement & AI)
Vòng lặp tự học: hội thoại → pattern → tri thức → gợi ý sale → làm giàu kho. */
function ciSpark(data, color, w = 72, h = 26) {
const max = Math.max(...data), min = Math.min(...data), rng = (max - min) || 1;
const pts = data.map((v, i) => `${(i / (data.length - 1)) * (w - 2) + 1},${h - 3 - ((v - min) / rng) * (h - 6)}`);
const last = pts[pts.length - 1].split(',');
return (
);
}
function CoverageBadge({ c }) {
const map = { covered: { t: 'success', l: 'Đã phủ' }, partial: { t: 'warning', l: 'Một phần' }, gap: { t: 'critical', l: 'Lỗ hổng' } };
const m = map[c] || map.gap;
return {m.l};
}
function TrendChip({ v, suffix = '%' }) {
const up = v >= 0;
return {Math.abs(v)}{suffix};
}
const KIcon = { script: 'flow', asset: 'paperclip', kb: 'book' };
function KnowledgeChip({ k }) {
return {k.name};
}
function CatDot({ cat, size = 26 }) {
const m = INTEL.catMeta[cat];
return ;
}
/* ---------- Loop strip ---------- */
function LoopStrip() {
return (
Vòng lặp tri thức— mỗi hội thoại làm kho thông minh hơn
{INTEL.loop.map((n, i) => (
{n.value}
{n.label}
{n.sub}
{i < INTEL.loop.length - 1 && }
))}
);
}
/* ---------- Pattern detail drawer ---------- */
function PatternDrawer({ p, auto, onClose }) {
const m = INTEL.catMeta[p.cat];
return (
>}>
{p.label}
{m.label}Hay gặp ở · {p.stage}
Win-rate khi xử lý
{p.win}%
Độ phủ
{p.autoLinked ? 'AI đã tự gắn' : 'Chưa gắn'}
CÂU KHÁCH THƯỜNG NÓI (mẫu AI gom)
{p.snippets.map((s, i) => (
{s.who}
{s.text}
))}
TRI THỨC ĐANG GẮN
{p.knowledge.length ?
{p.knowledge.map((k, i) => )}
:
Chưa có tri thức nào — đây là lỗ hổng. AI đã đưa vào hàng đợi đề xuất.
}
HƯỚNG XỬ LÝ TỐT NHẤT (AI học từ deal thắng)
{p.best}
Khi AI bắt được pattern này trong Inbox, sale sẽ thấy gợi ý {auto ? 'kèm script đã gắn sẵn (tự động)' : 'kèm đề xuất script (chờ duyệt)'}.
);
}
/* ---------- Enrichment queue ---------- */
const ENRICH_META = {
'create-script': { icon: 'plus', l: 'Tạo kịch bản', color: '#1a4fa3', cta: 'Tạo script', target: '/enablement/scripts' },
'promote-kb': { icon: 'arrowUp', l: 'Đẩy lên KB', color: '#0e7c4a', cta: 'Tạo bài KB', target: '/enablement/kb' },
'update': { icon: 'edit', l: 'Cập nhật', color: '#b45309', cta: 'Mở để sửa', target: '/enablement/kb' },
'auto': { icon: 'bolt', l: 'AI tự động', color: '#573b8a', cta: 'Xem', target: '/enablement/scripts' },
};
function EnrichCard({ item, onAct, done }) {
const m = ENRICH_META[item.type];
return (
{m.l}
{item.kind === 'auto' && ĐANG CHẠY}
{item.ev}
{item.title}
{item.detail}
{done ?
{item.kind === 'auto' ? 'Đã xác nhận' : 'Đã thêm vào kho'}
:
{item.kind === 'auto'
? <>>
: <>>}
}
);
}
/* ---------- Main ---------- */
function ConversationIntelligence() {
const [auto, setAuto] = useState('auto'); // suggest | auto
const [cat, setCat] = useState('all');
const [sort, setSort] = useState('freq');
const [sel, setSel] = useState(null);
const [enrichDone, setEnrichDone] = useState({});
const isAuto = auto === 'auto';
const cats = INTEL.catMeta;
let rows = INTEL.patterns.filter(p => cat === 'all' || p.cat === cat);
rows = [...rows].sort((a, b) => sort === 'freq' ? b.freq - a.freq : sort === 'win' ? a.win - b.win : (b.trend - a.trend));
const gapCount = INTEL.patterns.filter(p => p.coverage === 'gap').length;
const pendingEnrich = INTEL.enrichQueue.filter(e => e.kind === 'review');
return (
Làm giàu
>} />
{INTEL.kpis.map((k, i) => )}
{/* Pattern Radar */}
} pad={false}>
({ value: v, label: m.short }))]} />
{rows.map(p => {
const m = cats[p.cat];
return (
setSel(p)} className="ci-row"
style={{ display: 'grid', gridTemplateColumns: '26px minmax(0,1fr) 88px 96px 64px 18px', alignItems: 'center', gap: 12, padding: '12px 16px', borderTop: '1px solid var(--p-border-secondary)', cursor: 'pointer' }}>
{p.label}{p.isNew && MỚI}{p.autoLinked && isAuto && auto}
{m.label} · {p.stage}
{ciSpark(p.spark, m.color)}
{p.freq}
= 60 ? '#0e7c4a' : p.win >= 40 ? '#b45309' : '#b42318', textAlign: 'right' }}>{p.win}%
);
})}
auto = AI tự gắn script
Win-rate = tỉ lệ deal tiến stage khi xử lý đúng
{/* Right column */}
AI} pad>
{INTEL.enrichQueue.map(e => setEnrichDone(d => ({ ...d, [e.id]: true }))} />)}
AI tự gắn script vào pattern
Liên kết khi độ tương đồng ≥ 0.85 & win-rate ≥ 60%
setAuto(v ? 'auto' : 'suggest')} />
Cảnh báo lỗ hổng tri thức
Báo manager khi pattern mới chưa có lời giải
{}} />
Nhịp review định kỳ
Manager duyệt các liên kết AI đã tự tạo
{/* Effectiveness */}
Tri thứcLượt dùngKhách phản hồiĐẩy tiến stageWin-rateXu hướng
{INTEL.effectiveness.map(k => (
{k.name}
{k.uses}
{k.reply}%
= 60 ? '#0e7c4a' : k.win >= 40 ? '#b45309' : '#b42318' }}>{k.win}%
))}
{sel && setSel(null)} />}
);
}
Object.assign(window, { ConversationIntelligence });