For Nigerian real estate professionals
WQE™ lead scoring
ICP™ inspection system
CWP™ closing engine
DBTS™ diaspora mode
Antigha — diagnostic
:'no',added:YD,nextAction:'Send matching listings'}, {id:'l6',name:'Sade Williams',phone:'+234 810 111 3333',email:'sade@g.com',intent:'Rent',status:'Nurture',src:'WhatsApp',budget:'₦600K/yr',agent:'Chidi Bello',notes:'Early stage.',score:41,tier:'C',loc:'broad',time:'later',fin:'',dias:'no',added:YD,nextAction:'Check in after 7 days'}, ]; var DLIST=[ {id:'p1',addr:'12 Elm Court, Lekki Phase 1',price:54000000,cat:'Residential',status:'Active',comm:5,agent:'James Eko',beds:3,baths:2,notes:'Charming 3-bed terrace.',added:TD}, {id:'p2',addr:'5 Marina Blvd, Victoria Island',price:120000000,cat:'Commercial',status:'Pending',comm:4,agent:'Ada Nwosu',beds:0,baths:2,notes:'Waterfront commercial.',added:YD}, {id:'p3',addr:'Horizon Heights, Abuja',price:350000000,cat:'Off-plan',status:'Active',comm:6,agent:'Ada Nwosu',beds:0,baths:0,notes:'50-unit development.',added:YD}, {id:'p4',addr:'Lagos Island Shortlet',price:9500000,cat:'Shortlet',status:'Active',comm:10,agent:'Chidi Bello',beds:2,baths:2,notes:'Fully furnished.',added:TD}, {id:'p5',addr:'88 Oak Lane, GRA Port Harcourt',price:37500000,cat:'Residential',status:'New',comm:5,agent:'James Eko',beds:2,baths:1,notes:'Cozy starter home.',added:TD}, ]; var DPIPE=[ {id:'d1',title:'12 Elm Court',value:54000000,contact:'Bola Adeyemi',stage:'Inspection Scheduled',age:2,lc:1}, {id:'d2',title:'5 Marina Blvd',value:120000000,contact:'Kemi Suleiman',stage:'Offer Made',age:5,lc:3}, {id:'d3',title:'Horizon Heights',value:350000000,contact:'Femi Adeleke',stage:'Qualified',age:1,lc:0}, {id:'d4',title:'88 Oak Lane',value:37500000,contact:'Uche Obi',stage:'New Lead',age:8,lc:8}, {id:'d5',title:'PHC Duplex',value:85000000,contact:'Amaka Osei',stage:'Closing',age:3,lc:1}, ]; var DTASKS=[ {id:'t1',text:'Call Bola — confirm inspection for 12 Elm Court',due:YD,deal:'12 Elm Court',pri:'Urgent',agent:'James Eko',done:false}, {id:'t2',text:'Send video walkthrough to Amaka (diaspora buyer)',due:TD,deal:'PHC Duplex',pri:'High',agent:'Ada Nwosu',done:false}, {id:'t3',text:'Follow up on offer — 5 Marina Blvd',due:YD,deal:'5 Marina Blvd',pri:'High',agent:'Ada Nwosu',done:false}, {id:'t4',text:'Review agency agreement — Horizon Heights',due:TD,deal:'Horizon Heights',pri:'Normal',agent:'James Eko',done:false}, {id:'t5',text:'WhatsApp Sade — nurture check-in',due:TD,deal:'',pri:'Normal',agent:'Chidi Bello',done:true}, ]; var DAPPTS=[ {prop:'12 Elm Court, Lekki Phase 1',type:'Inspection',date:TD,time:'11:00',client:'Bola Adeyemi',remind:'2 hours before',dias:false,dfmt:''}, {prop:'Lagos Island Shortlet',type:'Viewing',date:TD,time:'15:00',client:'Amaka Osei',remind:'1 day before',dias:true,dfmt:'Live video call tour'}, ]; var DCOMM=[ {deal:'PHC Duplex',agent:'Ada Nwosu',expected:4250000,status:'Closing',referral:'Grace N.',split:'70/30'}, {deal:'5 Marina Blvd',agent:'Ada Nwosu',expected:4800000,status:'Pending',referral:'—',split:'100/0'}, {deal:'12 Elm Court',agent:'James Eko',expected:2700000,status:'Active',referral:'—',split:'100/0'}, ]; var DREFS=[ {by:'Grace Nkemdirim',deal:'PHC Duplex',pct:30,amount:1275000,status:'Pending'}, {by:'Tunde Fashola',deal:'88 Oak Lane (prev)',pct:20,amount:560000,status:'Paid'}, ]; var AGENTS=[ {name:'Ada Nwosu',role:'Senior Agent',color:'#1D9E75',bg:'#E1F5EE',leads:18,deals:5,closing:2,comm:9050000,last:'Today'}, {name:'James Eko',role:'Agent',color:'#534AB7',bg:'#EEEDFE',leads:12,deals:4,closing:1,comm:5400000,last:'Today'}, {name:'Chidi Bello',role:'Junior Agent',color:'#854F0B',bg:'#FAEEDA',leads:8,deals:2,closing:0,comm:950000,last:'Yesterday'}, {name:'Ngozi Adamu',role:'Agent',color:'#185FA5',bg:'#E6F1FB',leads:6,deals:1,closing:1,comm:2700000,last:'2 days ago'}, ]; var STAGES=['New Lead','Qualified','Inspection Scheduled','Inspection Done','Offer Made','Closing','Won','Lost']; var ACCENTS=['#1D9E75','#7F77DD','#378ADD','#D85A30','#D4537E','#BA7517','#0f0f0e']; var leads=ls('leads',DL),listings=ls('listings',DLIST),pipeline=ls('pipeline',DPIPE),tasks=ls('tasks',DTASKS),appts=ls('appts',DAPPTS); var accent=ls('accent','#1D9E75'),appName=ls('appname','PropOS'),userRole=ls('role','Agent'),userName=ls('uname','Chidi Bello'); var chatHistory=[];var msSelListing=DLIST[0];var msWaC=0,msInqC=0,msViews=0; var wqeData={};var wqeStep=0;var wqeLeadId=null; var antighaOpen=false;var antighaCtx='today'; function fc(v){var n=Number(v);if(n>=1e9)return'₦'+(n/1e9).toFixed(2)+'B';if(n>=1e6)return'₦'+(n/1e6).toFixed(1)+'M';if(n>=1000)return'₦'+(n/1000).toFixed(0)+'K';return'₦'+Math.round(n).toLocaleString()} function ini(n){return(n||'AG').split(' ').map(function(w){return w[0]}).join('').slice(0,2).toUpperCase()} function tic(t){return{A:'#A32D2D',B:'#854F0B',C:'#185FA5',D:'#5F5E5A'}[t]||'#888'} function tibg(t){return{A:'#FCEBEB',B:'#FAEEDA',C:'#E6F1FB',D:'#F1EFE8'}[t]||'#f0f0f0'} function bc(s){return'badge b-'+s.toLowerCase().replace(/[\s\/]/g,'')} function ok2(id){var e=document.getElementById(id);if(!e)return;e.style.display='inline';setTimeout(function(){e.style.display='none'},2200)} function applyAccent(a){accent=a;document.documentElement.style.setProperty('--ac',a);document.querySelectorAll('.sw-dot').forEach(function(s){s.style.outline=s.dataset.c===a?'2px solid var(--t1)':'';s.style.outlineOffset='2px'})} function liveCustom(){var el=document.getElementById('logo-name');if(el)el.textContent=(document.getElementById('c-name')||{}).value||'PropOS'} function saveCustom(){liveCustom();ss('appname',(document.getElementById('c-name')||{}).value||'PropOS');ss('accent',accent);ok2('c-ok')} function selPlan(p){} function closeModal(id){document.getElementById(id).classList.remove('open')} function selRole(el){document.querySelectorAll('.role-opt').forEach(function(r){r.classList.remove('sel')});el.classList.add('sel')} function buildSwatches(){var el=document.getElementById('swatches');if(!el)return;el.innerHTML='';ACCENTS.forEach(function(a){var d=document.createElement('div');d.className='sw-dot';d.style.cssText='width:24px;height:24px;border-radius:50%;background:'+a+';cursor:pointer;display:inline-block;outline-offset:2px';d.dataset.c=a;d.onclick=function(){applyAccent(a)};el.appendChild(d)});applyAccent(accent)} function doLogin(){ var name=(document.getElementById('lg-name')||{}).value||'Agent'; var roleEl=document.querySelector('.role-opt.sel'); userRole=roleEl?roleEl.dataset.role:'Agent';userName=name; ss('role',userRole);ss('uname',userName); document.getElementById('login-view').style.display='none'; document.getElementById('app-view').style.display='block'; document.getElementById('user-av').textContent=ini(name); document.getElementById('logo-role').textContent=' · '+userRole; document.getElementById('logo-name').textContent=appName; var cn=document.getElementById('c-name');if(cn)cn.value=appName; buildNav();buildSwatches();buildAgentSelect();sw('today'); } function doLogout(){document.getElementById('app-view').style.display='none';document.getElementById('login-view').style.display='block'} var NAVS=[ {id:'today',label:"Today's money"}, {id:'leads',label:'Leads',badge:function(){return leads.filter(function(l){return l.status==='Hot'}).length||''}}, {id:'pipeline',label:'Pipeline'}, {id:'listings',label:'Listings'}, {id:'appts',label:'Appointments'}, {id:'tasks',label:'Tasks',badge:function(){return tasks.filter(function(t){return !t.done&&t.due7)p+=40;else if(d.age>4)p+=25;else if(d.age>2)p+=10; if((d.lc||0)>5)p+=35;else if((d.lc||0)>2)p+=20;else if((d.lc||0)>1)p+=8; if(d.stage==='Offer Made'&&d.age>4)p+=15; if(d.stage==='Closing'&&d.age>3)p+=20; p=Math.min(p,100); var lv=p>=60?'h':p>=35?'m':'l'; var col={h:'#E24B4A',m:'#EF9F27',l:'#1D9E75'}[lv]; var lbl={h:'High risk',m:'Medium risk',l:'On track'}[lv]; return{pct:p,lv:lv,col:col,lbl:lbl}; } function waScript(tier,name,budget){ var s={A:'Hi '+name+', I have something that matches exactly what you described — '+budget+' range, ready to view now. Are you free this week? — [Your name]',B:'Hi '+name+', following up on our conversation. A property just became available that fits your criteria. Can I share the details? — [Your name]',C:'Hi '+name+', I've put together a few options that match what you mentioned. Happy to share when you're ready — no rush. — [Your name]',D:'Hi '+name+', just checking in to see if your plans have changed at all, or if there's anything specific you're looking for now. — [Your name]'}; return s[tier]||s['C']; } function ghostReviveScript(name){return'Hi '+name+', looks like something may have come up — totally understand. Just wanted to make sure you haven't missed anything urgent on the properties we discussed. Still happy to help if the timing works better now. — [Your name]'} function cwpScript(title){return'Quick update on '+title+' — we're at a critical point. Two things need to happen in the next 48 hours to keep this moving. When's the best time to talk today or tomorrow? — [Your name]'} function icpScript(){return'Just confirming our appointment tomorrow. We'll be at the property at [TIME] — the viewing takes about 30-40 minutes. I've arranged for the developer to be on call for technical questions. See you then! — [Your name]'} function copyWAScript(btn){var txt=btn.previousSibling?btn.previousSibling.textContent:btn.parentElement.querySelector('.wa-script-text')?btn.parentElement.querySelector('.wa-script-text').textContent:'';navigator.clipboard.writeText(txt.trim()).catch(function(){});btn.textContent='Copied!';setTimeout(function(){btn.textContent='Copy'},2000)} function renderToday(){ var hot=leads.filter(function(l){return l.status==='Hot'}); var todayA=appts.filter(function(a){return a.date===TD}); var closing=pipeline.filter(function(d){return d.stage==='Closing'||d.stage==='Offer Made'}); var overdue=tasks.filter(function(t){return !t.done&&t.due&&t.dueHere is what needs your attention right now — sorted by money at stake.'; document.getElementById('today-mg').innerHTML=[{l:'Hot leads',v:hot.length,d:'Call now',cl:'hot'},{l:'Appointments',v:todayA.length,d:'Today',cl:''},{l:'Near closing',v:closing.length,d:'Act today',cl:'grn'},{l:'Overdue tasks',v:overdue.length,d:overdue.length?'Deal risk':'All clear',cl:overdue.length?'hot':'grn'},{l:'Commission sitting',v:fc(totC),d:'Pipeline total',cl:''}].map(function(m){return'
'+m.l+'
'+m.v+'
'+m.d+'
'}).join(''); var h=''; if(hot.length){h+='

Hot leads — call now

';hot.slice(0,4).forEach(function(l){var wa='https://wa.me/'+l.phone.replace(/\D/g,'');h+='
'+l.name+' WQE™ '+l.tier+''+(l.dias==='yes'?'Diaspora':'') +'
'+l.phone+' · '+l.intent+' · '+l.budget+'
→ '+l.nextAction+'
'})} document.getElementById('today-hot').innerHTML=h; var ah='';if(todayA.length){ah='

Appointments today

';todayA.forEach(function(a){ah+='
'+a.prop+'
'+a.time+' · '+a.type+' · '+a.client+(a.dias?' DBTS™ · '+a.dfmt+'':'')+'
'})} document.getElementById('today-appts').innerHTML=ah; var ch='';if(closing.length){ch='

Deals near closing — act today

';closing.forEach(function(d){var r=dealRisk(d);ch+='
'+d.title+' '+r.lbl+'
'+d.contact+' · '+d.stage+' · '+fc(d.value)+'
'+r.pct+'% risk
'})} document.getElementById('today-closing').innerHTML=ch; var oh='';if(overdue.length){oh='

Overdue follow-ups — money at risk

';overdue.forEach(function(t){oh+='
'+t.text+'
Due: '+t.due+(t.deal?' · Deal: '+t.deal:'') +'
'})} else if(!hot.length&&!todayA.length&&!closing.length){oh='
You're clean. No urgent actions right now.
'} document.getElementById('today-overdue').innerHTML=oh; document.getElementById('today-rev').innerHTML='
Commission sitting in pipeline
'+fc(totC)+'
Closing this week
'+fc(clsC)+'
At risk
'+fc(totC-clsC)+'
'; } function showGhost(id){var l=leads.find(function(x){return x.id===id});if(!l)return;document.getElementById('mm-title').textContent='Ghost revival — '+l.name;document.getElementById('mm-body').innerHTML='

Send this pattern-interrupt message to re-open the conversation.

';document.getElementById('modal-main').classList.add('open')} function showCwp(id){var d=pipeline.find(function(x){return x.id===id});if(!d)return;document.getElementById('mm-title').textContent='CWP™ closing script — '+d.title;document.getElementById('mm-body').innerHTML='

This deal needs action in the next 48 hours. Use this script.

';document.getElementById('modal-main').classList.add('open')} function showIcp(){document.getElementById('mm-title').textContent='ICP™ pre-inspection script';document.getElementById('mm-body').innerHTML='

Send this the evening before. Reduces no-shows dramatically.

';document.getElementById('modal-main').classList.add('open')} // WQE STEPPER var WQE_STEPS=[ {key:'intent',label:'What is this buyer looking for?',sub:'Determines which scoring path applies.',opts:[{val:'Buy',label:'Buy a property',icon:'🏠'},{val:'Rent',label:'Rent a property',icon:'🔑'},{val:'Invest',label:'Invest for rental income',icon:'📈'},{val:'Off-plan',label:'Off-plan / development',icon:'🏗️'}]}, {key:'loc',label:'How specific is their location?',sub:'Buyers who know exactly where they want to buy are 3x more likely to close.',opts:[{val:'yes',label:'Specific area or estate',icon:'📍'},{val:'broad',label:'Broad area (city level)',icon:'🗺️'},{val:'no',label:'Open to suggestions',icon:'💭'},{val:'browsing',label:'Just browsing',icon:'👀'}]}, {key:'time',label:'When are they ready to move?',sub:'Timeline is the single strongest predictor of whether a deal closes.',opts:[{val:'now',label:'Immediately (0–4 weeks)',icon:'⚡'},{val:'soon',label:'1–3 months',icon:'📅'},{val:'later',label:'3–6 months',icon:'🗓️'},{val:'browsing',label:'No set timeline',icon:'♾️'}]}, {key:'fin',label:'What is their financing situation?',sub:'Financing readiness determines whether they can actually buy — not just dream.',opts:[{val:'yes',label:'Cash ready',icon:'💰'},{val:'mortgage',label:'Mortgage in progress',icon:'🏦'},{val:'no',label:'No clear plan yet',icon:'❓'}]}, ]; function openWQE(pf){wqeData={};wqeStep=0;wqeLeadId=pf.id||null;if(pf.id){var l=leads.find(function(x){return x.id===pf.id});if(l){wqeData.intent=l.intent;wqeData.loc=l.loc;wqeData.time=l.time;wqeData.fin=l.fin;wqeData.dias=l.dias;wqeData.name=l.name;wqeData.phone=l.phone;wqeData.budget=l.budget;wqeData.src=l.src}}document.getElementById('wqe-title').textContent=wqeLeadId?'Re-score lead (WQE™)':'WQE™ Lead Qualifier';renderWQEStep();document.getElementById('modal-wqe').classList.add('open')} function renderWQEStep(){ var el=document.getElementById('wqe-body'); if(wqeStep'}).join(''); var opts=st.opts.map(function(o){return'
'+o.icon+'
'+o.label+'
'}).join(''); var extras=''; if(wqeStep===0){extras='
Diaspora buyer — activates DBTS™ mode
'} el.innerHTML='
'+dots+'
'+st.label+'
'+st.sub+'
'+opts+'
'+extras+(wqeStep>0?'
'+(wqeData[st.key]?'':'')+'
':'')+'
'; } else {renderWQEResult()} } function wqeSel(k,v){wqeData[k]=v;renderWQEStep();if(wqeStep>0){setTimeout(function(){if(wqeData[WQE_STEPS[wqeStep].key])wqeNext()},300)}} function wqeNext(){if(wqeStep===0){var n=document.getElementById('wq-name');if(n)wqeData.name=n.value.trim();var p=document.getElementById('wq-phone');if(p)wqeData.phone=p.value;var b=document.getElementById('wq-budget');if(b)wqeData.budget=b.value;var s=document.getElementById('wq-src');if(s)wqeData.src=s.value;if(!wqeData.name){alert('Name is required');return}}if(!wqeData[WQE_STEPS[wqeStep].key]){alert('Please select an option');return}wqeStep++;renderWQEStep()} function calcWQE(){var s=0;if(wqeData.loc==='yes')s+=30;else if(wqeData.loc==='broad')s+=12;if(wqeData.time==='now')s+=30;else if(wqeData.time==='soon')s+=18;else if(wqeData.time==='later')s+=7;if(wqeData.fin==='yes')s+=30;else if(wqeData.fin==='mortgage')s+=14;if(wqeData.dias==='yes')s+=10;if(wqeData.intent==='Invest'||wqeData.intent==='Off-plan')s+=5;return Math.min(s,100)} function renderWQEResult(){ var score=calcWQE(); var tier=score>=80?'A':score>=60?'B':score>=40?'C':'D'; var status=score>=80?'Hot':score>=60?'Warm':score>=40?'Nurture':'Dead'; var nxt=score>=80?'Call within 10 minutes — move to pipeline.':score>=60?'Follow up within 48 hours — send matching listings.':score>=40?'Add to nurture — check in after 7 days.':'Archive. Do not pursue.'; var tc=tic(tier),tbg=tibg(tier); var vrd={A:'This lead is ready. Move now.They have financing, know exactly where they want, and are ready to buy immediately. Call within 10 minutes.',B:'Close, but not yet ready.Real intent, but one or more signals are missing. Send listings, build urgency, and get them to a viewing within 7 days.',C:'Too early. Do not chase.Add to nurture, send soft content, check in after 7 days. Chasing now will push them away.',D:'Do not waste time.No financing, no timeline, no committed location. Archive and move energy to A/B leads.'}; var abtns=''; if(tier==='A'){abtns='
';} else if(tier==='B'){abtns='
';} else if(tier==='C'){abtns='
';} else{abtns='
';} document.getElementById('wqe-body').innerHTML= '
'+tier+'
Score: '+score+' / 100
'+status+'
'+ '
Next action
'+nxt+'
'+ '
'+vrd[tier]+'
'+abtns+ ''+ '
'; } function saveWQELead(skipClose){if(!wqeData.name){alert('Name required');return}var score=calcWQE();var tier=score>=80?'A':score>=60?'B':score>=40?'C':'D';var status=score>=80?'Hot':score>=60?'Warm':score>=40?'Nurture':'Dead';var nxt=score>=80?'Call within 10 minutes':score>=60?'Follow up in 48 hours':score>=40?'Check in after 7 days':'Archive';var taskDue=score>=80?TD:new Date(Date.now()+(score>=60?2:7)*86400000).toISOString().slice(0,10);var taskTxt=score>=80?'Call '+wqeData.name+' — A-tier lead':score>=60?'Follow up with '+wqeData.name+' (B-tier)':'Nurture check-in — '+wqeData.name;if(wqeLeadId){var ex=leads.find(function(l){return l.id===wqeLeadId});if(ex){ex.score=score;ex.tier=tier;ex.status=status;ex.nextAction=nxt;ex.loc=wqeData.loc||ex.loc;ex.time=wqeData.time||ex.time;ex.fin=wqeData.fin||ex.fin;ex.dias=wqeData.dias||ex.dias;ex.budget=wqeData.budget||ex.budget}}else{leads.unshift({id:'l'+Date.now(),name:wqeData.name,phone:wqeData.phone||'',email:'',intent:wqeData.intent||'Buy',status:status,src:wqeData.src||'Manual',budget:wqeData.budget||'',agent:userName,notes:'',score:score,tier:tier,loc:wqeData.loc||'',time:wqeData.time||'',fin:wqeData.fin||'',dias:wqeData.dias||'no',added:TD,nextAction:nxt});tasks.unshift({id:'t'+Date.now(),text:taskTxt,due:taskDue,deal:'',pri:score>=80?'Urgent':score>=60?'High':'Normal',agent:userName,done:false})}ss('leads',leads);ss('tasks',tasks);buildNav();if(!skipClose)closeModal('modal-wqe');renderLeads();renderToday()} function wqeSaveCall(){saveWQELead(true);var ph=(wqeData.phone||'').replace(/\D/g,'');if(ph)window.open('tel:+'+ph)} function wqeSaveWA(){saveWQELead(true);var ph=(wqeData.phone||'').replace(/\D/g,'');var msg=waScript(calcWQE()>=80?'A':calcWQE()>=60?'B':calcWQE()>=40?'C':'D',wqeData.name,wqeData.budget);if(ph)window.open('https://wa.me/'+ph+'?text='+encodeURIComponent(msg),'_blank')} function renderLeads(){var q=(document.getElementById('ld-q').value||'').toLowerCase();var fs=document.getElementById('ld-st').value;var fsr=document.getElementById('ld-src').value;var f=leads.filter(function(l){return(!q||(l.name+' '+l.phone).toLowerCase().includes(q))&&(!fs||l.status===fs)&&(!fsr||l.src===fsr)});var tb=document.getElementById('ld-body');tb.innerHTML='';document.getElementById('ld-em').style.display=f.length?'none':'block';f.forEach(function(l){var i=leads.indexOf(l);var tr=document.createElement('tr');tr.innerHTML=''+l.name+''+(l.dias==='yes'?'Dias':'') +'
'+l.phone+'
'+l.tier+' · '+l.score+'→ '+(l.nextAction||'—')+''+l.status+''+l.budget+''+l.src+''+l.agent+'';tr.onclick=function(){showLead(l.id)};tb.appendChild(tr)})} function showLead(id){var l=leads.find(function(x){return x.id===id});if(!l)return;var wa='https://wa.me/'+l.phone.replace(/\D/g,'');document.getElementById('mm-title').textContent=l.name;document.getElementById('mm-body').innerHTML='
WQE™ Tier '+l.tier+' · Score: '+l.score+'/100
→ '+(l.nextAction||'—')+'
'+ ['Status','Intent','Budget','Source','Phone','Agent'].map(function(k,i){var v=[''+l.status+'',l.intent,l.budget,l.src,l.phone,l.agent][i];return'
'+k+''+v+'
'}).join('') +'
';document.getElementById('modal-main').classList.add('open')} function doneTask(id){var t=tasks.find(function(x){return x.id===id});if(t){t.done=true;ss('tasks',tasks);renderToday();buildNav()}} function showDeal(id){var d=pipeline.find(function(x){return x.id===id});if(!d)return;var r=dealRisk(d);document.getElementById('mm-title').textContent=d.title;document.getElementById('mm-body').innerHTML='
'+r.lbl+' ('+r.pct+'% risk score)
'+['Value','Contact','Stage','Days in stage'].map(function(k,i){var v=[fc(d.value),d.contact,''+d.stage+'',d.age+'d'][i];return'
'+k+''+v+'
'}).join('')+'

Move to stage

'+STAGES.map(function(s){return''}).join('')+'
';document.getElementById('modal-main').classList.add('open')} function renderKanban(){var kb=document.getElementById('kanban');kb.innerHTML='';var hi=pipeline.filter(function(d){return dealRisk(d).lv==='h'});var bn=document.getElementById('pipe-risk-banner');if(hi.length){bn.innerHTML='
'+hi.length+' deal'+(hi.length>1?'s':'')+' at high risk — '+hi.map(function(d){return d.title}).join(', ')+'
'}else bn.innerHTML='';STAGES.forEach(function(stage){var cards=pipeline.filter(function(p){return p.stage===stage});var col=document.createElement('div');col.className='kcol';col.dataset.stage=stage;col.innerHTML='
'+stage+''+cards.length+'
';var drop=document.createElement('div');drop.className='kdrop';col.appendChild(drop);cards.forEach(function(p){var r=dealRisk(p);var card=document.createElement('div');card.className='kcard';card.draggable=true;card.dataset.id=p.id;card.innerHTML='
'+p.title+'
'+p.contact+'
'+fc(p.value)+'
'+r.lbl+'';card.addEventListener('dragstart',function(){card.classList.add('dragging');window._did=p.id});card.addEventListener('dragend',function(){card.classList.remove('dragging');document.querySelectorAll('.kdrop').forEach(function(d){d.style.display='none'})});col.appendChild(card)});col.addEventListener('dragover',function(e){e.preventDefault();drop.style.display='block'});col.addEventListener('dragleave',function(){drop.style.display='none'});col.addEventListener('drop',function(e){e.preventDefault();drop.style.display='none';pipeline.forEach(function(p){if(p.id===window._did){p.stage=stage;p.age=0;p.lc=0}});ss('pipeline',pipeline);renderKanban();renderToday()});kb.appendChild(col)})} function renderListings(){var q=(document.getElementById('ls-q').value||'').toLowerCase();var fs=document.getElementById('ls-st').value;var fc2=document.getElementById('ls-cat').value;var f=listings.filter(function(l){return(!q||(l.addr+' '+l.agent).toLowerCase().includes(q))&&(!fs||l.status===fs)&&(!fc2||l.cat===fc2)});var tb=document.getElementById('ls-body');tb.innerHTML='';document.getElementById('ls-em').style.display=f.length?'none':'block';f.forEach(function(l){var i=listings.indexOf(l);var comm=l.comm?'₦'+Math.round(l.price*l.comm/100/1000)+'K ('+l.comm+'%)':'\—';var tr=document.createElement('tr');tr.innerHTML=''+l.addr+''+fc(l.price)+''+l.cat+''+l.status+''+comm+''+l.agent+'';tb.appendChild(tr)})} function addListing(){var a=document.getElementById('fls-addr').value.trim(),p=parseFloat(document.getElementById('fls-price').value);if(!a||!p){alert('Address and price required');return}listings.unshift({id:'ls'+Date.now(),addr:a,price:p,cat:document.getElementById('fls-cat').value,status:document.getElementById('fls-st').value,comm:parseFloat(document.getElementById('fls-comm').value)||5,agent:document.getElementById('fls-agent').value||userName,beds:parseInt(document.getElementById('fls-beds').value)||0,baths:parseInt(document.getElementById('fls-baths').value)||0,notes:document.getElementById('fls-notes').value,added:TD});ss('listings',listings);ok2('fls-ok');['fls-addr','fls-price','fls-comm','fls-agent','fls-beds','fls-baths','fls-notes'].forEach(function(id){document.getElementById(id).value=''})} function exportCSV(){var csv=['Address,Price,Category,Status,Commission%,Agent'].concat(listings.map(function(l){return'"'+l.addr+'",'+l.price+','+l.cat+','+l.status+','+l.comm+','+l.agent})).join('\n');var blob=new Blob([csv],{type:'text/csv'});var url=URL.createObjectURL(blob);var a=document.createElement('a');a.href=url;a.download='listings.csv';document.body.appendChild(a);a.click();document.body.removeChild(a);URL.revokeObjectURL(url)} function toggleDias(){var sw=document.getElementById('dias-sw');sw.classList.toggle('on');var on=sw.classList.contains('on');sw.style.background=on?'var(--ac)':'var(--bd2)';document.getElementById('dias-opts').style.display=on?'block':'none'} function populatePropSel(){var sel=document.getElementById('ap-prop');var cur=sel.value;sel.innerHTML='';listings.forEach(function(l){var o=document.createElement('option');o.value=l.addr;o.textContent=l.addr;sel.appendChild(o)});if(cur)sel.value=cur} function renderAppts(){var el=document.getElementById('appt-list');el.innerHTML='';var s=appts.slice().sort(function(a,b){return(a.date+a.time).localeCompare(b.date+b.time)});var up=s.filter(function(a){return a.date>=TD}),past=s.filter(function(a){return a.date
'+a.date+' '+a.time+' · '+a.type+' · '+a.client+(a.dias?' DBTS™ · '+a.dfmt+'':'')+'
';el.appendChild(d)})}if(!up.length&&!past.length){el.innerHTML='
No appointments yet.
';return}rg(up,'Upcoming');rg(past,'Past')} function addAppt(){var p=document.getElementById('ap-prop').value,d=document.getElementById('ap-date').value;if(!p||!d){alert('Select property and date');return}var sw=document.getElementById('dias-sw').classList.contains('on');var fmt=sw?document.querySelector('input[name=dfmt]:checked').value:'';var fmtL={recorded:'Recorded walkthrough',live:'Live video call tour',third:'Third-party site visit',relative:'Relative viewing',vr:'360° virtual tour'}[fmt]||'';;appts.push({prop:p,type:document.getElementById('ap-type').value,date:d,time:document.getElementById('ap-time').value,client:document.getElementById('ap-client').value||'—',remind:document.getElementById('ap-remind').value,dias:sw,dfmt:fmtL});ss('appts',appts);renderAppts();renderToday();document.getElementById('ap-date').value='';document.getElementById('ap-client').value='';ok2('ap-ok')} function renderTasks(){var q=(document.getElementById('tk-q').value||'').toLowerCase();var f=document.getElementById('tk-f').value;var ft=tasks.filter(function(t){if(!(!q||(t.text+' '+t.deal).toLowerCase().includes(q)))return false;if(f==='overdue')return !t.done&&t.due&&t.dueNo tasks match.';return}ft.forEach(function(t){var ov=!t.done&&t.due&&t.due'+(t.done?'
':'')+''+t.text+''+(t.deal?''+t.deal+'':'')+''+t.due+''+t.pri+'';d.onclick=function(){t.done=!t.done;ss('tasks',tasks);renderTasks();buildNav();renderToday()};el.appendChild(d)})} function addTask(){var txt=document.getElementById('ft-text').value.trim();if(!txt){alert('Task required');return}tasks.unshift({id:'t'+Date.now(),text:txt,due:document.getElementById('ft-due').value||TD,deal:document.getElementById('ft-deal').value,pri:document.getElementById('ft-pri').value,agent:userName,done:false});ss('tasks',tasks);buildNav();ok2('ft-ok');['ft-text','ft-due','ft-deal'].forEach(function(id){document.getElementById(id).value=''})} function renderTeam(){var sorted=AGENTS.slice().sort(function(a,b){return b.comm-a.comm});var total=AGENTS.reduce(function(s,a){return s+a.comm},0);document.getElementById('leaderboard').innerHTML=sorted.map(function(a,i){var rk=['1','2','3','4'][i];var rc=['gold','silver','bronze',''][i];return'
'+rk+'
'+ini(a.name)+'
'+a.name+'
'+a.role+'
'+a.deals+' deals
'+fc(a.comm)+'
'}).join('');document.getElementById('agent-cards').innerHTML=sorted.map(function(a){var pct=Math.round(a.comm/total*100);return'
'+ini(a.name)+'
'+a.name+'
'+a.role+' · '+a.last+'
'+a.leads+'
Leads
'+a.deals+'
Deals
'+a.closing+'
Closing
'+fc(a.comm)+'
Commission
'}).join('');var tb=document.getElementById('agent-table');tb.innerHTML='';sorted.forEach(function(a){var tr=document.createElement('tr');tr.innerHTML=''+a.name+''+a.leads+''+a.deals+''+a.closing+''+fc(a.comm)+''+a.last+'';tb.appendChild(tr)})} function buildAgentSelect(){var sel=document.getElementById('assign-agent');if(!sel)return;sel.innerHTML='';AGENTS.forEach(function(a){var o=document.createElement('option');o.value=a.name;o.textContent=a.name;sel.appendChild(o)})} function doAssign(){var deal=document.getElementById('assign-deal').value.trim();if(!deal){alert('Enter a lead or deal');return}ok2('assign-ok');document.getElementById('assign-deal').value='';document.getElementById('assign-note').value=''} function catHero(cat){var m={Residential:'linear-gradient(155deg,#1a1040 0%,#7F77DD 100%)',Commercial:'linear-gradient(155deg,#0a1a2a 0%,#185FA5 100%)','Off-plan':'linear-gradient(155deg,#0a2a1f 0%,#1D9E75 100%)',Shortlet:'linear-gradient(155deg,#2a1500 0%,#854F0B 100%)',Land:'linear-gradient(155deg,#0a1a00 0%,#3B6D11 100%)'};return m[cat]||'linear-gradient(155deg,#111 0%,#555 100%)'} function catAC(cat){var m={Residential:'#7F77DD',Commercial:'#185FA5','Off-plan':'#1D9E75',Shortlet:'#854F0B'};return m[cat]||'#1D9E75'} function renderMsPick(){var el=document.getElementById('ms-pick-list');el.innerHTML='';listings.forEach(function(l){var row=document.createElement('div');row.style.cssText='display:flex;align-items:center;gap:10px;padding:9px 12px;border-bottom:1px solid var(--bd);cursor:pointer;font-size:12px';if(msSelListing&&msSelListing.id===l.id)row.style.background='var(--ac2)';row.innerHTML='
'+l.addr+''+l.cat+''+fc(l.price)+'';row.onclick=function(){msSelListing=l;renderMsPick()};el.appendChild(row)})} function launchMS(id){var l=listings.find(function(x){return x.id===id});if(l){msSelListing=l;msProceed()}} function msProceed(){if(!msSelListing){alert('Select a listing');return}var l=msSelListing;document.getElementById('ms-title').value=l.addr;document.getElementById('ms-loc').value=l.addr.split(',').slice(1).join(',').trim()||l.addr;document.getElementById('ms-price').value=fc(l.price);document.getElementById('ms-pnote').value='Negotiable · Owner motivated';document.getElementById('ms-beds').value=l.beds||'';document.getElementById('ms-baths').value=l.baths||'';document.getElementById('ms-size').value='';document.getElementById('ms-cat').value=l.cat;document.getElementById('ms-desc').value=l.notes||'A beautiful property in a prime location.';document.getElementById('ms-f1').value='24/7 Security';document.getElementById('ms-f2').value='Ample Parking';document.getElementById('ms-f3').value='Fitted Kitchen';document.getElementById('ms-f4').value='Good Ventilation';document.getElementById('ms-agent').value=l.agent||userName;document.getElementById('ms-phone').value='+234 806 333 4444';document.getElementById('ms-agency').value='PropCo Realty';document.getElementById('ms-wamsg').value='Hi, I saw your listing for '+l.addr+' and I\'m interested.';msp('cust')} function msBuild(){var d={title:document.getElementById('ms-title').value||'Beautiful Property',loc:document.getElementById('ms-loc').value||'Lagos',price:document.getElementById('ms-price').value||'Price on request',pnote:document.getElementById('ms-pnote').value,beds:document.getElementById('ms-beds').value,baths:document.getElementById('ms-baths').value,size:document.getElementById('ms-size').value,cat:document.getElementById('ms-cat').value,desc:document.getElementById('ms-desc').value||'A great property.',f1:document.getElementById('ms-f1').value,f2:document.getElementById('ms-f2').value,f3:document.getElementById('ms-f3').value,f4:document.getElementById('ms-f4').value,agent:document.getElementById('ms-agent').value||'Agent',phone:document.getElementById('ms-phone').value||'+234 800 000 0000',agency:document.getElementById('ms-agency').value||'PropOS Realty',wamsg:document.getElementById('ms-wamsg').value||'Hi, I\'m interested.'};var ph=d.phone.replace(/\D/g,'');var waUrl='https://wa.me/'+ph+'?text='+encodeURIComponent(d.wamsg);var ac2=catAC(d.cat);var feats=[d.f1,d.f2,d.f3,d.f4].filter(Boolean);var html='
'+d.cat+'
'+d.title+'
'+d.loc+'
'+d.price+'
'+(d.pnote?'
'+d.pnote+'
':'')+'WhatsApp agent now
'+ '
'+ ['Main view','Living room','Bedroom','Kitchen'].map(function(l){return'
'+l+'
'}).join('')+'
'+ '
About
'+d.desc+'
'+ ((d.beds||d.baths||d.size)?'
Specs
'+(d.beds?'
'+d.beds+'
Beds
':'')+( d.baths?'
'+d.baths+'
Baths
':'')+( d.size?'
'+d.size+'
Size
':'')+'
':'')+ (feats.length?'
Features
'+feats.map(function(f){return'
'+f+'
'}).join('')+'
':'')+'
'+ini(d.agent)+'
'+d.agent+'
'+d.agency+'
Verified listingPropOS certifiedFast response
Quick enquiry

Sent! Agent will contact you within 1 hour.

P
'+d.agency+'
Powered by PropOS
';['ms-scr1','ms-scr2'].forEach(function(id){var el=document.getElementById(id);if(el)el.innerHTML=html});var slug=d.title.toLowerCase().replace(/[^a-z0-9]+/g,'-').slice(0,36)+'-'+Math.random().toString(36).slice(2,7);document.getElementById('ms-link').textContent='https://propos.ng/l/'+slug;msViews=Math.floor(Math.random()*14)+4;msStat()} function msStat(){['ms-views','ms-wa-c','ms-inq-c'].forEach(function(id,i){var e=document.getElementById(id);if(e)e.textContent=[msViews,msWaC,msInqC][i]})} function msCopy(e){var l=document.getElementById('ms-link').textContent;navigator.clipboard.writeText(l).catch(function(){});if(e&&e.target){var b=e.target;b.textContent='Copied!';setTimeout(function(){b.textContent='Copy'},2000)}} function msShareWA(){window.open('https://wa.me/?text='+encodeURIComponent('Check out this property: '+document.getElementById('ms-link').textContent),'_blank');msWaC++;msStat()} function msp(name){document.querySelectorAll('#ms-pills .pill').forEach(function(p){p.classList.toggle('on',p.getAttribute('onclick')&&p.getAttribute('onclick').includes("'"+name+"'"))});['sel','cust','prev','pub'].forEach(function(n){document.getElementById('ms-'+n+'-pane').style.display=n===name?'block':'none'});if(name==='prev')msBuild()} function renderCommission(){var tot=DCOMM.reduce(function(s,c){return s+c.expected},0);var cls=DCOMM.filter(function(c){return c.status==='Closing'}).reduce(function(s,c){return s+c.expected},0);var refP=DREFS.filter(function(r){return r.status==='Pending'}).reduce(function(s,r){return s+r.amount},0);document.getElementById('comm-mg').innerHTML=[{l:'Pipeline total',v:fc(tot),d:'All deals',cl:''},{l:'Closing this week',v:fc(cls),d:'Act now',cl:'grn'},{l:'Referrals due',v:fc(refP),d:'Pending payout',cl:'amb'}].map(function(m){return'
'+m.l+'
'+m.v+'
'+m.d+'
'}).join('');var cb=document.getElementById('comm-body');cb.innerHTML='';DCOMM.forEach(function(c){var tr=document.createElement('tr');tr.innerHTML=''+c.deal+''+c.agent+''+fc(c.expected)+''+c.status+''+c.referral+''+c.split+'';cb.appendChild(tr)});var rb=document.getElementById('ref-body');rb.innerHTML='';DREFS.forEach(function(r){var tr=document.createElement('tr');tr.innerHTML=''+r.by+''+r.deal+''+r.pct+'%'+fc(r.amount)+''+r.status+'';rb.appendChild(tr)})} var antighaOpen=false; function toggleAntigha(){antighaOpen=!antighaOpen;document.getElementById('antigha-panel').classList.toggle('open',antighaOpen)} function updateAntighaCtxBtns(page){var m={today:['Who should I call right now?','What deals are at risk?','Summarise my pipeline'],leads:['Which leads need attention?','Write a follow-up script','How do I qualify faster?'],pipeline:['Which deal is closest to closing?','What deals are at risk?','CWP™ closing script'],listings:['Which listing should I prioritise?','Generate a microsite description'],appts:['ICP™ confirmation message','How do I reduce no-shows?']};var btns=(m[page]||m.today);var el=document.getElementById('antigha-qbtns');if(!el)return;el.innerHTML=btns.map(function(q){return''}).join('')} function antighaQ(q){if(!antighaOpen)toggleAntigha();document.getElementById('antigha-in').value=q;sendAntigha()} async function sendAntigha(){var inp=document.getElementById('antigha-in'),msg=inp.value.trim();if(!msg)return;inp.value='';appendAntigha(msg,'user');chatHistory.push({role:'user',content:msg});document.getElementById('typing').style.display='flex';var hot=leads.filter(function(l){return l.status==='Hot'}).length;var ov=tasks.filter(function(t){return !t.done&&t.dueA':'
'+ini(userName)+'
')+'
'+text.replace(/\n/g,'
')+'
';wrap.appendChild(d);wrap.scrollTop=wrap.scrollHeight} applyAccent(accent);