{"id":3536,"date":"2026-04-14T20:53:26","date_gmt":"2026-04-14T13:53:26","guid":{"rendered":"https:\/\/hdinterior.vn\/?page_id=3536"},"modified":"2026-04-14T21:18:03","modified_gmt":"2026-04-14T14:18:03","slug":"crm-noi-bo","status":"publish","type":"page","link":"https:\/\/hdinterior.vn\/en\/crm-noi-bo\/","title":{"rendered":"CRM &#8211; N\u1ed9i b\u1ed9"},"content":{"rendered":"<p><!DOCTYPE html><br \/>\n<html lang=\"vi\"><br \/>\n<head><br \/>\n<meta charset=\"utf-8\"><br \/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><br \/>\n<title>HDInterior CRM<\/title><\/p>\n<style>\n\/* \u2500\u2500 CONFIG \u2500\u2500 paste your values in the SCRIPT section below *\/\n*{box-sizing:border-box;margin:0;padding:0}\nbody{font-family:Arial,sans-serif;background:#F4F5F7;color:#212121;font-size:14px;min-height:100vh}<\/p>\n<p>\/* LOGIN *\/\n#login-screen{min-height:100vh;display:flex;align-items:center;justify-content:center;background:#1A1A2E}\n.login-box{background:#fff;border-radius:12px;padding:36px 32px;width:340px;box-shadow:0 8px 32px rgba(0,0,0,.3)}\n.login-logo{font-size:20px;font-weight:bold;color:#1A1A2E;margin-bottom:4px}\n.login-sub{font-size:12px;color:#9E9E9E;margin-bottom:24px}\n.login-step{display:none}.login-step.show{display:block}\n.role-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-bottom:16px}\n.role-btn{padding:16px 8px;border:1.5px solid #E0E0E0;border-radius:8px;background:#fff;cursor:pointer;text-align:center;transition:all .15s}\n.role-btn:hover{border-color:#1A1A2E}\n.role-btn.sel{border-color:#1A1A2E;background:#1A1A2E;color:#fff}\n.role-icon{font-size:22px;margin-bottom:4px}\n.role-label{font-size:12px;font-weight:bold}\n.inp{width:100%;padding:10px 12px;font-size:14px;border:1px solid #E0E0E0;border-radius:6px;background:#fff;margin-bottom:12px;color:#212121;font-family:Arial,sans-serif}\n.inp:focus{outline:none;border-color:#1A1A2E}\n.login-btn-submit{width:100%;padding:12px;font-size:14px;font-weight:bold;background:#1A1A2E;color:#fff;border:none;border-radius:6px;cursor:pointer}\n.login-btn-submit:hover{background:#2D2D4E}\n.back-link{font-size:12px;color:#9E9E9E;cursor:pointer;text-align:center;margin-top:10px}\n.err{font-size:12px;color:#C62828;min-height:18px;margin-top:6px;text-align:center}<\/p>\n<p>\/* APP *\/\n#app{display:none}\n.topbar{background:#1A1A2E;color:#fff;padding:10px 20px;display:flex;justify-content:space-between;align-items:center}\n.topbar-title{font-size:14px;font-weight:bold}\n.chip{font-size:11px;background:rgba(255,255,255,.18);padding:2px 10px;border-radius:20px;margin-left:8px}\n.topbar-right{display:flex;gap:8px;align-items:center}\n.topbar-user{font-size:12px;opacity:.75}\n.wrap{max-width:1100px;margin:0 auto;padding:16px}\n.page{display:none}.page.on{display:block}\n.nav{display:flex;border-bottom:2px solid #E0E0E0;margin-bottom:18px;align-items:flex-end;justify-content:space-between}\n.nav-left{display:flex}\n.ntab{padding:9px 18px;font-size:13px;font-weight:bold;cursor:pointer;border:none;background:none;color:#9E9E9E;border-bottom:3px solid transparent;margin-bottom:-2px}\n.ntab.on{color:#1A1A2E;border-bottom:3px solid #1A1A2E}\n.subpage{display:none}.subpage.on{display:block}<\/p>\n<p>\/* FORMS *\/\nlabel{font-size:12px;color:#616161;display:block;margin-bottom:4px}\ninput[type=text],input[type=tel],input[type=number],input[type=email],input[type=password],select,textarea{width:100%;padding:8px 10px;font-size:13px;border:1px solid #BDBDBD;border-radius:6px;background:#fff;color:#212121;font-family:Arial,sans-serif}\ninput:focus,select:focus,textarea:focus{outline:none;border-color:#1A1A2E}\ntextarea{resize:vertical;min-height:64px}\n.g2{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.g3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}\n.f{margin-bottom:12px}\n.fsec{font-size:11px;font-weight:bold;color:#9E9E9E;text-transform:uppercase;letter-spacing:.06em;margin:18px 0 10px;padding-bottom:5px;border-bottom:1px solid #E0E0E0}<\/p>\n<p>\/* BUTTONS *\/\n.btn{padding:8px 16px;font-size:13px;font-weight:bold;border-radius:6px;cursor:pointer;border:1px solid #BDBDBD;background:#fff;color:#212121}\n.btn:hover{background:#F5F5F5}\n.btn.p{background:#1A1A2E;color:#fff;border-color:transparent}\n.btn.p:hover{background:#2D2D4E}\n.btn.g{background:#1D9E75;color:#fff;border-color:transparent}\n.btn.sm{padding:5px 11px;font-size:12px}\n.btn.xs{padding:3px 8px;font-size:11px}\n.btn.d{color:#C62828;border-color:#EF9A9A}\n.brow{display:flex;gap:8px;margin-top:14px;align-items:center;flex-wrap:wrap}<\/p>\n<p>\/* STATS *\/\n.stats{display:grid;gap:10px;margin-bottom:18px}\n.s4{grid-template-columns:repeat(4,1fr)}.s6{grid-template-columns:repeat(6,1fr)}\n.sc{background:#fff;border-radius:8px;padding:12px 16px;border:1px solid #E8E8E8}\n.sc-n{font-size:24px;font-weight:bold;color:#1A1A2E}\n.sc-l{font-size:11px;color:#757575;margin-top:2px}\n.sc.warn{border-color:#EF9F27;background:#FFFDE7}\n.sc.warn .sc-n{color:#E65100}<\/p>\n<p>\/* TABLES *\/\n.tbl{width:100%;border-collapse:collapse;background:#fff;border-radius:10px;overflow:hidden;border:1px solid #E8E8E8;font-size:13px}\n.tbl th{padding:10px 14px;font-size:11px;font-weight:bold;color:#fff;background:#1A1A2E;text-align:left;white-space:nowrap}\n.tbl td{padding:9px 14px;border-bottom:1px solid #F0F0F0;vertical-align:middle}\n.tbl tr:last-child td{border-bottom:none}\n.tbl tr:hover td{background:#FAFAFA}<\/p>\n<p>\/* BADGES *\/\n.badge{display:inline-block;padding:2px 9px;border-radius:20px;font-size:11px;font-weight:bold;white-space:nowrap}\n.b-new{background:#E3F2FD;color:#1565C0}\n.b-assigned{background:#E8F5E9;color:#2E7D32}\n.b-consulting{background:#EDE7F6;color:#4527A0}\n.b-proposal{background:#FFF8E1;color:#E65100}\n.b-wait{background:#FCE4EC;color:#880E4F}\n.b-closed{background:#C8E6C9;color:#1B5E20}\n.b-lost{background:#FFEBEE;color:#B71C1C}\n.b-problem{background:#FFEBEE;color:#B71C1C}\n.b-hot{background:#FBE9E7;color:#BF360C}\n.b-warm{background:#FFF8E1;color:#E65100}\n.b-cold{background:#E3F2FD;color:#1565C0}<\/p>\n<p>\/* LEAD CARDS *\/\n.lead-card-wrap{margin-bottom:10px}\n.lead-card{background:#fff;border:1px solid #E8E8E8;border-radius:10px 10px 0 0;padding:13px 16px;cursor:pointer;display:flex;justify-content:space-between;align-items:flex-start;gap:12px}\n.lead-card:only-child,.lead-card-wrap>div:only-child{border-radius:10px}\n.lead-card:hover{background:#FAFAFA}\n.lead-card.hot{border-left:4px solid #D85A30}\n.lead-card.warm{border-left:4px solid #EF9F27}\n.lead-card.cold{border-left:4px solid #378ADD}\n.lc-name{font-size:14px;font-weight:bold}\n.lc-meta{font-size:12px;color:#757575;margin-top:3px}\n.lc-tags{display:flex;gap:5px;flex-wrap:wrap;margin-top:6px}\n.lc-right{display:flex;flex-direction:column;align-items:flex-end;gap:5px;flex-shrink:0}\n.tag-info{font-size:11px;color:#757575;background:#F5F5F5;padding:2px 8px;border-radius:4px}<\/p>\n<p>\/* EXPAND DETAIL *\/\n.lead-detail{background:#fff;border:1px solid #E8E8E8;border-top:none;border-radius:0 0 10px 10px;padding:16px 18px;display:none}\n.lead-detail.open{display:block}\n.det-tabs{display:flex;border-bottom:1px solid #E0E0E0;margin-bottom:14px}\n.det-tab{padding:7px 14px;font-size:12px;font-weight:bold;cursor:pointer;border:none;background:none;color:#9E9E9E;border-bottom:2px solid transparent;margin-bottom:-1px}\n.det-tab.on{color:#1A1A2E;border-bottom:2px solid #1A1A2E}\n.dpane{display:none}.dpane.on{display:block}\n.det-sec{font-size:11px;font-weight:bold;color:#9E9E9E;text-transform:uppercase;letter-spacing:.06em;margin:14px 0 8px;padding-bottom:5px;border-bottom:1px solid #F0F0F0;display:flex;justify-content:space-between;align-items:center}\n.det-sec:first-child{margin-top:0}\n.status-bar{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}\n.status-opt{padding:6px 12px;border-radius:20px;font-size:12px;font-weight:bold;cursor:pointer;border:1.5px solid #E0E0E0;background:#fff;color:#757575;transition:all .15s}\n.status-opt:hover{border-color:#1A1A2E}\n.s-assigned .status-opt[data-s=assigned]{background:#2E7D32;border-color:#2E7D32;color:#fff}\n.s-consulting .status-opt[data-s=consulting]{background:#4527A0;border-color:#4527A0;color:#fff}\n.s-proposal .status-opt[data-s=proposal]{background:#E65100;border-color:#E65100;color:#fff}\n.s-wait .status-opt[data-s=wait]{background:#880E4F;border-color:#880E4F;color:#fff}\n.s-closed .status-opt[data-s=closed]{background:#1B5E20;border-color:#1B5E20;color:#fff}\n.s-lost .status-opt[data-s=lost]{background:#B71C1C;border-color:#B71C1C;color:#fff}\n.s-problem .status-opt[data-s=problem]{background:#B71C1C;border-color:#B71C1C;color:#fff}\n.mkt-info-row{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:8px}\n.mkt-chip{background:#FFF8E1;border-radius:6px;padding:5px 10px;font-size:12px}\n.mkt-chip-k{color:#9E9E9E;margin-right:4px}\n.mkt-chip-v{color:#424242;font-weight:500}\n.log-row{display:flex;gap:8px;padding:6px 0;border-bottom:1px solid #F8F8F8;align-items:flex-start}\n.log-row:last-child{border-bottom:none}\n.log-date{font-size:11px;color:#9E9E9E;min-width:68px;flex-shrink:0}\n.log-by{font-size:11px;font-weight:bold;color:#1A1A2E;min-width:46px;flex-shrink:0}\n.log-text{font-size:13px;flex:1}\n.sp-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px;margin-bottom:20px}\n.sp-card{background:#fff;border-radius:10px;padding:14px;border:1px solid #E8E8E8}\n.sp-name{font-size:14px;font-weight:bold;margin-bottom:8px}\n.sp-row{display:flex;justify-content:space-between;font-size:12px;color:#757575;padding:2px 0}\n.set-card{background:#fff;border-radius:10px;border:1px solid #E8E8E8;padding:16px 18px;margin-bottom:14px}\n.set-card h3{font-size:14px;font-weight:bold;margin-bottom:12px}\n.sale-li{display:flex;justify-content:space-between;align-items:center;padding:8px 0;border-bottom:1px solid #F5F5F5}\n.sale-li:last-child{border-bottom:none}\n.frow{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap;align-items:center}\n.frow select,.frow input{flex:1;min-width:100px;width:auto}\n.empty{text-align:center;padding:40px;color:#9E9E9E}\n.loading{text-align:center;padding:40px;color:#9E9E9E}\n.req::after{content:\" *\";color:#C62828}\n.toast{position:fixed;bottom:16px;left:50%;transform:translateX(-50%);background:#1A1A2E;color:#fff;padding:10px 20px;border-radius:8px;font-size:13px;opacity:0;transition:opacity .25s;pointer-events:none;z-index:9999;white-space:nowrap}\n.toast.show{opacity:1}\n.assign-modal{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:300;align-items:center;justify-content:center}\n.assign-modal.open{display:flex}\n.assign-box{background:#fff;border-radius:12px;padding:24px;width:420px;max-width:95vw}\n@media(max-width:640px){.g2,.g3{grid-template-columns:1fr}.stats{grid-template-columns:repeat(2,1fr)!important}.login-box{width:92vw;padding:24px 18px}}\n<\/style>\n<p><\/head><br \/>\n<body><\/p>\n<p><!-- \u2550\u2550 CONFIG \u2014 \u0110I\u1ec0N V\u00c0O \u0110\u00c2Y \u2550\u2550 --><br \/>\n<script>\nconst CONFIG = {\n  API_KEY: 'AIzaSyCjmtIF09LBJAJNOd9xPemqED_AD1e61xg',\n  CLIENT_ID: '751087909969-0l6hjnbr2b98j4p6hrug5st3rcoctaop.apps.googleusercontent.com',\n  SHEET_ID: '1sbXvbhwtP-kpuw-9HyW8G_Bo7HdH-AAKlVS83T80Pnc',\n  MGR_PASS: '1234',\n  MKT_PASS: 'mkt123',\n  LEADS_SHEET: 'Leads',\n  SALES_SHEET: 'Sales',\n};\n<\/script><\/p>\n<p><!-- LOGIN --><\/p>\n<div id=\"login-screen\">\n<div class=\"login-box\">\n<div class=\"login-logo\">HDInterior CRM<\/div>\n<div class=\"login-sub\">Ch\u1ecdn vai tr\u00f2 \u0111\u1ec3 \u0111\u0103ng nh\u1eadp<\/div>\n<div id=\"s1\" class=\"login-step show\">\n<div class=\"role-grid\">\n<div class=\"role-btn\" id=\"rb-mkt\" onclick=\"selRole('mkt')\">\n<div class=\"role-icon\">\ud83d\udccb<\/div>\n<div class=\"role-label\">MKT<\/div>\n<\/div>\n<div class=\"role-btn\" id=\"rb-manager\" onclick=\"selRole('manager')\">\n<div class=\"role-icon\">\ud83d\udcca<\/div>\n<div class=\"role-label\">Manager<\/div>\n<\/div>\n<div class=\"role-btn\" id=\"rb-sale\" onclick=\"selRole('sale')\">\n<div class=\"role-icon\">\ud83d\udc64<\/div>\n<div class=\"role-label\">Sale<\/div>\n<\/div><\/div>\n<p>      <button class=\"login-btn-submit\" onclick=\"goPin()\">Ti\u1ebfp theo \u2192<\/button><\/p>\n<div class=\"err\" id=\"e1\"><\/div>\n<\/p><\/div>\n<div id=\"s2\" class=\"login-step\">\n<div id=\"sale-select-wrap\" class=\"f\" style=\"display:none\">\n        <label>Ch\u1ecdn t\u00ean<\/label><br \/>\n        <select id=\"sale-sel\" class=\"inp\" style=\"margin-bottom:12px\"><\/select>\n      <\/div>\n<div class=\"f\">\n        <label id=\"pin-lbl\">M\u1eadt kh\u1ea9u<\/label><br \/>\n        <input class=\"inp\" type=\"password\" id=\"pin-inp\" placeholder=\"\u2022\u2022\u2022\u2022\" maxlength=\"20\" onkeydown=\"if(event.key==='Enter')doLogin()\">\n      <\/div>\n<p>      <button class=\"login-btn-submit\" onclick=\"doLogin()\">\u0110\u0103ng nh\u1eadp<\/button><\/p>\n<div class=\"err\" id=\"e2\"><\/div>\n<div class=\"back-link\" onclick=\"backRole()\">\u2190 Ch\u1ecdn l\u1ea1i<\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p><!-- APP --><\/p>\n<div id=\"app\">\n<div class=\"topbar\">\n<div style=\"display:flex;align-items:center\">\n<div class=\"topbar-title\">HDInterior CRM<\/div>\n<p>      <span class=\"chip\" id=\"role-chip\"><\/span>\n    <\/div>\n<div class=\"topbar-right\">\n      <span class=\"topbar-user\" id=\"user-name\"><\/span><br \/>\n      <button class=\"btn sm\" style=\"background:rgba(255,255,255,.15);color:#fff;border-color:transparent\" onclick=\"logout()\">\u0110\u0103ng xu\u1ea5t<\/button>\n    <\/div>\n<\/p><\/div>\n<p>  <!-- MKT --><\/p>\n<div id=\"mkt-app\" class=\"page\">\n<div class=\"wrap\">\n<div class=\"nav\">\n<div class=\"nav-left\">\n        <button class=\"ntab on\" onclick=\"mktTab('form')\">Nh\u1eadp lead m\u1edbi<\/button><br \/>\n        <button class=\"ntab\" onclick=\"mktTab('list')\">Lead \u0111\u00e3 nh\u1eadp<\/button>\n      <\/div>\n<\/div>\n<div id=\"mkt-form\" class=\"subpage on\">\n<div class=\"fsec\">Kh\u00e1ch h\u00e0ng<\/div>\n<div class=\"g2\">\n<div class=\"f\"><label class=\"req\">H\u1ecd t\u00ean<\/label><input id=\"m-name\" type=\"text\" placeholder=\"Nguy\u1ec5n V\u0103n A\"><\/div>\n<div class=\"f\"><label class=\"req\">Phone number<\/label><input id=\"m-phone\" type=\"tel\" placeholder=\"0912 345 678\"><\/div>\n<\/p><\/div>\n<div class=\"g2\">\n<div class=\"f\"><label>Zalo<\/label><input id=\"m-zalo\" type=\"text\"><\/div>\n<div class=\"f\"><label>E-mail<\/label><input id=\"m-email\" type=\"email\"><\/div>\n<\/p><\/div>\n<div class=\"fsec\">Project<\/div>\n<div class=\"g3\">\n<div class=\"f\"><label class=\"req\">Ngu\u1ed3n lead<\/label><br \/>\n            <select id=\"m-source\"><option value=\"\">&#8212; Ch\u1ecdn &#8212;<\/option><option>Facebook Ads<\/option><option>Zalo Ads<\/option><option>Referral \/ Gi\u1edbi thi\u1ec7u<\/option><option>Website \/ SEO<\/option><option>G\u1ecdi \u0111i\u1ec7n v\u00e0o<\/option><option>Kh\u00e1c<\/option><\/select><\/div>\n<div class=\"f\"><label>Lo\u1ea1i c\u00f4ng tr\u00ecnh<\/label><br \/>\n            <select id=\"m-type\"><option value=\"\">&#8212;<\/option><option>Apartment<\/option><option>Townhouse<\/option><option>Villa<\/option><option>Office<\/option><option>Shophouse<\/option><option>Kh\u00e1c<\/option><\/select><\/div>\n<div class=\"f\"><label>Di\u1ec7n t\u00edch (m\u00b2)<\/label><input id=\"m-area\" type=\"number\"><\/div>\n<\/p><\/div>\n<div class=\"g2\">\n<div class=\"f\"><label>Budget<\/label><br \/>\n            <select id=\"m-budget\"><option value=\"\">Ch\u01b0a \u0111\u1ec1 c\u1eadp<\/option><option>D\u01b0\u1edbi 200 tri\u1ec7u<\/option><option>200\u2013500 tri\u1ec7u<\/option><option>500tr\u20131 t\u1ef7<\/option><option>1\u20132 t\u1ef7<\/option><option>Tr\u00ean 2 t\u1ef7<\/option><\/select><\/div>\n<div class=\"f\"><label>Timeline<\/label><br \/>\n            <select id=\"m-timeline\"><option value=\"\">Ch\u01b0a \u0111\u1ec1 c\u1eadp<\/option><option>G\u1ea5p (trong 1 th\u00e1ng)<\/option><option>1\u20133 th\u00e1ng<\/option><option>3\u20136 th\u00e1ng<\/option><option>Tr\u00ean 6 th\u00e1ng<\/option><\/select><\/div>\n<\/p><\/div>\n<div class=\"f\"><label>Address<\/label><input id=\"m-address\" type=\"text\" placeholder=\"Qu\u1eadn \/ To\u00e0 nh\u00e0...\"><\/div>\n<div class=\"f\"><label>Ghi ch\u00fa t\u1eeb MKT<\/label><textarea id=\"m-note\" placeholder=\"Kh\u00e1ch nh\u1eafn qua FB, quan t\u00e2m chung c\u01b0 80m\u00b2...\"><\/textarea><\/div>\n<div class=\"brow\">\n          <button class=\"btn p\" onclick=\"mktSubmit()\">L\u01b0u lead<\/button><br \/>\n          <button class=\"btn\" onclick=\"mktClear()\">Xo\u00e1 tr\u1eafng<\/button><br \/>\n          <span id=\"mkt-st\" style=\"font-size:12px;color:#757575\"><\/span>\n        <\/div>\n<\/p><\/div>\n<div id=\"mkt-list\" class=\"subpage\">\n<div id=\"mkt-list-content\">\n<div class=\"loading\">\u0110ang t\u1ea3i&#8230;<\/div>\n<\/div><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>  <!-- MANAGER --><\/p>\n<div id=\"mgr-app\" class=\"page\">\n<div class=\"wrap\">\n<div class=\"nav\">\n<div class=\"nav-left\">\n          <button class=\"ntab on\" onclick=\"mgrTab('overview')\">T\u1ed5ng quan<\/button><br \/>\n          <button class=\"ntab\" onclick=\"mgrTab('assign')\">G\u00e1n lead<\/button><br \/>\n          <button class=\"ntab\" onclick=\"mgrTab('pipeline')\">Pipeline<\/button><br \/>\n          <button class=\"ntab\" onclick=\"mgrTab('settings')\">C\u00e0i \u0111\u1eb7t<\/button>\n        <\/div>\n<p>        <button class=\"btn sm\" style=\"margin-bottom:4px\" onclick=\"reloadMgr()\">\u21bb T\u1ea3i l\u1ea1i<\/button>\n      <\/div>\n<div id=\"mgr-overview\" class=\"subpage on\">\n<div class=\"stats s6\" id=\"mgr-stats\">\n<div class=\"loading\">\u0110ang t\u1ea3i&#8230;<\/div>\n<\/div>\n<div style=\"font-weight:bold;margin-bottom:10px\">Hi\u1ec7u su\u1ea5t t\u1eebng sale<\/div>\n<div class=\"sp-grid\" id=\"sale-perf\"><\/div>\n<div style=\"font-weight:bold;margin-bottom:10px\">C\u00f4ng tr\u00ecnh c\u1ea7n h\u1ed7 tr\u1ee3<\/div>\n<table class=\"tbl\" id=\"problems-table\">\n<tbody>\n<tr>\n<td style=\"text-align:center;padding:20px;color:#9E9E9E\">\u0110ang t\u1ea3i&#8230;<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/div>\n<div id=\"mgr-assign\" class=\"subpage\">\n<div style=\"font-size:13px;color:#757575;margin-bottom:12px\">Lead m\u1edbi t\u1eeb MKT \u2014 ch\u01b0a \u0111\u01b0\u1ee3c g\u00e1n sale<\/div>\n<table class=\"tbl\" id=\"assign-table\">\n<tbody>\n<tr>\n<td style=\"text-align:center;padding:20px;color:#9E9E9E\">\u0110ang t\u1ea3i&#8230;<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/div>\n<div id=\"mgr-pipeline\" class=\"subpage\">\n<div class=\"frow\">\n          <select id=\"pf-status\" onchange=\"renderPipeline()\"><option value=\"\">T\u1ea5t c\u1ea3 tr\u1ea1ng th\u00e1i<\/option><option value=\"new\">M\u1edbi<\/option><option value=\"assigned\">\u0110\u00e3 g\u00e1n<\/option><option value=\"consulting\">\u0110ang t\u01b0 v\u1ea5n<\/option><option value=\"proposal\">\u0110\u00e3 b\u00e1o gi\u00e1<\/option><option value=\"wait\">Ch\u1edd ph\u1ea3n h\u1ed3i<\/option><option value=\"closed\">Ch\u1ed1t deal<\/option><option value=\"lost\">Kh\u00f4ng ti\u1ebfp t\u1ee5c<\/option><option value=\"problem\">C\u1ea7n h\u1ed7 tr\u1ee3<\/option><\/select><br \/>\n          <select id=\"pf-sale\" onchange=\"renderPipeline()\"><option value=\"\">T\u1ea5t c\u1ea3 sale<\/option><\/select><br \/>\n          <input id=\"pf-q\" placeholder=\"T\u00ecm t\u00ean, S\u0110T...\" oninput=\"renderPipeline()\"><br \/>\n          <button class=\"btn g sm\" onclick=\"exportCSV()\">\u2193 CSV<\/button>\n        <\/div>\n<table class=\"tbl\" id=\"pipeline-table\">\n<tbody>\n<tr>\n<td colspan=\"7\" style=\"text-align:center;padding:20px;color:#9E9E9E\">\u0110ang t\u1ea3i&#8230;<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/div>\n<div id=\"mgr-settings\" class=\"subpage\">\n<div class=\"set-card\">\n<h3>Danh s\u00e1ch sale &#038; PIN<\/h3>\n<div id=\"sale-list-el\"><\/div>\n<div style=\"display:grid;grid-template-columns:1fr 100px 110px;gap:8px;margin-top:14px;align-items:end\">\n<div><label>T\u00ean sale<\/label><input type=\"text\" id=\"ns-name\" placeholder=\"Nguy\u1ec5n V\u0103n A\"><\/div>\n<div><label>PIN<\/label><input type=\"password\" id=\"ns-pin\" placeholder=\"\u2022\u2022\u2022\u2022\" maxlength=\"6\"><\/div>\n<p>            <button class=\"btn p\" style=\"height:38px\" onclick=\"addSale()\">Th\u00eam sale<\/button>\n          <\/div>\n<\/p><\/div>\n<div class=\"set-card\">\n<h3>\u0110\u1ed5i m\u1eadt kh\u1ea9u<\/h3>\n<div class=\"g2\">\n<div>\n              <label>M\u1eadt kh\u1ea9u Manager m\u1edbi<\/label><br \/>\n              <input type=\"password\" id=\"mgr-pw\" placeholder=\"Nh\u1eadp m\u1eadt kh\u1ea9u m\u1edbi\" style=\"margin-bottom:6px\"><br \/>\n              <input type=\"password\" id=\"mgr-pw2\" placeholder=\"X\u00e1c nh\u1eadn\"><br \/>\n              <button class=\"btn p sm\" style=\"margin-top:8px\" onclick=\"changePw('MGR_PASS','mgr-pw','mgr-pw2')\">L\u01b0u<\/button>\n            <\/div>\n<div>\n              <label>M\u1eadt kh\u1ea9u MKT m\u1edbi<\/label><br \/>\n              <input type=\"password\" id=\"mkt-pw\" placeholder=\"Nh\u1eadp m\u1eadt kh\u1ea9u m\u1edbi\" style=\"margin-bottom:6px\"><br \/>\n              <input type=\"password\" id=\"mkt-pw2\" placeholder=\"X\u00e1c nh\u1eadn\"><br \/>\n              <button class=\"btn p sm\" style=\"margin-top:8px\" onclick=\"changePw('MKT_PASS','mkt-pw','mkt-pw2')\">L\u01b0u<\/button>\n            <\/div>\n<\/p><\/div>\n<div class=\"err\" id=\"pw-err\" style=\"text-align:left;margin-top:8px\"><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>  <!-- SALE --><\/p>\n<div id=\"sale-app\" class=\"page\">\n<div class=\"wrap\">\n<div class=\"nav\">\n<div class=\"nav-left\">\n        <button class=\"ntab on\" onclick=\"saleTab('leads')\">Kh\u00e1ch c\u1ee7a t\u00f4i<\/button><br \/>\n        <button class=\"ntab\" onclick=\"saleTab('add')\">Th\u00eam lead<\/button>\n      <\/div>\n<p>      <button class=\"btn sm\" style=\"margin-bottom:4px\" onclick=\"reloadSale()\">\u21bb T\u1ea3i l\u1ea1i<\/button>\n      <\/div>\n<div id=\"sale-leads\" class=\"subpage on\">\n<div class=\"stats s4\" id=\"sale-stats\"><\/div>\n<div class=\"frow\">\n          <select id=\"sf-status\" onchange=\"renderSaleLeads()\"><option value=\"\">T\u1ea5t c\u1ea3<\/option><option value=\"assigned\">M\u1edbi nh\u1eadn<\/option><option value=\"consulting\">\u0110ang t\u01b0 v\u1ea5n<\/option><option value=\"proposal\">\u0110\u00e3 b\u00e1o gi\u00e1<\/option><option value=\"wait\">Ch\u1edd ph\u1ea3n h\u1ed3i<\/option><option value=\"closed\">Ch\u1ed1t deal<\/option><option value=\"lost\">Kh\u00f4ng ti\u1ebfp t\u1ee5c<\/option><option value=\"problem\">C\u1ea7n h\u1ed7 tr\u1ee3<\/option><\/select><br \/>\n          <input id=\"sf-q\" placeholder=\"T\u00ecm t\u00ean, S\u0110T...\" oninput=\"renderSaleLeads()\">\n        <\/div>\n<div id=\"sale-lead-list\">\n<div class=\"loading\">\u0110ang t\u1ea3i&#8230;<\/div>\n<\/div><\/div>\n<div id=\"sale-add\" class=\"subpage\">\n<div class=\"fsec\">Kh\u00e1ch h\u00e0ng<\/div>\n<div class=\"g2\">\n<div class=\"f\"><label class=\"req\">H\u1ecd t\u00ean<\/label><input id=\"a-name\" type=\"text\" placeholder=\"Nguy\u1ec5n V\u0103n A\"><\/div>\n<div class=\"f\"><label class=\"req\">S\u0110T<\/label><input id=\"a-phone\" type=\"tel\" placeholder=\"0912 345 678\"><\/div>\n<\/p><\/div>\n<div class=\"g2\">\n<div class=\"f\"><label>Zalo<\/label><input id=\"a-zalo\" type=\"text\"><\/div>\n<div class=\"f\"><label>E-mail<\/label><input id=\"a-email\" type=\"email\"><\/div>\n<\/p><\/div>\n<div class=\"fsec\">Project<\/div>\n<div class=\"g3\">\n<div class=\"f\"><label class=\"req\">Ngu\u1ed3n lead<\/label><br \/>\n            <select id=\"a-source\"><option value=\"\">&#8212; Ch\u1ecdn &#8212;<\/option><option>Facebook Ads<\/option><option>Zalo Ads<\/option><option>Referral \/ Gi\u1edbi thi\u1ec7u<\/option><option>Website \/ SEO<\/option><option>G\u1ecdi \u0111i\u1ec7n<\/option><option>Kh\u00e1c<\/option><\/select><\/div>\n<div class=\"f\"><label>Lo\u1ea1i CT<\/label><br \/>\n            <select id=\"a-type\"><option value=\"\">&#8212;<\/option><option>Apartment<\/option><option>Townhouse<\/option><option>Villa<\/option><option>Office<\/option><option>Shophouse<\/option><option>Kh\u00e1c<\/option><\/select><\/div>\n<div class=\"f\"><label>Di\u1ec7n t\u00edch (m\u00b2)<\/label><input id=\"a-area\" type=\"number\"><\/div>\n<\/p><\/div>\n<div class=\"g2\">\n<div class=\"f\"><label>Budget<\/label><br \/>\n            <select id=\"a-budget\"><option value=\"\">Ch\u01b0a r\u00f5<\/option><option>D\u01b0\u1edbi 200 tri\u1ec7u<\/option><option>200\u2013500 tri\u1ec7u<\/option><option>500tr\u20131 t\u1ef7<\/option><option>1\u20132 t\u1ef7<\/option><option>Tr\u00ean 2 t\u1ef7<\/option><\/select><\/div>\n<div class=\"f\"><label>Timeline<\/label><br \/>\n            <select id=\"a-timeline\"><option value=\"\">Ch\u01b0a r\u00f5<\/option><option>G\u1ea5p (trong 1 th\u00e1ng)<\/option><option>1\u20133 th\u00e1ng<\/option><option>3\u20136 th\u00e1ng<\/option><option>Tr\u00ean 6 th\u00e1ng<\/option><\/select><\/div>\n<\/p><\/div>\n<div class=\"f\"><label>Address<\/label><input id=\"a-address\" type=\"text\"><\/div>\n<div class=\"g2\">\n<div class=\"f\"><label>Tr\u1ea1ng th\u00e1i<\/label><br \/>\n            <select id=\"a-status\"><option value=\"assigned\">M\u1edbi nh\u1eadn<\/option><option value=\"consulting\">\u0110ang t\u01b0 v\u1ea5n<\/option><\/select><\/div>\n<div class=\"f\"><label>\u01afu ti\u00ean<\/label><br \/>\n            <select id=\"a-priority\"><option value=\"warm\">Warm<\/option><option value=\"hot\">Hot<\/option><option value=\"cold\">Cold<\/option><\/select><\/div>\n<\/p><\/div>\n<div class=\"f\"><label>Ghi ch\u00fa<\/label><textarea id=\"a-note\" placeholder=\"Ghi ch\u00fa ban \u0111\u1ea7u...\"><\/textarea><\/div>\n<div class=\"brow\">\n          <button class=\"btn p\" onclick=\"saleAddLead()\">L\u01b0u lead<\/button><br \/>\n          <button class=\"btn\" onclick=\"saleClearAdd()\">Xo\u00e1 tr\u1eafng<\/button><br \/>\n          <span id=\"a-st\" style=\"font-size:12px;color:#757575\"><\/span>\n        <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<p><!-- ASSIGN MODAL --><\/p>\n<div class=\"assign-modal\" id=\"assign-modal\">\n<div class=\"assign-box\">\n<div style=\"font-size:15px;font-weight:bold;margin-bottom:4px\" id=\"am-name\"><\/div>\n<div style=\"font-size:12px;color:#9E9E9E;margin-bottom:16px\" id=\"am-meta\"><\/div>\n<div class=\"f\"><label>G\u00e1n cho sale<\/label><select id=\"am-sale\" style=\"margin-bottom:12px\"><\/select><\/div>\n<div class=\"f\"><label>Ghi ch\u00fa cho sale (tu\u1ef3 ch\u1ecdn)<\/label><textarea id=\"am-note\" placeholder=\"Lead hot, li\u00ean h\u1ec7 ngay...\"><\/textarea><\/div>\n<div style=\"display:flex;gap:8px;margin-top:14px\">\n      <button class=\"btn p\" onclick=\"confirmAssign()\">G\u00e1n lead<\/button><br \/>\n      <button class=\"btn\" onclick=\"closeAssign()\">Hu\u1ef7<\/button>\n    <\/div>\n<\/p><\/div>\n<\/div>\n<div class=\"toast\" id=\"toast\"><\/div>\n<p><script>\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ GOOGLE SHEETS API \u2014 kh\u00f4ng c\u1ea7n Apps Script\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550<\/p>\n<p>const SL={new:'M\u1edbi',assigned:'\u0110\u00e3 g\u00e1n',consulting:'\u0110ang t\u01b0 v\u1ea5n',proposal:'\u0110\u00e3 b\u00e1o gi\u00e1',wait:'Ch\u1edd ph\u1ea3n h\u1ed3i',closed:'Ch\u1ed1t deal',lost:'Kh\u00f4ng ti\u1ebfp t\u1ee5c',problem:'C\u1ea7n h\u1ed7 tr\u1ee3'};\nconst SB={new:'b-new',assigned:'b-assigned',consulting:'b-consulting',proposal:'b-proposal',wait:'b-wait',closed:'b-closed',lost:'b-lost',problem:'b-problem'};\nconst PL={hot:'Hot',warm:'Warm',cold:'Cold'};\nconst PC={hot:'hot',warm:'warm',cold:'cold'};<\/p>\n<p>let CU=null,CR=null,leads=[],saleList=[],assigningId=null;<\/p>\n<p>\/\/ \u2500\u2500 SHEETS API HELPERS \u2500\u2500\nconst BASE = 'https:\/\/sheets.googleapis.com\/v4\/spreadsheets\/'+CONFIG.SHEET_ID;<\/p>\n<p>async function sheetRead(range){\n  const url=BASE+'\/values\/'+encodeURIComponent(range)+'?key='+CONFIG.API_KEY;\n  const r=await fetch(url);\n  if(!r.ok) throw new Error('Read failed: '+r.status);\n  const d=await r.json();\n  return d.values||[];\n}<\/p>\n<p>async function sheetAppend(range, values){\n  const url=BASE+'\/values\/'+encodeURIComponent(range)+':append?valueInputOption=RAW&#038;key='+CONFIG.API_KEY;\n  const r=await fetch(url,{\n    method:'POST',\n    headers:{'Content-Type':'application\/json','Authorization':'Bearer '+await getToken()},\n    body:JSON.stringify({values})\n  });\n  if(!r.ok) throw new Error('Append failed: '+r.status);\n  return r.json();\n}<\/p>\n<p>async function sheetUpdate(range, values){\n  const url=BASE+'\/values\/'+encodeURIComponent(range)+'?valueInputOption=RAW&#038;key='+CONFIG.API_KEY;\n  const r=await fetch(url,{\n    method:'PUT',\n    headers:{'Content-Type':'application\/json','Authorization':'Bearer '+await getToken()},\n    body:JSON.stringify({values})\n  });\n  if(!r.ok) throw new Error('Update failed: '+r.status);\n  return r.json();\n}<\/p>\n<p>\/\/ OAuth token via Google Identity Services\nlet _token=null, _tokenExpiry=0;\nasync function getToken(){\n  if(_token &#038;& Date.now()<_tokenExpiry) return _token;\n  return new Promise((resolve,reject)=>{\n    if(!window.google||!window.google.accounts){\n      reject(new Error('Google Identity Services ch\u01b0a load'));return;\n    }\n    const client=google.accounts.oauth2.initTokenClient({\n      client_id: CONFIG.CLIENT_ID||'',\n      scope:'https:\/\/www.googleapis.com\/auth\/spreadsheets',\n      callback:(resp)=>{\n        if(resp.error){reject(new Error(resp.error));return;}\n        _token=resp.access_token;\n        _tokenExpiry=Date.now()+(resp.expires_in-60)*1000;\n        resolve(_token);\n      }\n    });\n    client.requestAccessToken({prompt:''});\n  });\n}<\/p>\n<p>\/\/ \u2500\u2500 PARSE LEADS FROM SHEET \u2500\u2500\nconst COLS=['id','name','phone','zalo','email','source','type','area','address',\n  'status','priority','sale','assignedAt','mktNote',\n  'style','occupants','realBudget','budgetSource','decisionMaker',\n  'concern','material','priorityRoom','competitors','constructionTime',\n  'saleNote','logs','createdAt'];<\/p>\n<p>function parseLeads(rows){\n  if(!rows.length) return [];\n  const headers=rows[0].map(h=>String(h).trim());\n  return rows.slice(1).map(r=>{\n    const obj={};\n    COLS.forEach(k=>{\n      const i=headers.indexOf(k);\n      const v=(i>=0&#038;&i<r.length)?r[i]:'';\n      if(k==='logs'){try{obj[k]=JSON.parse(v||'[]')}catch(e){obj[k]=[]}}\n      else obj[k]=String(v||'');\n    });\n    return obj;\n  }).filter(l=>l.id);\n}<\/p>\n<p>function leadToRow(l){\n  return COLS.map(k=>k==='logs'?JSON.stringify(l[k]||[]):(l[k]||''));\n}<\/p>\n<p>\/\/ \u2500\u2500 LOAD DATA \u2500\u2500\nasync function loadLeads(){\n  try{\n    const rows=await sheetRead(CONFIG.LEADS_SHEET);\n    leads=parseLeads(rows);\n    return leads;\n  }catch(e){\n    \/\/ Sheet ch\u01b0a c\u00f3 header \u2014 t\u1ea1o m\u1edbi\n    if(e.message.includes('400')||e.message.includes('404')||leads.length===0){\n      leads=[];return leads;\n    }\n    throw e;\n  }\n}<\/p>\n<p>async function ensureLeadHeader(){\n  try{\n    const rows=await sheetRead(CONFIG.LEADS_SHEET+'!A1:A1');\n    if(!rows.length||!rows[0][0]){\n      await sheetAppend(CONFIG.LEADS_SHEET+'!A1', [COLS]);\n    }\n  }catch(e){\n    \/\/ Sheet doesn't exist yet \u2014 append will create it\n  }\n}<\/p>\n<p>async function saveLeadToSheet(lead){\n  try{\n    await ensureLeadHeader();\n    const rows=await sheetRead(CONFIG.LEADS_SHEET);\n    if(rows.length<=1){\n      \/\/ No data rows\n      await sheetAppend(CONFIG.LEADS_SHEET, [leadToRow(lead)]);\n      return;\n    }\n    const headers=rows[0].map(h=>String(h).trim());\n    const idCol=headers.indexOf('id');\n    let foundRow=-1;\n    for(let i=1;i<rows.length;i++){\n      if(rows[i][idCol]===String(lead.id)){foundRow=i+1;break;}\n    }\n    const row=leadToRow(lead);\n    if(foundRow>0){\n      await sheetUpdate(CONFIG.LEADS_SHEET+'!A'+foundRow+':'+colLetter(row.length-1)+foundRow,[row]);\n    }else{\n      await sheetAppend(CONFIG.LEADS_SHEET,[row]);\n    }\n  }catch(e){\n    throw e;\n  }\n}<\/p>\n<p>function colLetter(n){\n  let s='';\n  while(n>=0){s=String.fromCharCode(65+(n%26))+s;n=Math.floor(n\/26)-1;}\n  return s;\n}<\/p>\n<p>\/\/ \u2500\u2500 SALES LIST (localStorage) \u2500\u2500\nfunction getSales(){\n  try{return JSON.parse(localStorage.getItem('hd_sales')||'[]')}catch(e){return[]}\n}\nfunction saveSales(list){localStorage.setItem('hd_sales',JSON.stringify(list))}<\/p>\n<p>\/\/ \u2500\u2500 PASSWORDS (localStorage) \u2500\u2500\nfunction getPw(key){return localStorage.getItem('hd_'+key)||CONFIG[key]}\nfunction setPw(key,val){localStorage.setItem('hd_'+key,val)}<\/p>\n<p>\/\/ \u2500\u2500 UTILS \u2500\u2500\nfunction toast(m,d=2200){const el=document.getElementById('toast');el.textContent=m;el.classList.add('show');setTimeout(()=>el.classList.remove('show'),d)}\nfunction fmtD(iso){try{const d=new Date(iso);return d.getDate().toString().padStart(2,'0')+'\/'+(d.getMonth()+1).toString().padStart(2,'0')+' '+d.getHours().toString().padStart(2,'0')+':'+d.getMinutes().toString().padStart(2,'0')}catch(e){return''}}\nfunction getLead(id){return leads.find(x=>String(x.id)===String(id))}<\/p>\n<p>\/\/ \u2500\u2500 LOGIN \u2500\u2500\nlet selR=null;\nfunction selRole(r){\n  selR=r;\n  ['mkt','manager','sale'].forEach(x=>document.getElementById('rb-'+x).classList.toggle('sel',x===r));\n}\nfunction goPin(){\n  if(!selR){document.getElementById('e1').textContent='Ch\u1ecdn vai tr\u00f2 tr\u01b0\u1edbc';return}\n  document.getElementById('s1').classList.remove('show');\n  document.getElementById('s2').classList.add('show');\n  document.getElementById('pin-inp').value='';\n  document.getElementById('e2').textContent='';\n  const sw=document.getElementById('sale-select-wrap');\n  if(selR==='sale'){\n    sw.style.display='block';\n    document.getElementById('pin-lbl').textContent='Nh\u1eadp PIN c\u1ee7a b\u1ea1n';\n    const sel=document.getElementById('sale-sel');\n    const sales=getSales();\n    sel.innerHTML='<option value=\"\">-- Ch\u1ecdn t\u00ean --<\/option>'+sales.map(s=>'<option>'+s.name+'<\/option>').join('');\n  }else{\n    sw.style.display='none';\n    document.getElementById('pin-lbl').textContent=selR==='manager'?'M\u1eadt kh\u1ea9u Manager':'M\u1eadt kh\u1ea9u MKT';\n  }\n  setTimeout(()=>document.getElementById('pin-inp').focus(),100);\n}\nfunction backRole(){document.getElementById('s2').classList.remove('show');document.getElementById('s1').classList.add('show');}\nfunction doLogin(){\n  const pin=document.getElementById('pin-inp').value;\n  const sname=selR==='sale'?document.getElementById('sale-sel').value:'';\n  const err=document.getElementById('e2');\n  if(!pin){err.textContent='Nh\u1eadp m\u1eadt kh\u1ea9u \/ PIN';return}\n  if(selR==='sale'&#038;&!sname){err.textContent='Ch\u1ecdn t\u00ean tr\u01b0\u1edbc';return}\n  let ok=false;\n  if(selR==='manager')ok=pin===getPw('MGR_PASS');\n  else if(selR==='mkt')ok=pin===getPw('MKT_PASS');\n  else{\n    const sales=getSales();\n    const s=sales.find(x=>x.name===sname);\n    ok=s&#038;&String(s.pin)===String(pin);\n  }\n  if(!ok){err.textContent='M\u1eadt kh\u1ea9u \/ PIN kh\u00f4ng \u0111\u00fang';return}\n  CU=selR==='sale'?sname:(selR==='manager'?'Manager':'MKT');\n  CR=selR;\n  document.getElementById('login-screen').style.display='none';\n  document.getElementById('app').style.display='block';\n  document.getElementById('user-name').textContent=CU;\n  document.getElementById('role-chip').textContent=CR==='manager'?'Manager':CR==='mkt'?'MKT':'Sale';\n  saleList=getSales();\n  if(CR==='mkt'){document.getElementById('mkt-app').classList.add('on');}\n  else if(CR==='manager'){document.getElementById('mgr-app').classList.add('on');reloadMgr();}\n  else{document.getElementById('sale-app').classList.add('on');reloadSale();}\n}\nfunction logout(){\n  CU=null;CR=null;leads=[];\n  document.getElementById('app').style.display='none';\n  ['mkt-app','mgr-app','sale-app'].forEach(id=>document.getElementById(id).classList.remove('on'));\n  document.getElementById('s2').classList.remove('show');\n  document.getElementById('s1').classList.add('show');\n  ['mkt','manager','sale'].forEach(x=>document.getElementById('rb-'+x).classList.remove('sel'));\n  selR=null;\n  document.getElementById('login-screen').style.display='flex';\n}<\/p>\n<p>\/\/ \u2500\u2500 RELOAD \u2500\u2500\nasync function reloadMgr(){\n  try{\n    await loadLeads();\n    renderOverview();renderPipeline();renderAssign();\n  }catch(e){toast('L\u1ed7i t\u1ea3i: '+e.message,4000);}\n}\nasync function reloadSale(){\n  try{\n    await loadLeads();\n    renderSaleLeads();\n  }catch(e){toast('L\u1ed7i t\u1ea3i: '+e.message,4000);}\n}<\/p>\n<p>\/\/ \u2500\u2500 MKT \u2500\u2500\nfunction mktTab(t){\n  document.querySelectorAll('#mkt-app .ntab').forEach(el=>el.classList.toggle('on',el.getAttribute('onclick').includes(\"'\"+t+\"'\")));\n  document.getElementById('mkt-form').classList.toggle('on',t==='form');\n  document.getElementById('mkt-list').classList.toggle('on',t==='list');\n  if(t==='list'){\n    loadLeads().then(renderMktList).catch(e=>toast('L\u1ed7i: '+e.message));\n  }\n}\nasync function mktSubmit(){\n  const name=document.getElementById('m-name').value.trim();\n  const phone=document.getElementById('m-phone').value.trim();\n  const src=document.getElementById('m-source').value;\n  if(!name||!phone||!src){toast('C\u1ea7n \u0111i\u1ec1n h\u1ecd t\u00ean, S\u0110T v\u00e0 ngu\u1ed3n lead');return}\n  const st=document.getElementById('mkt-st');st.textContent='\u0110ang l\u01b0u...';\n  const lead={id:Date.now(),name,phone,\n    zalo:document.getElementById('m-zalo').value.trim(),\n    email:document.getElementById('m-email').value.trim(),\n    source:src,type:document.getElementById('m-type').value,\n    area:document.getElementById('m-area').value,\n    address:document.getElementById('m-address').value.trim(),\n    budget:document.getElementById('m-budget').value,\n    timeline:document.getElementById('m-timeline').value,\n    mktNote:document.getElementById('m-note').value.trim(),\n    status:'new',priority:'warm',sale:'',assignedAt:'',\n    style:'',occupants:'',realBudget:'',budgetSource:'',decisionMaker:'',\n    concern:'',material:'',priorityRoom:'',competitors:'',constructionTime:'',\n    saleNote:'',logs:JSON.stringify([{date:new Date().toISOString(),by:'MKT',note:'T\u1ea1o lead',status:'new'}]),\n    createdAt:new Date().toISOString()\n  };\n  try{\n    await saveLeadToSheet(lead);\n    leads.unshift(lead);mktClear();st.textContent='';toast('\u0110\u00e3 l\u01b0u: '+name);\n  }catch(e){st.textContent='L\u1ed7i: '+e.message;toast('L\u1ed7i l\u01b0u: '+e.message,4000);}\n}\nfunction mktClear(){\n  ['m-name','m-phone','m-zalo','m-email','m-area','m-address','m-note'].forEach(id=>{const el=document.getElementById(id);if(el)el.value=''});\n  ['m-source','m-type','m-budget','m-timeline'].forEach(id=>{const el=document.getElementById(id);if(el)el.selectedIndex=0});\n}\nfunction renderMktList(){\n  const el=document.getElementById('mkt-list-content');\n  const list=leads.slice().sort((a,b)=>b.createdAt>a.createdAt?1:-1);\n  if(!list.length){el.innerHTML='<\/p>\n<div class=\"empty\">Ch\u01b0a c\u00f3 lead n\u00e0o<\/div>\n<p>';return}\n  el.innerHTML='<\/p>\n<table class=\"tbl\">\n<thead>\n<tr>\n<th>H\u1ecd t\u00ean<\/th>\n<th>S\u0110T<\/th>\n<th>Ngu\u1ed3n<\/th>\n<th>Lo\u1ea1i CT<\/th>\n<th>Tr\u1ea1ng th\u00e1i<\/th>\n<th>Sale<\/th>\n<th>Ng\u00e0y t\u1ea1o<\/th>\n<\/tr>\n<\/thead>\n<tbody>'+\n    list.map(l=>'<\/p>\n<tr>\n<td style=\"font-weight:bold\">'+l.name+'<\/td>\n<td>'+l.phone+'<\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:12px\">'+(l.source||'\u2014')+'<\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:12px\">'+(l.type||'\u2014')+(l.area?' \u00b7 '+l.area+'m\u00b2':'')+'<\/td>\n<p>'+\n      '<\/p>\n<td><span class=\"badge '+(SB[l.status]||'b-new')+'\">'+(SL[l.status]||l.status)+'<\/span><\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:12px\">'+(l.sale||'<span style=\"color:#EF9F27\">Ch\u01b0a g\u00e1n<\/span>')+'<\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:11px;color:#9E9E9E\">'+fmtD(l.createdAt)+'<\/td>\n<\/tr>\n<p>').join('')+\n    '<\/tbody>\n<\/table>\n<p>';\n}<\/p>\n<p>\/\/ \u2500\u2500 MANAGER \u2500\u2500\nfunction mgrTab(t){\n  document.querySelectorAll('#mgr-app .ntab').forEach(el=>el.classList.toggle('on',el.getAttribute('onclick').includes(\"'\"+t+\"'\")));\n  ['mgr-overview','mgr-assign','mgr-pipeline','mgr-settings'].forEach(id=>document.getElementById(id).classList.remove('on'));\n  document.getElementById('mgr-'+t).classList.add('on');\n  if(t==='settings')renderSettings();\n  else renderByTab(t);\n}\nfunction renderByTab(t){\n  if(t==='overview')renderOverview();\n  if(t==='assign')renderAssign();\n  if(t==='pipeline')renderPipeline();\n}\nfunction renderOverview(){\n  const t=leads.length;\n  const unassigned=leads.filter(l=>l.status==='new').length;\n  const active=leads.filter(l=>!['closed','lost','new'].includes(l.status)).length;\n  const proposal=leads.filter(l=>l.status==='proposal').length;\n  const closed=leads.filter(l=>l.status==='closed').length;\n  const problems=leads.filter(l=>l.status==='problem'||(l.concern&#038;&l.concern.trim())).length;\n  document.getElementById('mgr-stats').innerHTML=\n    sc(t,'T\u1ed5ng lead')+sc(unassigned,'Ch\u1edd g\u00e1n sale',unassigned>0)+\n    sc(active,'\u0110ang x\u1eed l\u00fd')+sc(proposal,'\u0110\u00e3 b\u00e1o gi\u00e1')+\n    sc(closed,'Ch\u1ed1t deal')+sc(problems,'C\u1ea7n h\u1ed7 tr\u1ee3',problems>0);\n  const sm={};\n  leads.filter(l=>l.sale).forEach(l=>{\n    if(!sm[l.sale])sm[l.sale]={total:0,active:0,proposal:0,closed:0};\n    sm[l.sale].total++;\n    if(!['closed','lost','new'].includes(l.status))sm[l.sale].active++;\n    if(l.status==='proposal')sm[l.sale].proposal++;\n    if(l.status==='closed')sm[l.sale].closed++;\n  });\n  document.getElementById('sale-perf').innerHTML=Object.entries(sm).map(([n,d])=>\n    '<\/p>\n<div class=\"sp-card\">\n<div class=\"sp-name\">'+n+'<\/div>\n<p>'+\n    '<\/p>\n<div class=\"sp-row\"><span>T\u1ed5ng lead<\/span><b>'+d.total+'<\/b><\/div>\n<p>'+\n    '<\/p>\n<div class=\"sp-row\"><span>\u0110ang x\u1eed l\u00fd<\/span><b>'+d.active+'<\/b><\/div>\n<p>'+\n    '<\/p>\n<div class=\"sp-row\"><span>\u0110\u00e3 b\u00e1o gi\u00e1<\/span><b>'+d.proposal+'<\/b><\/div>\n<p>'+\n    '<\/p>\n<div class=\"sp-row\"><span>Ch\u1ed1t deal<\/span><b>'+d.closed+'<\/b><\/div>\n<p>'+\n    '<\/p>\n<div class=\"sp-row\"><span>T\u1ef7 l\u1ec7 ch\u1ed1t<\/span><b>'+(d.total>0?Math.round(d.closed\/d.total*100):0)+'%<\/b><\/div>\n<p>'+\n    '<\/p><\/div>\n<p>').join('')||'<\/p>\n<div style=\"color:#9E9E9E;font-size:13px\">Ch\u01b0a c\u00f3 lead n\u00e0o \u0111\u01b0\u1ee3c g\u00e1n<\/div>\n<p>';\n  const pl=leads.filter(l=>l.status==='problem'||(l.concern&#038;&l.concern.trim()));\n  document.getElementById('problems-table').innerHTML=pl.length?\n    '<\/p>\n<thead>\n<tr>\n<th>H\u1ecd t\u00ean<\/th>\n<th>Sale<\/th>\n<th>Tr\u1ea1ng th\u00e1i<\/th>\n<th>V\u1ea5n \u0111\u1ec1 sale b\u00e1o c\u00e1o<\/th>\n<\/tr>\n<\/thead>\n<p>'+\n    '<\/p>\n<tbody>'+pl.map(l=>'<\/p>\n<tr>\n<td style=\"font-weight:bold\">'+l.name+'<\/td>\n<td>'+(l.sale||'\u2014')+'<\/td>\n<p>'+\n      '<\/p>\n<td><span class=\"badge '+(SB[l.status]||'b-new')+'\">'+(SL[l.status]||l.status)+'<\/span><\/td>\n<p>'+\n      '<\/p>\n<td style=\"color:#C62828;font-weight:500\">'+(l.concern||'\u2014')+'<\/td>\n<\/tr>\n<p>').join('')+'<\/tbody>\n<p>':\n    '<\/p>\n<tbody>\n<tr>\n<td colspan=\"4\" style=\"text-align:center;color:#9E9E9E;padding:20px\">Kh\u00f4ng c\u00f3 v\u1ea5n \u0111\u1ec1 n\u00e0o<\/td>\n<\/tr>\n<\/tbody>\n<p>';\n}\nfunction sc(n,label,warn=false){\n  return'<\/p>\n<div class=\"sc'+(warn?' warn':'')+'\">\n<div class=\"sc-n\">'+n+'<\/div>\n<div class=\"sc-l\">'+(warn?'\u26a0 ':'')+label+'<\/div>\n<\/div>\n<p>';\n}\nfunction renderAssign(){\n  const newLeads=leads.filter(l=>l.status==='new');\n  const el=document.getElementById('assign-table');\n  if(!newLeads.length){el.innerHTML='<\/p>\n<tbody>\n<tr>\n<td colspan=\"6\" style=\"text-align:center;color:#9E9E9E;padding:24px\">Kh\u00f4ng c\u00f3 lead m\u1edbi n\u00e0o<\/td>\n<\/tr>\n<\/tbody>\n<p>';return}\n  el.innerHTML='<\/p>\n<thead>\n<tr>\n<th>H\u1ecd t\u00ean<\/th>\n<th>S\u0110T<\/th>\n<th>Ngu\u1ed3n<\/th>\n<th>Lo\u1ea1i CT<\/th>\n<th>Budget<\/th>\n<th>H\u00e0nh \u0111\u1ed9ng<\/th>\n<\/tr>\n<\/thead>\n<p>'+\n    '<\/p>\n<tbody>'+newLeads.map(l=>'<\/p>\n<tr style=\"background:#FFFDE7\">'+\n      '<\/p>\n<td style=\"font-weight:bold\">'+l.name+'<\/td>\n<td>'+l.phone+'<\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:12px\">'+(l.source||'\u2014')+'<\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:12px\">'+(l.type||'\u2014')+(l.area?' \u00b7 '+l.area+'m\u00b2':'')+'<\/td>\n<p>'+\n      '<\/p>\n<td style=\"font-size:12px\">'+(l.budget||'\u2014')+'<\/td>\n<p>'+\n      '<\/p>\n<td><button class=\"btn sm p\" onclick=\"openAssign(\\''+l.id+'\\')\">G\u00e1n sale \u2192<\/button><\/td>\n<\/tr>\n<p>').join('')+\n    '<\/tbody>\n<p>';\n}\nfunction renderPipeline(){\n  const sf=document.getElementById('pf-status').value;\n  const ss=document.getElementById('pf-sale').value;\n  const sq=(document.getElementById('pf-q').value||'').toLowerCase();\n  const sel=document.getElementById('pf-sale');const cur=sel.value;\n  const names=[...new Set(leads.filter(l=>l.sale).map(l=>l.sale))];\n  sel.innerHTML='<option value=\"\">T\u1ea5t c\u1ea3 sale<\/option>'+names.map(n=>'<option'+(n===cur?' selected':'')+'>'+n+'<\/option>').join('');\n  const list=leads.filter(l=>{\n    if(sf&#038;&l.status!==sf)return false;\n    if(ss&#038;&l.sale!==ss)return false;\n    if(sq&#038;&!(l.name||'').toLowerCase().includes(sq)&#038;&!(l.phone||'').includes(sq))return false;\n    return true;\n  });\n  const rows=list.map(l=>'<\/p>\n<tr>'+\n    '<\/p>\n<td style=\"font-weight:bold\">'+l.name+'<\/td>\n<td>'+l.phone+'<\/td>\n<p>'+\n    '<\/p>\n<td><span class=\"badge '+(SB[l.status]||'b-new')+'\">'+(SL[l.status]||l.status)+'<\/span><\/td>\n<p>'+\n    '<\/p>\n<td>'+(l.sale||'<span style=\"color:#E65100\">Ch\u01b0a g\u00e1n<\/span>')+'<\/td>\n<p>'+\n    '<\/p>\n<td style=\"font-size:12px\">'+(l.type||'\u2014')+(l.area?' \u00b7 '+l.area+'m\u00b2':'')+'<\/td>\n<p>'+\n    '<\/p>\n<td style=\"font-size:12px\">'+(l.budget||'\u2014')+'<\/td>\n<p>'+\n    '<\/p>\n<td style=\"font-size:12px;color:#C62828\">'+(l.concern||'')+'<\/td>\n<\/tr>\n<p>').join('');\n  document.getElementById('pipeline-table').innerHTML=\n    '<\/p>\n<thead>\n<tr>\n<th>H\u1ecd t\u00ean<\/th>\n<th>S\u0110T<\/th>\n<th>Tr\u1ea1ng th\u00e1i<\/th>\n<th>Sale<\/th>\n<th>C\u00f4ng tr\u00ecnh<\/th>\n<th>Budget<\/th>\n<th>V\u1ea5n \u0111\u1ec1<\/th>\n<\/tr>\n<\/thead>\n<p>'+\n    '<\/p>\n<tbody>'+(rows||'<\/p>\n<tr>\n<td colspan=\"7\" style=\"text-align:center;color:#9E9E9E;padding:24px\">Kh\u00f4ng c\u00f3 lead n\u00e0o<\/td>\n<\/tr>\n<p>')+'<\/tbody>\n<p>';\n}\nfunction renderSettings(){\n  const sales=getSales();\n  const el=document.getElementById('sale-list-el');\n  el.innerHTML=sales.length?sales.map(s=>\n    '<\/p>\n<div class=\"sale-li\">\n<div><b>'+s.name+'<\/b><\/div>\n<p>'+\n    '<\/p>\n<div style=\"display:flex;gap:6px\">'+\n      '<input type=\"password\" id=\"ep-'+s.name+'\" placeholder=\"PIN m\u1edbi\" maxlength=\"6\" style=\"width:80px;padding:4px 8px;font-size:12px\">'+\n      '<button class=\"btn xs\" onclick=\"updatePin(\\''+s.name+'\\')\">\u0110\u1ed5i PIN<\/button>'+\n      '<button class=\"btn xs d\" onclick=\"removeSale(\\''+s.name+'\\')\">Xo\u00e1<\/button>'+\n    '<\/div>\n<\/div>\n<p>').join(''):\n    '<\/p>\n<div style=\"color:#9E9E9E;font-size:13px;padding:8px 0\">Ch\u01b0a c\u00f3 sale n\u00e0o<\/div>\n<p>';\n}\nfunction addSale(){\n  const n=document.getElementById('ns-name').value.trim();\n  const p=document.getElementById('ns-pin').value.trim();\n  if(!n||!p){toast('Nh\u1eadp \u0111\u1ee7 t\u00ean v\u00e0 PIN');return}\n  const sales=getSales();\n  if(sales.find(s=>s.name===n)){toast('T\u00ean \u0111\u00e3 t\u1ed3n t\u1ea1i');return}\n  sales.push({name:n,pin:p});saveSales(sales);saleList=sales;\n  document.getElementById('ns-name').value='';document.getElementById('ns-pin').value='';\n  renderSettings();toast('\u0110\u00e3 th\u00eam: '+n);\n}\nfunction updatePin(name){\n  const p=document.getElementById('ep-'+name).value.trim();\n  if(!p){toast('Nh\u1eadp PIN m\u1edbi');return}\n  const sales=getSales();const s=sales.find(x=>x.name===name);\n  if(s){s.pin=p;saveSales(sales);document.getElementById('ep-'+name).value='';toast('\u0110\u00e3 \u0111\u1ed5i PIN: '+name);}\n}\nfunction removeSale(name){\n  if(!confirm('Xo\u00e1 sale \"'+name+'\"?'))return;\n  saveSales(getSales().filter(s=>s.name!==name));renderSettings();toast('\u0110\u00e3 xo\u00e1: '+name);\n}\nfunction changePw(key,id1,id2){\n  const p1=document.getElementById(id1).value;\n  const p2=document.getElementById(id2).value;\n  const err=document.getElementById('pw-err');\n  if(!p1){err.textContent='Nh\u1eadp m\u1eadt kh\u1ea9u m\u1edbi';return}\n  if(p1!==p2){err.textContent='Kh\u00f4ng kh\u1edbp';return}\n  setPw(key,p1);document.getElementById(id1).value='';document.getElementById(id2).value='';\n  err.textContent='';toast('\u0110\u00e3 \u0111\u1ed5i m\u1eadt kh\u1ea9u');\n}<\/p>\n<p>\/\/ \u2500\u2500 ASSIGN \u2500\u2500\nfunction openAssign(id){\n  assigningId=id;const l=getLead(id);if(!l)return;\n  document.getElementById('am-name').textContent=l.name;\n  document.getElementById('am-meta').textContent=l.phone+(l.type?' \u00b7 '+l.type:'')+(l.budget?' \u00b7 '+l.budget:'');\n  document.getElementById('am-note').value='';\n  const sel=document.getElementById('am-sale');\n  sel.innerHTML='<option value=\"\">-- Ch\u1ecdn sale --<\/option>'+getSales().map(s=>'<option>'+s.name+'<\/option>').join('');\n  document.getElementById('assign-modal').classList.add('open');\n}\nfunction closeAssign(){document.getElementById('assign-modal').classList.remove('open');assigningId=null;}\nasync function confirmAssign(){\n  const sale=document.getElementById('am-sale').value;\n  const note=document.getElementById('am-note').value.trim();\n  if(!sale){toast('Ch\u1ecdn sale tr\u01b0\u1edbc');return}\n  const l=getLead(assigningId);if(!l)return;\n  l.sale=sale;l.status='assigned';l.assignedAt=new Date().toISOString();\n  const logs=typeof l.logs==='string'?JSON.parse(l.logs||'[]'):l.logs||[];\n  logs.push({date:new Date().toISOString(),by:'Manager',note:'G\u00e1n cho '+sale+(note?' \u2014 '+note:''),status:'assigned'});\n  l.logs=JSON.stringify(logs);\n  try{\n    await saveLeadToSheet(l);\n    closeAssign();renderOverview();renderAssign();renderPipeline();\n    toast('\u0110\u00e3 g\u00e1n '+l.name+' \u2192 '+sale);\n  }catch(e){toast('L\u1ed7i: '+e.message,4000);}\n}<\/p>\n<p>\/\/ \u2500\u2500 SALE \u2500\u2500\nfunction saleTab(t){\n  document.querySelectorAll('#sale-app .ntab').forEach(el=>el.classList.toggle('on',el.getAttribute('onclick').includes(\"'\"+t+\"'\")));\n  document.getElementById('sale-leads').classList.toggle('on',t==='leads');\n  document.getElementById('sale-add').classList.toggle('on',t==='add');\n  if(t==='leads')renderSaleLeads();\n}\nfunction renderSaleLeads(){\n  const my=leads.filter(l=>l.sale===CU);\n  const t=my.length,a=my.filter(l=>!['closed','lost'].includes(l.status)).length;\n  const p=my.filter(l=>l.status==='proposal').length,c=my.filter(l=>l.status==='closed').length;\n  document.getElementById('sale-stats').innerHTML=\n    sc(t,'Kh\u00e1ch c\u1ee7a t\u00f4i')+sc(a,'\u0110ang x\u1eed l\u00fd')+sc(p,'\u0110\u00e3 b\u00e1o gi\u00e1')+sc(c,'Ch\u1ed1t deal');\n  const sf=document.getElementById('sf-status').value;\n  const sq=(document.getElementById('sf-q').value||'').toLowerCase();\n  const list=my.filter(l=>{\n    if(sf&#038;&l.status!==sf)return false;\n    if(sq&#038;&!(l.name||'').toLowerCase().includes(sq)&#038;&!(l.phone||'').includes(sq))return false;\n    return true;\n  });\n  const el=document.getElementById('sale-lead-list');\n  if(!list.length){el.innerHTML='<\/p>\n<div class=\"empty\">Kh\u00f4ng c\u00f3 kh\u00e1ch n\u00e0o<\/div>\n<p>';return}\n  el.innerHTML=list.map(l=>buildCard(l)).join('');\n}\nfunction buildCard(l){\n  const logs=typeof l.logs==='string'?JSON.parse(l.logs||'[]'):l.logs||[];\n  return'<\/p>\n<div class=\"lead-card-wrap\" id=\"wrap-'+l.id+'\">'+\n    '<\/p>\n<div class=\"lead-card '+(PC[l.priority]||'warm')+'\" onclick=\"toggleCard(\\''+l.id+'\\')\">'+\n      '<\/p>\n<div style=\"flex:1\">'+\n        '<\/p>\n<div class=\"lc-name\">'+l.name+'<\/div>\n<p>'+\n        '<\/p>\n<div class=\"lc-meta\">'+l.phone+(l.source?' \u00b7 '+l.source:'')+'<\/div>\n<p>'+\n        (l.mktNote?'<\/p>\n<div class=\"lc-meta\" style=\"font-style:italic\">MKT: '+l.mktNote+'<\/div>\n<p>':'')+\n        '<\/p>\n<div class=\"lc-tags\">'+\n          (l.type?'<span class=\"tag-info\">'+l.type+(l.area?' \u00b7 '+l.area+'m\u00b2':'')+'<\/span>':'')+\n          (l.budget?'<span class=\"tag-info\">'+l.budget+'<\/span>':'')+\n          (l.concern?'<span class=\"badge b-problem\" style=\"font-size:10px\">\u26a0 '+l.concern+'<\/span>':'')+\n        '<\/div>\n<p>'+\n      '<\/p><\/div>\n<p>'+\n      '<\/p>\n<div class=\"lc-right\">'+\n        '<span class=\"badge '+(SB[l.status]||'b-new')+'\">'+(SL[l.status]||l.status)+'<\/span>'+\n        '<span style=\"font-size:12px;color:#9E9E9E\" id=\"arr-'+l.id+'\">\u203a Chi ti\u1ebft<\/span>'+\n      '<\/div>\n<p>'+\n    '<\/p><\/div>\n<p>'+\n    '<\/p>\n<div class=\"lead-detail\" id=\"det-'+l.id+'\">'+\n      '<\/p>\n<div class=\"det-tabs\">'+\n        '<button class=\"det-tab on\" id=\"dtab-info-'+l.id+'\" onclick=\"detTab(\\''+l.id+'\\',\\'info\\')\">Th\u00f4ng tin<\/button>'+\n        '<button class=\"det-tab\" id=\"dtab-log-'+l.id+'\" onclick=\"detTab(\\''+l.id+'\\',\\'log\\')\">L\u1ecbch s\u1eed<\/button>'+\n      '<\/div>\n<p>'+\n      '<\/p>\n<div id=\"dpane-info-'+l.id+'\" class=\"dpane on\">'+buildInfoPane(l)+'<\/div>\n<p>'+\n      '<\/p>\n<div id=\"dpane-log-'+l.id+'\" class=\"dpane\">'+buildLogPane(l,logs)+'<\/div>\n<p>'+\n    '<\/p><\/div>\n<p>'+\n  '<\/p><\/div>\n<p>';\n}\nfunction buildInfoPane(l){\n  return'<\/p>\n<div class=\"det-sec\">Tr\u1ea1ng th\u00e1i<\/div>\n<p>'+\n    '<\/p>\n<div class=\"status-bar s-'+l.status+'\" id=\"sbar-'+l.id+'\">'+\n      ['assigned','consulting','proposal','wait','closed','lost','problem'].map(s=>\n        '<\/p>\n<div class=\"status-opt'+(l.status===s?' sel':'')+'\" data-s=\"'+s+'\" onclick=\"setStatus(\\''+l.id+'\\',\\''+s+'\\')\">'+SL[s]+'<\/div>\n<p>'\n      ).join('')+\n    '<\/p><\/div>\n<p>'+\n    '<\/p>\n<div class=\"g2\" style=\"margin-top:10px\">'+\n      '<\/p>\n<div class=\"f\"><label>\u01afu ti\u00ean<\/label>'+\n        '<select onchange=\"upField(\\''+l.id+'\\',\\'priority\\',this.value)\">'+\n          '<option value=\"hot\"'+(l.priority==='hot'?' selected':'')+'>\ud83d\udd34 Hot<\/option>'+\n          '<option value=\"warm\"'+(l.priority==='warm'?' selected':'')+'>\ud83d\udfe1 Warm<\/option>'+\n          '<option value=\"cold\"'+(l.priority==='cold'?' selected':'')+'>\ud83d\udd35 Cold<\/option>'+\n        '<\/select><\/div>\n<p>'+\n      '<\/p>\n<div class=\"f\"><label>V\u1ea5n \u0111\u1ec1 c\u1ea7n h\u1ed7 tr\u1ee3 Manager<\/label>'+\n        '<input type=\"text\" id=\"d-concern-'+l.id+'\" value=\"'+(l.concern||'')+'\" placeholder=\"Ghi ng\u1eafn \u0111\u1ec3 Manager th\u1ea5y...\" onchange=\"upField(\\''+l.id+'\\',\\'concern\\',this.value)\">'+\n      '<\/div>\n<p>'+\n    '<\/p><\/div>\n<p>'+\n    '<\/p>\n<div class=\"det-sec\">Th\u00f4ng tin t\u1eeb MKT<\/div>\n<p>'+\n    '<\/p>\n<div class=\"mkt-info-row\">'+\n      mktChip('Lo\u1ea1i CT',l.type+(l.area?' \u00b7 '+l.area+'m\u00b2':''))+\n      mktChip('\u0110\u1ecba ch\u1ec9',l.address)+mktChip('Budget',l.budget)+mktChip('Timeline',l.timeline)+\n    '<\/div>\n<p>'+(l.mktNote?'<\/p>\n<div style=\"font-size:12px;background:#FFF8E1;border-left:3px solid #EF9F27;padding:8px 12px;border-radius:0 4px 4px 0;margin-bottom:8px;font-style:italic\">'+l.mktNote+'<\/div>\n<p>':'')+\n    '<\/p>\n<div class=\"det-sec\">Khai th\u00e1c s\u00e2u<\/div>\n<p>'+\n    field('d-style-'+l.id,'Phong c\u00e1ch \/ style',l.style,'Japandi, Hi\u1ec7n \u0111\u1ea1i, Indochine...')+\n    '<\/p>\n<div class=\"g2\">'+\n      field('d-occupants-'+l.id,'Th\u00e0nh ph\u1ea7n gia \u0111\u00ecnh',l.occupants,'VD: 4 ng\u01b0\u1eddi, v\u1ee3 ch\u1ed3ng + 2 con nh\u1ecf')+\n      field('d-priorityRoom-'+l.id,'Ph\u00f2ng \u01b0u ti\u00ean \u0111\u1ea7u t\u01b0',l.priorityRoom,'VD: Ph\u00f2ng kh\u00e1ch + b\u1ebfp')+\n    '<\/div>\n<p>'+\n    '<\/p>\n<div class=\"g2\">'+\n      field('d-realBudget-'+l.id,'Budget th\u1ef1c sau trao \u0111\u1ed5i',l.realBudget,'VD: ~800tr, linh ho\u1ea1t th\u00eam 100tr')+\n      field('d-budgetSource-'+l.id,'Ngu\u1ed3n v\u1ed1n &#038; thanh to\u00e1n',l.budgetSource,'VD: Ti\u1ec1n s\u1eb5n \/ Vay 50%')+\n    '<\/div>\n<p>'+\n    '<\/p>\n<div class=\"g2\">'+\n      field('d-decisionMaker-'+l.id,'Ng\u01b0\u1eddi quy\u1ebft \u0111\u1ecbnh cu\u1ed1i',l.decisionMaker,'VD: V\u1ee3 quy\u1ebft \/ C\u1ea3 hai')+\n      field('d-constructionTime-'+l.id,'Timeline th\u1ef1c t\u1ebf',l.constructionTime,'VD: Xong tr\u01b0\u1edbc T\u1ebft')+\n    '<\/div>\n<p>'+\n    '<\/p>\n<div class=\"g2\">'+\n      field('d-material-'+l.id,'V\u1eadt li\u1ec7u y\u00eau th\u00edch \/ kh\u00f4ng mu\u1ed1n',l.material,'VD: Th\u00edch g\u1ed7 t\u1ef1 nhi\u00ean')+\n      field('d-competitors-'+l.id,'\u0110\u00e3 tham kh\u1ea3o \u0111\u01a1n v\u1ecb n\u00e0o',l.competitors,'VD: G\u1eb7p NT A, ch\u01b0a \u01b0ng v\u00ec gi\u00e1 cao')+\n    '<\/div>\n<p>'+\n    '<\/p>\n<div class=\"f\"><label>\u0110i\u1ec1u kh\u00e1ch lo ng\u1ea1i<\/label>'+\n      '<input type=\"text\" id=\"d-concernD-'+l.id+'\" value=\"'+(l.concern||'')+'\" placeholder=\"VD: S\u1ee3 ch\u1eadm ti\u1ebfn \u0111\u1ed9...\" onchange=\"upField(\\''+l.id+'\\',\\'concern\\',this.value)\"><\/div>\n<p>'+\n    '<\/p>\n<div class=\"f\"><label>Ghi ch\u00fa th\u00eam<\/label>'+\n      '<textarea id=\"d-saleNote-'+l.id+'\" style=\"min-height:56px\" onchange=\"upField(\\''+l.id+'\\',\\'saleNote\\',this.value)\">'+(l.saleNote||'')+'<\/textarea><\/div>\n<p>'+\n    '<\/p>\n<div style=\"display:flex;gap:8px;margin-top:12px;padding-top:10px;border-top:1px solid #F0F0F0\">'+\n      '<button class=\"btn p sm\" onclick=\"saveLead(\\''+l.id+'\\')\">L\u01b0u<\/button>'+\n      '<button class=\"btn d xs\" onclick=\"delLead(\\''+l.id+'\\')\">Xo\u00e1 lead<\/button>'+\n      '<span id=\"savest-'+l.id+'\" style=\"font-size:12px;color:#757575\"><\/span>'+\n    '<\/div>\n<p>';\n}\nfunction buildLogPane(l,logs){\n  return'<\/p>\n<div style=\"display:flex;gap:8px;margin-bottom:10px\">'+\n    '<textarea id=\"log-inp-'+l.id+'\" placeholder=\"Ghi n\u1ed9i dung cu\u1ed9c g\u1ecdi \/ g\u1eb7p v\u1eeba xong...\" style=\"flex:1;min-height:56px\"><\/textarea>'+\n    '<button class=\"btn p sm\" style=\"align-self:flex-end\" onclick=\"addLog(\\''+l.id+'\\')\">Ghi<\/button>'+\n    '<\/div>\n<p>'+\n    '<\/p>\n<div id=\"logs-'+l.id+'\">'+buildLogsHtml(logs)+'<\/div>\n<p>';\n}\nfunction buildLogsHtml(logs){\n  if(!logs||!logs.length)return'<\/p>\n<div style=\"color:#9E9E9E;font-size:12px\">Ch\u01b0a c\u00f3 l\u1ecbch s\u1eed<\/div>\n<p>';\n  return logs.slice().reverse().map(g=>\n    '<\/p>\n<div class=\"log-row\"><span class=\"log-date\">'+fmtD(g.date)+'<\/span>'+\n    '<span class=\"log-by\">'+(g.by||'Sale')+'<\/span>'+\n    '<span class=\"log-text\">'+g.note+'<\/span><\/div>\n<p>').join('');\n}\nfunction mktChip(k,v){if(!v)return'';return'<\/p>\n<div class=\"mkt-chip\"><span class=\"mkt-chip-k\">'+k+'<\/span><span class=\"mkt-chip-v\">'+v+'<\/span><\/div>\n<p>';}\nfunction field(id,label,val,ph){return'<\/p>\n<div class=\"f\"><label>'+label+'<\/label><input type=\"text\" id=\"'+id+'\" value=\"'+(val||'')+'\" placeholder=\"'+ph+'\"><\/div>\n<p>';}<\/p>\n<p>function toggleCard(id){\n  const det=document.getElementById('det-'+id);\n  const arr=document.getElementById('arr-'+id);\n  const open=det.classList.toggle('open');\n  arr.textContent=open?'\u2039 Thu g\u1ecdn':'\u203a Chi ti\u1ebft';\n}\nfunction detTab(id,tab){\n  ['info','log'].forEach(t=>{\n    const btn=document.getElementById('dtab-'+t+'-'+id);\n    const pane=document.getElementById('dpane-'+t+'-'+id);\n    if(btn)btn.classList.toggle('on',t===tab);\n    if(pane)pane.classList.toggle('on',t===tab);\n  });\n}\nfunction setStatus(id,s){\n  const l=getLead(id);if(!l)return;\n  l.status=s;\n  const bar=document.getElementById('sbar-'+id);\n  if(bar){bar.className='status-bar s-'+s;bar.querySelectorAll('.status-opt').forEach(el=>el.classList.toggle('sel',el.dataset.s===s));}\n  const card=document.querySelector('#wrap-'+id+' .lead-card');\n  if(card){const b=card.querySelector('.badge');if(b){b.className='badge '+(SB[s]||'');b.textContent=SL[s]||s;}}\n}\nfunction upField(id,field,val){const l=getLead(id);if(l)l[field]=val;}\nfunction collectForm(id){\n  const l=getLead(id);if(!l)return l;\n  const map={style:'d-style-',occupants:'d-occupants-',realBudget:'d-realBudget-',\n    budgetSource:'d-budgetSource-',decisionMaker:'d-decisionMaker-',constructionTime:'d-constructionTime-',\n    priorityRoom:'d-priorityRoom-',material:'d-material-',competitors:'d-competitors-',saleNote:'d-saleNote-'};\n  Object.entries(map).forEach(([f,pre])=>{const el=document.getElementById(pre+id);if(el)l[f]=el.value;});\n  const cd=document.getElementById('d-concernD-'+id);if(cd)l.concern=cd.value;\n  return l;\n}\nasync function saveLead(id){\n  const l=collectForm(id);if(!l)return;\n  const st=document.getElementById('savest-'+id);st.textContent='\u0110ang l\u01b0u...';\n  const logs=typeof l.logs==='string'?JSON.parse(l.logs||'[]'):l.logs||[];\n  logs.push({date:new Date().toISOString(),by:CU,note:'C\u1eadp nh\u1eadt th\u00f4ng tin',status:l.status});\n  l.logs=JSON.stringify(logs);\n  try{\n    await saveLeadToSheet(l);\n    st.textContent='\u0110\u00e3 l\u01b0u \u2713';renderSaleLeads();toast('\u0110\u00e3 l\u01b0u: '+l.name);\n  }catch(e){st.textContent='L\u1ed7i';toast('L\u1ed7i: '+e.message,4000);}\n}\nasync function addLog(id){\n  const l=getLead(id);if(!l)return;\n  const inp=document.getElementById('log-inp-'+id);\n  const note=inp.value.trim();if(!note)return;\n  const logs=typeof l.logs==='string'?JSON.parse(l.logs||'[]'):l.logs||[];\n  logs.push({date:new Date().toISOString(),by:CU,note,status:l.status});\n  l.logs=JSON.stringify(logs);\n  inp.value='';\n  try{\n    await saveLeadToSheet(l);\n    const el=document.getElementById('logs-'+id);\n    if(el)el.innerHTML=buildLogsHtml(logs);\n    toast('\u0110\u00e3 ghi ch\u00fa');\n  }catch(e){toast('L\u1ed7i: '+e.message,4000);}\n}\nasync function delLead(id){\n  \/\/ Mark as deleted by setting status, or actually remove\n  if(!confirm('Xo\u00e1 lead n\u00e0y?'))return;\n  leads=leads.filter(x=>String(x.id)!==String(id));\n  document.getElementById('wrap-'+id)?.remove();\n  renderSaleLeads();toast('\u0110\u00e3 xo\u00e1 kh\u1ecfi view (c\u1ea7n xo\u00e1 th\u1ee7 c\u00f4ng trong Sheets)');\n}\nasync function saleAddLead(){\n  const name=document.getElementById('a-name').value.trim();\n  const phone=document.getElementById('a-phone').value.trim();\n  const src=document.getElementById('a-source').value;\n  if(!name||!phone||!src){toast('C\u1ea7n \u0111i\u1ec1n h\u1ecd t\u00ean, S\u0110T v\u00e0 ngu\u1ed3n lead');return}\n  const st=document.getElementById('a-st');st.textContent='\u0110ang l\u01b0u...';\n  const note=document.getElementById('a-note').value.trim();\n  const status=document.getElementById('a-status').value;\n  const lead={id:Date.now(),name,phone,\n    zalo:document.getElementById('a-zalo').value.trim(),\n    email:document.getElementById('a-email').value.trim(),\n    source:src,type:document.getElementById('a-type').value,\n    area:document.getElementById('a-area').value,\n    address:document.getElementById('a-address').value.trim(),\n    budget:document.getElementById('a-budget').value,\n    timeline:document.getElementById('a-timeline').value,\n    mktNote:'',status,priority:document.getElementById('a-priority').value,\n    sale:CU,assignedAt:new Date().toISOString(),\n    style:'',occupants:'',realBudget:'',budgetSource:'',decisionMaker:'',\n    concern:'',material:'',priorityRoom:'',competitors:'',constructionTime:'',\n    saleNote:'',logs:JSON.stringify([{date:new Date().toISOString(),by:CU,note:note||'T\u1ea1o lead',status}]),\n    createdAt:new Date().toISOString()\n  };\n  try{\n    await saveLeadToSheet(lead);\n    leads.unshift(lead);saleClearAdd();saleTab('leads');st.textContent='';toast('\u0110\u00e3 l\u01b0u: '+name);\n  }catch(e){st.textContent='L\u1ed7i: '+e.message;toast('L\u1ed7i: '+e.message,4000);}\n}\nfunction saleClearAdd(){\n  ['a-name','a-phone','a-zalo','a-email','a-area','a-address','a-note'].forEach(id=>{const el=document.getElementById(id);if(el)el.value=''});\n  ['a-source','a-type','a-budget','a-timeline'].forEach(id=>{const el=document.getElementById(id);if(el)el.selectedIndex=0});\n  document.getElementById('a-status').value='assigned';\n  document.getElementById('a-priority').value='warm';\n}<\/p>\n<p>\/\/ \u2500\u2500 EXPORT CSV \u2500\u2500\nfunction exportCSV(){\n  if(!leads.length){toast('Ch\u01b0a c\u00f3 lead');return}\n  const h=['H\u1ecd t\u00ean','S\u0110T','Ngu\u1ed3n','Lo\u1ea1i CT','Di\u1ec7n t\u00edch','Budget','\u0110\u1ecba ch\u1ec9','Tr\u1ea1ng th\u00e1i','Sale','Phong c\u00e1ch','Budget th\u1ef1c','Ng\u00e0y t\u1ea1o'];\n  const rows=leads.map(l=>[l.name,l.phone,l.source||'',l.type||'',l.area||'',l.budget||'',l.address||'',SL[l.status]||l.status,l.sale||'',l.style||'',l.realBudget||'',l.createdAt?new Date(l.createdAt).toLocaleDateString('vi-VN'):'']);\n  const csv='\\uFEFF'+[h,...rows].map(r=>r.map(v=>'\"'+String(v||'').replace(\/\"\/g,'\"\"')+'\"').join(',')).join('\\n');\n  const a=document.createElement('a');a.href='data:text\/csv;charset=utf-8,'+encodeURIComponent(csv);a.download='leads_'+new Date().toISOString().slice(0,10)+'.csv';a.click();\n}\n<\/script><\/p>\n<p><!-- Google Identity Services for OAuth --><br \/>\n<script src=\"https:\/\/accounts.google.com\/gsi\/client\" async><\/script><br \/>\n<\/body><br \/>\n<\/html><\/p>","protected":false},"excerpt":{"rendered":"","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3536","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/pages\/3536","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/comments?post=3536"}],"version-history":[{"count":0,"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/pages\/3536\/revisions"}],"wp:attachment":[{"href":"https:\/\/hdinterior.vn\/en\/wp-json\/wp\/v2\/media?parent=3536"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}