/* AAU CRM — Customer Profile 360 — playbook-aware (script, qualify gate, signals, MAKE THE MOVE) */
function StatCard({ icon, label, value, tone }) {
return (
);
}
function CustomerProfile360({ id }) {
const leads = useLeads();
const viewer = useViewer();
const lead = LeadStore.byId(id);
const [tab, setTab] = useState('overview');
const [move, setMove] = useState(false);
const [assign, setAssign] = useState(false);
const [edit, setEdit] = useState(false);
if (!lead) return navigate('/leads')}>Về danh sách} />
;
if (!SalesAccess.canSee(lead, viewer)) return navigate('/leads')}>Về Pipeline} />
;
const canEdit = SalesAccess.canEdit(viewer);
const st = AAU.stageById(lead.stage);
const g = pbGuide(st.code) || {};
const meta = (window.PLAYBOOK && PLAYBOOK.scriptTypeMeta[g.type]) || {};
const qCount = Object.values(lead.qualify).filter(Boolean).length;
const seedTimeline = [
{ type: 'chat', icon: 'message', color: '#0084ff', at: '8 phút trước', title: 'Tin nhắn ' + (AAU.channels[lead.channel]?.label || ''), sub: lead.signal ? '"' + lead.signal.text + '"' : 'Khách tương tác' },
{ type: 'asset', icon: 'paperclip', color: '#573b8a', at: '2 giờ trước', title: 'Đã gửi tài liệu', sub: (g.send && g.send[0]) || 'Brochure' },
{ type: 'create', icon: 'plus', color: '#8a8a8a', at: AAU.fmtDate(lead.createdAt), title: 'Lead được tạo', sub: 'Nguồn: ' + (AAU.sourceMeta[lead.source]?.label) + ' · Nhánh ' + (lead.branch || '—') },
];
const moveHist = (lead.history || []).map(h => ({ type: 'stage', icon: 'kanban', color: '#f59e0b', at: h.at, title: 'Chuyển ' + h.from + ' → ' + h.to, sub: 'Lý do: ' + h.reason + ' · trigger: ' + h.trigger }));
const timeline = [...moveHist, ...seedTimeline];
const qLabels = { bizModel: ['Mô hình kinh doanh rõ', lead.bizModel + ' · ' + lead.chainSize], painpoint: ['Có painpoint cụ thể', lead.painpoints[0] || '—'], courseMap: ['Map đúng khóa học', AAU.courseById(lead.courseInterest)?.name || '—'], budget: ['Đủ khả năng tài chính', 'Doanh thu ~' + AAU.fmtVNDm(lead.revenue) + '/th'] };
return (
navigate('/leads') }, { label: lead.company }]}
title={{lead.company} {lead.hot && }}
subtitle={lead.name + ' · ' + lead.role + ' · ' + lead.bizModel + ' · ' + lead.region}
actions={<>{canEdit && }{canEdit ? : }>} />
{st.branch && }
{st.lane && }
{lead.signal && }
{lead.dealValue > 0 && Deal {AAU.fmtVND(lead.dealValue)}}
Khóa: {(AAU.courseById(lead.courseInterest) || {}).code || '—'}
Phụ trách: {AAU.users.find(u => u.id === lead.assignedTo)?.name || 'Chưa gán'}{canEdit && setAssign(true)}>{lead.assignedTo ? 'Đổi' : 'Phân công'}}
= 4 ? '#0e7c4a' : '#b06f00'} />
{tab === 'overview' && (
NHU CẦU
{lead.painpoints.map((p, i) => {p})}{AAU.courseById(lead.courseInterest)?.name}
{lead.objection &&
OBJECTION / BLOCKER
{lead.objection}
}
)}
{tab === 'qualify' && (
Lead phải đủ 4 điều kiện mới được move sang 3.1 Qualify. Click để cập nhật.
{Object.keys(qLabels).map(k => {
const on = !!lead.qualify[k];
return (
LeadStore.toggleQualify(lead.id, k) : undefined}>
{qLabels[k][0]}
{qLabels[k][1]}
);
})}
Qualify score: {qCount}/4 — {qCount >= 4 ? Đủ điều kiện → 3.1 Qualify : Thiếu {4 - qCount} điều kiện → nurture 3.0 (SOFT)}
)}
{tab === 'timeline' && (
{timeline.map((t, i) => (
{i < timeline.length - 1 &&
}
))}
)}
{tab === 'history' && (
(lead.history && lead.history.length) ? (
| Từ | Đến | Lý do | Trigger |
{lead.history.map((h, i) => | {h.from} | {h.to} | {h.reason} | {h.trigger} |
)}
) :
)}
{/* MAKE THE MOVE script card */}
{st.code} · {g.title || st.name}
{g.objective}
{g.openings && g.openings.length > 0 && (
KỊCH BẢN — {meta.label}
{g.openings.map((o, i) =>
{o}
)}
)}
{g.send && g.send.length > 0 && (
Tài liệu gửi
{g.send.map((s, i) => {s})}
)}
{g.cadence && {g.cadence}
}
{canEdit ? : Vai trò chỉ-xem — không thể chuyển stage.
}
{/* next action */}
Hành động kế tiếp
{lead.nextAction}
{move && setMove(false)} onMove={(lid, to, r, t) => { LeadStore.move(lid, to, r, t); setMove(false); }} onToggleQualify={(lid, k) => LeadStore.toggleQualify(lid, k)} readOnly={!canEdit} />}
{assign && setAssign(false)} />}
{edit && setEdit(false)} />}
);
}
function LeadEditDrawer({ lead, onClose }) {
const [f, setF] = useState({
phone: lead.phone, email: lead.email, fb: lead.fb, region: lead.region,
bizModel: lead.bizModel, industry: lead.industry, chainSize: lead.chainSize,
revenue: lead.revenue, dealValue: lead.dealValue || 0,
painpoints: (lead.painpoints || []).join(', '), objection: lead.objection || '',
});
const set = (k, v) => setF(p => ({ ...p, [k]: v }));
const num = v => Number(String(v).replace(/\D/g, '')) || 0;
function save() {
LeadStore.update(lead.id, {
phone: f.phone, email: f.email, fb: f.fb, region: f.region,
bizModel: f.bizModel, industry: f.industry, chainSize: f.chainSize,
revenue: num(f.revenue), dealValue: num(f.dealValue),
painpoints: f.painpoints.split(',').map(s => s.trim()).filter(Boolean),
objection: f.objection.trim(),
});
onClose();
}
return (
>}>
Thông tin định danh & B2B do sales nhập tay (chat tự động chỉ gợi ý). Qualify chỉnh ở tab Qualify.
ĐỊNH DANH
set('phone', v)} />
set('email', v)} />
set('fb', v)} />
set('region', v)} />
KINH DOANH (B2B)
set('bizModel', v)} />
set('industry', v)} />
set('chainSize', v)} />
set('revenue', v)} />
NHU CẦU & DEAL
);
}
Object.assign(window, { CustomerProfile360, StatCard });