/* AAU CRM — Unified Inbox (3 columns, interactive) */ const INBOX_LABELS = [ { id: 'hot', label: 'Hot', color: '#ef4444' }, { id: 'proposal', label: 'Chờ proposal', color: '#f59e0b' }, { id: 'callback', label: 'Hẹn gọi lại', color: '#3b82f6' }, { id: 'franchise', label: 'Nhượng quyền', color: '#8b5cf6' }, { id: 'care', label: 'Cần CSKH', color: '#0a9e6e' }, { id: 'spam', label: 'Rác / Spam', color: '#9ca3af' }, ]; const labelById = (id) => INBOX_LABELS.find(l => l.id === id); const SENTIMENT = { cv1: 'pos', cv2: 'neu', cv3: 'neg', cv4: 'pos', cv5: 'neu', cv6: 'neg', cv7: 'neu', cv8: 'pos' }; const SENT_META = { pos: { l: 'Thiện chí', c: '#0a9e6e' }, neu: { l: 'Trung lập', c: '#8a8a8a' }, neg: { l: 'Do dự', c: '#c4320a' } }; const DUPES = { L1: 'Khoa BBQ — hồ sơ cũ (T9/2025)' }; const ME_ID = 'u5'; // người đang trực inbox (demo) function ChannelAvatar({ ch, name, color, size = 40 }) { const c = (AAU.channels && AAU.channels[ch]) || { color: '#8a8f98', short: (ch || '?').toUpperCase() }; return (
{c.short[0]}
); } function LabelChip({ id, small, onRemove }) { const l = labelById(id); if (!l) return null; return ( {l.label} {onRemove && { e.stopPropagation(); onRemove(); }}>} ); } function SentimentChip({ s }) { const m = SENT_META[s] || SENT_META.neu; return {m.l}; } /* ── Call modal (click-to-call → log + disposition) ── */ function CallModal({ lead, onClose, onLog }) { const [phase, setPhase] = useState('calling'); const [sec, setSec] = useState(0); const [disp, setDisp] = useState('consulted'); const [note, setNote] = useState(''); useEffect(() => { if (phase !== 'calling') return; const t = setInterval(() => setSec(s => s + 1), 1000); return () => clearInterval(t); }, [phase]); const mmss = `${String(Math.floor(sec / 60)).padStart(2, '0')}:${String(sec % 60).padStart(2, '0')}`; const dispo = [ { v: 'consulted', l: 'Đã tư vấn xong', tone: 'success' }, { v: 'callback', l: 'Hẹn gọi lại', tone: 'info' }, { v: 'noanswer', l: 'Không nghe máy', tone: 'warning' }, { v: 'wrong', l: 'Sai số', tone: 'critical' }, { v: 'refused', l: 'Từ chối', tone: 'critical' }, ]; return ( setPhase('ended')} style={{ margin: '0 auto' }}>Kết thúc cuộc gọi :
}>
{lead.name}
{lead.phone}
{phase === 'calling' ? Đang kết nối · {mmss} : Đã kết thúc · {mmss}}
{phase === 'ended' && (
KẾT QUẢ CUỘC GỌI
{dispo.map(d => ( ))}
GHI CHÚ